summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2013-04-01 14:41:51 -0700
committerJean-Baptiste Queru <jbq@google.com>2013-04-01 14:41:51 -0700
commit2bd2b7c2623d4266384e890271869efc044aabff (patch)
tree0b31f50e55975b6354ed458314e17b4441bb4e17 /plugins
parent1d526b16d476792ca7ce47616d55833115e8d6ab (diff)
downloadidea-2bd2b7c2623d4266384e890271869efc044aabff.tar.gz
Snapshot ee98b298267d0e09d2cd2f0731b6480a56dd48e7 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: I4515f72af131fdea9fc6905a4dc0fe9532409a81
Diffstat (limited to 'plugins')
-rw-r--r--plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java2
-rw-r--r--plugins/InspectionGadgets/src/META-INF/plugin.xml8
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties48
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java94
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/assignment/AssignmentToSuperclassFieldInspection.java107
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java34
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspection.java35
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspection.java25
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java40
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/NonFinalUtilityClassInspection.java5
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java17
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspection.java54
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateConditionInspection.java73
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java20
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspection.java165
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java22
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java24
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java32
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java3
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/jdk/AutoBoxingInspection.java205
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/jdk/ForeachStatementInspection.java7
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java22
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java128
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java24
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java276
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfStatementBranch.java22
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java55
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java8
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java284
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/numeric/DivideByZeroInspection.java48
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java188
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java12
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java3
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java15
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/FormatUtils.java19
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ParenthesesUtils.java54
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/SwitchUtils.java212
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java105
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java69
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java44
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspection.java34
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/AnnotationNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassComplexity.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassMethodCount.html5
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/AssignmentToSuperclassField.html9
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ClassComplexity.html8
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ClassCoupling.html5
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ClassInheritanceDepth.html4
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ClassNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ClassNestingDepth.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ClassWithoutNoArgConstructor.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ConstantNamingConvention.html7
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ConstructorCount.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/CyclomaticComplexity.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/DuplicateCondition.html3
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/EnumSwitchStatementWhichMissesCases.html3
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedClassNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedConstantNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/FieldCount.html7
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ForCanBeForeach.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/IfStatementWithTooManyBranches.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/InstanceMethodNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/InstanceVariableNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/JUnitAbstractTestClassNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/JUnitTestClassNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/LocalVariableNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/LogStatementGuardedByLogCondition.html20
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/LoggingConditionDisagreesWithLogStatement.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/MethodCanBeVariableArityMethod.html4
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/MethodCount.html6
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/MethodCoupling.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/MultipleReturnPointsPerMethod.html13
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/MultiplyOrDivideByPowerOfTwo.html4
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/NegatedConditional.html3
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/NegatedIfElse.html3
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/NestingDepth.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/NonCommentSourceStatements.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexArithmeticExpression.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexBooleanExpression.html7
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/PackageNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ParameterNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerConstructor.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerMethod.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/PlaceholderCountMatchesArgumentCount.html9
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/PointlessNullCheck.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ReplaceAssignmentWithOperatorAssignment.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ResultOfObjectAllocationIgnored.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/StaticMethodNamingConvention.html4
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/StaticVariableNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html6
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/StringConstructor.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/StringReplaceableByStringBuffer.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooFewBranches.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooManyBranches.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ThrownExceptionsPerMethod.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/TryFinallyCanBeTryWithResources.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/TypeParameterNamingConvention.html2
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/WhileCanBeForeach.html2
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/constant_if/Comment.after.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/constant_if/Comment.java8
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Negated.after.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Negated.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Normal.after.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Normal.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/errorhandling/throws_runtime_exception/MoveThrows.java (renamed from plugins/InspectionGadgets/test/com/siyeh/igfixes/errorhandling/throws_runtime_exception/moveThrows.java)0
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/logging/string_concatenation_argument_to_log_call/UseOfConstant.after.java11
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/logging/string_concatenation_argument_to_log_call/UseOfConstant.java11
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/if_can_be_switch/Comment.after.java15
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/if_can_be_switch/Comment.java13
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/expected.xml7
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/assignment/assignment_to_superclass_field/AssignmentToSuperclassField.java25
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/assignment/assignment_to_superclass_field/expected.xml24
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/IgnoreResultsOfReadInspection.java23
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ignore_result_of_call/IgnoreResultOfCall.java10
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ignore_result_of_call/expected.xml9
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/result_of_object_allocation_ignored/ResultOfObjectAllocationIgnored.java (renamed from plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ResultOfObjectAllocationIgnoredInspection.java)6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/result_of_object_allocation_ignored/expected.xml16
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java2
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/PrimitiveArrayArgumentToVariableArgMethod.java (renamed from plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/PrimitiveArrayArgumnetToVariableArgMethod.java)12
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/expected.xml2
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/non_final_utility_class/NonFinalUtilityClass.java3
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_boolean_branch/DuplicateBooleanBranch.java8
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_boolean_branch/expected.xml16
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_condition/DuplicateCondition.java12
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_condition/expected.xml37
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/FallthruInSwitch.java2
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/expected.xml7
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/overly_complex_boolean_expression/OverlyComplexBooleanExpression.java13
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/overly_complex_boolean_expression/expected.xml9
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression/PointlessBooleanExpression.java (renamed from plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression_ignore_cont_const/PointlessBooleanExpression.java)7
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression/expected.xml (renamed from plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression_ignore_cont_const/expected.xml)7
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_null_check/expected.xml16
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/AutoBoxing.java8
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/expected.xml14
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/LogStatementGuardedByLogCondition.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/expected.xml7
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/IfCanBeSwitch.java31
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/expected.xml13
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java7
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/divide_by_zero/DivideByZero.java13
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/divide_by_zero/expected.xml16
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/ImplicitNumericConversion.java4
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/expected.xml7
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java5
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_parentheses/UnnecessaryParenthesesInspection.java5
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter/SynchronizationOnLocalVariableOrMethodParameter.java34
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter/expected.xml9
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java73
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/assignment/AssignmentToSuperclassFieldInspectionTest.java25
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.java10
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspectionTest.java10
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/PrimitiveArrayArgumnetToVariableArgMethodInspectionTest.java11
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspectionTest.java25
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspectionTest.java10
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/DuplicateConditionInspectionTest.java10
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspectionTest.java13
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspectionTest.java4
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessBooleanExpressionFixTest.java5
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessNullCheckFixTest.java7
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/ConstantIfFixTest.java33
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/SimplifiableEqualsExpressionFixTest.java34
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/errorhandling/ThrowsRuntimeExceptionInspectionFixTest.java4
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/logging/StringConcatenationArgumentToLogCallFixTest.java41
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/migration/IfCanBeSwitchFixTest.java36
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java62
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspectionTest.java31
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/IfCanBeSwitchInspectionTest.java13
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java7
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/DivideByZeroInspectionTest.java10
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspectionTest.java21
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomErrorElementFilter.java13
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java41
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectedLanguage.java2
-rw-r--r--plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java8
-rw-r--r--plugins/IntentionPowerPak/src/META-INF/plugin.xml2
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties6
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsPredicate.java17
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java30
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsPredicate.java9
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ExceptionUtils.java23
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MulticatchPredicate.java12
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMultiCatchIntention.java (renamed from plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMulticatchIntention.java)34
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java9
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java22
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java32
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java73
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/IterableForEachLoopPredicate.java11
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java49
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java59
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceableWithOperatorAssignmentPredicate.java (renamed from plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/AssignmentExpressionReplaceableWithOperatorAssigment.java)30
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConcatenationUtils.java20
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ParenthesesUtils.java49
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/IfStatementBranch.java24
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LabelSearchVisitor.java14
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LocalVariableUsageVisitor.java45
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java297
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/SwitchUtils.java256
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java82
-rw-r--r--plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/after.java.template (renamed from plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/after.java.template)0
-rw-r--r--plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/before.java.template (renamed from plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/before.java.template)0
-rw-r--r--plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/description.html7
-rw-r--r--plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/description.html8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/catchToThrows/SingleCatch.java2
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/detail/PolyadicParentheses.java20
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/detail/PolyadicParentheses_after.java22
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/Simple.java12
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/Simple_after.java13
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/TypeAnno.java16
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/TypeAnno_after.java17
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch.java13
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch_after.java15
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/NoChange.java7
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/NoException.java8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Polyadic.java8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Polyadic_after.java8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Prefix.java7
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Prefix_after.java7
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods.java18
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods_after.java16
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/PolyadicAssignment.java7
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/PolyadicAssignment_after.java7
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/Excluded.java8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/PolyadicExpression.java8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/PolyadicExpression_after.java8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression2.java8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression2_after.java8
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Comments.java14
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Comments_after.java16
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Long.java10
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Polyadic.java13
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Polyadic_after.java19
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef.java12
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef2Dim.java12
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef2Dim_after.java12
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRefUniqueParamName.java14
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRefUniqueParamName_after.java14
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef_after.java12
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayMethodRef.java9
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayMethodRef_after.java9
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/DetailExceptionsIntentionTest.java2
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitMultiCatchIntentionTest.java34
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java1
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/FlipExpressionIntentionTest.java39
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntentionTest.java4
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntentionTest.java37
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/parenthesis/UnnecessaryParenthesesIntentionTest.java1
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchlIntentionTest.java39
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceMethodReferenceWithLambdaIntentionTest.java16
-rw-r--r--plugins/android-designer/src/com/intellij/android/designer/designSurface/RootView.java15
-rw-r--r--plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidDexBuildTarget.java7
-rw-r--r--plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/JpsAntExtensionService.java11
-rw-r--r--plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/impl/JpsAntInstallationImpl.java2
-rw-r--r--plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java6
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/config/execution/InputRequestHandler.java7
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/config/impl/AntBuildFileImpl.java54
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java4
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java13
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntClasspathEditorPanel.form2
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntUIUtil.java6
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java10
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/dom/AntDomRefIdConverter.java2
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/dom/ClassProvider.java120
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java128
-rw-r--r--plugins/ant/tests/data/highlighting/RefidInCustomDomElement.xml7
-rw-r--r--plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java4
-rw-r--r--plugins/cucumber-jvm-formatter/cucumber-jvm-formatter.iml13
-rw-r--r--plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatter.java349
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java12
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java4
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsContentRevision.java3
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsRootAsStringConfigurationPanel.java4
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java3
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsMessages/CvsCompositeListener.java4
-rw-r--r--plugins/devkit/devkit.iml10
-rw-r--r--plugins/devkit/lib/dtdparser113.jarbin0 -> 40982 bytes
-rw-r--r--plugins/devkit/resources/META-INF/plugin.xml4
-rw-r--r--plugins/devkit/src/build/PluginModuleBuildScopeProvider.java6
-rw-r--r--plugins/devkit/src/dom/generator/DTDModelLoader.java339
-rw-r--r--plugins/devkit/src/dom/generator/DomGenDialog.java79
-rw-r--r--plugins/devkit/src/dom/generator/DomGenPanel.form137
-rw-r--r--plugins/devkit/src/dom/generator/DomGenPanel.java177
-rw-r--r--plugins/devkit/src/dom/generator/Emitter.java36
-rw-r--r--plugins/devkit/src/dom/generator/FieldDesc.java78
-rw-r--r--plugins/devkit/src/dom/generator/FileManager.java33
-rw-r--r--plugins/devkit/src/dom/generator/GenerateDomModelAction.java34
-rw-r--r--plugins/devkit/src/dom/generator/JetBrainsEmitter.java679
-rw-r--r--plugins/devkit/src/dom/generator/Main.java61
-rw-r--r--plugins/devkit/src/dom/generator/MergingFileManager.java248
-rw-r--r--plugins/devkit/src/dom/generator/ModelDesc.java171
-rw-r--r--plugins/devkit/src/dom/generator/ModelGen.java189
-rw-r--r--plugins/devkit/src/dom/generator/ModelLoader.java28
-rw-r--r--plugins/devkit/src/dom/generator/NamespaceDesc.java84
-rw-r--r--plugins/devkit/src/dom/generator/TypeDesc.java55
-rw-r--r--plugins/devkit/src/dom/generator/Util.java224
-rw-r--r--plugins/devkit/src/dom/generator/XSDModelLoader.java681
-rw-r--r--plugins/devkit/src/dom/impl/InspectionsPropertiesReferenceProviderContributor.java4
-rw-r--r--plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java15
-rw-r--r--plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java23
-rw-r--r--plugins/eclipse/common-eclipse-util/src/EclipseModuleManager.java8
-rw-r--r--plugins/eclipse/common-eclipse-util/src/EclipseProjectFinder.java20
-rw-r--r--plugins/eclipse/common-eclipse-util/src/IdeaXml.java2
-rw-r--r--plugins/eclipse/common-eclipse-util/src/conversion/AbstractIdeaSpecificSettings.java23
-rw-r--r--plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathReader.java5
-rw-r--r--plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathSerializer.java13
-rw-r--r--plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsIdeaSpecificSettings.java22
-rw-r--r--plugins/eclipse/resources/EclipseBundle.properties2
-rw-r--r--plugins/eclipse/resources/META-INF/plugin.xml3
-rw-r--r--plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java12
-rw-r--r--plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java6
-rw-r--r--plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java2
-rw-r--r--plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java47
-rw-r--r--plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java101
-rw-r--r--plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseNatureImporter.java52
-rw-r--r--plugins/generate-tostring/src/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspection.java42
-rw-r--r--plugins/generate-tostring/testSrc/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspectionTest.java47
-rw-r--r--plugins/git4idea/git4idea.iml1
-rw-r--r--plugins/git4idea/resources/icons/ball0.pngbin282 -> 284 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball0@2x.pngbin0 -> 515 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball1.pngbin273 -> 278 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball1@2x.pngbin0 -> 505 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball2.pngbin281 -> 284 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball2@2x.pngbin0 -> 502 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball3.pngbin274 -> 275 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball3@2x.pngbin0 -> 504 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball4.pngbin277 -> 284 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball4@2x.pngbin0 -> 517 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball5.pngbin280 -> 278 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball5@2x.pngbin0 -> 508 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball6.pngbin281 -> 285 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball6@2x.pngbin0 -> 538 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball7.pngbin274 -> 279 bytes
-rw-r--r--plugins/git4idea/resources/icons/ball7@2x.pngbin0 -> 493 bytes
-rw-r--r--plugins/git4idea/resources/icons/branch.pngbin497 -> 444 bytes
-rw-r--r--plugins/git4idea/resources/icons/branch@2x.pngbin0 -> 860 bytes
-rw-r--r--plugins/git4idea/resources/icons/branch@2x_dark.pngbin0 -> 863 bytes
-rw-r--r--plugins/git4idea/resources/icons/branch_dark.pngbin457 -> 448 bytes
-rw-r--r--plugins/git4idea/resources/icons/cherryPick.pngbin585 -> 546 bytes
-rw-r--r--plugins/git4idea/resources/icons/cherryPick@2x.pngbin0 -> 1151 bytes
-rw-r--r--plugins/git4idea/resources/icons/cherryPick@2x_dark.pngbin0 -> 1156 bytes
-rw-r--r--plugins/git4idea/resources/icons/cherryPick_dark.pngbin577 -> 547 bytes
-rw-r--r--plugins/git4idea/resources/icons/greyball.pngbin272 -> 267 bytes
-rw-r--r--plugins/git4idea/resources/icons/greyball@2x.pngbin0 -> 449 bytes
-rw-r--r--plugins/git4idea/rt/src/org/jetbrains/git4idea/GitExternalApp.java24
-rw-r--r--plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassApp.java116
-rw-r--r--plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassXmlRpcClient.java80
-rw-r--r--plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassXmlRpcHandler.java55
-rw-r--r--plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java2
-rw-r--r--plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java6
-rw-r--r--plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java3
-rw-r--r--plugins/git4idea/src/META-INF/plugin.xml9
-rw-r--r--plugins/git4idea/src/git4idea/GitDeprecatedRemote.java2
-rw-r--r--plugins/git4idea/src/git4idea/GitRevisionNumber.java1
-rw-r--r--plugins/git4idea/src/git4idea/GitTag.java1
-rw-r--r--plugins/git4idea/src/git4idea/GitUtil.java4
-rw-r--r--plugins/git4idea/src/git4idea/GitVcs.java29
-rw-r--r--plugins/git4idea/src/git4idea/actions/GitAdd.java93
-rw-r--r--plugins/git4idea/src/git4idea/actions/GitPull.java23
-rw-r--r--plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java5
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitBranchOperation.java2
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitBranchUtil.java1
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java17
-rw-r--r--plugins/git4idea/src/git4idea/changes/GitChangeUtils.java12
-rw-r--r--plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java4
-rw-r--r--plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java3
-rw-r--r--plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java9
-rw-r--r--plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java6
-rw-r--r--plugins/git4idea/src/git4idea/commands/Git.java4
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitCommand.java41
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitCommandResult.java5
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHandler.java93
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java70
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java35
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHttpAuthenticator.java54
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java240
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitImpl.java26
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java43
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java40
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitSSHIdeaService.java52
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java4
-rw-r--r--plugins/git4idea/src/git4idea/config/GitConfigUtil.java5
-rw-r--r--plugins/git4idea/src/git4idea/config/GitVersion.java2
-rw-r--r--plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java1
-rw-r--r--plugins/git4idea/src/git4idea/history/GitHistoryUtils.java19
-rw-r--r--plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java3
-rw-r--r--plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java9
-rw-r--r--plugins/git4idea/src/git4idea/history/wholeTree/MoreAction.java81
-rw-r--r--plugins/git4idea/src/git4idea/i18n/GitBundle.properties1
-rw-r--r--plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java25
-rw-r--r--plugins/git4idea/src/git4idea/merge/GitMergeDialog.java2
-rw-r--r--plugins/git4idea/src/git4idea/merge/GitMergeProvider.java1
-rw-r--r--plugins/git4idea/src/git4idea/merge/GitMerger.java1
-rw-r--r--plugins/git4idea/src/git4idea/merge/GitPullDialog.java28
-rw-r--r--plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java2
-rw-r--r--plugins/git4idea/src/git4idea/push/GitPushLog.java5
-rw-r--r--plugins/git4idea/src/git4idea/push/GitPusher.java41
-rw-r--r--plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java1
-rw-r--r--plugins/git4idea/src/git4idea/rebase/GitRebaser.java1
-rw-r--r--plugins/git4idea/src/git4idea/repo/GitFakeRepositoryManager.java76
-rw-r--r--plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java11
-rw-r--r--plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java2
-rw-r--r--plugins/git4idea/src/git4idea/roots/GitRootScanner.java18
-rw-r--r--plugins/git4idea/src/git4idea/stash/GitStashUtils.java1
-rw-r--r--plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java2
-rw-r--r--plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java5
-rw-r--r--plugins/git4idea/src/git4idea/ui/GitResetDialog.java1
-rw-r--r--plugins/git4idea/src/git4idea/ui/GitTagDialog.java2
-rw-r--r--plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java4
-rw-r--r--plugins/git4idea/src/git4idea/update/GitFetcher.java9
-rw-r--r--plugins/git4idea/src/git4idea/update/GitMergeUpdater.java1
-rw-r--r--plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java1
-rw-r--r--plugins/git4idea/src/git4idea/update/GitUpdater.java1
-rw-r--r--plugins/git4idea/src/git4idea/util/GitFileUtils.java5
-rw-r--r--plugins/git4idea/src/git4idea/util/NetrcData.java196
-rw-r--r--plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java298
-rw-r--r--plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcHandlerService.java163
-rw-r--r--plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcSshService.java105
-rw-r--r--plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java22
-rw-r--r--plugins/git4idea/test-features/git4idea/git-add.feature35
-rw-r--r--plugins/git4idea/test-features/git4idea/git-http.feature28
-rw-r--r--plugins/git4idea/test-stepdefs/git4idea/GeneralStepdefs.java52
-rw-r--r--plugins/git4idea/test-stepdefs/git4idea/GitAddSteps.java80
-rw-r--r--plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java14
-rw-r--r--plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java211
-rw-r--r--plugins/git4idea/test-stepdefs/git4idea/GitRemoteSteps.java173
-rw-r--r--plugins/git4idea/testFramework/META-INF/plugin.xml20
-rw-r--r--plugins/git4idea/testFramework/git4idea/remote/GitHttpAuthTestService.java66
-rw-r--r--plugins/git4idea/testFramework/git4idea/test/GitExecutor.java44
-rw-r--r--plugins/git4idea/testFramework/git4idea/test/GitTest.java2
-rw-r--r--plugins/git4idea/testFramework/git4idea/test/GitTestImpl.java7
-rw-r--r--plugins/git4idea/tests/git4idea/history/GitAnnotationsClosedTest.java13
-rw-r--r--plugins/git4idea/tests/git4idea/history/GitLogPerformanceTest.java12
-rw-r--r--plugins/git4idea/tests/git4idea/util/NetrcDataTest.java72
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java5
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java1
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java37
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java11
-rw-r--r--plugins/gradle/resources/i18n/GradleBundle.properties21
-rw-r--r--plugins/gradle/resources/icons/gradle.pngbin439 -> 463 bytes
-rw-r--r--plugins/gradle/resources/icons/gradle@2x.pngbin0 -> 841 bytes
-rw-r--r--plugins/gradle/resources/icons/gradleImport.pngbin640 -> 440 bytes
-rw-r--r--plugins/gradle/resources/icons/gradleImport@2x.pngbin0 -> 870 bytes
-rw-r--r--plugins/gradle/resources/icons/gradleImport@2x_dark.pngbin0 -> 874 bytes
-rw-r--r--plugins/gradle/resources/icons/gradleImport_dark.pngbin0 -> 441 bytes
-rw-r--r--plugins/gradle/resources/icons/gradleNavigate.pngbin750 -> 525 bytes
-rw-r--r--plugins/gradle/resources/icons/gradleNavigate@2x.pngbin0 -> 974 bytes
-rw-r--r--plugins/gradle/resources/icons/gradleNavigate@2x_dark.pngbin0 -> 977 bytes
-rw-r--r--plugins/gradle/resources/icons/gradleNavigate_dark.pngbin0 -> 515 bytes
-rw-r--r--plugins/gradle/resources/icons/task.pngbin0 -> 558 bytes
-rw-r--r--plugins/gradle/resources/icons/toolWindowGradle.pngbin754 -> 399 bytes
-rw-r--r--plugins/gradle/resources/icons/toolWindowGradle@2x.pngbin0 -> 776 bytes
-rw-r--r--plugins/gradle/src/META-INF/plugin.xml7
-rw-r--r--plugins/gradle/src/icons/GradleIcons.java9
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleLinkedProjectAction.java4
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleSyncTreeNodeAction.java4
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleOpenScriptAction.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java6
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRemoveIdeEntityAction.java16
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleSyncAction.java77
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleSyncOutdatedLibraryAction.java50
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyExportedUserChange.java78
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyScopeUserChange.java92
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyUserChange.java10
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleModuleAwareUserChange.java8
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleUserProjectChange.java18
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleAutoImporter.java4
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleLibraryDependencyExportedChange.java47
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleLibraryDependencyScopeUserChange.java48
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleModuleDependencyExportedChange.java47
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleModuleDependencyScopeUserChange.java48
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChange.java14
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangeVisitor.java4
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangesCalculator.java155
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLocalSettings.java50
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java64
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java50
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java14
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyExportedChange.java6
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyScopeChange.java10
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleTaskLocation.java42
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/AbstractGradleTask.java (renamed from plugins/gradle/src/org/jetbrains/plugins/gradle/task/AbstractGradleTask.java)43
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleExecuteTaskTask.java55
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleRefreshTasksListTask.java87
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleResolveProjectTask.java (renamed from plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleResolveProjectTask.java)20
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTask.java (renamed from plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTask.java)5
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskAware.java (renamed from plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskAware.java)2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskId.java (renamed from plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskId.java)2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskManager.java (renamed from plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java)2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskState.java (renamed from plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskState.java)2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskType.java (renamed from plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskType.java)4
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java37
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleEntityManageHelper.java44
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java4
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectManager.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/model/gradle/GradleTaskDescriptor.java109
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManager.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManagerImpl.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationEvent.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListener.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListenerAdapter.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacade.java27
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleBuildManager.java72
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleProjectResolver.java4
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProgressNotificationManager.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleService.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleApiFacadeImpl.java15
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleBuildManagerImpl.java116
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java140
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/RemoteGradleServiceHelper.java205
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/AbstractRemoteGradleServiceWrapper.java66
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleApiFacadeWrapper.java15
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleBuildManagerWrapper.java67
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleProjectResolverWrapper.java41
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java17
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java61
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java10
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksList.java118
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksModel.java85
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksPanel.java265
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleDataKeys.java8
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java44
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java22
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleInstallationManager.java72
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java129
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/util/TextIcon.java2
-rw-r--r--plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java4
-rw-r--r--plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java9
-rw-r--r--plugins/groovy/resources/icons/griffon/griffon-icon-24x24.pngbin1730 -> 1313 bytes
-rw-r--r--plugins/groovy/resources/icons/griffon/griffon-icon-24x24@2x.pngbin0 -> 2802 bytes
-rw-r--r--plugins/groovy/resources/icons/griffon/griffon.pngbin909 -> 771 bytes
-rw-r--r--plugins/groovy/resources/icons/griffon/griffon@2x.pngbin0 -> 1717 bytes
-rw-r--r--plugins/groovy/resources/icons/griffon/griffonToolWindow.pngbin709 -> 691 bytes
-rw-r--r--plugins/groovy/resources/icons/griffon/griffonToolWindow@2x.pngbin0 -> 1536 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/GroovyDoc.pngbin738 -> 671 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/GroovyDoc@2x.pngbin0 -> 1422 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/abstractClass.pngbin578 -> 456 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/abstractClass@2x.pngbin0 -> 980 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/annotationType.pngbin667 -> 533 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/annotationType@2x.pngbin0 -> 1261 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/ant_task.pngbin667 -> 521 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/ant_task@2x.pngbin0 -> 1054 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/ant_task@2x_dark.pngbin0 -> 949 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/ant_task_dark.pngbin0 -> 502 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/class.pngbin529 -> 400 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/class@2x.pngbin0 -> 807 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/def.pngbin125 -> 185 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/def@2x.pngbin0 -> 530 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/def@2x_dark.pngbin0 -> 542 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/def_dark.pngbin0 -> 189 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/dynamicProperty.pngbin748 -> 624 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/dynamicProperty@2x.pngbin0 -> 1314 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/dynamicProperty_13.pngbin1474 -> 551 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/dynamicProperty_13@2x.pngbin0 -> 1163 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/enum.pngbin490 -> 357 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/enum@2x.pngbin0 -> 607 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/field.pngbin724 -> 400 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/field@2x.pngbin0 -> 681 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_16x16.pngbin686 -> 713 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_16x16@2x.pngbin0 -> 1763 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_16x16@2x_dark.pngbin0 -> 1764 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_16x16_dark.pngbin0 -> 714 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_sdk.pngbin694 -> 568 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_sdk@2x.pngbin0 -> 1505 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_sdk@2x_dark.pngbin0 -> 1503 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_sdk_dark.pngbin0 -> 570 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_target.pngbin743 -> 783 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/gant_target@2x.pngbin0 -> 1851 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/groovy-transparent.icobin3638 -> 5430 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/groovy.icobin3638 -> 5430 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/groovy_13x13.pngbin1529 -> 615 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/groovy_13x13@2x.pngbin0 -> 1379 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/groovy_16x16.pngbin846 -> 700 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/groovy_16x16@2x.pngbin0 -> 1539 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/groovy_32x32.pngbin1943 -> 1544 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/groovy_32x32@2x.pngbin0 -> 3279 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/interface.pngbin547 -> 389 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/interface@2x.pngbin0 -> 684 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/method.pngbin654 -> 383 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/method@2x.pngbin0 -> 755 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/property.pngbin748 -> 616 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/property@2x.pngbin0 -> 1314 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/variable.pngbin742 -> 423 bytes
-rw-r--r--plugins/groovy/resources/icons/groovy/variable@2x.pngbin0 -> 785 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/action_method.pngbin849 -> 615 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/action_method@2x.pngbin0 -> 1221 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/config_folder_closed.pngbin732 -> 411 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/config_folder_closed@2x.pngbin0 -> 778 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/config_folder_closed@2x_dark.pngbin0 -> 757 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/config_folder_closed_dark.pngbin0 -> 412 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/controller.pngbin778 -> 669 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/controller@2x.pngbin0 -> 1389 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/domain_class.pngbin776 -> 221 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/domain_class@2x.pngbin0 -> 245 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/groovy_mvc_plugin.pngbin797 -> 845 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/groovy_mvc_plugin@2x.pngbin0 -> 2095 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/groovy_mvc_plugin@2x_dark.pngbin0 -> 2096 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/groovy_mvc_plugin_dark.pngbin0 -> 837 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/modelsNode.pngbin446 -> 344 bytes
-rw-r--r--plugins/groovy/resources/icons/mvc/modelsNode@2x.pngbin0 -> 590 bytes
-rw-r--r--plugins/groovy/resources/inspectionDescriptions/TypeCustomizer.html7
-rw-r--r--plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/after.groovy.template5
-rw-r--r--plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/before.groovy.template4
-rw-r--r--plugins/groovy/resources/standardDsls/metaDsl.gdsl9
-rw-r--r--plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java1
-rw-r--r--plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java507
-rw-r--r--plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java489
-rw-r--r--plugins/groovy/src/META-INF/plugin.xml98
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/AnnotationCollectorChecker.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/CustomAnnotationChecker.java17
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/FieldAnnotationChecker.java20
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAnnotatorImpl.java65
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java179
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/TypeCheckedAnnotationChecker.java53
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java73
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromUsageFix.java38
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateGetterFromUsageFix.java50
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java80
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateSetterFromUsageFix.java58
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrCreateFromUsageBaseFix.java153
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java6
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicMethodFix.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicPropertyFix.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyClsCustomNavigationPolicy.java (renamed from plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/JavaClsMethodElementEvaluator.java)32
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyTargetElementEvaluator.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/navigation/actions/GroovyGotoSuperHandler.java12
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties8
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java81
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInArgumentCheckInspection.java7
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrFieldAlreadyDefinedInspection.java29
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java8
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/resources/TypeCustomizerInspection.java129
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java28
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/JavaStylePropertiesUtil.java8
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.java3
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/ConfigSlurperMapContentProvider.java18
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/GroovyMapValueTypeEnhancer.java17
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java36
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyClassDescriptor.java3
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy39
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java82
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java10
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/dsltop/GroovyDslDefaultMembers.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/DeclarationType.java (renamed from plugins/groovy/testdata/resolve/class/innerClassIsNotResolvedInAnonymous/A.groovy)15
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java38
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/scopes/Scope.groovy94
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyQuoteHandler.java3
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinBlockStatementHandler.java52
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinControlStatementHandler.java54
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinIfHandler.java54
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinStatementsHandler.groovy44
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinStatementsHandler.java48
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonToolWindowFactory.java18
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/DefaultHighlighter.java106
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/EachToForIntention.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertClosureToMethodIntention.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionIntention.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionPredicate.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java38
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java6
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyClassNameInsertHandler.java8
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java6
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyReferenceCharFilter.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/GroovySmartEnterProcessor.java55
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrListFixer.java12
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrSynchronizedFixer.java46
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java14
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyAnnotationAttributeInfoHandler.java201
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyTypeParameterInfoHandler.java168
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java13
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java7
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeArguments.java13
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java9
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrNamedArgumentSearchVisitor.java8
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSynchronizedStatement.java16
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java7
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java10
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrReferenceExpression.java5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ControlFlowBuilderUtil.java23
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java98
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java50
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java3
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java15
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementImpl.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java30
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java21
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java10
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java45
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java3
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSynchronizedStatementImpl.java17
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java20
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java15
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java89
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java21
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java56
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java7
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java14
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java10
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightVariable.java30
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java15
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GrAnnotationPattern.java42
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.java5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java20
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrBooleanTypeConverter.java41
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrContainerTypeConverter.java (renamed from plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrContainerTypeConverter.java)5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrStringTypeConverter.java (renamed from plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrStringTypeConverter.java)5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrTypeConverter.java (renamed from plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GrTypeConverter.java)5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrImportUtil.java74
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java16
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/StaticChecker.java7
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java26
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/DeclarationCacheKey.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java139
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java8
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethod.java9
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java13
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java22
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java33
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java5
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcConsole.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java6
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties1
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java11
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java114
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java75
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java41
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SetterWriter.java192
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/CustomMethodInvocator.java63
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/MapGetterSetterInvocator.java80
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java25
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java53
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java27
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java10
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodConflictSolver.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java30
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java21
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java6
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyMemberHandler.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java7
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java4
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java6
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java15
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java17
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockVariableDescriptor.java17
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/util/ResolveProfiler.java114
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy16
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java2
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy17
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy18
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy52
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy2
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy6
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/JoinLineTest.groovy34
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy9
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy1
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java19
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy9
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy46
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/AnnotationsParsingTest.groovy5
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy10
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy3
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy4
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy28
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy36
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy50
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/smartEnter/SmartEnterTest.groovy25
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/FileGenerationTest.groovy2
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy20
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodTest.groovy46
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java2
-rw-r--r--plugins/groovy/testdata/groovy/actions/smartEnter/listFixer.test6
-rw-r--r--plugins/groovy/testdata/groovy/controlFlow/pendingFromIf.test23
-rw-r--r--plugins/groovy/testdata/groovy/refactoring/extractMethod/autoSelectExpression.test11
-rw-r--r--plugins/groovy/testdata/groovy/refactoring/inlineMethod/badReturns.test19
-rw-r--r--plugins/groovy/testdata/groovy/refactoring/inlineMethod/cannotInlineMethodRef.test7
-rw-r--r--plugins/groovy/testdata/highlighting/missingReturn/Finally.groovy2
-rw-r--r--plugins/groovy/testdata/parsing/groovy/annotations/keywordsAttributes.test44
-rw-r--r--plugins/groovy/testdata/parsing/groovy/expressions/new/emptyTypeArgs.test14
-rw-r--r--plugins/groovy/testdata/parsing/groovy/expressions/references/emptyTypeArgs.test17
-rw-r--r--plugins/groovy/testdata/parsing/groovy/types/emptyTypeArgs.test29
-rw-r--r--plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java4
-rw-r--r--plugins/groovy/testdata/refactoring/convertGroovyToJava/file/mapAccess2.groovy7
-rw-r--r--plugins/groovy/testdata/refactoring/convertGroovyToJava/file/mapAccess2.java8
-rw-r--r--plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties6
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java42
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java4
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java7
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java10
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java4
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java17
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java6
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java6
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java10
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java20
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java6
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java93
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java4
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java27
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgMergeProvider.java46
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java10
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java7
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java25
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java29
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java4
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java3
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java22
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java25
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java4
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java26
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/util/HgBranchesAndTags.java53
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java41
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java9
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUiUtil.java21
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java15
-rw-r--r--plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java54
-rw-r--r--plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java58
-rw-r--r--plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java89
-rw-r--r--plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java2
-rw-r--r--plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java206
-rw-r--r--plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java185
-rw-r--r--plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java51
-rw-r--r--plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml13
-rw-r--r--plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/AbstractJavaFxPackager.java338
-rw-r--r--plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxAntGenerator.java219
-rw-r--r--plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxPackagerConstants.java29
-rw-r--r--plugins/javaFX/javaFX-CE/javaFX-CE.iml3
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/GenerateGetterSetterTest.java60
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/AbstractJavaFXQuickFixTest.java40
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/AbstractJavaFXTestCase.java56
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXCollapseSubtagToAttributeTest.java4
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXDefaultTagInspectionTest.java37
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java179
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXImportTest.java15
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXOptimizeImportsTest.java32
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java78
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java31
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXUnresolvedFxIdReferenceInspectionTest.java56
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCoercingTest.java64
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java94
-rw-r--r--plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/packaging/JavaFxAntTaskTest.java283
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/javaFX-jps-plugin.iml17
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/META-INF/services/org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider1
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension2
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxApplicationArtifactType.java11
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactBuildTaskProvider.java229
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactProperties.java187
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactPropertiesSerializer.java62
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxModelSerializerExtension.java18
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactProperties.java65
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactPropertiesSerializer.java77
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactType.java26
-rw-r--r--plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderModelSerializerExtension.java33
-rw-r--r--plugins/javaFX/javaFX.iml3
-rw-r--r--plugins/javaFX/resources/inspectionDescriptions/JavaFxUnresolvedFxIdReference.html5
-rw-r--r--plugins/javaFX/src/META-INF/common-javaFX-plugin.xml15
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataExternalizer.java50
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataIndexer.java92
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java11
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxIdsIndex.java88
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxSettingsConfigurable.java2
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java132
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/codeInsight/JavaFxGetterSetterPrototypeProvider.java88
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java10
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java28
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java28
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java249
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxImportsOptimizer.java32
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java2
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxImplicitUsageProvider.java65
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxUnresolvedFxIdReferenceInspection.java143
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/UnwrapTagFix.java6
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxCollapseSubTagToAttributeIntention.java45
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxWrapWithDefineIntention.java64
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java180
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java3
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java113
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java102
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java18
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java38
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java75
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxColorReference.java69
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxColorReferenceProvider.java55
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java36
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java3
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerFieldSearcher.java95
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java1
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java38
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxImportClassFix.java2
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxScopeEnlager.java51
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxScopeEnlarger.java67
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java22
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxApplicationArtifactType.java125
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxApplicationClassBrowser.java88
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactProperties.java400
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.form204
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.java179
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesProvider.java46
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxEditCertificatesDialog.form120
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxEditCertificatesDialog.java114
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/ant/JavaFxChunkBuildExtension.java239
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactProperties.java62
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesEditor.form37
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesEditor.java77
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesProvider.java46
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactType.java58
-rw-r--r--plugins/javaFX/src/resources/projectTemplates/Java/JavaFX Application.zipbin10558 -> 10544 bytes
-rw-r--r--plugins/javaFX/testData/coercing/invalidDouble.fxml7
-rw-r--r--plugins/javaFX/testData/coercing/invalidInteger.fxml5
-rw-r--r--plugins/javaFX/testData/coercing/referencedTag.fxml6
-rw-r--r--plugins/javaFX/testData/coercing/rootTagSubtagsCoercing.fxml18
-rw-r--r--plugins/javaFX/testData/completion/acceptableSourceOnly.fxml7
-rw-r--r--plugins/javaFX/testData/completion/allowPropertyTypeClass.fxml8
-rw-r--r--plugins/javaFX/testData/completion/allowPropertyTypeClass_after.fxml8
-rw-r--r--plugins/javaFX/testData/completion/booleanValues.fxml2
-rw-r--r--plugins/javaFX/testData/completion/childrenInsideGridPaneRoot.fxml5
-rw-r--r--plugins/javaFX/testData/completion/childrenInsideGridPaneRoot_after.fxml5
-rw-r--r--plugins/javaFX/testData/completion/classInsideObjectProperty.fxml7
-rw-r--r--plugins/javaFX/testData/completion/classInsideObjectProperty_after.fxml8
-rw-r--r--plugins/javaFX/testData/completion/defaultPropertyIncludeOnce.fxml5
-rw-r--r--plugins/javaFX/testData/completion/defaultPropertyWrappedField.fxml4
-rw-r--r--plugins/javaFX/testData/completion/includedRootAttributes.fxml6
-rw-r--r--plugins/javaFX/testData/completion/includedRootAttributes_after.fxml6
-rw-r--r--plugins/javaFX/testData/completion/includedRootRootAttributes.fxml6
-rw-r--r--plugins/javaFX/testData/completion/includedRootRootAttributes_after.fxml6
-rw-r--r--plugins/javaFX/testData/completion/infinity.fxml5
-rw-r--r--plugins/javaFX/testData/completion/namedColors.fxml5
-rw-r--r--plugins/javaFX/testData/completion/namedColors_after.fxml5
-rw-r--r--plugins/javaFX/testData/completion/noInfinity.fxml5
-rw-r--r--plugins/javaFX/testData/completion/primitiveProperties.fxml8
-rw-r--r--plugins/javaFX/testData/completion/primitiveProperties_after.fxml8
-rw-r--r--plugins/javaFX/testData/completion/primitiveSubtags.fxml4
-rw-r--r--plugins/javaFX/testData/completion/rootTagNameLayout.fxml1
-rw-r--r--plugins/javaFX/testData/completion/rootTagNameLayout_after.fxml2
-rw-r--r--plugins/javaFX/testData/generateGetterSetter/afterDouble.java17
-rw-r--r--plugins/javaFX/testData/generateGetterSetter/afterString.java5
-rw-r--r--plugins/javaFX/testData/generateGetterSetter/beforeDouble.java5
-rw-r--r--plugins/javaFX/testData/generateGetterSetter/beforeString.java5
-rw-r--r--plugins/javaFX/testData/highlighting/InjectedControllerFields.java16
-rw-r--r--plugins/javaFX/testData/highlighting/MyController.java1
-rw-r--r--plugins/javaFX/testData/highlighting/NoParamsHandler.java4
-rw-r--r--plugins/javaFX/testData/highlighting/WrongBindingType.java4
-rw-r--r--plugins/javaFX/testData/highlighting/absenceOfDefineAttributes.fxml3
-rw-r--r--plugins/javaFX/testData/highlighting/acceptReferenceInsideDefine.fxml8
-rw-r--r--plugins/javaFX/testData/highlighting/allowIncludeTagInsideDefine.fxml11
-rw-r--r--plugins/javaFX/testData/highlighting/btn.fxml1
-rw-r--r--plugins/javaFX/testData/highlighting/charsetInInclude.fxml3
-rw-r--r--plugins/javaFX/testData/highlighting/copyReference.fxml5
-rw-r--r--plugins/javaFX/testData/highlighting/custom/CustomComponentFieldsWithSameProperties.java30
-rw-r--r--plugins/javaFX/testData/highlighting/custom/customComponentFieldsWithSameProperties.fxml6
-rw-r--r--plugins/javaFX/testData/highlighting/defaultPropertyField.fxml8
-rw-r--r--plugins/javaFX/testData/highlighting/idOutOfHierarchy.fxml10
-rw-r--r--plugins/javaFX/testData/highlighting/includedForm.fxml6
-rw-r--r--plugins/javaFX/testData/highlighting/injected/FooVBox.java25
-rw-r--r--plugins/javaFX/testData/highlighting/injected/MyController.java7
-rw-r--r--plugins/javaFX/testData/highlighting/injected/injectedController.fxml5
-rw-r--r--plugins/javaFX/testData/highlighting/lineChartInstantiation.fxml9
-rw-r--r--plugins/javaFX/testData/highlighting/namedColor.fxml5
-rw-r--r--plugins/javaFX/testData/highlighting/noParamsHandler.fxml5
-rw-r--r--plugins/javaFX/testData/highlighting/primitiveSubtags.fxml6
-rw-r--r--plugins/javaFX/testData/highlighting/referencePosition.fxml12
-rw-r--r--plugins/javaFX/testData/highlighting/rootTagCoercedUnchecked.fxml3
-rw-r--r--plugins/javaFX/testData/highlighting/rootTagOnDifferentLevels.fxml10
-rw-r--r--plugins/javaFX/testData/highlighting/staticPropertiesCustomLayout.fxml7
-rw-r--r--plugins/javaFX/testData/highlighting/unexpectedNode.fxml8
-rw-r--r--plugins/javaFX/testData/highlighting/wrongBindingType.fxml7
-rw-r--r--plugins/javaFX/testData/importing/Insets.java1
-rw-r--r--plugins/javaFX/testData/importing/TextField.java2
-rw-r--r--plugins/javaFX/testData/importing/insets.fxml6
-rw-r--r--plugins/javaFX/testData/importing/insets_after.fxml7
-rw-r--r--plugins/javaFX/testData/importing/textField.fxml8
-rw-r--r--plugins/javaFX/testData/importing/textField_after.fxml9
-rw-r--r--plugins/javaFX/testData/inspections/unresolvedFxId/Controller.java1
-rw-r--r--plugins/javaFX/testData/inspections/unresolvedFxId/Controller_after.java5
-rw-r--r--plugins/javaFX/testData/inspections/unresolvedFxId/unknownRef.fxml5
-rw-r--r--plugins/javaFX/testData/intentions/collapseToAttr/styleclass.fxml9
-rw-r--r--plugins/javaFX/testData/intentions/collapseToAttr/styleclass_after.fxml5
-rw-r--r--plugins/javaFX/testData/optimizeImports/dblImports.fxml7
-rw-r--r--plugins/javaFX/testData/optimizeImports/dblImports_after.fxml6
-rw-r--r--plugins/javaFX/testData/optimizeImports/staticPropertiesAttrAndCustomComponents.fxml6
-rw-r--r--plugins/javaFX/testData/optimizeImports/staticPropertiesAttrAndCustomComponents_after.fxml6
-rw-r--r--plugins/javaFX/testData/optimizeImports/staticPropertiesTagAndCustomComponents.fxml5
-rw-r--r--plugins/javaFX/testData/optimizeImports/staticPropertiesTagAndCustomComponents_after.fxml5
-rw-r--r--plugins/javaFX/testData/quickfix/CreateControllerMethodInGroovy.groovy1
-rw-r--r--plugins/javaFX/testData/quickfix/CreateControllerMethodInGroovy_after.groovy5
-rw-r--r--plugins/javaFX/testData/quickfix/CreateField.java1
-rw-r--r--plugins/javaFX/testData/quickfix/CreateField_after.java5
-rw-r--r--plugins/javaFX/testData/quickfix/createControllerMethodInGroovy.fxml5
-rw-r--r--plugins/javaFX/testData/quickfix/createField.fxml5
-rw-r--r--plugins/javaFX/testData/quickfix/wrapWithDefine.fxml6
-rw-r--r--plugins/javaFX/testData/quickfix/wrapWithDefine_after.fxml8
-rw-r--r--plugins/javaFX/testData/rename/ControllerFieldWithRefs.java3
-rw-r--r--plugins/javaFX/testData/rename/Handler.java3
-rw-r--r--plugins/javaFX/testData/rename/controllerFieldWithRefs.fxml13
-rw-r--r--plugins/javaFX/testData/rename/controllerFieldWithRefs_after.fxml13
-rw-r--r--plugins/javaFX/testData/rename/handler.fxml8
-rw-r--r--plugins/javaFX/testData/rename/handler_after.fxml8
-rw-r--r--plugins/javaFX/testData/rename/idWithRefs.fxml8
-rw-r--r--plugins/javaFX/testData/rename/idWithRefs_after.fxml8
-rw-r--r--plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java12
-rw-r--r--plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java19
-rw-r--r--plugins/junit/src/com/intellij/execution/junit/TestObject.java26
-rw-r--r--plugins/junit/src/com/intellij/execution/junit/TestsPattern.java23
-rw-r--r--plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java2
-rw-r--r--plugins/junit/src/com/intellij/execution/junit2/ui/TestsPacketsReceiver.java8
-rw-r--r--plugins/junit/src/com/intellij/execution/junit2/ui/model/JUnitListenersNotifier.java2
-rw-r--r--plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java5
-rw-r--r--plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java32
-rw-r--r--plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTarget.java4
-rw-r--r--plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenArtifact.java22
-rw-r--r--plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenCoordinate.java27
-rw-r--r--plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenId.java4
-rw-r--r--plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexFetcher.java13
-rw-r--r--plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java2
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java17
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java32
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java2
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java3
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java72
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java27
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java64
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java8
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java1
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java8
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java37
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java103
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java1
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java3
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java2
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java4
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java42
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java1
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenClasspathsAndSearchScopesTest.java78
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenResolveToWorkspaceTest.java142
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java74
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java67
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java2
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/bundle/X.java3
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/bundle/xxx.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/bundle/xxx_en.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/bundle/xxx_ru_RU.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/bundle/yyy.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/sortByType/X.java3
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/sortByType/a.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/sortByType/xxx.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/sortByType/xxx2.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/sortByType/xxx_en.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/sortByType/yyy.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/standAlone/X.java3
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/standAlone/a.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/standAlone/xxx.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/standAlone/xxx2.properties1
-rw-r--r--plugins/properties/testData/propertiesFile/projectView/standAlone/yyy.properties1
-rw-r--r--plugins/properties/testSrc/com/intellij/lang/properties/PropertiesProjectViewTest.java114
-rw-r--r--plugins/svn4idea/bindSvn/bindSvn.iml25
-rw-r--r--plugins/svn4idea/bindSvn/lib/javahl.jarbin0 -> 168896 bytes
-rw-r--r--plugins/svn4idea/bindSvn/lib/javahlsrc.zipbin0 -> 210516 bytes
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/AuthenticationCallback.java109
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventHandler.java30
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventType.java49
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindClient.java925
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindUtil.java104
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnCommitRunner.java217
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/LineCommandListener.java40
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java)32
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java)20
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java415
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java)18
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/config/SvnBindException.java54
-rw-r--r--plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/status/LockWrapper.java121
-rw-r--r--plugins/svn4idea/bindSvn/src/org/tigris/subversion/javahl/BindClientException.java47
-rw-r--r--plugins/svn4idea/lib/sqljet.jarbin755723 -> 757103 bytes
-rw-r--r--plugins/svn4idea/lib/svnkit-javahl.jarbin330142 -> 330141 bytes
-rw-r--r--plugins/svn4idea/lib/svnkit-javahl16.zipbin166033 -> 166032 bytes
-rw-r--r--plugins/svn4idea/lib/svnkit.jarbin3376358 -> 3378829 bytes
-rw-r--r--plugins/svn4idea/lib/svnkitsrc.zipbin2119640 -> 2120588 bytes
-rw-r--r--plugins/svn4idea/lib/trilead.jarbin247578 -> 248764 bytes
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java26
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java155
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties10
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java86
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java27
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java24
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java98
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java85
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java62
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java591
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java165
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AddLineConverter.java38
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandFactory.java59
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java13
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java17
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java198
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java113
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java18
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form10
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java21
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java16
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java145
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LocalChangesAction.java29
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/MergeDialogI.java34
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java268
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMergeContentsVariants.java26
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSLCredentialsDialog.java7
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java6
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java17
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java157
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java38
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java25
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java41
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java10
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java1
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java23
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteraction.java68
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteractionImpl.java164
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeWayOptionsPanel.form94
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeWayOptionsPanel.java85
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java3
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/lowLevel/PrimitivePool.java113
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/ListMergeStatus.java47
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java21
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java12
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/networking/SSLProtocolExceptionParser.java87
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/status/DiffContentRevision.java3
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnRevisionPanel.java5
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java5
-rw-r--r--plugins/svn4idea/svn4idea-tests.iml1
-rw-r--r--plugins/svn4idea/svn4idea.iml11
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java59
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/QuickMergeTestInteraction.java149
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SSLExceptionParserTest.java41
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java3
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommitTest.java492
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java27
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java630
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java3
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java510
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnRenameTest.java1
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java1
-rw-r--r--plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java8
-rw-r--r--plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java15
-rw-r--r--plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java1
-rw-r--r--plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java4
-rw-r--r--plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form12
-rw-r--r--plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java10
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/actions/ShowTaskDescription.java18
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java6
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java86
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/fogbugz/FogBugzRepository.java11
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java32
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java40
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java9
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java3
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryType.java7
-rw-r--r--plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUiTest.java12
-rw-r--r--plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java29
-rw-r--r--plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java11
-rw-r--r--plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java68
-rw-r--r--plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java18
-rw-r--r--plugins/testng/src/com/theoryinpractice/testng/TestNGReferenceContributor.java6
-rw-r--r--plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java62
-rw-r--r--plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java22
-rw-r--r--plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java19
-rw-r--r--plugins/testng/src/com/theoryinpractice/testng/model/TestNGListenersTableModel.java2
-rw-r--r--plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java2
-rw-r--r--plugins/ui-designer-core/src/META-INF/plugin.xml4
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java5
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/DesignerCustomizations.java40
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java19
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.java65
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/actions/DeselectAllAction.java34
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java109
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java4
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/actions/SelectSameTypeAction.java57
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/actions/SelectSiblingsAction.java53
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java5
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeDropListener.java2
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/CaptionPanel.java7
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/ComponentGlassLayer.java (renamed from plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeGlassLayer.java)24
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java136
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/EmptyEditableArea.java79
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java9
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/RootView.java18
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/ScalableComponent.java26
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/ZoomProvider.java40
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/ZoomType.java48
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/InsertFeedback.java2
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/LineFeedback.java2
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java6
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/ResizePoint.java14
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/AbstractCreationTool.java2
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/InputTool.java25
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/MarqueeTracker.java57
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ResizeTracker.java25
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTool.java80
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java6
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java31
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ToolProvider.java3
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/model/IComponentDeletionParticipant.java22
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java29
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/model/RadComponent.java209
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/model/RadVisualComponent.java135
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/model/VariationPaletteItem.java105
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/palette/DefaultPaletteItem.java34
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItem.java30
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItemsComponent.java28
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java6
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/propertyTable/actions/RestoreDefault.java2
-rw-r--r--plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java3
-rw-r--r--plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java7
-rw-r--r--plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java15
-rw-r--r--plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java4
-rw-r--r--plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/ClientPropertiesProperty.java2
-rw-r--r--plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/GridLayoutColumnProperties.java4
-rw-r--r--plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java7
-rw-r--r--plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java6
-rw-r--r--plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathAppComponent.java2
-rw-r--r--plugins/xslt-debugger/engine/xslt-debugger-engine.iml2
-rw-r--r--plugins/xslt-debugger/xslt-debugger.iml2
1249 files changed, 33558 insertions, 8513 deletions
diff --git a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java
index 1905bd08a41b..34b5d446e3ba 100644
--- a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java
+++ b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ShowByteCodeAction.java
@@ -113,7 +113,7 @@ public class ShowByteCodeAction extends AnAction {
Processor<JBPopup> pinCallback = new Processor<JBPopup>() {
@Override
public boolean process(JBPopup popup) {
- codeViewerManager.createToolWindow(targetElement, targetElement);
+ codeViewerManager.recreateToolWindow(targetElement, targetElement);
popup.cancel();
return false;
}
diff --git a/plugins/InspectionGadgets/src/META-INF/plugin.xml b/plugins/InspectionGadgets/src/META-INF/plugin.xml
index 3e5977f50329..07af779efc64 100644
--- a/plugins/InspectionGadgets/src/META-INF/plugin.xml
+++ b/plugins/InspectionGadgets/src/META-INF/plugin.xml
@@ -107,6 +107,10 @@
key="assignment.to.static.field.from.instance.method.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.assignment.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.assignment.AssignmentToStaticFieldFromInstanceMethodInspection"/>
+ <localInspection language="JAVA" shortName="AssignmentToSuperclassField" bundle="com.siyeh.InspectionGadgetsBundle"
+ key="assignment.to.superclass.field.display.name" groupBundle="messages.InspectionsBundle"
+ groupKey="group.names.assignment.issues" enabledByDefault="false" level="WARNING"
+ implementationClass="com.siyeh.ig.assignment.AssignmentToSuperclassFieldInspection"/>
<localInspection language="JAVA" shortName="AssignmentUsedAsCondition" bundle="com.siyeh.InspectionGadgetsBundle"
key="assignment.used.as.condition.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.assignment.issues" enabledByDefault="false" level="WARNING"
@@ -1441,6 +1445,10 @@
<localInspection language="JAVA" suppressId="NonConstantLogger" shortName="NonStaticFinalLogger" bundle="com.siyeh.InspectionGadgetsBundle"
key="non.constant.logger.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.logging.issues"
enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.logging.NonStaticFinalLoggerInspection"/>
+ <localInspection language="JAVA" shortName="PlaceholderCountMatchesArgumentCount" bundle="com.siyeh.InspectionGadgetsBundle"
+ key="placeholder.count.matches.argument.count.display.name" groupBundle="messages.InspectionsBundle"
+ groupKey="group.names.logging.issues" enabledByDefault="false" level="WARNING"
+ implementationClass="com.siyeh.ig.logging.PlaceholderCountMatchesArgumentCountInspection"/>
<localInspection language="JAVA" shortName="PublicMethodWithoutLogging" bundle="com.siyeh.InspectionGadgetsBundle"
key="public.method.without.logging.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.logging.issues" enabledByDefault="false" level="WARNING"
diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties
index fdcff59f758f..941a1b5f473a 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -201,7 +201,7 @@ no.logger.problem.descriptor=Class <code>#ref</code> does not declare a logger #
non.constant.logger.display.name=Non-constant logger
non.constant.logger.problem.descriptor=Non-constant logger field <code>#ref</code> #loc
public.method.without.logging.display.name='public' method without logging
-public.method.without.logging.problem.descriptor='public' method <code>#ref()</code> has no logging statement #loc
+public.method.without.logging.problem.descriptor='public' method <code>#ref()</code> has no logging call #loc
action.reset.telemetry.description=Reset telemetry data
telemetry.table.column.inspection.name=Inspection
@@ -886,7 +886,7 @@ iterator.next.does.not.throw.nosuchelementexception.problem.descriptor=<code>Ite
infinite.loop.statement.problem.descriptor=<code>#ref</code> statement cannot complete without throwing an exception #loc
confusing.floating.point.literal.problem.descriptor=Confusing floating point literal <code>#ref</code> #loc
overly.complex.arithmetic.expression.problem.descriptor=Overly complex arithmetic expression #loc
-overly.complex.boolean.expression.problem.descriptor=Overly complex boolean expression #loc
+overly.complex.boolean.expression.problem.descriptor=Overly complex boolean expression ({0} terms) #loc
labeled.statement.problem.descriptor=Labeled statement <code>#ref:</code> #loc
break.statement.with.label.problem.descriptor=<code>#ref</code> statement with label #loc
continue.statement.with.label.problem.descriptor=<code>#ref</code> statement with label #loc
@@ -1226,7 +1226,7 @@ object.notify.replace.quickfix=Replace with 'notifyAll()'
safe.lock.problem.descriptor=''{0}'' should be locked in front of a ''try'' block and unlocked in the corresponding ''finally'' block #loc
synchronized.method.problem.descriptor=Method ''{0}()'' declared <code>#ref</code> #loc
synchronized.method.include.option=Include native methods
-synchronized.method.ignore.synchronized.super.option=Ignore overrides synchronized methods
+synchronized.method.ignore.synchronized.super.option=Ignore methods overriding a synchronized method
synchronized.method.move.quickfix=Move synchronization into method
thread.run.replace.quickfix=Replace with 'start()'
volatile.field.problem.descriptor=Volatile field <code>#ref</code> of type ''{0}'' #loc
@@ -1245,9 +1245,9 @@ encapsulate.variable.quickfix=Encapsulate field ''{0}''
extract.method.quickfix=Extract method
inline.call.quickfix=Inline call
inline.variable.quickfix=Inline variable
-pointless.nullcheck.display.name=Pointless 'null' check
-pointless.nullcheck.problem.descriptor=Pointless 'null' check can be removed
-pointless.nullcheck.simplify.quickfix=Simplify
+pointless.nullcheck.display.name=Unnecessary 'null' check before 'instanceof' expression
+pointless.nullcheck.problem.descriptor=Unnecessary 'null' check before 'instanceof' expression
+pointless.nullcheck.simplify.quickfix=Remove unnecessary ''{0}'' condition
introduce.constant.quickfix=Introduce constant
make.class.cloneable.quickfix=Make class 'Cloneable'
make.interface.cloneable.quickfix=Make interface 'Cloneable'
@@ -1345,8 +1345,7 @@ unnecessarily.qualified.static.usage.problem.descriptor1=Unnecessarily qualified
unnecessarily.qualified.static.usage.ignore.field.option=Ignore unnecessarily qualified field accesses
unnecessarily.qualified.static.usage.ignore.method.option=Ignore unnecessarily qualified method calls
unnecessary.interface.modifier.problem.descriptor=Modifier <code>#ref</code> is redundant for interfaces #loc
-unnecessary.interface.modifier.inner.interface.of.interface.problem.descriptor=Modifier <code>#ref</code> is redundant for inner interfaces of interfaces #loc
-unnecessary.interface.modifier.inner.interface.of.class.problem.descriptor=Modifier <code>#ref</code> is redundant for inner interfaces of classes #loc
+unnecessary.interface.modifier.inner.interface.of.interface.problem.descriptor=Modifier <code>#ref</code> is redundant for inner interfaces #loc
unnecessary.interface.modifier.problem.descriptor2=Modifier <code>#ref</code> is redundant for interface methods #loc
unnecessary.interface.modifier.problem.descriptor3=Modifier <code>#ref</code> is redundant for inner classes of interfaces #loc
unnecessary.interface.modifier.problem.descriptor4=Modifier <code>#ref</code> is redundant for interface fields #loc
@@ -1474,7 +1473,7 @@ choose.class.type.to.ignore=Choose class type to ignore
loop.condition.not.updated.inside.loop.display.name=Loop variable not updated inside loop
loop.condition.not.updated.inside.loop.problem.descriptor='#ref' is not updated inside loop #loc
utility.class.without.private.constructor.option=Ignore classes with only a main method
-super.class.logger.option=Ignore classes with an accessible logger declared in a super class
+super.class.logger.option=Ignore classes with an accessible logger declared in a superclass
static.method.only.used.in.one.class.display.name=Static method only used from one other class
static.method.only.used.in.one.class.problem.descriptor=Static method <code>#ref()</code> is only used from class ''{0}'' #loc
static.method.only.used.in.one.class.problem.descriptor.anonymous.implementing=Static method <code>#ref()</code> is only used from an anonymous class implementing ''{0}'' #loc
@@ -1695,7 +1694,7 @@ unnecessary.constant.array.creation.expression.display.name=Constant array creat
unnecessary.constant.array.creation.expression.problem.descriptor=<code>#ref</code> can be replaced with array initializer expression #loc
unnecessary.constant.array.creation.expression.quickfix=Replace with array initializer expression
ambiguous.method.call.display.name=Inherited method called, while local method might have been expected
-ambiguous.method.call.problem.descriptor=Method <code>#ref()</code> from super class ''{0}'' called, when method from class ''{1}'' might have been expected #loc
+ambiguous.method.call.problem.descriptor=Method <code>#ref()</code> from superclass ''{0}'' called, when method from class ''{1}'' might have been expected #loc
ambiguous.method.call.quickfix=Add 'super' qualifier to method call
change.modifier.quickfix=Make ''{0}''
the.whole.project=the whole project
@@ -1708,11 +1707,12 @@ logger.initialized.with.foreign.class.display.name=Logger initialized with forei
logger.factory.method.name=Logger factory method name
logger.factory.class.name=Logger factory class name
make.static.final.quickfix=Make ''{0}'' static final
-logging.condition.disagrees.with.log.statement.display.name=Logging condition does not match log statement
-logging.condition.disagrees.with.log.statement.problem.descriptor=Logging condition <code>#ref()</code> does not match ''{0}()'' log statement #loc
-log.statement.guarded.by.log.condition.display.name=Log statement not guarded by log condition
-log.statement.guarded.by.log.condition.problem.descriptor=<code>#ref()</code> log statement not guarded by log condition #loc
+logging.condition.disagrees.with.log.statement.display.name=Log condition does not match logging call
+logging.condition.disagrees.with.log.statement.problem.descriptor=Log condition <code>#ref()</code> does not match ''{0}()'' logging call #loc
+log.statement.guarded.by.log.condition.display.name=Logging call not guarded by log condition
+log.statement.guarded.by.log.condition.problem.descriptor=<code>#ref()</code> logging calls not guarded by log condition #loc
log.statement.guarded.by.log.condition.quickfix=Surround with log condition
+log.statement.guarded.by.log.condition.flag.all.unguarded.option=Flag all unguarded logging calls
key.set.iteration.may.use.entry.set.display.name=Iteration over 'keySet()' may be replaced with 'entrySet()' iteration
key.set.iteration.may.use.entry.set.problem.descriptor=Iteration over <code>#ref</code> may be replaced with 'entrySet()' iteration #loc
key.set.iteration.may.use.entry.set.quickfix=Replace with 'entrySet()' iteration
@@ -1809,7 +1809,7 @@ logger.class.name=Logger class name
ignore.exceptions.declared.in.tests.option=Ignore exceptions declared in &tests
ignore.exceptions.declared.on.library.override.option=Ignore exceptions declared on methods overriding a &library method
allow.resource.to.be.opened.inside.a.try.block=Allow resource to be opened inside a 'try' block
-log.method.name=Log method name
+log.method.name=Logging method name
log.condition.text=Log condition text
ignore.if.annotated.by=Ignore if annotated by
only.weaken.to.an.interface=Only weaken to an interface
@@ -1860,7 +1860,7 @@ boxing.boxed.value.quickfix=Remove unnecessary boxing
unnecessary.javadoc.link.option=Ignore inline links to super methods
constant.junit.assert.argument.display.name=Constant JUnit assert argument
constant.junit.assert.argument.problem.descriptor=Argument <code>#ref</code> is constant #loc
-test.case.with.no.test.methods.option=Ignore test cases which have super classes with test methods
+test.case.with.no.test.methods.option=Ignore test cases which have superclasses with test methods
package.dot.html.may.be.package.info.display.name='package.html' may be converted to 'package-info.java'
package.dot.html.may.be.package.info.exists.problem.descriptor=<code>package.html</code> is ignored because <code>package-info.java</code> exists
package.dot.html.may.be.package.info.problem.descriptor=<code>package.html</code> may be converted to <code>package-info.java</code>
@@ -1897,6 +1897,7 @@ arrays.hash.code.quickfix=Replace with 'Arrays.hashCode()'
method.can.be.variable.arity.method.display.name=Method can be variable arity method
method.can.be.variable.arity.method.problem.descriptor=<code>#ref()</code> can be converted to variable arity method #loc
method.can.be.variable.arity.method.ignore.byte.short.option=<html>Ignore methods with a last parameter of type byte[] or short[]</html>
+method.can.be.variable.arity.method.ignore.overriding.methods=Ignore methods overriding a super method
convert.to.variable.arity.method.quickfix=Convert to variable arity method
mismatched.string.builder.query.update.display.name=Mismatched query and update of StringBuilder
mismatched.string.builder.updated.problem.descriptor=Contents of {0} <code>#ref</code> are updated, but never queried #loc
@@ -1970,9 +1971,9 @@ throws.runtime.exception.quickfix=Remove ''{0}'' from ''throws'' clause
throws.runtime.exception.move.quickfix=Move ''{0}'' to Javadoc ''@throws'' tag
empty.class.ignore.parameterization.option=Ignore class if it is a parameterization of a super type
ambiguous.field.access.display.name=Inherited field accessed while local variable, parameter or field access from surrounding class might be expected
-ambiguous.field.access.hides.local.variable.problem.descriptor=Field <code>#ref</code> from super class ''{0}'' accessed, while local variable access might be expected #loc
-ambiguous.field.access.hides.parameter.problem.descriptor=Field <code>#ref</code> from super class ''{0}'' accessed, while parameter access might be expected #loc
-ambiguous.field.access.hides.field.problem.descriptor=Field <code>#ref</code> from super class ''{0}'' accessed, while field access from surrounding class might be expected #loc
+ambiguous.field.access.hides.local.variable.problem.descriptor=Field <code>#ref</code> from superclass ''{0}'' accessed, while local variable access might be expected #loc
+ambiguous.field.access.hides.parameter.problem.descriptor=Field <code>#ref</code> from superclass ''{0}'' accessed, while parameter access might be expected #loc
+ambiguous.field.access.hides.field.problem.descriptor=Field <code>#ref</code> from superclass ''{0}'' accessed, while field access from surrounding class might be expected #loc
ambiguous.field.access.quickfix=Add 'super' qualifier to field access
string.builder.replaceable.by.string.quickfix=Replace 'StringBuilder' with 'String'
string.buffer.replaceable.by.string.quickfix=Replace 'StringBuffer' with 'String'
@@ -1984,7 +1985,7 @@ externalizable.without.public.no.arg.constructor.problem.descriptor=Externalizab
make.constructor.public=Make constructor 'public'
string.concatenation.missing.whitespace.display.name=String literal concatenation missing whitespace
string.concatenation.missing.whitespace.problem.descriptor=String literal concatenation missing whitespace #loc
-string.concatenation.missing.whitespace.option=Ignore when one or both sides are not string literals
+string.concatenation.missing.whitespace.option=Ignore when one or both sides are not literals
negated.equality.expression.display.name=Negated equality expression
negated.equality.expression.problem.descriptor=Negating ''{0}'' #loc
negated.equality.expression.quickfix=Remove negation
@@ -2013,4 +2014,9 @@ arrays.as.list.with.one.argument.quickfix=Replace with call to 'Collections.sing
arrays.as.list.with.zero.arguments.quickfix=Replace with call to 'Collections.emptyList()'
ignore.classes.extending.throwable.option=Ignore classes extending 'Throwable'
string.concatenation.argument.to.log.call.display.name=Non-constant string concatenation as argument to logging call
-string.concatenation.argument.to.log.call.problem.descriptor=Non-constant string concatenation as argument to <code>#ref()</code> logging call #loc \ No newline at end of file
+string.concatenation.argument.to.log.call.problem.descriptor=Non-constant string concatenation as argument to <code>#ref()</code> logging call #loc
+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
+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}''
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java
index bbedd0243112..835046511e74 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2012 Bas Leijdekkers
+ * Copyright 2006-2013 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,48 +64,36 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
@NonNls final StringBuilder builder = new StringBuilder();
final Iterator<PsiClass> iterator = weakerClasses.iterator();
if (iterator.hasNext()) {
- builder.append('\'');
- builder.append(iterator.next().getQualifiedName());
- builder.append('\'');
+ builder.append('\'').append(iterator.next().getQualifiedName()).append('\'');
while (iterator.hasNext()) {
- builder.append(", '");
- builder.append(iterator.next().getQualifiedName());
- builder.append('\'');
+ builder.append(", '").append(iterator.next().getQualifiedName()).append('\'');
}
}
final Object info = infos[0];
if (info instanceof PsiField) {
- return InspectionGadgetsBundle.message(
- "type.may.be.weakened.field.problem.descriptor",
+ return InspectionGadgetsBundle.message("type.may.be.weakened.field.problem.descriptor",
builder.toString());
}
else if (info instanceof PsiParameter) {
- return InspectionGadgetsBundle.message(
- "type.may.be.weakened.parameter.problem.descriptor",
+ return InspectionGadgetsBundle.message("type.may.be.weakened.parameter.problem.descriptor",
builder.toString());
}
else if (info instanceof PsiMethod) {
- return InspectionGadgetsBundle.message(
- "type.may.be.weakened.method.problem.descriptor",
+ return InspectionGadgetsBundle.message("type.may.be.weakened.method.problem.descriptor",
builder.toString());
}
- return InspectionGadgetsBundle.message(
- "type.may.be.weakened.problem.descriptor", builder.toString());
+ return InspectionGadgetsBundle.message("type.may.be.weakened.problem.descriptor", builder.toString());
}
@Override
@Nullable
public JComponent createOptionsPanel() {
- final MultipleCheckboxOptionsPanel optionsPanel =
- new MultipleCheckboxOptionsPanel(this);
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
- "type.may.be.weakened.ignore.option"),
+ final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("type.may.be.weakened.ignore.option"),
"useRighthandTypeAsWeakestTypeInAssignments");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
- "type.may.be.weakened.collection.method.option"),
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("type.may.be.weakened.collection.method.option"),
"useParameterizedTypeForCollectionMethods");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
- "type.may.be.weakened.do.not.weaken.to.object.option"),
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("type.may.be.weakened.do.not.weaken.to.object.option"),
"doNotWeakenToJavaLangObject");
optionsPanel.addCheckbox(InspectionGadgetsBundle.message("only.weaken.to.an.interface"),
"onlyWeakentoInterface");
@@ -137,19 +125,16 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
@NotNull
public String getName() {
- return InspectionGadgetsBundle.message(
- "type.may.be.weakened.quickfix", fqClassName);
+ return InspectionGadgetsBundle.message("type.may.be.weakened.quickfix", fqClassName);
}
@Override
- protected void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
final PsiTypeElement typeElement;
if (parent instanceof PsiVariable) {
- final PsiVariable variable =
- (PsiVariable)parent;
+ final PsiVariable variable = (PsiVariable)parent;
typeElement = variable.getTypeElement();
}
else if (parent instanceof PsiMethod) {
@@ -162,8 +147,7 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
if (typeElement == null) {
return;
}
- final PsiJavaCodeReferenceElement componentReferenceElement =
- typeElement.getInnermostComponentReferenceElement();
+ final PsiJavaCodeReferenceElement componentReferenceElement = typeElement.getInnermostComponentReferenceElement();
if (componentReferenceElement == null) {
return;
}
@@ -179,28 +163,23 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
if (aClass == null) {
return;
}
- final PsiTypeParameter[] typeParameters =
- aClass.getTypeParameters();
+ final PsiTypeParameter[] typeParameters = aClass.getTypeParameters();
final PsiElementFactory factory = facade.getElementFactory();
final PsiClassType type;
- if (typeParameters.length != 0 &&
- typeParameters.length == parameterTypes.length) {
- final Map<PsiTypeParameter, PsiType> typeParameterMap =
- new HashMap();
+ if (typeParameters.length != 0 && typeParameters.length == parameterTypes.length) {
+ final Map<PsiTypeParameter, PsiType> typeParameterMap = new HashMap();
for (int i = 0; i < typeParameters.length; i++) {
final PsiTypeParameter typeParameter = typeParameters[i];
final PsiType parameterType = parameterTypes[i];
typeParameterMap.put(typeParameter, parameterType);
}
- final PsiSubstitutor substitutor =
- factory.createSubstitutor(typeParameterMap);
+ final PsiSubstitutor substitutor = factory.createSubstitutor(typeParameterMap);
type = factory.createType(aClass, substitutor);
}
else {
type = factory.createTypeByFQClassName(fqClassName, scope);
}
- final PsiJavaCodeReferenceElement referenceElement =
- factory.createReferenceElementByType(type);
+ final PsiJavaCodeReferenceElement referenceElement = factory.createReferenceElementByType(type);
componentReferenceElement.replace(referenceElement);
}
}
@@ -217,8 +196,7 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
super.visitVariable(variable);
if (variable instanceof PsiParameter) {
final PsiParameter parameter = (PsiParameter)variable;
- final PsiElement declarationScope =
- parameter.getDeclarationScope();
+ final PsiElement declarationScope = parameter.getDeclarationScope();
if (declarationScope instanceof PsiCatchSection) {
// do not weaken catch block parameters
return;
@@ -235,8 +213,7 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
// super methods
return;
}
- final Query<PsiMethod> overridingSearch =
- OverridingMethodsSearch.search(method);
+ final Query<PsiMethod> overridingSearch = OverridingMethodsSearch.search(method);
if (overridingSearch.findFirst() != null) {
// do not try to weaken parameters of methods with
// overriding methods.
@@ -255,21 +232,16 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
if (variable instanceof PsiParameter) {
final PsiElement parent = variable.getParent();
if (parent instanceof PsiForeachStatement) {
- final PsiForeachStatement foreachStatement =
- (PsiForeachStatement)parent;
- final PsiExpression iteratedValue =
- foreachStatement.getIteratedValue();
- if (!(iteratedValue instanceof PsiNewExpression) &&
- !(iteratedValue instanceof
- PsiTypeCastExpression)) {
+ final PsiForeachStatement foreachStatement = (PsiForeachStatement)parent;
+ final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
+ if (!(iteratedValue instanceof PsiNewExpression) && !(iteratedValue instanceof PsiTypeCastExpression)) {
return;
}
}
}
else {
final PsiExpression initializer = variable.getInitializer();
- if (!(initializer instanceof PsiNewExpression) &&
- !(initializer instanceof PsiTypeCastExpression)) {
+ if (!(initializer instanceof PsiNewExpression) && !(initializer instanceof PsiTypeCastExpression)) {
return;
}
}
@@ -281,14 +253,11 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
if (doNotWeakenToJavaLangObject) {
final Project project = variable.getProject();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
- final PsiClass javaLangObjectClass =
- facade.findClass(CommonClassNames.JAVA_LANG_OBJECT,
- variable.getResolveScope());
+ final PsiClass javaLangObjectClass = facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, variable.getResolveScope());
weakestClasses.remove(javaLangObjectClass);
}
if (onlyWeakentoInterface) {
- for (Iterator<PsiClass> iterator = weakestClasses.iterator();
- iterator.hasNext(); ) {
+ for (Iterator<PsiClass> iterator = weakestClasses.iterator(); iterator.hasNext(); ) {
final PsiClass weakestClass = iterator.next();
if (!weakestClass.isInterface()) {
iterator.remove();
@@ -313,8 +282,7 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
// do not try to weaken methods with super methods
return;
}
- final Query<PsiMethod> overridingSearch =
- OverridingMethodsSearch.search(method);
+ final Query<PsiMethod> overridingSearch = OverridingMethodsSearch.search(method);
if (overridingSearch.findFirst() != null) {
// do not try to weaken methods with overriding methods.
return;
@@ -326,9 +294,7 @@ public class TypeMayBeWeakenedInspection extends BaseInspection {
if (doNotWeakenToJavaLangObject) {
final Project project = method.getProject();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
- final PsiClass javaLangObjectClass =
- facade.findClass(CommonClassNames.JAVA_LANG_OBJECT,
- method.getResolveScope());
+ final PsiClass javaLangObjectClass = facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, method.getResolveScope());
weakestClasses.remove(javaLangObjectClass);
}
if (onlyWeakentoInterface) {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/assignment/AssignmentToSuperclassFieldInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/assignment/AssignmentToSuperclassFieldInspection.java
new file mode 100644
index 000000000000..a28257d497c5
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/assignment/AssignmentToSuperclassFieldInspection.java
@@ -0,0 +1,107 @@
+/*
+ * 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.siyeh.ig.assignment;
+
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class AssignmentToSuperclassFieldInspection extends BaseInspection {
+
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("assignment.to.superclass.field.display.name");
+ }
+
+ @NotNull
+ @Override
+ protected String buildErrorString(Object... infos) {
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)infos[0];
+ final PsiClass superclass = (PsiClass)infos[1];
+ return InspectionGadgetsBundle.message("assignment.to.superclass.field.problem.descriptor",
+ referenceExpression.getReferenceName(), superclass.getName());
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new AssignmentToSuperclassFieldVisitor();
+ }
+
+ private static class AssignmentToSuperclassFieldVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitAssignmentExpression(PsiAssignmentExpression expression) {
+ super.visitAssignmentExpression(expression);
+ final PsiExpression lhs = expression.getLExpression();
+ checkSuperclassField(lhs);
+ }
+
+ @Override
+ public void visitPrefixExpression(PsiPrefixExpression expression) {
+ super.visitPrefixExpression(expression);
+ final PsiExpression operand = expression.getOperand();
+ checkSuperclassField(operand);
+ }
+
+ @Override
+ public void visitPostfixExpression(PsiPostfixExpression expression) {
+ super.visitPostfixExpression(expression);
+ final PsiExpression operand = expression.getOperand();
+ checkSuperclassField(operand);
+ }
+
+ private void checkSuperclassField(PsiExpression expression) {
+ if (!(expression instanceof PsiReferenceExpression)) {
+ return;
+ }
+ final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class);
+ if (method == null || !method.isConstructor()) {
+ return;
+ }
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
+ final PsiExpression qualifierExpression = referenceExpression.getQualifierExpression();
+ if (qualifierExpression != null &&
+ !(qualifierExpression instanceof PsiThisExpression) && !(qualifierExpression instanceof PsiSuperExpression)) {
+ return;
+ }
+ final PsiElement target = referenceExpression.resolve();
+ if (!(target instanceof PsiField)) {
+ return;
+ }
+ final PsiField field = (PsiField)target;
+ final PsiClass fieldClass = field.getContainingClass();
+ if (fieldClass == null) {
+ return;
+ }
+ final PsiClass assignmentClass = method.getContainingClass();
+ final String name = fieldClass.getQualifiedName();
+ if (name == null || !InheritanceUtil.isInheritor(assignmentClass, true, name)) {
+ return;
+ }
+ registerError(expression, referenceExpression, fieldClass);
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java
index 873a2407a5cc..c476f9a6af38 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.ui.CheckBox;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -77,8 +78,7 @@ public class IgnoreResultOfCallInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "result.of.method.call.ignored.display.name");
+ return InspectionGadgetsBundle.message("result.of.method.call.ignored.display.name");
}
@Override
@@ -86,9 +86,7 @@ public class IgnoreResultOfCallInspection extends BaseInspection {
public String buildErrorString(Object... infos) {
final PsiClass containingClass = (PsiClass)infos[0];
final String className = containingClass.getName();
- return InspectionGadgetsBundle.message(
- "result.of.method.call.ignored.problem.descriptor",
- className);
+ return InspectionGadgetsBundle.message("result.of.method.call.ignored.problem.descriptor", className);
}
@Override
@@ -106,9 +104,9 @@ public class IgnoreResultOfCallInspection extends BaseInspection {
@Override
public JComponent createOptionsPanel() {
final JPanel panel = new JPanel(new BorderLayout());
- final ListTable table = new ListTable(new ListWrappingTableModel(Arrays.asList(classNames, methodNamePatterns), InspectionGadgetsBundle
- .message("result.of.method.call.ignored.class.column.title"), InspectionGadgetsBundle
- .message("result.of.method.call.ignored.method.column.title")));
+ final ListTable table = new ListTable(new ListWrappingTableModel(
+ Arrays.asList(classNames, methodNamePatterns), InspectionGadgetsBundle.message("result.of.method.call.ignored.class.column.title"),
+ InspectionGadgetsBundle.message("result.of.method.call.ignored.method.column.title")));
final JPanel tablePanel = UiUtils.createAddRemovePanel(table);
final CheckBox checkBox =
new CheckBox(InspectionGadgetsBundle.message("result.of.method.call.ignored.non.library.option"), this, "m_reportAllNonLibraryCalls");
@@ -130,15 +128,13 @@ public class IgnoreResultOfCallInspection extends BaseInspection {
private class IgnoreResultOfCallVisitor extends BaseInspectionVisitor {
@Override
- public void visitExpressionStatement(
- @NotNull PsiExpressionStatement statement) {
+ public void visitExpressionStatement(@NotNull PsiExpressionStatement statement) {
super.visitExpressionStatement(statement);
final PsiExpression expression = statement.getExpression();
if (!(expression instanceof PsiMethodCallExpression)) {
return;
}
- final PsiMethodCallExpression call =
- (PsiMethodCallExpression)expression;
+ final PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
final PsiMethod method = call.resolveMethod();
if (method == null || method.isConstructor()) {
return;
@@ -151,13 +147,14 @@ public class IgnoreResultOfCallInspection extends BaseInspection {
if (aClass == null) {
return;
}
- if (m_reportAllNonLibraryCalls &&
- !LibraryUtil.classIsInLibrary(aClass)) {
+ if (PsiUtilCore.hasErrorElementChild(statement)) {
+ return;
+ }
+ if (m_reportAllNonLibraryCalls && !LibraryUtil.classIsInLibrary(aClass)) {
registerMethodCallError(call, aClass);
return;
}
- final PsiReferenceExpression methodExpression =
- call.getMethodExpression();
+ final PsiReferenceExpression methodExpression = call.getMethodExpression();
final String methodName = methodExpression.getReferenceName();
if (methodName == null) {
return;
@@ -176,8 +173,7 @@ public class IgnoreResultOfCallInspection extends BaseInspection {
}
}
- private boolean methodNamesMatch(String methodName,
- String methodNamePattern) {
+ private boolean methodNamesMatch(String methodName, String methodNamePattern) {
Pattern pattern;
if (patternCache != null) {
pattern = patternCache.get(methodNamePattern);
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspection.java
index 71f2ae53732f..90921cdb2cc1 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2008 Dave Griffith, Bas Leijdekkers
+ * Copyright 2006-2013 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.
@@ -23,21 +23,18 @@ import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NotNull;
-public class PrimitiveArrayArgumentToVariableArgMethodInspection
- extends BaseInspection {
+public class PrimitiveArrayArgumentToVariableArgMethodInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "primitive.array.argument.to.var.arg.method.display.name");
+ return InspectionGadgetsBundle.message("primitive.array.argument.to.var.arg.method.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "primitive.array.argument.to.var.arg.method.problem.descriptor");
+ return InspectionGadgetsBundle.message("primitive.array.argument.to.var.arg.method.problem.descriptor");
}
@Override
@@ -50,12 +47,10 @@ public class PrimitiveArrayArgumentToVariableArgMethodInspection
return new PrimitiveArrayArgumentToVariableArgVisitor();
}
- private static class PrimitiveArrayArgumentToVariableArgVisitor
- extends BaseInspectionVisitor {
+ private static class PrimitiveArrayArgumentToVariableArgVisitor extends BaseInspectionVisitor {
@Override
- public void visitMethodCallExpression(
- @NotNull PsiMethodCallExpression call) {
+ public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
super.visitMethodCallExpression(call);
if (!PsiUtil.isLanguageLevel5OrHigher(call)) {
return;
@@ -70,7 +65,8 @@ public class PrimitiveArrayArgumentToVariableArgMethodInspection
if (!isPrimitiveArrayType(argumentType)) {
return;
}
- final PsiMethod method = call.resolveMethod();
+ final JavaResolveResult result = call.resolveMethodGenerics();
+ final PsiMethod method = (PsiMethod)result.getElement();
if (method == null) {
return;
}
@@ -79,13 +75,12 @@ public class PrimitiveArrayArgumentToVariableArgMethodInspection
return;
}
final PsiParameter[] parameters = parameterList.getParameters();
- final PsiParameter lastParameter =
- parameters[parameters.length - 1];
+ final PsiParameter lastParameter = parameters[parameters.length - 1];
if (!lastParameter.isVarArgs()) {
return;
}
final PsiType parameterType = lastParameter.getType();
- if (isDeepPrimitiveArrayType(parameterType)) {
+ if (isDeepPrimitiveArrayType(parameterType, result.getSubstitutor())) {
return;
}
registerError(lastArgument);
@@ -93,9 +88,6 @@ public class PrimitiveArrayArgumentToVariableArgMethodInspection
}
private static boolean isPrimitiveArrayType(PsiType type) {
- if (type == null) {
- return false;
- }
if (!(type instanceof PsiArrayType)) {
return false;
}
@@ -103,11 +95,12 @@ public class PrimitiveArrayArgumentToVariableArgMethodInspection
return TypeConversionUtil.isPrimitiveAndNotNull(componentType);
}
- private static boolean isDeepPrimitiveArrayType(PsiType type) {
- if (!(type instanceof PsiArrayType)) {
+ private static boolean isDeepPrimitiveArrayType(PsiType type, PsiSubstitutor substitutor) {
+ if (!(type instanceof PsiEllipsisType)) {
return false;
}
final PsiType componentType = type.getDeepComponentType();
- return TypeConversionUtil.isPrimitiveAndNotNull(componentType);
+ final PsiType substitute = substitutor.substitute(componentType);
+ return TypeConversionUtil.isPrimitiveAndNotNull(substitute.getDeepComponentType());
}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspection.java
index bb3c3d3cdc41..eace327f462d 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -23,40 +23,33 @@ import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.NotNull;
-public class ResultOfObjectAllocationIgnoredInspection
- extends BaseInspection {
+public class ResultOfObjectAllocationIgnoredInspection extends BaseInspection {
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "result.of.object.allocation.ignored.display.name");
+ return InspectionGadgetsBundle.message("result.of.object.allocation.ignored.display.name");
}
@NotNull
public String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "result.of.object.allocation.ignored.problem.descriptor");
+ return InspectionGadgetsBundle.message("result.of.object.allocation.ignored.problem.descriptor");
}
public BaseInspectionVisitor buildVisitor() {
- return new IgnoreResultOfCallVisitor();
+ return new ResultOfObjectAllocationIgnoredVisitor();
}
- private static class IgnoreResultOfCallVisitor
- extends BaseInspectionVisitor {
+ private static class ResultOfObjectAllocationIgnoredVisitor extends BaseInspectionVisitor {
@Override
- public void visitExpressionStatement(
- @NotNull PsiExpressionStatement statement) {
+ public void visitExpressionStatement(@NotNull PsiExpressionStatement statement) {
super.visitExpressionStatement(statement);
final PsiExpression expression = statement.getExpression();
if (!(expression instanceof PsiNewExpression)) {
return;
}
- final PsiNewExpression newExpression =
- (PsiNewExpression)expression;
- final PsiExpression[] arrayDimensions =
- newExpression.getArrayDimensions();
+ final PsiNewExpression newExpression = (PsiNewExpression)expression;
+ final PsiExpression[] arrayDimensions = newExpression.getArrayDimensions();
if (arrayDimensions.length != 0) {
return;
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java
index f8157a8d301a..2d4ae7233d51 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,9 @@ import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ExpressionUtils;
+import com.siyeh.ig.psiutils.FormatUtils;
import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -68,11 +70,12 @@ public class StringConcatenationMissingWhitespaceInspection extends BaseInspecti
if (!JavaTokenType.PLUS.equals(tokenType) || !ExpressionUtils.hasStringType(expression)) {
return;
}
+ final boolean formatCall = FormatUtils.isFormatCallArgument(expression);
final PsiExpression[] operands = expression.getOperands();
PsiExpression lhs = operands[0];
for (int i = 1; i < operands.length; i++) {
final PsiExpression rhs = operands[i];
- if (isMissingWhitespace(lhs, rhs)) {
+ if (isMissingWhitespace(lhs, rhs, formatCall)) {
final PsiJavaToken token = expression.getTokenBeforeOperand(rhs);
if (token != null) {
registerError(token);
@@ -82,39 +85,38 @@ public class StringConcatenationMissingWhitespaceInspection extends BaseInspecti
}
}
- private boolean isMissingWhitespace(PsiExpression lhs, PsiExpression rhs) {
- final boolean lhsIsString = ExpressionUtils.hasStringType(lhs);
- final PsiLiteralExpression lhsLiteral = ExpressionUtils.getLiteral(lhs);
- final PsiLiteralExpression rhsLiteral = ExpressionUtils.getLiteral(rhs);
- if (lhsLiteral != null && lhsIsString) {
- final String value = (String)lhsLiteral.getValue();
- if (value == null) {
+ private boolean isMissingWhitespace(PsiExpression lhs, PsiExpression rhs, boolean formatCall) {
+ @NonNls final String lhsLiteral = ExpressionUtils.getLiteralString(lhs);
+ if (lhsLiteral != null) {
+ final int length = lhsLiteral.length();
+ if (length == 0) {
return false;
}
- final int length = value.length();
- if (length == 0) {
+ if (formatCall && lhsLiteral.endsWith("%n")) {
return false;
}
- final char c = value.charAt(length - 1);
+ final char c = lhsLiteral.charAt(length - 1);
if (Character.isWhitespace(c) || !Character.isLetterOrDigit(c)) {
return false;
}
}
- else if (ignoreNonStringLiterals || rhsLiteral == null || lhsIsString) {
+ else if (ignoreNonStringLiterals) {
return false;
}
- final boolean rhsIsString = ExpressionUtils.hasStringType(rhs);
- if (rhsLiteral != null && rhsIsString) {
- final String value = (String)rhsLiteral.getValue();
- if ((value == null) || value.isEmpty()) {
+ @NonNls final String rhsLiteral = ExpressionUtils.getLiteralString(rhs);
+ if (rhsLiteral != null) {
+ if (rhsLiteral.isEmpty()) {
+ return false;
+ }
+ if (formatCall && rhsLiteral.startsWith("%n")) {
return false;
}
- final char c = value.charAt(0);
+ final char c = rhsLiteral.charAt(0);
if (Character.isWhitespace(c) || !Character.isLetterOrDigit(c)) {
return false;
}
}
- else if (ignoreNonStringLiterals || rhsIsString) {
+ else if (ignoreNonStringLiterals) {
return false;
}
return true;
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/NonFinalUtilityClassInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/NonFinalUtilityClassInspection.java
index 0f6498eebb94..71041c17cea0 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/NonFinalUtilityClassInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/classlayout/NonFinalUtilityClassInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -64,7 +64,8 @@ public class NonFinalUtilityClassInspection extends BaseInspection {
if (!UtilityClassUtil.isUtilityClass(aClass)) {
return;
}
- if (aClass.hasModifierProperty(PsiModifier.FINAL)) {
+ if (aClass.hasModifierProperty(PsiModifier.FINAL) ||
+ aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
registerClassError(aClass, aClass);
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
index 4e06728a7a75..088dbf977482 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
@@ -119,9 +119,20 @@ public class ConstantIfStatementInspection extends BaseInspection {
final PsiStatement[] statements = block.getStatements();
if (statements.length > 0) {
assert containingElement != null;
- final PsiElement added =
- containingElement.addRangeBefore(statements[0],
- statements[statements.length - 1], statement);
+ final PsiJavaToken lBrace = block.getLBrace();
+ final PsiJavaToken rBrace = block.getRBrace();
+ PsiElement added = null;
+ if (lBrace != null && rBrace != null) {
+ final PsiElement firstNonBrace = lBrace.getNextSibling();
+ final PsiElement lastNonBrace = rBrace.getPrevSibling();
+ if (firstNonBrace != null && lastNonBrace != null) {
+ added = containingElement.addRangeBefore(firstNonBrace, lastNonBrace, statement);
+ }
+ }
+ if (added == null) {
+ added = containingElement.addRangeBefore(statements[0],
+ statements[statements.length - 1], statement);
+ }
final Project project = statement.getProject();
final CodeStyleManager codeStyleManager =
CodeStyleManager.getInstance(project);
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspection.java
index e53d902dad71..2bd2fcae11d1 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2007 Dave Griffith, Bas Leijdekkers
+ * Copyright 2006-2013 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.
@@ -31,39 +31,33 @@ public class DuplicateBooleanBranchInspection extends BaseInspection {
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "duplicate.boolean.branch.display.name");
+ return InspectionGadgetsBundle.message("duplicate.boolean.branch.display.name");
}
@NotNull
protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "duplicate.boolean.branch.problem.descriptor");
+ return InspectionGadgetsBundle.message("duplicate.boolean.branch.problem.descriptor");
}
public BaseInspectionVisitor buildVisitor() {
return new DuplicateBooleanBranchVisitor();
}
- private static class DuplicateBooleanBranchVisitor
- extends BaseInspectionVisitor {
+ private static class DuplicateBooleanBranchVisitor extends BaseInspectionVisitor {
@Override
- public void visitBinaryExpression(PsiBinaryExpression expression) {
- super.visitBinaryExpression(expression);
+ public void visitPolyadicExpression(PsiPolyadicExpression expression) {
+ super.visitPolyadicExpression(expression);
final IElementType tokenType = expression.getOperationTokenType();
- if (!tokenType.equals(JavaTokenType.ANDAND) &&
- !tokenType.equals(JavaTokenType.OROR)) {
+ if (!tokenType.equals(JavaTokenType.ANDAND) && !tokenType.equals(JavaTokenType.OROR)) {
return;
}
-
PsiElement parent = expression.getParent();
while (parent instanceof PsiParenthesizedExpression) {
parent = parent.getParent();
}
if (parent instanceof PsiBinaryExpression) {
- final PsiBinaryExpression parentExpression =
- (PsiBinaryExpression)parent;
+ final PsiBinaryExpression parentExpression = (PsiBinaryExpression)parent;
if (tokenType.equals(parentExpression.getOperationTokenType())) {
return;
}
@@ -74,8 +68,7 @@ public class DuplicateBooleanBranchInspection extends BaseInspection {
if (numConditions < 2) {
return;
}
- final PsiExpression[] conditionArray =
- conditions.toArray(new PsiExpression[numConditions]);
+ final PsiExpression[] conditionArray = conditions.toArray(new PsiExpression[numConditions]);
final boolean[] matched = new boolean[conditionArray.length];
Arrays.fill(matched, false);
for (int i = 0; i < conditionArray.length; i++) {
@@ -88,9 +81,7 @@ public class DuplicateBooleanBranchInspection extends BaseInspection {
continue;
}
final PsiExpression testCondition = conditionArray[j];
- final boolean areEquivalent =
- EquivalenceChecker.expressionsAreEquivalent(
- condition, testCondition);
+ final boolean areEquivalent = EquivalenceChecker.expressionsAreEquivalent(condition, testCondition);
if (areEquivalent) {
registerError(testCondition);
if (!matched[i]) {
@@ -103,29 +94,24 @@ public class DuplicateBooleanBranchInspection extends BaseInspection {
}
}
- private static void collectConditions(PsiExpression condition,
- Set<PsiExpression> conditions,
- IElementType tokenType) {
+ private static void collectConditions(PsiExpression condition, Set<PsiExpression> conditions, IElementType tokenType) {
if (condition == null) {
return;
}
if (condition instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)condition;
- final PsiExpression contents =
- parenthesizedExpression.getExpression();
+ final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)condition;
+ final PsiExpression contents = parenthesizedExpression.getExpression();
collectConditions(contents, conditions, tokenType);
return;
}
- if (condition instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)condition;
- final IElementType testTokeType = binaryExpression.getOperationTokenType();
+ if (condition instanceof PsiPolyadicExpression) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)condition;
+ final IElementType testTokeType = polyadicExpression.getOperationTokenType();
if (testTokeType.equals(tokenType)) {
- final PsiExpression lhs = binaryExpression.getLOperand();
- collectConditions(lhs, conditions, tokenType);
- final PsiExpression rhs = binaryExpression.getROperand();
- collectConditions(rhs, conditions, tokenType);
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ for (PsiExpression operand : operands) {
+ collectConditions(operand, conditions, tokenType);
+ }
return;
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateConditionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateConditionInspection.java
index 0962eb7784ab..905868060d5c 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateConditionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/DuplicateConditionInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -42,30 +42,25 @@ public class DuplicateConditionInspection extends BaseInspection {
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "duplicate.condition.display.name");
+ return InspectionGadgetsBundle.message("duplicate.condition.display.name");
}
@NotNull
protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "duplicate.condition.problem.descriptor");
+ return InspectionGadgetsBundle.message("duplicate.condition.problem.descriptor");
}
@Nullable
public JComponent createOptionsPanel() {
- return new SingleCheckboxOptionsPanel(
- InspectionGadgetsBundle.message(
- "duplicate.condition.ignore.method.calls.option"),
- this, "ignoreMethodCalls");
+ return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("duplicate.condition.ignore.method.calls.option"),
+ this, "ignoreMethodCalls");
}
public BaseInspectionVisitor buildVisitor() {
return new DuplicateConditionVisitor();
}
- private class DuplicateConditionVisitor
- extends BaseInspectionVisitor {
+ private class DuplicateConditionVisitor extends BaseInspectionVisitor {
@Override
public void visitIfStatement(@NotNull PsiIfStatement statement) {
@@ -84,8 +79,7 @@ public class DuplicateConditionInspection extends BaseInspection {
if (numConditions < 2) {
return;
}
- final PsiExpression[] conditionArray =
- conditions.toArray(new PsiExpression[numConditions]);
+ final PsiExpression[] conditionArray = conditions.toArray(new PsiExpression[numConditions]);
final boolean[] matched = new boolean[conditionArray.length];
Arrays.fill(matched, false);
for (int i = 0; i < conditionArray.length; i++) {
@@ -98,60 +92,51 @@ public class DuplicateConditionInspection extends BaseInspection {
continue;
}
final PsiExpression testCondition = conditionArray[j];
- final boolean areEquivalent =
- EquivalenceChecker.expressionsAreEquivalent(
- condition, testCondition);
+ final boolean areEquivalent = EquivalenceChecker.expressionsAreEquivalent(condition, testCondition);
if (areEquivalent) {
+ if (!ignoreMethodCalls || !containsMethodCallExpression(testCondition)) {
+ registerError(testCondition);
+ if (!matched[i]) {
+ registerError(condition);
+ }
+ }
matched[i] = true;
matched[j] = true;
- if (ignoreMethodCalls &&
- containsMethodCallExpression(testCondition)) {
- break;
- }
- registerError(testCondition);
- if (!matched[i]) {
- registerError(condition);
- }
}
}
}
}
- private void collectConditionsForIfStatement(
- PsiIfStatement statement, Set<PsiExpression> conditions, int depth) {
- if (depth > LIMIT_DEPTH) return;
-
+ private void collectConditionsForIfStatement(PsiIfStatement statement, Set<PsiExpression> conditions, int depth) {
+ if (depth > LIMIT_DEPTH) {
+ return;
+ }
final PsiExpression condition = statement.getCondition();
collectConditionsForExpression(condition, conditions);
final PsiStatement branch = statement.getElseBranch();
if (branch instanceof PsiIfStatement) {
- collectConditionsForIfStatement((PsiIfStatement)branch,
- conditions, depth + 1);
+ collectConditionsForIfStatement((PsiIfStatement)branch, conditions, depth + 1);
}
}
- private void collectConditionsForExpression(
- PsiExpression condition, Set<PsiExpression> conditions) {
+ private void collectConditionsForExpression(PsiExpression condition, Set<PsiExpression> conditions) {
if (condition == null) {
return;
}
if (condition instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)condition;
- final PsiExpression contents =
- parenthesizedExpression.getExpression();
+ final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)condition;
+ final PsiExpression contents = parenthesizedExpression.getExpression();
collectConditionsForExpression(contents, conditions);
return;
}
- if (condition instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)condition;
- final IElementType tokenType = binaryExpression.getOperationTokenType();
+ if (condition instanceof PsiPolyadicExpression) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)condition;
+ final IElementType tokenType = polyadicExpression.getOperationTokenType();
if (JavaTokenType.OROR.equals(tokenType)) {
- final PsiExpression lhs = binaryExpression.getLOperand();
- collectConditionsForExpression(lhs, conditions);
- final PsiExpression rhs = binaryExpression.getROperand();
- collectConditionsForExpression(rhs, conditions);
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ for (PsiExpression operand : operands) {
+ collectConditionsForExpression(operand, conditions);
+ }
return;
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java
index b98a32051bb3..fd09a2c674b3 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/FallthruInSwitchStatementInspection.java
@@ -80,19 +80,19 @@ public class FallthruInSwitchStatementInspection extends BaseInspection {
private static final Pattern commentPattern = Pattern.compile("(?i)falls?\\s*thro?u");
@Override
- public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) {
- super.visitSwitchStatement(statement);
- final PsiCodeBlock body = statement.getBody();
+ public void visitSwitchStatement(@NotNull PsiSwitchStatement switchStatement) {
+ super.visitSwitchStatement(switchStatement);
+ final PsiCodeBlock body = switchStatement.getBody();
if (body == null) {
return;
}
final PsiStatement[] statements = body.getStatements();
for (int i = 1; i < statements.length; i++) {
- final PsiStatement child = statements[i];
- if (!(child instanceof PsiSwitchLabelStatement)) {
+ final PsiStatement statement = statements[i];
+ if (!(statement instanceof PsiSwitchLabelStatement)) {
continue;
}
- final PsiElement previousSibling = PsiTreeUtil.skipSiblingsBackward(child, PsiWhiteSpace.class);
+ final PsiElement previousSibling = PsiTreeUtil.skipSiblingsBackward(statement, PsiWhiteSpace.class);
if (previousSibling instanceof PsiComment) {
final PsiComment comment = (PsiComment)previousSibling;
final String commentText = comment.getText();
@@ -100,9 +100,13 @@ public class FallthruInSwitchStatementInspection extends BaseInspection {
continue;
}
}
- final PsiStatement previousStatement = PsiTreeUtil.getPrevSiblingOfType(child, PsiStatement.class);
+ final PsiStatement previousStatement = PsiTreeUtil.getPrevSiblingOfType(statement, PsiStatement.class);
+ if (previousStatement instanceof PsiSwitchLabelStatement) {
+ // don't warn if there are no regular statements after the switch label
+ continue;
+ }
if (ControlFlowUtils.statementMayCompleteNormally(previousStatement)) {
- registerError(child);
+ registerError(statement);
}
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspection.java
index 02d49095d541..b24f5203b0b2 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -24,30 +24,23 @@ import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.ExtractMethodFix;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import javax.swing.JComponent;
-import javax.swing.JFormattedTextField;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
+import javax.swing.*;
+import java.awt.*;
import java.text.NumberFormat;
import java.util.HashSet;
import java.util.Set;
-public class OverlyComplexBooleanExpressionInspection
- extends BaseInspection {
+public class OverlyComplexBooleanExpressionInspection extends BaseInspection {
- private static final Set<String> s_booleanOperators =
- new HashSet<String>(5);
+ private static final Set<IElementType> s_booleanOperators = new HashSet<IElementType>(5);
static {
- s_booleanOperators.add("&&");
- s_booleanOperators.add("||");
- s_booleanOperators.add("^");
- s_booleanOperators.add("&");
- s_booleanOperators.add("|");
+ s_booleanOperators.add(JavaTokenType.ANDAND);
+ s_booleanOperators.add(JavaTokenType.OROR);
+ s_booleanOperators.add(JavaTokenType.XOR);
+ s_booleanOperators.add(JavaTokenType.AND);
+ s_booleanOperators.add(JavaTokenType.OR);
}
/**
@@ -63,32 +56,28 @@ public class OverlyComplexBooleanExpressionInspection
@Override
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "overly.complex.boolean.expression.display.name");
+ return InspectionGadgetsBundle.message("overly.complex.boolean.expression.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "overly.complex.boolean.expression.problem.descriptor");
+ final Integer termCount = (Integer)infos[0];
+ return InspectionGadgetsBundle.message("overly.complex.boolean.expression.problem.descriptor", termCount);
}
@Override
public JComponent createOptionsPanel() {
final JPanel panel = new JPanel(new GridBagLayout());
final CheckBox ignoreConjunctionsDisjunctionsCheckBox =
- new CheckBox(InspectionGadgetsBundle.message(
- "overly.complex.boolean.expression.ignore.option"),
+ new CheckBox(InspectionGadgetsBundle.message("overly.complex.boolean.expression.ignore.option"),
this, "m_ignorePureConjunctionsDisjunctions");
final NumberFormat formatter = NumberFormat.getIntegerInstance();
formatter.setParseIntegerOnly(true);
- final JFormattedTextField termLimitTextField =
- prepareNumberEditor("m_limit");
+ final JFormattedTextField termLimitTextField = prepareNumberEditor("m_limit");
final GridBagConstraints constraints = new GridBagConstraints();
- final JLabel label = new JLabel(InspectionGadgetsBundle.message(
- "overly.complex.boolean.expression.max.terms.option"));
+ final JLabel label = new JLabel(InspectionGadgetsBundle.message("overly.complex.boolean.expression.max.terms.option"));
constraints.anchor = GridBagConstraints.BASELINE_LEADING;
constraints.fill = GridBagConstraints.HORIZONTAL;
@@ -122,26 +111,22 @@ public class OverlyComplexBooleanExpressionInspection
return new OverlyComplexBooleanExpressionVisitor();
}
- private class OverlyComplexBooleanExpressionVisitor
- extends BaseInspectionVisitor {
+ private class OverlyComplexBooleanExpressionVisitor extends BaseInspectionVisitor {
@Override
- public void visitBinaryExpression(
- @NotNull PsiBinaryExpression expression) {
- super.visitBinaryExpression(expression);
+ public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) {
+ super.visitPolyadicExpression(expression);
checkExpression(expression);
}
@Override
- public void visitPrefixExpression(
- @NotNull PsiPrefixExpression expression) {
+ public void visitPrefixExpression(@NotNull PsiPrefixExpression expression) {
super.visitPrefixExpression(expression);
checkExpression(expression);
}
@Override
- public void visitParenthesizedExpression(
- @NotNull PsiParenthesizedExpression expression) {
+ public void visitParenthesizedExpression(@NotNull PsiParenthesizedExpression expression) {
super.visitParenthesizedExpression(expression);
checkExpression(expression);
}
@@ -150,112 +135,78 @@ public class OverlyComplexBooleanExpressionInspection
if (!isBoolean(expression)) {
return;
}
- if (isParentBoolean(expression)) {
+ final PsiElement parent = expression.getParent();
+ if (parent instanceof PsiExpression && isBoolean((PsiExpression)parent)) {
return;
}
final int numTerms = countTerms(expression);
if (numTerms <= m_limit) {
return;
}
- if (m_ignorePureConjunctionsDisjunctions &&
- expression instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final PsiJavaToken sign = binaryExpression.getOperationSign();
- final String signText = sign.getText();
- if (s_booleanOperators.contains(signText)) {
- if (isPureConjunctionDisJunction(expression, signText)) {
- return;
- }
- }
+ if (m_ignorePureConjunctionsDisjunctions && isPureConjunctionDisjunction(expression)) {
+ return;
}
- registerError(expression);
+ registerError(expression, Integer.valueOf(numTerms));
}
private int countTerms(PsiExpression expression) {
if (!isBoolean(expression)) {
return 1;
}
- if (expression instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final PsiExpression lhs = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
- return countTerms(lhs) + countTerms(rhs);
+ if (expression instanceof PsiPolyadicExpression) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ int count = 0;
+ for (PsiExpression operand : operands) {
+ count += countTerms(operand);
+ }
+ return count;
}
else if (expression instanceof PsiPrefixExpression) {
- final PsiPrefixExpression prefixExpression =
- (PsiPrefixExpression)expression;
- final PsiExpression operand = prefixExpression.getOperand();
- return countTerms(operand);
+ final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
+ return countTerms(prefixExpression.getOperand());
}
else if (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- final PsiExpression contents =
- parenthesizedExpression.getExpression();
- return countTerms(contents);
+ final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
+ return countTerms(parenthesizedExpression.getExpression());
}
return 1;
}
- private boolean isParentBoolean(PsiExpression expression) {
- final PsiElement parent = expression.getParent();
- if (!(parent instanceof PsiExpression)) {
- return false;
- }
- return isBoolean((PsiExpression)parent);
- }
-
private boolean isBoolean(PsiExpression expression) {
- if (expression instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final PsiJavaToken sign = binaryExpression.getOperationSign();
- final String signText = sign.getText();
- return s_booleanOperators.contains(signText);
+ if (expression instanceof PsiPolyadicExpression) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ return s_booleanOperators.contains(polyadicExpression.getOperationTokenType());
}
else if (expression instanceof PsiPrefixExpression) {
- final PsiPrefixExpression prefixExpression =
- (PsiPrefixExpression)expression;
- final IElementType tokenType = prefixExpression.getOperationTokenType();
- return tokenType.equals(JavaTokenType.EXCL);
+ final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
+ return JavaTokenType.EXCL.equals(prefixExpression.getOperationTokenType());
}
else if (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- final PsiExpression contents =
- parenthesizedExpression.getExpression();
- return isBoolean(contents);
+ final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
+ return isBoolean(parenthesizedExpression.getExpression());
}
return false;
}
- private boolean isPureConjunctionDisJunction(
- @Nullable PsiExpression expression,
- @NotNull String operator) {
- if (expression == null) {
+ private boolean isPureConjunctionDisjunction(PsiExpression expression) {
+ if (!(expression instanceof PsiPolyadicExpression)) {
return false;
}
- if (expression instanceof PsiPrefixExpression ||
- expression instanceof PsiParenthesizedExpression) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final IElementType sign = polyadicExpression.getOperationTokenType();
+ if (!s_booleanOperators.contains(sign)) {
return false;
}
- if (!(expression instanceof PsiBinaryExpression)) {
- return true;
- }
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final PsiJavaToken sign = binaryExpression.getOperationSign();
- final String signText = sign.getText();
- if (s_booleanOperators.contains(signText) &&
- !operator.equals(signText)) {
- return false;
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ for (PsiExpression operand : operands) {
+ if (!(operand instanceof PsiReferenceExpression) &&
+ !(operand instanceof PsiMethodCallExpression) &&
+ !(operand instanceof PsiLiteralExpression)) {
+ return false;
+ }
}
- final PsiExpression lOperand = binaryExpression.getLOperand();
- final PsiExpression rOperand = binaryExpression.getROperand();
- return isPureConjunctionDisJunction(lOperand, operator) &&
- isPureConjunctionDisJunction(rOperand, operator);
+ return true;
}
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
index b522c2f1e176..953bbe18e771 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -183,17 +183,19 @@ public class PointlessBooleanExpressionInspection extends BaseInspection {
}
buildSimplifiedExpression(expressions, "==", negate, out);
}
+ else {
+ out.append(expression.getText());
+ }
}
private void buildSimplifiedExpression(List<PsiExpression> expressions, String token, boolean negate, StringBuilder out) {
if (expressions.size() == 1) {
final PsiExpression expression = expressions.get(0);
- final String expressionText = expression.getText();
if (isBoxedTypeComparison(token, expression)) {
- out.append(expressionText).append(" != null && ");
+ out.append(expression.getText()).append(" != null && ");
}
if (!negate) {
- out.append(expressionText);
+ out.append(expression.getText());
return;
}
if (ComparisonUtils.isComparison(expression)) {
@@ -206,10 +208,10 @@ public class PointlessBooleanExpressionInspection extends BaseInspection {
}
else {
if (ParenthesesUtils.getPrecedence(expression) > ParenthesesUtils.PREFIX_PRECEDENCE) {
- out.append("!(").append(expressionText).append(')');
+ out.append("!(").append(expression.getText()).append(')');
}
else {
- out.append('!').append(expressionText);
+ out.append('!').append(expression.getText());
}
}
}
@@ -221,11 +223,19 @@ public class PointlessBooleanExpressionInspection extends BaseInspection {
for (PsiExpression expression : expressions) {
if (useToken) {
out.append(token);
+ final PsiElement previousSibling = expression.getPrevSibling();
+ if (previousSibling instanceof PsiWhiteSpace) {
+ out.append(previousSibling.getText());
+ }
}
else {
useToken = true;
}
buildSimplifiedExpression(expression, out);
+ final PsiElement nextSibling = expression.getNextSibling();
+ if (nextSibling instanceof PsiWhiteSpace) {
+ out.append(nextSibling.getText());
+ }
}
if (negate) {
out.append(')');
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
index 49d523a38e7a..1500f27a01aa 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Jetbrains
+ * Copyright 2011-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.
@@ -20,7 +20,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -63,25 +62,28 @@ public class PointlessNullCheckInspection extends BaseInspection {
@Override
public InspectionGadgetsFix buildFix(Object... infos) {
- return new PointlessNullCheckFix();
+ final PsiExpression expression = (PsiExpression)infos[0];
+ return new PointlessNullCheckFix(expression.getText());
}
private static class PointlessNullCheckFix extends InspectionGadgetsFix {
+ private final String myExpressionText;
+
+ public PointlessNullCheckFix(String expressionText) {
+ myExpressionText = expressionText;
+ }
+
@Override
@NotNull
public String getName() {
- return InspectionGadgetsBundle.message(
- "pointless.nullcheck.simplify.quickfix");
+ return InspectionGadgetsBundle.message("pointless.nullcheck.simplify.quickfix", myExpressionText);
}
@Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ public void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
- final PsiBinaryExpression binaryExpression =
- PsiTreeUtil.getParentOfType(element,
- PsiBinaryExpression.class);
+ final PsiBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(element, PsiBinaryExpression.class);
if (binaryExpression == null) {
return;
}
@@ -164,7 +166,7 @@ public class PointlessNullCheckInspection extends BaseInspection {
if (!referencesEqual(referenceExpression1, referenceExpression2)) {
return;
}
- registerError(binaryExpression);
+ registerError(binaryExpression, binaryExpression);
}
@Nullable
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
index 545e44c3c8f5..5469e57f6b6c 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2012 Bas Leijdekkers
+ * Copyright 2011-2013 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -29,6 +28,7 @@ import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -66,7 +66,7 @@ public class SimplifiableEqualsExpressionInspection extends BaseInspection {
}
@Override
- protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = ParenthesesUtils.getParentSkipParentheses(element);
if (!(parent instanceof PsiPolyadicExpression)) {
@@ -78,11 +78,13 @@ public class SimplifiableEqualsExpressionInspection extends BaseInspection {
return;
}
PsiExpression operand = ParenthesesUtils.stripParentheses(operands[1]);
+ @NonNls final StringBuilder newExpressionText = new StringBuilder();
if (operand instanceof PsiPrefixExpression) {
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)operand;
if (!JavaTokenType.EXCL.equals(prefixExpression.getOperationTokenType())) {
return;
}
+ newExpressionText.append('!');
operand = ParenthesesUtils.stripParentheses(prefixExpression.getOperand());
}
if (!(operand instanceof PsiMethodCallExpression)) {
@@ -102,41 +104,41 @@ public class SimplifiableEqualsExpressionInspection extends BaseInspection {
}
final PsiExpression argument = arguments[0];
final PsiType type = argument.getType();
- final String newQualifierText;
if (PsiType.BOOLEAN.equals(type)) {
final Object value = ExpressionUtils.computeConstantExpression(argument);
if (Boolean.TRUE.equals(value)) {
- newQualifierText = "java.lang.Boolean.TRUE";
+ newExpressionText.append("java.lang.Boolean.TRUE");
}
else if (Boolean.FALSE.equals(value)) {
- newQualifierText = "java.lang.Boolean.FALSE";
+ newExpressionText.append("java.lang.Boolean.FALSE");
}
else {
- newQualifierText = "java.lang.Boolean.valueOf(" + argument.getText() + ")";
+ newExpressionText.append("java.lang.Boolean.valueOf(").append(argument.getText()).append(')');
}
}
else if (PsiType.BYTE.equals(type)) {
- newQualifierText = "java.lang.Byte.valueOf(" + argument.getText() + ')';
+ newExpressionText.append("java.lang.Byte.valueOf(").append(argument.getText()).append(')');
}
else if (PsiType.SHORT.equals(type)) {
- newQualifierText = "java.lang.Short.valueOf(" + argument.getText() + ')';
+ newExpressionText.append("java.lang.Short.valueOf(").append(argument.getText()).append(')');
}
else if (PsiType.INT.equals(type)) {
- newQualifierText = "java.lang.Integer.valueOf(" + argument.getText() + ')';
+ newExpressionText.append("java.lang.Integer.valueOf(").append(argument.getText()).append(')');
}
else if (PsiType.LONG.equals(type)) {
- newQualifierText = "java.lang.Long.valueOf(" + argument.getText() + ')';
+ newExpressionText.append("java.lang.Long.valueOf(").append(argument.getText()).append(')');
}
else if (PsiType.FLOAT.equals(type)) {
- newQualifierText = "java.lang.Float.valueOf(" + argument.getText() + ')';
+ newExpressionText.append("java.lang.Float.valueOf(").append(argument.getText()).append(')');
}
else if (PsiType.DOUBLE.equals(type)) {
- newQualifierText = "java.lang.Double.valueOf(" + argument.getText() + ')';
+ newExpressionText.append("java.lang.Double.valueOf(").append(argument.getText()).append(')');
}
else {
- newQualifierText = argument.getText();
+ newExpressionText.append(argument.getText());
}
- replaceExpression(polyadicExpression, newQualifierText + "." + referenceName + "(" + qualifier.getText() + ")");
+ newExpressionText.append('.').append(referenceName).append('(').append(qualifier.getText()).append(')');
+ replaceExpression(polyadicExpression, newExpressionText.toString());
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java
index 4abf7a9dd66d..9691da48d6a2 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/MakeClassFinalFix.java
@@ -69,6 +69,7 @@ public class MakeClassFinalFix extends InspectionGadgetsFix {
return;
}
modifierList.setModifierProperty(PsiModifier.FINAL, true);
+ modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
return;
}
final MultiMap<PsiElement, String> conflicts = new MultiMap();
@@ -90,6 +91,7 @@ public class MakeClassFinalFix extends InspectionGadgetsFix {
final AccessToken token = WriteAction.start();
try {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
+ modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
}
finally {
token.finish();
@@ -103,6 +105,7 @@ public class MakeClassFinalFix extends InspectionGadgetsFix {
}
if (conflictsDialogOK) {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
+ modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
}
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk/AutoBoxingInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
index 58365dc85ad3..fddeb66b389a 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,20 +17,16 @@ package com.siyeh.ig.jdk;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.lang.StdLanguages;
+import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
-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.psiutils.ClassUtils;
-import com.siyeh.ig.psiutils.ExpectedTypeUtils;
-import com.siyeh.ig.psiutils.MethodCallUtils;
-import com.siyeh.ig.psiutils.TypeUtils;
+import com.siyeh.ig.psiutils.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,8 +45,7 @@ public class AutoBoxingInspection extends BaseInspection {
/**
* @noinspection StaticCollection
*/
- @NonNls static final Map<String, String> s_boxingClasses =
- new HashMap<String, String>(8);
+ @NonNls static final Map<String, String> s_boxingClasses = new HashMap<String, String>(8);
static {
s_boxingClasses.put("byte", CommonClassNames.JAVA_LANG_BYTE);
@@ -85,15 +80,13 @@ public class AutoBoxingInspection extends BaseInspection {
@Override
@NotNull
public String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "auto.boxing.problem.descriptor");
+ return InspectionGadgetsBundle.message("auto.boxing.problem.descriptor");
}
@Override
@Nullable
public JComponent createOptionsPanel() {
- return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
- "auto.boxing.ignore.added.to.collection.option"), this,
+ return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("auto.boxing.ignore.added.to.collection.option"), this,
"ignoreAddedToCollection");
}
@@ -111,17 +104,13 @@ public class AutoBoxingInspection extends BaseInspection {
@NotNull
public String getName() {
- return InspectionGadgetsBundle.message(
- "auto.boxing.make.boxing.explicit.quickfix");
+ return InspectionGadgetsBundle.message("auto.boxing.make.boxing.explicit.quickfix");
}
@Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
- final PsiExpression expression =
- (PsiExpression)descriptor.getPsiElement();
- final PsiType expectedType =
- ExpectedTypeUtils.findExpectedType(expression, false);
+ public void doFix(Project project, ProblemDescriptor descriptor) {
+ final PsiExpression expression = (PsiExpression)descriptor.getPsiElement();
+ final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false);
if (expectedType == null) {
return;
}
@@ -141,7 +130,11 @@ public class AutoBoxingInspection extends BaseInspection {
if (shortcutReplace(expression, classToConstruct)) {
return;
}
- @NonNls final String expressionText = expression.getText();
+ final PsiExpression strippedExpression = ParenthesesUtils.stripParentheses(expression);
+ if (strippedExpression == null) {
+ return;
+ }
+ @NonNls final String expressionText = strippedExpression.getText();
@NonNls final String newExpression;
if ("true".equals(expressionText)) {
newExpression = "java.lang.Boolean.TRUE";
@@ -150,84 +143,59 @@ public class AutoBoxingInspection extends BaseInspection {
newExpression = "java.lang.Boolean.FALSE";
}
else {
- newExpression = classToConstruct + ".valueOf(" +
- expressionText + ')';
+ newExpression = classToConstruct + ".valueOf(" + expressionText + ')';
}
replaceExpression(expression, newExpression);
}
- private static boolean shortcutReplace(PsiExpression expression,
- String classToConstruct) {
+ private static boolean shortcutReplace(PsiExpression expression, String classToConstruct) {
if (!(expression instanceof PsiMethodCallExpression)) {
return false;
}
- final PsiMethodCallExpression methodCallExpression =
- (PsiMethodCallExpression)expression;
- final PsiReferenceExpression methodExpression =
- methodCallExpression.getMethodExpression();
- final PsiExpression qualifierExpression =
- methodExpression.getQualifierExpression();
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+ final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+ final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
if (qualifierExpression == null) {
return false;
}
if (classToConstruct.equals(CommonClassNames.JAVA_LANG_INTEGER)) {
- if (MethodCallUtils.isCallToMethod(methodCallExpression,
- CommonClassNames.JAVA_LANG_INTEGER, PsiType.INT,
- "intValue")) {
+ if (MethodCallUtils.isCallToMethod(methodCallExpression, CommonClassNames.JAVA_LANG_INTEGER, PsiType.INT, "intValue")) {
expression.replace(qualifierExpression);
return true;
}
}
- else if (classToConstruct.equals(
- CommonClassNames.JAVA_LANG_SHORT)) {
- if (MethodCallUtils.isCallToMethod(methodCallExpression,
- CommonClassNames.JAVA_LANG_SHORT, PsiType.SHORT,
- "shortValue")) {
+ else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_SHORT)) {
+ if (MethodCallUtils.isCallToMethod(methodCallExpression, CommonClassNames.JAVA_LANG_SHORT, PsiType.SHORT, "shortValue")) {
expression.replace(qualifierExpression);
return true;
}
}
- else if (classToConstruct.equals(
- CommonClassNames.JAVA_LANG_BYTE)) {
- if (MethodCallUtils.isCallToMethod(methodCallExpression,
- CommonClassNames.JAVA_LANG_BYTE, PsiType.BYTE,
- "byteValue")) {
+ else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_BYTE)) {
+ if (MethodCallUtils.isCallToMethod(methodCallExpression, CommonClassNames.JAVA_LANG_BYTE, PsiType.BYTE, "byteValue")) {
expression.replace(qualifierExpression);
return true;
}
}
- else if (classToConstruct.equals(
- CommonClassNames.JAVA_LANG_CHARACTER)) {
- if (MethodCallUtils.isCallToMethod(methodCallExpression,
- CommonClassNames.JAVA_LANG_CHARACTER, PsiType.CHAR,
- "charValue")) {
+ else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_CHARACTER)) {
+ if (MethodCallUtils.isCallToMethod(methodCallExpression, CommonClassNames.JAVA_LANG_CHARACTER, PsiType.CHAR, "charValue")) {
expression.replace(qualifierExpression);
return true;
}
}
- else if (classToConstruct.equals(
- CommonClassNames.JAVA_LANG_LONG)) {
- if (MethodCallUtils.isCallToMethod(methodCallExpression,
- CommonClassNames.JAVA_LANG_LONG, PsiType.LONG,
- "longValue")) {
+ else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_LONG)) {
+ if (MethodCallUtils.isCallToMethod(methodCallExpression, CommonClassNames.JAVA_LANG_LONG, PsiType.LONG, "longValue")) {
expression.replace(qualifierExpression);
return true;
}
}
- else if (classToConstruct.equals(
- CommonClassNames.JAVA_LANG_FLOAT)) {
- if (MethodCallUtils.isCallToMethod(methodCallExpression,
- CommonClassNames.JAVA_LANG_FLOAT, PsiType.FLOAT,
- "floatValue")) {
+ else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_FLOAT)) {
+ if (MethodCallUtils.isCallToMethod(methodCallExpression, CommonClassNames.JAVA_LANG_FLOAT, PsiType.FLOAT, "floatValue")) {
expression.replace(qualifierExpression);
return true;
}
}
- else if (classToConstruct.equals(
- CommonClassNames.JAVA_LANG_DOUBLE)) {
- if (MethodCallUtils.isCallToMethod(methodCallExpression,
- CommonClassNames.JAVA_LANG_DOUBLE, PsiType.DOUBLE,
- "doubleValue")) {
+ else if (classToConstruct.equals(CommonClassNames.JAVA_LANG_DOUBLE)) {
+ if (MethodCallUtils.isCallToMethod(methodCallExpression, CommonClassNames.JAVA_LANG_DOUBLE, PsiType.DOUBLE, "doubleValue")) {
expression.replace(qualifierExpression);
return true;
}
@@ -240,7 +208,7 @@ public class AutoBoxingInspection extends BaseInspection {
@Override
public void visitElement(PsiElement element) {
- if (element.getLanguage() != StdLanguages.JAVA) {
+ if (element.getLanguage() != JavaLanguage.INSTANCE) {
return;
}
if (!PsiUtil.isLanguageLevel5OrHigher(element)) {
@@ -250,79 +218,74 @@ public class AutoBoxingInspection extends BaseInspection {
}
@Override
- public void visitArrayAccessExpression(
- PsiArrayAccessExpression expression) {
+ public void visitArrayAccessExpression(PsiArrayAccessExpression expression) {
super.visitArrayAccessExpression(expression);
checkExpression(expression);
}
@Override
- public void visitBinaryExpression(
- PsiBinaryExpression expression) {
- super.visitBinaryExpression(expression);
+ public void visitAssignmentExpression(PsiAssignmentExpression expression) {
+ super.visitAssignmentExpression(expression);
checkExpression(expression);
}
@Override
- public void visitConditionalExpression(
- PsiConditionalExpression expression) {
+ public void visitConditionalExpression(PsiConditionalExpression expression) {
super.visitConditionalExpression(expression);
checkExpression(expression);
}
@Override
- public void visitLiteralExpression(
- PsiLiteralExpression expression) {
+ public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
+ super.visitInstanceOfExpression(expression);
+ checkExpression(expression);
+ }
+
+ @Override
+ public void visitLiteralExpression(PsiLiteralExpression expression) {
super.visitLiteralExpression(expression);
checkExpression(expression);
}
@Override
- public void visitPostfixExpression(
- PsiPostfixExpression expression) {
- super.visitPostfixExpression(expression);
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
checkExpression(expression);
}
@Override
- public void visitPrefixExpression(
- PsiPrefixExpression expression) {
- super.visitPrefixExpression(expression);
+ public void visitParenthesizedExpression(PsiParenthesizedExpression expression) {
+ super.visitParenthesizedExpression(expression);
checkExpression(expression);
}
@Override
- public void visitReferenceExpression(
- PsiReferenceExpression expression) {
- super.visitReferenceExpression(expression);
+ public void visitPolyadicExpression(PsiPolyadicExpression expression) {
+ super.visitPolyadicExpression(expression);
checkExpression(expression);
}
@Override
- public void visitMethodCallExpression(
- PsiMethodCallExpression expression) {
- super.visitMethodCallExpression(expression);
+ public void visitPostfixExpression(PsiPostfixExpression expression) {
+ super.visitPostfixExpression(expression);
checkExpression(expression);
}
@Override
- public void visitTypeCastExpression(
- PsiTypeCastExpression expression) {
- super.visitTypeCastExpression(expression);
+ public void visitPrefixExpression(PsiPrefixExpression expression) {
+ super.visitPrefixExpression(expression);
checkExpression(expression);
}
@Override
- public void visitAssignmentExpression(
- PsiAssignmentExpression expression) {
- super.visitAssignmentExpression(expression);
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
+ super.visitReferenceExpression(expression);
checkExpression(expression);
}
@Override
- public void visitParenthesizedExpression(
- PsiParenthesizedExpression expression) {
- super.visitParenthesizedExpression(expression);
+ public void visitTypeCastExpression(PsiTypeCastExpression expression) {
+ super.visitTypeCastExpression(expression);
checkExpression(expression);
}
@@ -331,35 +294,22 @@ public class AutoBoxingInspection extends BaseInspection {
return;
}
final PsiType expressionType = expression.getType();
- if (expressionType == null) {
+ if (expressionType == null || expressionType.equals(PsiType.VOID) || !TypeConversionUtil.isPrimitiveAndNotNull(expressionType)) {
return;
}
- if (expressionType.equals(PsiType.VOID)) {
- return;
- }
- if (!TypeConversionUtil.isPrimitiveAndNotNull(expressionType)) {
- return;
- }
- final PsiPrimitiveType primitiveType =
- (PsiPrimitiveType)expressionType;
- final PsiClassType boxedType =
- primitiveType.getBoxedType(expression);
+ final PsiPrimitiveType primitiveType = (PsiPrimitiveType)expressionType;
+ final PsiClassType boxedType = primitiveType.getBoxedType(expression);
if (boxedType == null) {
return;
}
- final PsiType expectedType =
- ExpectedTypeUtils.findExpectedType(expression, false);
- if (expectedType == null) {
- return;
- }
- if (ClassUtils.isPrimitive(expectedType)) {
+ final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false);
+ if (expectedType == null || ClassUtils.isPrimitive(expectedType)) {
return;
}
if (!expectedType.isAssignableFrom(boxedType)) {
// JLS 5.2 Assignment Conversion
// check if a narrowing primitive conversion is applicable
- if (!(expectedType instanceof PsiClassType) ||
- !PsiUtil.isConstantExpression(expression)) {
+ if (!(expectedType instanceof PsiClassType) || !PsiUtil.isConstantExpression(expression)) {
return;
}
final PsiClassType classType = (PsiClassType)expectedType;
@@ -367,10 +317,8 @@ public class AutoBoxingInspection extends BaseInspection {
if (!convertableBoxedClassNames.contains(className)) {
return;
}
- if (!PsiType.BYTE.equals(expressionType) &&
- !PsiType.CHAR.equals(expressionType) &&
- !PsiType.SHORT.equals(expressionType) &&
- !PsiType.INT.equals(expressionType)) {
+ if (!PsiType.BYTE.equals(expressionType) && !PsiType.CHAR.equals(expressionType) &&
+ !PsiType.SHORT.equals(expressionType) && !PsiType.INT.equals(expressionType)) {
return;
}
}
@@ -390,21 +338,14 @@ public class AutoBoxingInspection extends BaseInspection {
if (!(grandParent instanceof PsiMethodCallExpression)) {
return false;
}
- final PsiMethodCallExpression methodCallExpression =
- (PsiMethodCallExpression)grandParent;
- final PsiReferenceExpression methodExpression =
- methodCallExpression.getMethodExpression();
- @NonNls final String methodName =
- methodExpression.getReferenceName();
- if (!"put".equals(methodName) && !"set".equals(methodName) &&
- !"add".equals(methodName)) {
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)grandParent;
+ final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+ @NonNls final String methodName = methodExpression.getReferenceName();
+ if (!"put".equals(methodName) && !"set".equals(methodName) && !"add".equals(methodName)) {
return false;
}
- final PsiExpression qualifier =
- methodExpression.getQualifierExpression();
- return TypeUtils.expressionHasTypeOrSubtype(qualifier,
- CommonClassNames.JAVA_UTIL_COLLECTION,
- CommonClassNames.JAVA_UTIL_MAP) != null;
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
+ return TypeUtils.expressionHasTypeOrSubtype(qualifier, CommonClassNames.JAVA_UTIL_COLLECTION, CommonClassNames.JAVA_UTIL_MAP) != null;
}
}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk/ForeachStatementInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
index 564e93955541..ecbb3a369540 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -21,6 +21,7 @@ import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -137,6 +138,10 @@ public class ForeachStatementInspection extends BaseInspection {
@Override
public void visitForeachStatement(@NotNull PsiForeachStatement statement) {
super.visitForeachStatement(statement);
+ final PsiExpression iteratedValue = statement.getIteratedValue();
+ if (iteratedValue == null || !InheritanceUtil.isInheritor(iteratedValue.getType(), CommonClassNames.JAVA_LANG_ITERABLE)) {
+ return;
+ }
registerStatementError(statement);
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java
index 8a773ed83bf9..95a1b73e0a11 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LogStatementGuardedByLogConditionInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2012 Bas Leijdekkers
+ * Copyright 2008-2013 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.ui.CheckBox;
import com.intellij.util.ui.FormBuilder;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -57,6 +58,9 @@ public class LogStatementGuardedByLogConditionInspection extends BaseInspection
final List<String> logMethodNameList = new ArrayList();
final List<String> logConditionMethodNameList = new ArrayList();
+ @SuppressWarnings("PublicField")
+ public boolean flagAllUnguarded = false;
+
public LogStatementGuardedByLogConditionInspection() {
parseString(loggerMethodAndconditionMethodNames, logMethodNameList, logConditionMethodNameList);
}
@@ -84,6 +88,8 @@ public class LogStatementGuardedByLogConditionInspection extends BaseInspection
InspectionGadgetsBundle.message("log.condition.text")));
panel.add(UiUtils.createAddRemovePanel(table), BorderLayout.CENTER);
panel.add(FormBuilder.createFormBuilder().addLabeledComponent(classNameLabel, loggerClassNameField).getPanel(), BorderLayout.NORTH);
+ panel.add(new CheckBox(InspectionGadgetsBundle.message("log.statement.guarded.by.log.condition.flag.all.unguarded.option"),
+ this, "flagAllUnguarded"), BorderLayout.SOUTH);
return panel;
}
@@ -215,9 +221,17 @@ public class LogStatementGuardedByLogConditionInspection extends BaseInspection
if (arguments.length == 0) {
return;
}
- final PsiExpression firstArgument = arguments[0];
- if (PsiUtil.isConstantExpression(firstArgument)) {
- return;
+ if (!flagAllUnguarded) {
+ boolean constant = true;
+ for (PsiExpression argument : arguments) {
+ if (!PsiUtil.isConstantExpression(argument)) {
+ constant = false;
+ break;
+ }
+ }
+ if (constant) {
+ return;
+ }
}
registerMethodCallError(expression);
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java
new file mode 100644
index 000000000000..0a6ef31fcc7e
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2013 Bas Leijdekkers
+ *
+ * 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.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.util.containers.ContainerUtilRt;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.ExpressionUtils;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+public class PlaceholderCountMatchesArgumentCountInspection extends BaseInspection {
+
+ @NonNls
+ private static final Set<String> loggingMethodNames = ContainerUtilRt.newHashSet("trace", "debug", "info", "warn", "error");
+
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("placeholder.count.matches.argument.count.display.name");
+ }
+
+ @NotNull
+ @Override
+ protected String buildErrorString(Object... infos) {
+ final int argumentCount = ((Integer)infos[0]).intValue();
+ final int placeholderCount = ((Integer)infos[1]).intValue();
+ if (argumentCount > placeholderCount) {
+ return InspectionGadgetsBundle.message("placeholder.count.matches.argument.count.more.problem.descriptor",
+ argumentCount, placeholderCount);
+ }
+ else {
+ return InspectionGadgetsBundle.message("placeholder.count.matches.argument.count.fewer.problem.descriptor",
+ argumentCount, placeholderCount);
+ }
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new PlaceholderCountMatchesArgumentCountVisitor();
+ }
+
+ private static class PlaceholderCountMatchesArgumentCountVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+ final String name = methodExpression.getReferenceName();
+ if (!loggingMethodNames.contains(name)) {
+ return;
+ }
+ final PsiExpressionList argumentList = expression.getArgumentList();
+ final PsiExpression[] arguments = argumentList.getExpressions();
+ if (arguments.length == 0) {
+ return;
+ }
+ final PsiExpression firstArgument = arguments[0];
+ final int placeholderCount;
+ final int argumentCount;
+ if (InheritanceUtil.isInheritor(firstArgument.getType(), "org.slf4j.Marker")) {
+ if (arguments.length < 2) {
+ return;
+ }
+ final PsiExpression secondArgument = arguments[1];
+ if (!ExpressionUtils.hasStringType(secondArgument)) {
+ return;
+ }
+ final String value = (String)ExpressionUtils.computeConstantExpression(secondArgument);
+ if (value == null) {
+ return;
+ }
+ placeholderCount = countPlaceholders(value);
+ argumentCount = hasThrowableType(arguments[arguments.length - 1]) ? arguments.length - 3 : arguments.length - 2;
+ }
+ else if (ExpressionUtils.hasStringType(firstArgument)) {
+ final String value = (String)ExpressionUtils.computeConstantExpression(firstArgument);
+ if (value == null) {
+ return;
+ }
+ placeholderCount = countPlaceholders(value);
+ argumentCount = hasThrowableType(arguments[arguments.length - 1]) ? arguments.length - 2 : arguments.length - 1;
+ } else {
+ return;
+ }
+ if (placeholderCount == argumentCount) {
+ return;
+ }
+ registerMethodCallError(expression, argumentCount, placeholderCount);
+ }
+
+ private static boolean hasThrowableType(PsiExpression lastArgument) {
+ return InheritanceUtil.isInheritor(lastArgument.getType(), "java.lang.Throwable");
+ }
+
+ public static int countPlaceholders(String value) {
+ int count = 0;
+ int index = value.indexOf("{}");
+ while (index >= 0) {
+ if (index <= 0 || value.charAt(index - 1) != '\\') {
+ count++;
+ }
+ index = value.indexOf("{}", index + 1);
+ }
+ return count;
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
index 85adba71c3bc..4c96475dd177 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,9 +25,11 @@ import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ExpressionUtils;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import gnu.trove.THashSet;
import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,6 +42,7 @@ import java.util.Set;
*/
public class StringConcatenationArgumentToLogCallInspection extends BaseInspection {
+ @NonNls
private static final Set<String> logNames = new THashSet<String>();
static {
logNames.add("trace");
@@ -95,8 +98,8 @@ public class StringConcatenationArgumentToLogCallInspection extends BaseInspecti
if (arguments.length == 0) {
return;
}
- final StringBuilder newMethodCall = new StringBuilder(methodCallExpression.getMethodExpression().getText());
- newMethodCall.append("(");
+ @NonNls final StringBuilder newMethodCall = new StringBuilder(methodCallExpression.getMethodExpression().getText());
+ newMethodCall.append('(');
PsiExpression argument = arguments[0];
int usedArguments;
if (!(argument instanceof PsiPolyadicExpression)) {
@@ -137,11 +140,11 @@ public class StringConcatenationArgumentToLogCallInspection extends BaseInspecti
boolean inStringLiteral = false;
for (PsiExpression operand : operands) {
if (ExpressionUtils.isEvaluatedAtCompileTime(operand)) {
- if (ExpressionUtils.hasStringType(operand)) {
+ if (ExpressionUtils.hasStringType(operand) && operand instanceof PsiLiteralExpression) {
final String text = operand.getText();
final int count = StringUtil.getOccurrenceCount(text, "{}");
for (int i = 0; i < count && usedArguments + i < arguments.length; i++) {
- newArguments.add((PsiExpression)arguments[i + usedArguments].copy());
+ newArguments.add(ParenthesesUtils.stripParentheses((PsiExpression)arguments[i + usedArguments].copy()));
}
usedArguments += count;
if (!inStringLiteral) {
@@ -165,7 +168,7 @@ public class StringConcatenationArgumentToLogCallInspection extends BaseInspecti
}
}
else {
- newArguments.add((PsiExpression)operand.copy());
+ newArguments.add(ParenthesesUtils.stripParentheses((PsiExpression)operand.copy()));
if (!inStringLiteral) {
if (addPlus) {
newMethodCall.append('+');
@@ -193,13 +196,18 @@ public class StringConcatenationArgumentToLogCallInspection extends BaseInspecti
else {
comma =true;
}
- newMethodCall.append(newArgument.getText());
+ if (newArgument != null) {
+ newMethodCall.append(newArgument.getText());
+ }
}
newMethodCall.append('}');
}
else {
for (PsiExpression newArgument : newArguments) {
- newMethodCall.append(',').append(newArgument.getText());
+ newMethodCall.append(',');
+ if (newArgument != null) {
+ newMethodCall.append(newArgument.getText());
+ }
}
}
newMethodCall.append(')');
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
index 743f5b98f49d..c5a57122701d 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Bas Leijdekkers
+ * Copyright 2011-2013 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,19 +15,20 @@
*/
package com.siyeh.ig.migration;
+import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.DocumentAdapter;
-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.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.SwitchUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
@@ -71,8 +72,7 @@ public class IfCanBeSwitchInspection extends BaseInspection {
@NotNull
@Override
protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "if.can.be.switch.problem.descriptor");
+ return InspectionGadgetsBundle.message("if.can.be.switch.problem.descriptor");
}
@Override
@@ -83,12 +83,10 @@ public class IfCanBeSwitchInspection extends BaseInspection {
@Override
public JComponent createOptionsPanel() {
final JPanel panel = new JPanel(new GridBagLayout());
- final JLabel label = new JLabel(InspectionGadgetsBundle.message(
- "if.can.be.switch.minimum.branch.option"));
+ final JLabel label = new JLabel(InspectionGadgetsBundle.message("if.can.be.switch.minimum.branch.option"));
final NumberFormat formatter = NumberFormat.getIntegerInstance();
formatter.setParseIntegerOnly(true);
- final JFormattedTextField valueField =
- new JFormattedTextField(formatter);
+ final JFormattedTextField valueField = new JFormattedTextField(formatter);
valueField.setValue(Integer.valueOf(minimumBranches));
valueField.setColumns(2);
final Document document = valueField.getDocument();
@@ -122,9 +120,7 @@ public class IfCanBeSwitchInspection extends BaseInspection {
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 2;
- final JCheckBox checkBox1 = new JCheckBox(
- InspectionGadgetsBundle.message("if.can.be.switch.int.option"),
- suggestIntSwitches);
+ final JCheckBox checkBox1 = new JCheckBox(InspectionGadgetsBundle.message("if.can.be.switch.int.option"), suggestIntSwitches);
final ButtonModel model1 = checkBox1.getModel();
model1.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
@@ -134,9 +130,7 @@ public class IfCanBeSwitchInspection extends BaseInspection {
panel.add(checkBox1, constraints);
constraints.gridy = 2;
constraints.weighty = 1.0;
- final JCheckBox checkBox2 = new JCheckBox(
- InspectionGadgetsBundle.message("if.can.be.switch.enum.option"),
- suggestEnumSwitches);
+ final JCheckBox checkBox2 = new JCheckBox(InspectionGadgetsBundle.message("if.can.be.switch.enum.option"), suggestEnumSwitches);
final ButtonModel model2 = checkBox2.getModel();
model2.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
@@ -160,8 +154,7 @@ public class IfCanBeSwitchInspection extends BaseInspection {
}
@Override
- protected void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement().getParent();
if (!(element instanceof PsiIfStatement)) {
return;
@@ -171,41 +164,31 @@ public class IfCanBeSwitchInspection extends BaseInspection {
PsiStatement breakTarget = null;
String labelString = "";
if (ControlFlowUtils.statementContainsNakedBreak(ifStatement)) {
- breakTarget = PsiTreeUtil.getParentOfType(ifStatement,
- PsiLoopStatement.class, PsiSwitchStatement.class);
+ breakTarget = PsiTreeUtil.getParentOfType(ifStatement, PsiLoopStatement.class, PsiSwitchStatement.class);
if (breakTarget != null) {
final PsiElement parent = breakTarget.getParent();
if (parent instanceof PsiLabeledStatement) {
- final PsiLabeledStatement labeledStatement =
- (PsiLabeledStatement)parent;
- labelString =
- labeledStatement.getLabelIdentifier().getText();
+ final PsiLabeledStatement labeledStatement = (PsiLabeledStatement)parent;
+ labelString = labeledStatement.getLabelIdentifier().getText();
breakTarget = labeledStatement;
breaksNeedRelabeled = true;
}
else {
- labelString =
- SwitchUtils.findUniqueLabelName(ifStatement,
- "label");
+ labelString = SwitchUtils.findUniqueLabelName(ifStatement, "label");
breaksNeedRelabeled = true;
}
}
}
final PsiIfStatement statementToReplace = ifStatement;
-
- final List<IfStatementBranch> branches =
- new ArrayList<IfStatementBranch>(20);
- final PsiExpression switchExpression =
- SwitchUtils.getSwitchExpression(ifStatement,
- myMinimumBranches);
+ final PsiExpression switchExpression = SwitchUtils.getSwitchExpression(ifStatement, myMinimumBranches);
if (switchExpression == null) {
return;
}
+ final List<IfStatementBranch> branches = new ArrayList<IfStatementBranch>(20);
while (true) {
final PsiExpression condition = ifStatement.getCondition();
final PsiStatement thenBranch = ifStatement.getThenBranch();
- final IfStatementBranch ifBranch =
- new IfStatementBranch(thenBranch, false);
+ final IfStatementBranch ifBranch = new IfStatementBranch(thenBranch, false);
extractCaseExpressions(condition, switchExpression, ifBranch);
if (!branches.isEmpty()) {
extractIfComments(ifStatement, ifBranch);
@@ -220,8 +203,7 @@ public class IfCanBeSwitchInspection extends BaseInspection {
break;
}
else {
- final IfStatementBranch elseIfBranch =
- new IfStatementBranch(elseBranch, true);
+ final IfStatementBranch elseIfBranch = new IfStatementBranch(elseBranch, true);
final PsiKeyword elseKeyword = ifStatement.getElseElement();
extractIfComments(elseKeyword, elseIfBranch);
extractStatementComments(elseBranch, elseIfBranch);
@@ -230,14 +212,10 @@ public class IfCanBeSwitchInspection extends BaseInspection {
}
}
- @NonNls final StringBuilder switchStatementText =
- new StringBuilder();
- switchStatementText.append("switch(");
- switchStatementText.append(switchExpression.getText());
- switchStatementText.append("){");
+ @NonNls final StringBuilder switchStatementText = new StringBuilder();
+ switchStatementText.append("switch(").append(switchExpression.getText()).append("){");
final PsiType type = switchExpression.getType();
- final boolean castToInt = type != null &&
- type.equalsToText(CommonClassNames.JAVA_LANG_INTEGER);
+ final boolean castToInt = type != null && type.equalsToText(CommonClassNames.JAVA_LANG_INTEGER);
for (IfStatementBranch branch : branches) {
boolean hasConflicts = false;
for (IfStatementBranch testBranch : branches) {
@@ -248,40 +226,30 @@ public class IfCanBeSwitchInspection extends BaseInspection {
hasConflicts = true;
}
}
- dumpBranch(branch, castToInt, hasConflicts, breaksNeedRelabeled,
- labelString, switchStatementText);
+ dumpBranch(branch, castToInt, hasConflicts, breaksNeedRelabeled, labelString, switchStatementText);
}
switchStatementText.append('}');
- final JavaPsiFacade psiFacade =
- JavaPsiFacade.getInstance(element.getProject());
+ final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(element.getProject());
final PsiElementFactory factory = psiFacade.getElementFactory();
if (breaksNeedRelabeled) {
final StringBuilder out = new StringBuilder();
if (!(breakTarget instanceof PsiLabeledStatement)) {
- out.append(labelString);
- out.append(':');
+ out.append(labelString).append(':');
}
- termReplace(out, breakTarget, statementToReplace,
- switchStatementText);
+ termReplace(breakTarget, statementToReplace, switchStatementText, out);
final String newStatementText = out.toString();
- final PsiStatement newStatement =
- factory.createStatementFromText(newStatementText,
- element);
+ final PsiStatement newStatement = factory.createStatementFromText(newStatementText, element);
breakTarget.replace(newStatement);
}
else {
- final PsiStatement newStatement =
- factory.createStatementFromText(
- switchStatementText.toString(), element);
+ final PsiStatement newStatement = factory.createStatementFromText(switchStatementText.toString(), element);
statementToReplace.replace(newStatement);
}
}
@Nullable
- public static <T extends PsiElement> T getPrevSiblingOfType(
- @Nullable PsiElement element,
- @NotNull Class<T> aClass,
- @NotNull Class<? extends PsiElement>... stopAt) {
+ public static <T extends PsiElement> T getPrevSiblingOfType(@Nullable PsiElement element, @NotNull Class<T> aClass,
+ @NotNull Class<? extends PsiElement>... stopAt) {
if (element == null) {
return null;
}
@@ -297,18 +265,15 @@ public class IfCanBeSwitchInspection extends BaseInspection {
return (T)sibling;
}
- private static void extractIfComments(PsiElement element,
- IfStatementBranch out) {
- PsiComment comment = getPrevSiblingOfType(element,
- PsiComment.class, PsiStatement.class);
+ private static void extractIfComments(PsiElement element, IfStatementBranch out) {
+ PsiComment comment = getPrevSiblingOfType(element, PsiComment.class, PsiStatement.class);
while (comment != null) {
final PsiElement sibling = comment.getPrevSibling();
final String commentText;
if (sibling instanceof PsiWhiteSpace) {
final String whiteSpaceText = sibling.getText();
if (whiteSpaceText.startsWith("\n")) {
- commentText = whiteSpaceText.substring(1) +
- comment.getText();
+ commentText = whiteSpaceText.substring(1) + comment.getText();
}
else {
commentText = comment.getText();
@@ -318,23 +283,19 @@ public class IfCanBeSwitchInspection extends BaseInspection {
commentText = comment.getText();
}
out.addComment(commentText);
- comment = getPrevSiblingOfType(comment, PsiComment.class,
- PsiStatement.class);
+ comment = getPrevSiblingOfType(comment, PsiComment.class, PsiStatement.class);
}
}
- private static void extractStatementComments(PsiElement element,
- IfStatementBranch out) {
- PsiComment comment = getPrevSiblingOfType(element,
- PsiComment.class, PsiStatement.class, PsiKeyword.class);
+ private static void extractStatementComments(PsiElement element, IfStatementBranch out) {
+ PsiComment comment = getPrevSiblingOfType(element, PsiComment.class, PsiStatement.class, PsiKeyword.class);
while (comment != null) {
final PsiElement sibling = comment.getPrevSibling();
final String commentText;
if (sibling instanceof PsiWhiteSpace) {
final String whiteSpaceText = sibling.getText();
if (whiteSpaceText.startsWith("\n")) {
- commentText = whiteSpaceText.substring(1) +
- comment.getText();
+ commentText = whiteSpaceText.substring(1) + comment.getText();
}
else {
commentText = comment.getText();
@@ -344,14 +305,11 @@ public class IfCanBeSwitchInspection extends BaseInspection {
commentText = comment.getText();
}
out.addStatementComment(commentText);
- comment = getPrevSiblingOfType(comment, PsiComment.class,
- PsiStatement.class, PsiKeyword.class);
+ comment = getPrevSiblingOfType(comment, PsiComment.class, PsiStatement.class, PsiKeyword.class);
}
}
- private static void termReplace(
- StringBuilder out, PsiElement target,
- PsiElement replace, StringBuilder stringToReplaceWith) {
+ private static void termReplace(PsiElement target, PsiElement replace, StringBuilder stringToReplaceWith, StringBuilder out) {
if (target.equals(replace)) {
out.append(stringToReplaceWith);
}
@@ -361,95 +319,75 @@ public class IfCanBeSwitchInspection extends BaseInspection {
else {
final PsiElement[] children = target.getChildren();
for (final PsiElement child : children) {
- termReplace(out, child, replace, stringToReplaceWith);
+ termReplace(child, replace, stringToReplaceWith, out);
}
}
}
- private static void extractCaseExpressions(
- PsiExpression expression, PsiExpression switchExpression,
- IfStatementBranch values) {
+ private static void extractCaseExpressions(PsiExpression expression, PsiExpression switchExpression, IfStatementBranch branch) {
if (expression instanceof PsiMethodCallExpression) {
- final PsiMethodCallExpression methodCallExpression =
- (PsiMethodCallExpression)expression;
- final PsiExpressionList argumentList =
- methodCallExpression.getArgumentList();
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+ final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
final PsiExpression argument = arguments[0];
- final PsiReferenceExpression methodExpression =
- methodCallExpression.getMethodExpression();
- final PsiExpression qualifierExpression =
- methodExpression.getQualifierExpression();
- if (EquivalenceChecker.expressionsAreEquivalent(switchExpression,
- argument)) {
- values.addCaseExpression(qualifierExpression);
+ final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+ final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
+ if (EquivalenceChecker.expressionsAreEquivalent(switchExpression, argument)) {
+ branch.addCaseExpression(qualifierExpression);
}
else {
- values.addCaseExpression(argument);
+ branch.addCaseExpression(argument);
}
}
- else if (expression instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final PsiExpression lhs = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
- final IElementType tokenType = binaryExpression.getOperationTokenType();
+ else if (expression instanceof PsiPolyadicExpression) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ final IElementType tokenType = polyadicExpression.getOperationTokenType();
if (JavaTokenType.OROR.equals(tokenType)) {
- extractCaseExpressions(lhs, switchExpression,
- values);
- extractCaseExpressions(rhs, switchExpression,
- values);
+ for (PsiExpression operand : operands) {
+ extractCaseExpressions(operand, switchExpression, branch);
+ }
}
- else {
- if (EquivalenceChecker.expressionsAreEquivalent(
- switchExpression, rhs)) {
- values.addCaseExpression(lhs);
+ else if (operands.length == 2) {
+ final PsiExpression lhs = operands[0];
+ final PsiExpression rhs = operands[1];
+ if (EquivalenceChecker.expressionsAreEquivalent(switchExpression, rhs)) {
+ branch.addCaseExpression(lhs);
}
else {
- values.addCaseExpression(rhs);
+ branch.addCaseExpression(rhs);
}
}
}
else if (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- final PsiExpression contents =
- parenthesizedExpression.getExpression();
- extractCaseExpressions(contents, switchExpression, values);
+ final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
+ final PsiExpression contents = parenthesizedExpression.getExpression();
+ extractCaseExpressions(contents, switchExpression, branch);
}
}
- private static void dumpBranch(
- IfStatementBranch branch, boolean castToInt, boolean wrap,
- boolean renameBreaks, String breakLabelName,
- @NonNls StringBuilder switchStatementText) {
+ private static void dumpBranch(IfStatementBranch branch, boolean castToInt, boolean wrap, boolean renameBreaks, String breakLabelName,
+ @NonNls StringBuilder switchStatementText) {
dumpComments(branch.getComments(), switchStatementText);
if (branch.isElse()) {
switchStatementText.append("default: ");
}
else {
- for (PsiExpression caseExpression : branch.getConditions()) {
- switchStatementText.append("case ");
- switchStatementText.append(getCaseLabelText(caseExpression,
- castToInt));
- switchStatementText.append(": ");
+ for (PsiExpression caseExpression : branch.getCaseExpressions()) {
+ switchStatementText.append("case ").append(getCaseLabelText(caseExpression, castToInt)).append(": ");
}
}
dumpComments(branch.getStatementComments(), switchStatementText);
- dumpBody(branch.getStatement(), wrap, renameBreaks, breakLabelName,
- switchStatementText);
+ dumpBody(branch.getStatement(), wrap, renameBreaks, breakLabelName, switchStatementText);
}
@NonNls
- private static String getCaseLabelText(PsiExpression expression,
- boolean castToInt) {
+ private static String getCaseLabelText(PsiExpression expression, boolean castToInt) {
if (expression instanceof PsiReferenceExpression) {
- final PsiReferenceExpression referenceExpression =
- (PsiReferenceExpression)expression;
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiElement target = referenceExpression.resolve();
if (target instanceof PsiEnumConstant) {
- final PsiEnumConstant enumConstant =
- (PsiEnumConstant)target;
+ final PsiEnumConstant enumConstant = (PsiEnumConstant)target;
return enumConstant.getName();
}
}
@@ -470,42 +408,34 @@ public class IfCanBeSwitchInspection extends BaseInspection {
return expression.getText();
}
- private static void dumpComments(List<String> comments,
- StringBuilder switchStatementText) {
+ private static void dumpComments(List<String> comments, StringBuilder switchStatementText) {
if (comments.isEmpty()) {
return;
}
switchStatementText.append('\n');
for (String comment : comments) {
- switchStatementText.append(comment);
- switchStatementText.append('\n');
+ switchStatementText.append(comment).append('\n');
}
}
- private static void dumpBody(
- PsiStatement bodyStatement, boolean wrap, boolean renameBreaks,
- String breakLabelName,
- @NonNls StringBuilder switchStatementText) {
+ private static void dumpBody(PsiStatement bodyStatement, boolean wrap, boolean renameBreaks, String breakLabelName,
+ @NonNls StringBuilder switchStatementText) {
if (wrap) {
switchStatementText.append('{');
}
if (bodyStatement instanceof PsiBlockStatement) {
- final PsiCodeBlock codeBlock =
- ((PsiBlockStatement)bodyStatement).getCodeBlock();
+ final PsiCodeBlock codeBlock = ((PsiBlockStatement)bodyStatement).getCodeBlock();
final PsiElement[] children = codeBlock.getChildren();
//skip the first and last members, to unwrap the block
for (int i = 1; i < children.length - 1; i++) {
final PsiElement child = children[i];
- appendElement(switchStatementText, child, renameBreaks,
- breakLabelName);
+ appendElement(child, renameBreaks, breakLabelName, switchStatementText);
}
}
else {
- appendElement(switchStatementText, bodyStatement,
- renameBreaks, breakLabelName);
+ appendElement(bodyStatement, renameBreaks, breakLabelName, switchStatementText);
}
- if (ControlFlowUtils.statementMayCompleteNormally(
- bodyStatement)) {
+ if (ControlFlowUtils.statementMayCompleteNormally(bodyStatement)) {
switchStatementText.append("break;");
}
if (wrap) {
@@ -513,38 +443,44 @@ public class IfCanBeSwitchInspection extends BaseInspection {
}
}
- private static void appendElement(
- @NonNls StringBuilder switchStatementText,
- PsiElement element, boolean renameBreakElements,
- String breakLabelString) {
+ private static void appendElement(PsiElement element, boolean renameBreakElements, String breakLabelString,
+ @NonNls StringBuilder switchStatementText) {
final String text = element.getText();
if (!renameBreakElements) {
switchStatementText.append(text);
}
else if (element instanceof PsiBreakStatement) {
- final PsiIdentifier identifier =
- ((PsiBreakStatement)element).getLabelIdentifier();
+ final PsiBreakStatement breakStatement = (PsiBreakStatement)element;
+ final PsiIdentifier identifier = breakStatement.getLabelIdentifier();
if (identifier == null) {
- switchStatementText.append("break ");
- switchStatementText.append(breakLabelString);
- switchStatementText.append(';');
+ switchStatementText.append("break ").append(breakLabelString).append(';');
}
else {
switchStatementText.append(text);
}
}
- else if (element instanceof PsiBlockStatement ||
- element instanceof PsiCodeBlock ||
- element instanceof PsiIfStatement) {
+ else if (element instanceof PsiBlockStatement || element instanceof PsiCodeBlock || element instanceof PsiIfStatement) {
final PsiElement[] children = element.getChildren();
for (final PsiElement child : children) {
- appendElement(switchStatementText, child,
- renameBreakElements, breakLabelString);
+ appendElement(child, renameBreakElements, breakLabelString, switchStatementText);
}
}
else {
switchStatementText.append(text);
}
+ final PsiElement lastChild = element.getLastChild();
+ if (isEndOfLineComment(lastChild)) {
+ switchStatementText.append('\n');
+ }
+ }
+
+ private static boolean isEndOfLineComment(PsiElement element) {
+ if (!(element instanceof PsiComment)) {
+ return false;
+ }
+ final PsiComment comment = (PsiComment)element;
+ final IElementType tokenType = comment.getTokenType();
+ return JavaTokenType.END_OF_LINE_COMMENT.equals(tokenType);
}
}
@@ -562,11 +498,18 @@ public class IfCanBeSwitchInspection extends BaseInspection {
if (parent instanceof PsiIfStatement) {
return;
}
- final PsiExpression switchExpression =
- SwitchUtils.getSwitchExpression(statement, minimumBranches);
+ final PsiExpression switchExpression = SwitchUtils.getSwitchExpression(statement, minimumBranches);
if (switchExpression == null) {
return;
}
+ final PsiExpression unwrappedExpression = ParenthesesUtils.stripParentheses(switchExpression);
+ if (unwrappedExpression instanceof PsiReferenceExpression) {
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)unwrappedExpression;
+ final PsiElement target = referenceExpression.resolve();
+ if (target instanceof PsiModifierListOwner && NullableNotNullManager.isNullable((PsiModifierListOwner)target)) {
+ return;
+ }
+ }
final PsiType type = switchExpression.getType();
if (!suggestIntSwitches) {
if (type instanceof PsiClassType) {
@@ -577,10 +520,7 @@ public class IfCanBeSwitchInspection extends BaseInspection {
return;
}
}
- else if (PsiType.INT.equals(type) ||
- PsiType.SHORT.equals(type) ||
- PsiType.BYTE.equals(type) ||
- PsiType.CHAR.equals(type)) {
+ else if (PsiType.INT.equals(type) || PsiType.SHORT.equals(type) || PsiType.BYTE.equals(type) || PsiType.CHAR.equals(type)) {
return;
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfStatementBranch.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfStatementBranch.java
index 6d5513ac4d3f..2efb2a90f817 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfStatementBranch.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/IfStatementBranch.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -24,7 +24,7 @@ class IfStatementBranch {
private final Set<String> topLevelVariables = new HashSet<String>(3);
private final LinkedList<String> comments = new LinkedList<String>();
private final LinkedList<String> statementComments = new LinkedList<String>();
- private final List<PsiExpression> conditions = new ArrayList<PsiExpression>(3);
+ private final List<PsiExpression> caseExpressions = new ArrayList<PsiExpression>(3);
private final PsiStatement statement;
private final boolean elseBranch;
@@ -43,29 +43,27 @@ class IfStatementBranch {
}
public void addCaseExpression(PsiExpression expression) {
- conditions.add(expression);
+ caseExpressions.add(expression);
}
public PsiStatement getStatement() {
return statement;
}
- public List<PsiExpression> getConditions() {
- return Collections.unmodifiableList(conditions);
+ public List<PsiExpression> getCaseExpressions() {
+ return Collections.unmodifiableList(caseExpressions);
}
public boolean isElse() {
return elseBranch;
}
- public boolean topLevelDeclarationsConflictWith(
- IfStatementBranch testBranch) {
+ public boolean topLevelDeclarationsConflictWith(IfStatementBranch testBranch) {
final Set<String> topLevel = testBranch.topLevelVariables;
return intersects(topLevelVariables, topLevel);
}
- private static boolean intersects(Set<String> set1,
- Set<String> set2) {
+ private static boolean intersects(Set<String> set1, Set<String> set2) {
for (final String s : set1) {
if (set2.contains(s)) {
return true;
@@ -87,10 +85,8 @@ class IfStatementBranch {
return;
}
if (statement instanceof PsiDeclarationStatement) {
- final PsiDeclarationStatement declarationStatement =
- (PsiDeclarationStatement)statement;
- final PsiElement[] elements =
- declarationStatement.getDeclaredElements();
+ final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)statement;
+ final PsiElement[] elements = declarationStatement.getDeclaredElements();
for (PsiElement element : elements) {
final PsiVariable variable = (PsiVariable)element;
final String varName = variable.getName();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
index 1c171d52fc5d..f4ea3c7365a2 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Bas Leijdekkers
+ * Copyright 2011-2013 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,11 @@
package com.siyeh.ig.migration;
import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
+import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -36,26 +36,30 @@ public class MethodCanBeVariableArityMethodInspection extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean ignoreByteAndShortArrayParameters = false;
+ @SuppressWarnings("PublicField")
+ public boolean ignoreOverridingMethods = false;
+
@Nls
@NotNull
@Override
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "method.can.be.variable.arity.method.display.name");
+ return InspectionGadgetsBundle.message("method.can.be.variable.arity.method.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "method.can.be.variable.arity.method.problem.descriptor");
+ return InspectionGadgetsBundle.message("method.can.be.variable.arity.method.problem.descriptor");
}
@Override
public JComponent createOptionsPanel() {
- return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
- "method.can.be.variable.arity.method.ignore.byte.short.option"),
- this, "ignoreByteAndShortArrayParameters");
+ final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
+ panel.addCheckbox(InspectionGadgetsBundle.message("method.can.be.variable.arity.method.ignore.byte.short.option"),
+ "ignoreByteAndShortArrayParameters");
+ panel.addCheckbox(InspectionGadgetsBundle.message("method.can.be.variable.arity.method.ignore.overriding.methods"),
+ "ignoreOverridingMethods");
+ return panel;
}
@Override
@@ -63,19 +67,16 @@ public class MethodCanBeVariableArityMethodInspection extends BaseInspection {
return new MethodCanBeVariableArityMethodFix();
}
- private static class MethodCanBeVariableArityMethodFix
- extends InspectionGadgetsFix {
+ private static class MethodCanBeVariableArityMethodFix extends InspectionGadgetsFix {
@NotNull
@Override
public String getName() {
- return InspectionGadgetsBundle.message(
- "convert.to.variable.arity.method.quickfix");
+ return InspectionGadgetsBundle.message("convert.to.variable.arity.method.quickfix");
}
@Override
- protected void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
if (!(parent instanceof PsiMethod)) {
@@ -87,19 +88,15 @@ public class MethodCanBeVariableArityMethodInspection extends BaseInspection {
return;
}
final PsiParameter[] parameters = parameterList.getParameters();
- final PsiParameter lastParameter =
- parameters[parameters.length - 1];
+ final PsiParameter lastParameter = parameters[parameters.length - 1];
final PsiType type = lastParameter.getType();
if (!(type instanceof PsiArrayType)) {
return;
}
final PsiArrayType arrayType = (PsiArrayType)type;
final PsiType componentType = arrayType.getComponentType();
- final PsiElementFactory factory =
- JavaPsiFacade.getElementFactory(project);
- final PsiTypeElement newTypeElement =
- factory.createTypeElementFromText(
- componentType.getCanonicalText() + "...", method);
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
+ final PsiTypeElement newTypeElement = factory.createTypeElementFromText(componentType.getCanonicalText() + "...", method);
final PsiTypeElement typeElement = lastParameter.getTypeElement();
if (typeElement != null) {
typeElement.replace(newTypeElement);
@@ -112,8 +109,7 @@ public class MethodCanBeVariableArityMethodInspection extends BaseInspection {
return new MethodCanBeVariableArityMethodVisitor();
}
- private class MethodCanBeVariableArityMethodVisitor
- extends BaseInspectionVisitor {
+ private class MethodCanBeVariableArityMethodVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(PsiMethod method) {
@@ -126,8 +122,7 @@ public class MethodCanBeVariableArityMethodInspection extends BaseInspection {
return;
}
final PsiParameter[] parameters = parameterList.getParameters();
- final PsiParameter lastParameter =
- parameters[parameters.length - 1];
+ final PsiParameter lastParameter = parameters[parameters.length - 1];
final PsiType type = lastParameter.getType();
if (!(type instanceof PsiArrayType)) {
return;
@@ -142,14 +137,16 @@ public class MethodCanBeVariableArityMethodInspection extends BaseInspection {
return;
}
if (ignoreByteAndShortArrayParameters) {
- if (PsiType.BYTE.equals(componentType) ||
- PsiType.SHORT.equals(componentType)) {
+ if (PsiType.BYTE.equals(componentType) || PsiType.SHORT.equals(componentType)) {
return;
}
}
if (LibraryUtil.isOverrideOfLibraryMethod(method)) {
return;
}
+ if (ignoreOverridingMethods && SuperMethodsSearch.search(method, null, true, false).findFirst() != null) {
+ return;
+ }
registerMethodError(method);
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java
index c14c170ca84a..f4bddcd25294 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/TryFinallyCanBeTryWithResourcesInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -84,6 +84,10 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
if (tryBlock == null) {
return;
}
+ final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
+ if (finallyBlock == null) {
+ return;
+ }
final PsiElement[] tryBlockChildren = tryBlock.getChildren();
final Set<PsiLocalVariable> variables = new HashSet();
for (PsiLocalVariable variable : collectVariables(tryStatement)) {
@@ -145,8 +149,6 @@ public class TryFinallyCanBeTryWithResourcesInspection extends BaseInspection {
for (PsiCatchSection catchSection : catchSections) {
newTryStatementText.append(catchSection.getText());
}
- final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
- assert finallyBlock != null;
final PsiElement[] finallyChildren = finallyBlock.getChildren();
boolean appended = false;
final int finallyChildrenLength = finallyChildren.length - 1;
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
index 0d04a5cbf93a..a2907b363187 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -50,15 +50,13 @@ public class WhileCanBeForeachInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "while.can.be.foreach.display.name");
+ return InspectionGadgetsBundle.message("while.can.be.foreach.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "while.can.be.foreach.problem.descriptor");
+ return InspectionGadgetsBundle.message("while.can.be.foreach.problem.descriptor");
}
@Override
@@ -79,43 +77,33 @@ public class WhileCanBeForeachInspection extends BaseInspection {
}
@Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ public void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement whileElement = descriptor.getPsiElement();
- final PsiWhileStatement whileStatement =
- (PsiWhileStatement)whileElement.getParent();
+ final PsiWhileStatement whileStatement = (PsiWhileStatement)whileElement.getParent();
replaceWhileWithForEach(whileStatement);
}
- private static void replaceWhileWithForEach(
- @NotNull PsiWhileStatement whileStatement)
- throws IncorrectOperationException {
+ private static void replaceWhileWithForEach(@NotNull PsiWhileStatement whileStatement) {
final PsiStatement body = whileStatement.getBody();
if (body == null) {
return;
}
- final PsiStatement initialization =
- getPreviousStatement(whileStatement);
- final PsiDeclarationStatement declaration =
- (PsiDeclarationStatement)initialization;
+ final PsiStatement initialization = getPreviousStatement(whileStatement);
+ final PsiDeclarationStatement declaration = (PsiDeclarationStatement)initialization;
if (declaration == null) {
return;
}
- final PsiElement declaredElement =
- declaration.getDeclaredElements()[0];
+ final PsiElement declaredElement = declaration.getDeclaredElements()[0];
if (!(declaredElement instanceof PsiLocalVariable)) {
return;
}
final PsiLocalVariable iterator = (PsiLocalVariable)declaredElement;
- final PsiMethodCallExpression initializer =
- (PsiMethodCallExpression)iterator.getInitializer();
+ final PsiMethodCallExpression initializer = (PsiMethodCallExpression)iterator.getInitializer();
if (initializer == null) {
return;
}
- final PsiReferenceExpression methodExpression =
- initializer.getMethodExpression();
- final PsiExpression collection =
- methodExpression.getQualifierExpression();
+ final PsiReferenceExpression methodExpression = initializer.getMethodExpression();
+ final PsiExpression collection = methodExpression.getQualifierExpression();
if (collection == null) {
return;
}
@@ -125,85 +113,62 @@ public class WhileCanBeForeachInspection extends BaseInspection {
}
final Project project = whileStatement.getProject();
final PsiStatement firstStatement = getFirstStatement(body);
- final boolean isDeclaration =
- isIteratorNextDeclaration(firstStatement, iterator,
- contentType);
+ final boolean isDeclaration = isIteratorNextDeclaration(firstStatement, iterator, contentType);
final PsiStatement statementToSkip;
- @NonNls String contentVariableName;
+ @NonNls final String contentVariableName;
if (isDeclaration) {
- final PsiDeclarationStatement declarationStatement =
- (PsiDeclarationStatement)firstStatement;
+ final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)firstStatement;
if (declarationStatement == null) {
return;
}
- final PsiElement[] declaredElements =
- declarationStatement.getDeclaredElements();
- final PsiLocalVariable localVariable =
- (PsiLocalVariable)declaredElements[0];
+ final PsiElement[] declaredElements = declarationStatement.getDeclaredElements();
+ final PsiLocalVariable localVariable = (PsiLocalVariable)declaredElements[0];
contentVariableName = localVariable.getName();
statementToSkip = declarationStatement;
}
else {
if (collection instanceof PsiReferenceExpression) {
- final PsiJavaCodeReferenceElement referenceElement
- = (PsiJavaCodeReferenceElement)collection;
- final String collectionName =
- referenceElement.getReferenceName();
- contentVariableName = createNewVariableName(
- whileStatement, contentType, collectionName);
+ final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)collection;
+ final String collectionName = referenceElement.getReferenceName();
+ contentVariableName = createNewVariableName(whileStatement, contentType, collectionName);
}
else {
- contentVariableName =
- createNewVariableName(whileStatement, contentType,
- null);
+ contentVariableName = createNewVariableName(whileStatement, contentType, null);
}
statementToSkip = null;
}
- final CodeStyleSettings codeStyleSettings =
- CodeStyleSettingsManager.getSettings(project);
- @NonNls final String finalString =
- codeStyleSettings.GENERATE_FINAL_PARAMETERS ? "final " : "";
+ final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
@NonNls final StringBuilder out = new StringBuilder();
out.append("for(");
- out.append(finalString);
- out.append(contentType.getCanonicalText());
- out.append(' ');
- out.append(contentVariableName);
- out.append(": ");
- out.append(collection.getText());
- out.append(')');
- // add cast if type returned by collection is not assignable to
- // the iterator type.
- final PsiType iteratorContentType =
- getContentType(iterator.getType(), iterator);
- if (iteratorContentType != null &&
- !TypeConversionUtil.isAssignable(iteratorContentType,
- contentType)) {
- final String typeText = iteratorContentType.getCanonicalText();
- contentVariableName = '(' + typeText + ')' +
- contentVariableName;
- }
- replaceIteratorNext(body, contentVariableName,
- iterator, contentType, statementToSkip, out);
- final Query<PsiReference> query =
- ReferencesSearch.search(iterator, iterator.getUseScope());
+ if (codeStyleSettings.GENERATE_FINAL_PARAMETERS) {
+ out.append("final ");
+ }
+ final PsiType iteratorContentType = getContentType(iterator.getType(), iterator);
+ if (iteratorContentType == null) {
+ return;
+ }
+ out.append(iteratorContentType.getCanonicalText()).append(' ').append(contentVariableName).append(": ");
+ if (!TypeConversionUtil.isAssignable(iteratorContentType, contentType)) {
+ out.append("(java.lang.Iterable<").append(iteratorContentType.getCanonicalText()).append(">)");
+ }
+ out.append(collection.getText()).append(')');
+
+ replaceIteratorNext(body, contentVariableName, iterator, contentType, statementToSkip, out);
+ final Query<PsiReference> query = ReferencesSearch.search(iterator, iterator.getUseScope());
boolean deleteIterator = true;
for (PsiReference usage : query) {
final PsiElement element = usage.getElement();
if (PsiTreeUtil.isAncestor(whileStatement, element, true)) {
continue;
}
- final PsiAssignmentExpression assignment =
- PsiTreeUtil.getParentOfType(element,
- PsiAssignmentExpression.class);
+ final PsiAssignmentExpression assignment = PsiTreeUtil.getParentOfType(element, PsiAssignmentExpression.class);
if (assignment == null) {
// iterator is read after while loop,
// so cannot be deleted
deleteIterator = false;
break;
}
- final PsiExpression expression =
- assignment.getRExpression();
+ final PsiExpression expression = assignment.getRExpression();
initializer.delete();
iterator.setInitializer(expression);
final PsiElement statement = assignment.getParent();
@@ -231,8 +196,7 @@ public class WhileCanBeForeachInspection extends BaseInspection {
if (parameters.length == 1) {
final PsiType parameterType = parameters[0];
if (parameterType instanceof PsiCapturedWildcardType) {
- final PsiCapturedWildcardType wildcardType =
- (PsiCapturedWildcardType)parameterType;
+ final PsiCapturedWildcardType wildcardType = (PsiCapturedWildcardType)parameterType;
final PsiType bound = wildcardType.getUpperBound();
if (bound != null) {
return bound;
@@ -245,10 +209,8 @@ public class WhileCanBeForeachInspection extends BaseInspection {
return TypeUtils.getObjectType(context);
}
- private static void replaceIteratorNext(
- @NotNull PsiElement element, String contentVariableName,
- PsiVariable iterator, PsiType contentType,
- PsiElement childToSkip, StringBuilder out) {
+ private static void replaceIteratorNext(@NotNull PsiElement element, String contentVariableName, PsiVariable iterator,
+ PsiType contentType, PsiElement childToSkip, StringBuilder out) {
if (isIteratorNext(element, iterator, contentType)) {
out.append(contentVariableName);
}
@@ -266,43 +228,30 @@ public class WhileCanBeForeachInspection extends BaseInspection {
else if (child.equals(childToSkip)) {
skippingWhiteSpace = true;
}
- else if (child instanceof PsiWhiteSpace &&
- skippingWhiteSpace) {
- //don't do anything
- }
- else {
+ else if (!(child instanceof PsiWhiteSpace) || !skippingWhiteSpace) {
skippingWhiteSpace = false;
- replaceIteratorNext(child, contentVariableName,
- iterator, contentType, childToSkip, out);
+ replaceIteratorNext(child, contentVariableName, iterator, contentType, childToSkip, out);
}
}
}
}
}
- private static boolean shouldSkip(PsiVariable iterator,
- PsiType contentType,
- PsiElement child) {
+ private static boolean shouldSkip(PsiVariable iterator, PsiType contentType, PsiElement child) {
if (!(child instanceof PsiExpressionStatement)) {
return false;
}
- final PsiExpressionStatement expressionStatement =
- (PsiExpressionStatement)child;
- final PsiExpression expression =
- expressionStatement.getExpression();
+ final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)child;
+ final PsiExpression expression = expressionStatement.getExpression();
return isIteratorNext(expression, iterator, contentType);
}
- private static boolean isIteratorNextDeclaration(
- PsiStatement statement, PsiVariable iterator,
- PsiType contentType) {
+ private static boolean isIteratorNextDeclaration(PsiStatement statement, PsiVariable iterator, PsiType contentType) {
if (!(statement instanceof PsiDeclarationStatement)) {
return false;
}
- final PsiDeclarationStatement declarationStatement =
- (PsiDeclarationStatement)statement;
- final PsiElement[] elements =
- declarationStatement.getDeclaredElements();
+ final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)statement;
+ final PsiElement[] elements = declarationStatement.getDeclaredElements();
if (elements.length != 1) {
return false;
}
@@ -315,15 +264,12 @@ public class WhileCanBeForeachInspection extends BaseInspection {
return isIteratorNext(initializer, iterator, contentType);
}
- private static boolean isIteratorNext(PsiElement element,
- PsiVariable iterator,
- PsiType contentType) {
+ private static boolean isIteratorNext(PsiElement element, PsiVariable iterator, PsiType contentType) {
if (element == null) {
return false;
}
if (element instanceof PsiTypeCastExpression) {
- final PsiTypeCastExpression castExpression =
- (PsiTypeCastExpression)element;
+ final PsiTypeCastExpression castExpression = (PsiTypeCastExpression)element;
final PsiType type = castExpression.getType();
if (type == null) {
return false;
@@ -331,23 +277,19 @@ public class WhileCanBeForeachInspection extends BaseInspection {
if (!type.equals(contentType)) {
return false;
}
- final PsiExpression operand =
- castExpression.getOperand();
+ final PsiExpression operand = castExpression.getOperand();
return isIteratorNext(operand, iterator, contentType);
}
if (!(element instanceof PsiMethodCallExpression)) {
return false;
}
- final PsiMethodCallExpression callExpression =
- (PsiMethodCallExpression)element;
- final PsiExpressionList argumentList =
- callExpression.getArgumentList();
+ final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)element;
+ final PsiExpressionList argumentList = callExpression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
if (arguments.length != 0) {
return false;
}
- final PsiReferenceExpression reference =
- callExpression.getMethodExpression();
+ final PsiReferenceExpression reference = callExpression.getMethodExpression();
@NonNls final String referenceName = reference.getReferenceName();
if (!HardcodedMethodConstants.NEXT.equals(referenceName)) {
return false;
@@ -356,26 +298,20 @@ public class WhileCanBeForeachInspection extends BaseInspection {
if (!(expression instanceof PsiReferenceExpression)) {
return false;
}
- final PsiReferenceExpression referenceExpression =
- (PsiReferenceExpression)expression;
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiElement target = referenceExpression.resolve();
return iterator.equals(target);
}
- private static String createNewVariableName(
- @NotNull PsiWhileStatement scope, PsiType type,
- String containerName) {
+ private static String createNewVariableName(@NotNull PsiWhileStatement scope, PsiType type, String containerName) {
final Project project = scope.getProject();
- final JavaCodeStyleManager codeStyleManager =
- JavaCodeStyleManager.getInstance(project);
+ final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
@NonNls String baseName;
if (containerName != null) {
baseName = StringUtils.createSingularFromName(containerName);
}
else {
- final SuggestedNameInfo suggestions =
- codeStyleManager.suggestVariableName(
- VariableKind.LOCAL_VARIABLE, null, null, type);
+ final SuggestedNameInfo suggestions = codeStyleManager.suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, type);
final String[] names = suggestions.names;
if (names != null && names.length > 0) {
baseName = names[0];
@@ -387,13 +323,11 @@ public class WhileCanBeForeachInspection extends BaseInspection {
if (baseName == null || baseName.length() == 0) {
baseName = "value";
}
- return codeStyleManager.suggestUniqueVariableName(baseName, scope,
- true);
+ return codeStyleManager.suggestUniqueVariableName(baseName, scope, true);
}
@Nullable
- private static PsiStatement getFirstStatement(
- @NotNull PsiStatement body) {
+ private static PsiStatement getFirstStatement(@NotNull PsiStatement body) {
if (body instanceof PsiBlockStatement) {
final PsiBlockStatement block = (PsiBlockStatement)body;
final PsiCodeBlock codeBlock = block.getCodeBlock();
@@ -410,12 +344,10 @@ public class WhileCanBeForeachInspection extends BaseInspection {
return new WhileCanBeForeachVisitor();
}
- private static class WhileCanBeForeachVisitor
- extends BaseInspectionVisitor {
+ private static class WhileCanBeForeachVisitor extends BaseInspectionVisitor {
@Override
- public void visitWhileStatement(
- @NotNull PsiWhileStatement whileStatement) {
+ public void visitWhileStatement(@NotNull PsiWhileStatement whileStatement) {
super.visitWhileStatement(whileStatement);
if (!PsiUtil.isLanguageLevel5OrHigher(whileStatement)) {
return;
@@ -512,59 +444,47 @@ public class WhileCanBeForeachInspection extends BaseInspection {
return true;
}
- private static boolean isHasNextCalled(PsiVariable iterator,
- PsiExpression condition) {
+ private static boolean isHasNextCalled(PsiVariable iterator, PsiExpression condition) {
if (!(condition instanceof PsiMethodCallExpression)) {
return false;
}
- final PsiMethodCallExpression call =
- (PsiMethodCallExpression)condition;
+ final PsiMethodCallExpression call = (PsiMethodCallExpression)condition;
final PsiExpressionList argumentList = call.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
if (arguments.length != 0) {
return false;
}
- final PsiReferenceExpression methodExpression =
- call.getMethodExpression();
- @NonNls final String methodName =
- methodExpression.getReferenceName();
+ final PsiReferenceExpression methodExpression = call.getMethodExpression();
+ @NonNls final String methodName = methodExpression.getReferenceName();
if (!HardcodedMethodConstants.HAS_NEXT.equals(methodName)) {
return false;
}
- final PsiExpression qualifier =
- methodExpression.getQualifierExpression();
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier == null) {
return true;
}
if (!(qualifier instanceof PsiReferenceExpression)) {
return false;
}
- final PsiReferenceExpression referenceExpression =
- (PsiReferenceExpression)qualifier;
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
final PsiElement target = referenceExpression.resolve();
return iterator.equals(target);
}
- private static int calculateCallsToIteratorNext(PsiVariable iterator,
- PsiElement context) {
- final NumCallsToIteratorNextVisitor visitor =
- new NumCallsToIteratorNextVisitor(iterator);
+ private static int calculateCallsToIteratorNext(PsiVariable iterator, PsiElement context) {
+ final NumCallsToIteratorNextVisitor visitor = new NumCallsToIteratorNextVisitor(iterator);
context.accept(visitor);
return visitor.getNumCallsToIteratorNext();
}
- private static boolean isIteratorRemoveCalled(PsiVariable iterator,
- PsiElement context) {
- final IteratorMethodCallVisitor visitor =
- new IteratorMethodCallVisitor(iterator);
+ private static boolean isIteratorRemoveCalled(PsiVariable iterator, PsiElement context) {
+ final IteratorMethodCallVisitor visitor = new IteratorMethodCallVisitor(iterator);
context.accept(visitor);
return visitor.isMethodCalled();
}
- private static boolean isIteratorHasNextCalled(PsiVariable iterator,
- PsiElement context) {
- final IteratorHasNextVisitor visitor =
- new IteratorHasNextVisitor(iterator);
+ private static boolean isIteratorHasNextCalled(PsiVariable iterator, PsiElement context) {
+ final IteratorHasNextVisitor visitor = new IteratorHasNextVisitor(iterator);
context.accept(visitor);
return visitor.isHasNextCalled();
}
@@ -572,17 +492,14 @@ public class WhileCanBeForeachInspection extends BaseInspection {
@Nullable
public static PsiStatement getPreviousStatement(PsiElement context) {
- final PsiElement prevStatement =
- PsiTreeUtil.skipSiblingsBackward(context,
- PsiWhiteSpace.class, PsiComment.class);
+ final PsiElement prevStatement = PsiTreeUtil.skipSiblingsBackward(context, PsiWhiteSpace.class, PsiComment.class);
if (!(prevStatement instanceof PsiStatement)) {
return null;
}
return (PsiStatement)prevStatement;
}
- private static class NumCallsToIteratorNextVisitor
- extends JavaRecursiveElementVisitor {
+ private static class NumCallsToIteratorNextVisitor extends JavaRecursiveElementVisitor {
private int numCallsToIteratorNext = 0;
private final PsiVariable iterator;
@@ -592,23 +509,18 @@ public class WhileCanBeForeachInspection extends BaseInspection {
}
@Override
- public void visitMethodCallExpression(
- @NotNull PsiMethodCallExpression callExpression) {
+ public void visitMethodCallExpression(@NotNull PsiMethodCallExpression callExpression) {
super.visitMethodCallExpression(callExpression);
- final PsiReferenceExpression methodExpression =
- callExpression.getMethodExpression();
- @NonNls final String methodName =
- methodExpression.getReferenceName();
+ final PsiReferenceExpression methodExpression = callExpression.getMethodExpression();
+ @NonNls final String methodName = methodExpression.getReferenceName();
if (!HardcodedMethodConstants.NEXT.equals(methodName)) {
return;
}
- final PsiExpression qualifier =
- methodExpression.getQualifierExpression();
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (!(qualifier instanceof PsiReferenceExpression)) {
return;
}
- final PsiReferenceExpression referenceExpression =
- (PsiReferenceExpression)qualifier;
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
final PsiElement target = referenceExpression.resolve();
if (!iterator.equals(target)) {
return;
@@ -621,8 +533,7 @@ public class WhileCanBeForeachInspection extends BaseInspection {
}
}
- private static class IteratorMethodCallVisitor
- extends JavaRecursiveElementVisitor {
+ private static class IteratorMethodCallVisitor extends JavaRecursiveElementVisitor {
private boolean methodCalled = false;
private final PsiVariable iterator;
@@ -639,25 +550,21 @@ public class WhileCanBeForeachInspection extends BaseInspection {
}
@Override
- public void visitMethodCallExpression(
- @NotNull PsiMethodCallExpression expression) {
+ public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
if (methodCalled) {
return;
}
super.visitMethodCallExpression(expression);
- final PsiReferenceExpression methodExpression =
- expression.getMethodExpression();
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
final String name = methodExpression.getReferenceName();
if (HardcodedMethodConstants.NEXT.equals(name)) {
return;
}
- final PsiExpression qualifier =
- methodExpression.getQualifierExpression();
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (!(qualifier instanceof PsiReferenceExpression)) {
return;
}
- final PsiReferenceExpression referenceExpression =
- (PsiReferenceExpression)qualifier;
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
final PsiElement target = referenceExpression.resolve();
if (iterator.equals(target)) {
methodCalled = true;
@@ -669,8 +576,7 @@ public class WhileCanBeForeachInspection extends BaseInspection {
}
}
- private static class IteratorHasNextVisitor
- extends JavaRecursiveElementVisitor {
+ private static class IteratorHasNextVisitor extends JavaRecursiveElementVisitor {
private boolean hasNextCalled = false;
private final PsiVariable iterator;
@@ -687,22 +593,18 @@ public class WhileCanBeForeachInspection extends BaseInspection {
}
@Override
- public void visitMethodCallExpression(
- @NotNull PsiMethodCallExpression expression) {
+ public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
- final PsiReferenceExpression methodExpression =
- expression.getMethodExpression();
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
@NonNls final String name = methodExpression.getReferenceName();
if (!HardcodedMethodConstants.HAS_NEXT.equals(name)) {
return;
}
- final PsiExpression qualifier =
- methodExpression.getQualifierExpression();
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (!(qualifier instanceof PsiReferenceExpression)) {
return;
}
- final PsiReferenceExpression referenceExpression =
- (PsiReferenceExpression)qualifier;
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
final PsiElement target = referenceExpression.resolve();
if (iterator.equals(target)) {
hasNextCalled = true;
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/DivideByZeroInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/DivideByZeroInspection.java
index b75a3030b72c..4745746b8474 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/DivideByZeroInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/DivideByZeroInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -48,51 +48,43 @@ public class DivideByZeroInspection extends BaseInspection {
private static class DivisionByZeroVisitor extends BaseInspectionVisitor {
@Override
- public void visitBinaryExpression(
- @NotNull PsiBinaryExpression expression) {
- super.visitBinaryExpression(expression);
- final PsiExpression rhs = expression.getROperand();
- if (rhs == null) {
- return;
- }
+ public void visitPolyadicExpression(PsiPolyadicExpression expression) {
+ super.visitPolyadicExpression(expression);
final IElementType tokenType = expression.getOperationTokenType();
- if (!tokenType.equals(JavaTokenType.DIV) &&
- !tokenType.equals(JavaTokenType.PERC)) {
+ if (!JavaTokenType.DIV.equals(tokenType) && !JavaTokenType.PERC.equals(tokenType)) {
return;
}
- final Object value =
- ConstantExpressionUtil.computeCastTo(rhs, PsiType.DOUBLE);
- if (!(value instanceof Double)) {
- return;
- }
- final double constantValue = ((Double)value).doubleValue();
- if (constantValue == 0.0 || constantValue == -0.0) {
- registerError(expression);
+ final PsiExpression[] operands = expression.getOperands();
+ for (int i = 1; i < operands.length; i++) {
+ final PsiExpression operand = operands[i];
+ if (isZero(operand)) {
+ registerError(operand);
+ return;
+ }
}
}
@Override
- public void visitAssignmentExpression(
- PsiAssignmentExpression expression) {
+ public void visitAssignmentExpression(PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
final PsiExpression rhs = expression.getRExpression();
if (rhs == null) {
return;
}
final IElementType tokenType = expression.getOperationTokenType();
- if (!tokenType.equals(JavaTokenType.DIVEQ)
- && !tokenType.equals(JavaTokenType.PERCEQ)) {
+ if (!tokenType.equals(JavaTokenType.DIVEQ) && !tokenType.equals(JavaTokenType.PERCEQ) || isZero(rhs)) {
return;
}
- final Object value = ConstantExpressionUtil.computeCastTo(rhs,
- PsiType.DOUBLE);
+ registerError(expression);
+ }
+
+ private static boolean isZero(PsiExpression expression) {
+ final Object value = ConstantExpressionUtil.computeCastTo(expression, PsiType.DOUBLE);
if (!(value instanceof Double)) {
- return;
+ return false;
}
final double constantValue = ((Double)value).doubleValue();
- if (constantValue == 0.0 || constantValue == -0.0) {
- registerError(expression);
- }
+ return constantValue == 0.0 || constantValue == -0.0;
}
}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
index ef871d3fa632..c8271b32f46d 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -19,9 +19,8 @@ import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
-import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.tree.IElementType;
-import com.intellij.util.IncorrectOperationException;
+import com.intellij.psi.util.PsiUtil;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -30,21 +29,19 @@ import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
+import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.HashMap;
-import java.util.Map;
public class ImplicitNumericConversionInspection extends BaseInspection {
/**
* @noinspection StaticCollection
*/
- private static final Map<PsiType, Integer> typePrecisions =
- new HashMap<PsiType, Integer>(7);
+ private static final gnu.trove.TObjectIntHashMap<PsiType> typePrecisions = new TObjectIntHashMap<PsiType>(7);
static {
typePrecisions.put(PsiType.BYTE, 1);
@@ -68,22 +65,17 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "implicit.numeric.conversion.display.name");
+ return InspectionGadgetsBundle.message("implicit.numeric.conversion.display.name");
}
@Override
public JComponent createOptionsPanel() {
- final MultipleCheckboxOptionsPanel optionsPanel =
- new MultipleCheckboxOptionsPanel(this);
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
- "implicit.numeric.conversion.ignore.widening.conversion.option"),
+ final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("implicit.numeric.conversion.ignore.widening.conversion.option"),
"ignoreWideningConversions");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
- "implicit.numeric.conversion.ignore.char.conversion.option"),
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("implicit.numeric.conversion.ignore.char.conversion.option"),
"ignoreCharConversions");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
- "implicit.numeric.conversion.ignore.constant.conversion.option"),
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("implicit.numeric.conversion.ignore.constant.conversion.option"),
"ignoreConstantConversions");
return optionsPanel;
}
@@ -93,8 +85,7 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
public String buildErrorString(Object... infos) {
final PsiType type = (PsiType)infos[1];
final PsiType expectedType = (PsiType)infos[2];
- return InspectionGadgetsBundle.message(
- "implicit.numeric.conversion.problem.descriptor",
+ return InspectionGadgetsBundle.message("implicit.numeric.conversion.problem.descriptor",
type.getPresentableText(), expectedType.getPresentableText());
}
@@ -105,25 +96,19 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
@Override
public InspectionGadgetsFix buildFix(Object... infos) {
- return new ImplicitNumericConversionFix((PsiExpression)infos[0],
- (PsiType)infos[2]);
+ return new ImplicitNumericConversionFix((PsiExpression)infos[0], (PsiType)infos[2]);
}
- private static class ImplicitNumericConversionFix
- extends InspectionGadgetsFix {
+ private static class ImplicitNumericConversionFix extends InspectionGadgetsFix {
private final String m_name;
- ImplicitNumericConversionFix(PsiExpression expression,
- PsiType expectedType) {
+ ImplicitNumericConversionFix(PsiExpression expression, PsiType expectedType) {
if (isConvertible(expression, expectedType)) {
- m_name = InspectionGadgetsBundle.message(
- "implicit.numeric.conversion.convert.quickfix",
- expectedType.getCanonicalText());
+ m_name = InspectionGadgetsBundle.message("implicit.numeric.conversion.convert.quickfix", expectedType.getCanonicalText());
}
else {
- m_name = InspectionGadgetsBundle.message(
- "implicit.numeric.conversion.make.explicit.quickfix");
+ m_name = InspectionGadgetsBundle.message("implicit.numeric.conversion.make.explicit.quickfix");
}
}
@@ -133,18 +118,14 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
}
@Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
- final PsiExpression expression = (
- PsiExpression)descriptor.getPsiElement();
- final PsiType expectedType =
- ExpectedTypeUtils.findExpectedType(expression, true);
+ public void doFix(Project project, ProblemDescriptor descriptor) {
+ final PsiExpression expression = (PsiExpression)descriptor.getPsiElement();
+ final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true);
if (expectedType == null) {
return;
}
if (isConvertible(expression, expectedType)) {
- final String newExpression =
- convertExpression(expression, expectedType);
+ final String newExpression = convertExpression(expression, expectedType);
if (newExpression == null) {
return;
}
@@ -152,14 +133,11 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
}
else {
final String newExpression;
- if (ParenthesesUtils.getPrecedence(expression) <=
- ParenthesesUtils.TYPE_CAST_PRECEDENCE) {
- newExpression = '(' + expectedType.getCanonicalText() +
- ')' + expression.getText();
+ if (ParenthesesUtils.getPrecedence(expression) <= ParenthesesUtils.TYPE_CAST_PRECEDENCE) {
+ newExpression = '(' + expectedType.getCanonicalText() + ')' + expression.getText();
}
else {
- newExpression = '(' + expectedType.getCanonicalText() +
- ")(" + expression.getText() + ')';
+ newExpression = '(' + expectedType.getCanonicalText() + ")(" + expression.getText() + ')';
}
replaceExpression(expression, newExpression);
}
@@ -167,50 +145,41 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
@Nullable
@NonNls
- private static String convertExpression(
- PsiExpression expression, PsiType expectedType) {
+ private static String convertExpression(PsiExpression expression, PsiType expectedType) {
final PsiType expressionType = expression.getType();
if (expressionType == null) {
return null;
}
- if (expressionType.equals(PsiType.INT) &&
- expectedType.equals(PsiType.LONG)) {
+ if (expressionType.equals(PsiType.INT) && expectedType.equals(PsiType.LONG)) {
return expression.getText() + 'L';
}
- if (expressionType.equals(PsiType.INT) &&
- expectedType.equals(PsiType.FLOAT)) {
+ if (expressionType.equals(PsiType.INT) && expectedType.equals(PsiType.FLOAT)) {
return expression.getText() + ".0F";
}
- if (expressionType.equals(PsiType.INT) &&
- expectedType.equals(PsiType.DOUBLE)) {
+ if (expressionType.equals(PsiType.INT) && expectedType.equals(PsiType.DOUBLE)) {
return expression.getText() + ".0";
}
- if (expressionType.equals(PsiType.LONG) &&
- expectedType.equals(PsiType.FLOAT)) {
+ if (expressionType.equals(PsiType.LONG) && expectedType.equals(PsiType.FLOAT)) {
final String text = expression.getText();
final int length = text.length();
return text.substring(0, length - 1) + ".0F";
}
- if (expressionType.equals(PsiType.LONG) &&
- expectedType.equals(PsiType.DOUBLE)) {
+ if (expressionType.equals(PsiType.LONG) && expectedType.equals(PsiType.DOUBLE)) {
final String text = expression.getText();
final int length = text.length();
return text.substring(0, length - 1) + ".0";
}
- if (expressionType.equals(PsiType.DOUBLE) &&
- expectedType.equals(PsiType.FLOAT)) {
+ if (expressionType.equals(PsiType.DOUBLE) && expectedType.equals(PsiType.FLOAT)) {
final String text = expression.getText();
final int length = text.length();
- if (text.charAt(length - 1) == 'd' ||
- text.charAt(length - 1) == 'D') {
+ if (text.charAt(length - 1) == 'd' || text.charAt(length - 1) == 'D') {
return text.substring(0, length - 1) + 'F';
}
else {
return text + 'F';
}
}
- if (expressionType.equals(PsiType.FLOAT) &&
- expectedType.equals(PsiType.DOUBLE)) {
+ if (expressionType.equals(PsiType.FLOAT) && expectedType.equals(PsiType.DOUBLE)) {
final String text = expression.getText();
final int length = text.length();
return text.substring(0, length - 1);
@@ -218,10 +187,8 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
return null; //can't happen
}
- private static boolean isConvertible(PsiExpression expression,
- PsiType expectedType) {
- if (!(expression instanceof PsiLiteralExpression) &&
- !isNegatedLiteral(expression)) {
+ private static boolean isConvertible(PsiExpression expression, PsiType expectedType) {
+ if (!(expression instanceof PsiLiteralExpression) && !isNegatedLiteral(expression)) {
return false;
}
final PsiType expressionType = expression.getType();
@@ -237,16 +204,14 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
if (isIntegral(expressionType) && isFloatingPoint(expectedType)) {
return true;
}
- return isFloatingPoint(expressionType) &&
- isFloatingPoint(expectedType);
+ return isFloatingPoint(expressionType) && isFloatingPoint(expectedType);
}
private static boolean isNegatedLiteral(PsiExpression expression) {
if (!(expression instanceof PsiPrefixExpression)) {
return false;
}
- final PsiPrefixExpression prefixExpression =
- (PsiPrefixExpression)expression;
+ final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
final IElementType tokenType = prefixExpression.getOperationTokenType();
if (!JavaTokenType.MINUS.equals(tokenType)) {
return false;
@@ -256,85 +221,72 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
}
private static boolean isIntegral(@Nullable PsiType expressionType) {
- return PsiType.INT.equals(expressionType) ||
- PsiType.LONG.equals(expressionType);
+ return PsiType.INT.equals(expressionType) || PsiType.LONG.equals(expressionType);
}
private static boolean isFloatingPoint(@Nullable PsiType expressionType) {
- return PsiType.FLOAT.equals(expressionType) ||
- PsiType.DOUBLE.equals(expressionType);
+ return PsiType.FLOAT.equals(expressionType) || PsiType.DOUBLE.equals(expressionType);
}
}
- private class ImplicitNumericConversionVisitor
- extends BaseInspectionVisitor {
+ private class ImplicitNumericConversionVisitor extends BaseInspectionVisitor {
@Override
- public void visitBinaryExpression(
- PsiBinaryExpression expression) {
- super.visitBinaryExpression(expression);
+ public void visitPolyadicExpression(PsiPolyadicExpression expression) {
+ super.visitPolyadicExpression(expression);
checkExpression(expression);
}
@Override
- public void visitConditionalExpression(
- PsiConditionalExpression expression) {
+ public void visitConditionalExpression(PsiConditionalExpression expression) {
super.visitConditionalExpression(expression);
checkExpression(expression);
}
@Override
- public void visitLiteralExpression(
- PsiLiteralExpression expression) {
+ public void visitLiteralExpression(PsiLiteralExpression expression) {
super.visitLiteralExpression(expression);
checkExpression(expression);
}
@Override
- public void visitPostfixExpression(
- PsiPostfixExpression expression) {
+ public void visitPostfixExpression(PsiPostfixExpression expression) {
super.visitPostfixExpression(expression);
checkExpression(expression);
}
@Override
- public void visitPrefixExpression(
- PsiPrefixExpression expression) {
+ public void visitPrefixExpression(PsiPrefixExpression expression) {
super.visitPrefixExpression(expression);
checkExpression(expression);
}
@Override
- public void visitReferenceExpression(
- PsiReferenceExpression expression) {
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
checkExpression(expression);
}
@Override
- public void visitMethodCallExpression(
- PsiMethodCallExpression expression) {
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
checkExpression(expression);
}
@Override
- public void visitTypeCastExpression(
- PsiTypeCastExpression expression) {
+ public void visitTypeCastExpression(PsiTypeCastExpression expression) {
super.visitTypeCastExpression(expression);
checkExpression(expression);
}
@Override
- public void visitAssignmentExpression(
- PsiAssignmentExpression expression) {
+ public void visitAssignmentExpression(PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
checkExpression(expression);
}
@Override
- public void visitParenthesizedExpression(
- PsiParenthesizedExpression expression) {
+ public void visitParenthesizedExpression(PsiParenthesizedExpression expression) {
super.visitParenthesizedExpression(expression);
checkExpression(expression);
}
@@ -347,42 +299,28 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
if (ignoreConstantConversions) {
PsiExpression rootExpression = expression;
while (rootExpression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)rootExpression;
+ final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)rootExpression;
rootExpression = parenthesizedExpression.getExpression();
}
- if (rootExpression instanceof PsiLiteralExpression) {
- return;
- }
- else if (PsiUtil.isConstantExpression(rootExpression)) {
+ if (rootExpression instanceof PsiLiteralExpression || PsiUtil.isConstantExpression(rootExpression)) {
return;
}
}
final PsiType expressionType = expression.getType();
- if (expressionType == null) {
+ if (expressionType == null || !ClassUtils.isPrimitiveNumericType(expressionType)) {
return;
}
- if (!ClassUtils.isPrimitiveNumericType(expressionType)) {
+ if (PsiType.CHAR.equals(expressionType) && (ignoreCharConversions || isArgumentOfStringIndexOf(parent))) {
return;
}
- if (PsiType.CHAR.equals(expressionType)) {
- if (ignoreCharConversions) {
- return;
- }
- if (isArgumentOfStringIndexOf(parent)) {
- return;
- }
- }
- final PsiType expectedType =
- ExpectedTypeUtils.findExpectedType(expression, true);
+ final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true);
if (!ClassUtils.isPrimitiveNumericType(expectedType)) {
return;
}
if (expressionType.equals(expectedType)) {
return;
}
- if (ignoreWideningConversions && hasLowerPrecision(expressionType,
- expectedType)) {
+ if (ignoreWideningConversions && hasLowerPrecision(expressionType, expectedType)) {
return;
}
if (ignoreCharConversions && PsiType.CHAR.equals(expectedType)) {
@@ -399,13 +337,10 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
if (!(grandParent instanceof PsiMethodCallExpression)) {
return false;
}
- final PsiMethodCallExpression methodCallExpression =
- (PsiMethodCallExpression)grandParent;
- final PsiReferenceExpression methodExpression =
- methodCallExpression.getMethodExpression();
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)grandParent;
+ final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
final String methodName = methodExpression.getReferenceName();
- if (!HardcodedMethodConstants.INDEX_OF.equals(methodName) &&
- !HardcodedMethodConstants.LAST_INDEX_OF.equals(methodName)) {
+ if (!HardcodedMethodConstants.INDEX_OF.equals(methodName) && !HardcodedMethodConstants.LAST_INDEX_OF.equals(methodName)) {
return false;
}
final PsiMethod method = methodCallExpression.resolveMethod();
@@ -421,10 +356,9 @@ public class ImplicitNumericConversionInspection extends BaseInspection {
}
}
- static boolean hasLowerPrecision(PsiType expressionType,
- PsiType expectedType) {
- final Integer operandPrecision = typePrecisions.get(expressionType);
- final Integer castPrecision = typePrecisions.get(expectedType);
+ static boolean hasLowerPrecision(PsiType expressionType, PsiType expectedType) {
+ final int operandPrecision = typePrecisions.get(expressionType);
+ final int castPrecision = typePrecisions.get(expectedType);
return operandPrecision <= castPrecision;
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
index 7760b9377942..8a71995910f1 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
@@ -180,10 +180,7 @@ public class UnnecessaryExplicitNumericCastInspection extends BaseInspection {
else if (parent instanceof PsiAssignmentExpression) {
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
final PsiType lhsType = assignmentExpression.getType();
- if (!castType.equals(lhsType)) {
- return true;
- }
- return !isLegalAssignmentConversion(operand, lhsType);
+ return !castType.equals(lhsType) || !isLegalAssignmentConversion(operand, lhsType);
}
else if (parent instanceof PsiVariable) {
final PsiVariable variable = (PsiVariable)parent;
@@ -235,12 +232,9 @@ public class UnnecessaryExplicitNumericCastInspection extends BaseInspection {
if (targetMethod != newMethodCall.resolveMethod()) {
return true;
}
- return false;
- }
- else {
- final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false);
- return !castType.equals(expectedType) || !isLegalWideningConversion(operand, castType);
}
+ final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, false);
+ return !castType.equals(expectedType) || !isLegalWideningConversion(operand, castType);
}
static boolean isLegalWideningConversion(PsiExpression expression, PsiType requiredType) {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
index bb76ee23d292..7fe4542d12fd 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java
@@ -16,6 +16,7 @@
package com.siyeh.ig.psiutils;
import com.intellij.psi.*;
+import com.intellij.psi.impl.source.jsp.jspJava.JspClassLevelDeclarationStatement;
import com.intellij.psi.impl.source.jsp.jspJava.JspTemplateStatement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NonNls;
@@ -93,7 +94,7 @@ public class ControlFlowUtils {
else if (statement instanceof PsiSwitchStatement) {
return switchStatementMayCompleteNormally((PsiSwitchStatement)statement);
}
- else if (statement instanceof JspTemplateStatement) {
+ else if (statement instanceof JspTemplateStatement || statement instanceof JspClassLevelDeclarationStatement) {
return true;
}
else {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java
index c79a60d198f7..15edeedc9246 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ExpressionUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2012 Bas Leijdekkers
+ * Copyright 2005-2013 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -155,6 +155,19 @@ public class ExpressionUtils {
}
@Nullable
+ public static String getLiteralString(@Nullable PsiExpression expression) {
+ final PsiLiteralExpression literal = getLiteral(expression);
+ if (literal == null) {
+ return null;
+ }
+ final Object value = literal.getValue();
+ if (value == null) {
+ return null;
+ }
+ return value.toString();
+ }
+
+ @Nullable
public static PsiLiteralExpression getLiteral(@Nullable PsiExpression expression) {
expression = ParenthesesUtils.stripParentheses(expression);
if (expression instanceof PsiLiteralExpression) {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/FormatUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/FormatUtils.java
index 2265a74437e0..68e431e5652f 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/FormatUtils.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/FormatUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2012 Bas Leijdekkers
+ * Copyright 2010-2013 Bas Leijdekkers
*
* 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.siyeh.ig.psiutils;
import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -46,10 +47,8 @@ public class FormatUtils {
private FormatUtils() {}
- public static boolean isFormatCall(
- PsiMethodCallExpression expression) {
- final PsiReferenceExpression methodExpression =
- expression.getMethodExpression();
+ public static boolean isFormatCall(PsiMethodCallExpression expression) {
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
final String name = methodExpression.getReferenceName();
if (!formatMethodNames.contains(name)) {
return false;
@@ -66,6 +65,16 @@ public class FormatUtils {
return formatClassNames.contains(className);
}
+ public static boolean isFormatCallArgument(PsiElement element) {
+ final PsiExpressionList expressionList =
+ PsiTreeUtil.getParentOfType(element, PsiExpressionList.class, true, PsiCodeBlock.class, PsiStatement.class, PsiClass.class);
+ if (expressionList == null) {
+ return false;
+ }
+ final PsiElement parent = expressionList.getParent();
+ return parent instanceof PsiMethodCallExpression && isFormatCall((PsiMethodCallExpression)parent);
+ }
+
@Nullable
public static PsiExpression getFormatArgument(PsiExpressionList argumentList) {
final PsiExpression[] arguments = argumentList.getExpressions();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ParenthesesUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ParenthesesUtils.java
index 74535a305bb8..8523c161d0fa 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ParenthesesUtils.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ParenthesesUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -259,12 +259,15 @@ public class ParenthesesUtils {
return;
}
else if (parent instanceof PsiArrayAccessExpression) {
- // use addAfter() + delete() instead of replace() to
- // workaround automatic insertion of parentheses by psi
- final PsiExpression newExpression = (PsiExpression)parent.addAfter(body, parenthesizedExpression);
- parenthesizedExpression.delete();
- removeParentheses(newExpression, ignoreClarifyingParentheses);
- return;
+ final PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression)parent;
+ if (parenthesizedExpression == arrayAccessExpression.getIndexExpression()) {
+ // use addAfter() + delete() instead of replace() to
+ // workaround automatic insertion of parentheses by psi
+ final PsiExpression newExpression = (PsiExpression)parent.addAfter(body, parenthesizedExpression);
+ parenthesizedExpression.delete();
+ removeParentheses(newExpression, ignoreClarifyingParentheses);
+ return;
+ }
}
final PsiExpression parentExpression = (PsiExpression)parent;
final int parentPrecedence = getPrecedence(parentExpression);
@@ -441,18 +444,36 @@ public class ParenthesesUtils {
if (child == null) {
return true;
}
+ if (parent instanceof PsiArrayAccessExpression) {
+ final PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression)parent;
+ final PsiExpression indexExpression = arrayAccessExpression.getIndexExpression();
+ if (expression == indexExpression) {
+ return false;
+ }
+ }
return areParenthesesNeeded(child, (PsiExpression)parent, ignoreClarifyingParentheses);
}
- public static boolean areParenthesesNeeded(PsiExpression expression, PsiExpression parentExpression,
- boolean ignoreClarifyingParentheses) {
- if (parentExpression instanceof PsiParenthesizedExpression || parentExpression instanceof PsiArrayAccessExpression ||
- parentExpression instanceof PsiArrayInitializerExpression) {
+ private static boolean areParenthesesNeeded(PsiExpression expression, PsiExpression parentExpression,
+ boolean ignoreClarifyingParentheses) {
+ if (parentExpression instanceof PsiParenthesizedExpression || parentExpression instanceof PsiArrayInitializerExpression) {
return false;
}
final int parentPrecedence = getPrecedence(parentExpression);
final int childPrecedence = getPrecedence(expression);
if (parentPrecedence > childPrecedence) {
+ if (ignoreClarifyingParentheses) {
+ if (expression instanceof PsiPolyadicExpression) {
+ if (parentExpression instanceof PsiPolyadicExpression ||
+ parentExpression instanceof PsiConditionalExpression ||
+ parentExpression instanceof PsiInstanceOfExpression) {
+ return true;
+ }
+ }
+ else if (expression instanceof PsiInstanceOfExpression) {
+ return true;
+ }
+ }
return false;
}
if (parentExpression instanceof PsiPolyadicExpression && expression instanceof PsiPolyadicExpression) {
@@ -484,9 +505,11 @@ public class ParenthesesUtils {
}
}
final IElementType parentOperator = parentPolyadicExpression.getOperationTokenType();
- final IElementType childOperator = childPolyadicExpression.getOperationTokenType();
- if (ignoreClarifyingParentheses && !childOperator.equals(parentOperator)) {
- return true;
+ if (ignoreClarifyingParentheses) {
+ final IElementType childOperator = childPolyadicExpression.getOperationTokenType();
+ if (!childOperator.equals(parentOperator)) {
+ return true;
+ }
}
final PsiExpression[] parentOperands = parentPolyadicExpression.getOperands();
if (!PsiTreeUtil.isAncestor(parentOperands[0], expression, false)) {
@@ -494,8 +517,7 @@ public class ParenthesesUtils {
return true;
}
}
- return false;
}
- return parentPrecedence != childPrecedence;
+ return parentPrecedence < childPrecedence;
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/SwitchUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/SwitchUtils.java
index 43a243ef9c03..653038346c10 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/SwitchUtils.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/SwitchUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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,6 +18,7 @@ package com.siyeh.ig.psiutils;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -25,11 +26,9 @@ import org.jetbrains.annotations.Nullable;
public class SwitchUtils {
- private SwitchUtils() {
- }
+ private SwitchUtils() {}
- public static int calculateBranchCount(
- @NotNull PsiSwitchStatement statement) {
+ public static int calculateBranchCount(@NotNull PsiSwitchStatement statement) {
final PsiCodeBlock body = statement.getBody();
int branches = 0;
if (body == null) {
@@ -45,25 +44,17 @@ public class SwitchUtils {
}
@Nullable
- public static PsiExpression getSwitchExpression(PsiIfStatement statement,
- int minimumBranches) {
+ public static PsiExpression getSwitchExpression(PsiIfStatement statement, int minimumBranches) {
final PsiExpression condition = statement.getCondition();
- final LanguageLevel languageLevel =
- PsiUtil.getLanguageLevel(statement);
- final PsiExpression possibleSwitchExpression =
- determinePossibleSwitchExpressions(condition, languageLevel);
- if (possibleSwitchExpression == null) {
- return null;
- }
- if (SideEffectChecker.mayHaveSideEffects(possibleSwitchExpression)) {
+ final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(statement);
+ final PsiExpression possibleSwitchExpression = determinePossibleSwitchExpressions(condition, languageLevel);
+ if (!canBeSwitchExpression(possibleSwitchExpression, languageLevel)) {
return null;
}
int branchCount = 0;
while (true) {
branchCount++;
- final PsiExpression caseCondition = statement.getCondition();
- if (!canBeMadeIntoCase(caseCondition, possibleSwitchExpression,
- languageLevel)) {
+ if (!canBeMadeIntoCase(statement.getCondition(), possibleSwitchExpression, languageLevel)) {
break;
}
final PsiStatement elseBranch = statement.getElseBranch();
@@ -81,103 +72,48 @@ public class SwitchUtils {
return null;
}
- private static boolean canBeMadeIntoCase(
- PsiExpression expression, PsiExpression switchExpression,
- LanguageLevel languageLevel) {
- while (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- expression = parenthesizedExpression.getExpression();
- }
+ private static boolean canBeMadeIntoCase(PsiExpression expression, PsiExpression switchExpression, LanguageLevel languageLevel) {
+ expression = ParenthesesUtils.stripParentheses(expression);
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
- final PsiExpression stringCaseExpression =
- determinePossibleStringSwitchExpression(expression);
- if (EquivalenceChecker.expressionsAreEquivalent(switchExpression,
- stringCaseExpression)) {
+ final PsiExpression stringSwitchExpression = determinePossibleStringSwitchExpression(expression);
+ if (EquivalenceChecker.expressionsAreEquivalent(switchExpression, stringSwitchExpression)) {
return true;
}
}
- if (!(expression instanceof PsiBinaryExpression)) {
+ if (!(expression instanceof PsiPolyadicExpression)) {
return false;
}
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final IElementType operation = binaryExpression.getOperationTokenType();
- final PsiExpression lhs = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final IElementType operation = polyadicExpression.getOperationTokenType();
+ final PsiExpression[] operands = polyadicExpression.getOperands();
if (operation.equals(JavaTokenType.OROR)) {
- return canBeMadeIntoCase(lhs, switchExpression, languageLevel) &&
- canBeMadeIntoCase(rhs, switchExpression, languageLevel);
- }
- else if (operation.equals(JavaTokenType.EQEQ)) {
- return (canBeCaseLabel(lhs, languageLevel) &&
- EquivalenceChecker.expressionsAreEquivalent(
- switchExpression, rhs))
- ||
- (canBeCaseLabel(rhs, languageLevel) &&
- EquivalenceChecker.expressionsAreEquivalent(
- switchExpression, lhs));
- }
- else {
- return false;
- }
- }
-
- private static PsiExpression determinePossibleSwitchExpressions(
- PsiExpression expression, LanguageLevel languageLevel) {
- while (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- expression = parenthesizedExpression.getExpression();
- }
- if (expression == null) {
- return null;
- }
- if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
- final PsiExpression jdk17Expression =
- determinePossibleStringSwitchExpression(expression);
- if (jdk17Expression != null) {
- return jdk17Expression;
+ for (PsiExpression operand : operands) {
+ if (!canBeMadeIntoCase(operand, switchExpression, languageLevel)) {
+ return false;
+ }
}
+ return true;
}
- if (!(expression instanceof PsiBinaryExpression)) {
- return null;
- }
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final IElementType operation = binaryExpression.getOperationTokenType();
- final PsiExpression lhs = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
- if (operation.equals(JavaTokenType.OROR)) {
- return determinePossibleSwitchExpressions(lhs, languageLevel);
+ else if (operation.equals(JavaTokenType.EQEQ) && operands.length == 2) {
+ return (canBeCaseLabel(operands[0], languageLevel) && EquivalenceChecker.expressionsAreEquivalent(switchExpression, operands[1])) ||
+ (canBeCaseLabel(operands[1], languageLevel) && EquivalenceChecker.expressionsAreEquivalent(switchExpression, operands[0]));
}
- else if (operation.equals(JavaTokenType.EQEQ)) {
- if (canBeCaseLabel(lhs, languageLevel) &&
- canBeSwitchExpression(rhs, languageLevel)) {
- return rhs;
- }
- else if (canBeCaseLabel(rhs, languageLevel) &&
- canBeSwitchExpression(lhs, languageLevel)) {
- return lhs;
- }
+ else {
+ return false;
}
- return null;
}
private static boolean canBeSwitchExpression(PsiExpression expression, LanguageLevel languageLevel) {
- if (expression == null) {
+ if (expression == null || SideEffectChecker.mayHaveSideEffects(expression)) {
return false;
}
final PsiType type = expression.getType();
- if (PsiType.CHAR.equals(type) || PsiType.BYTE.equals(type) ||
- PsiType.SHORT.equals(type) || PsiType.INT.equals(type)) {
+ if (PsiType.CHAR.equals(type) || PsiType.BYTE.equals(type) || PsiType.SHORT.equals(type) || PsiType.INT.equals(type)) {
return true;
}
else if (type instanceof PsiClassType) {
- if (type.equalsToText(CommonClassNames.JAVA_LANG_CHARACTER) ||
- type.equalsToText(CommonClassNames.JAVA_LANG_BYTE) ||
- type.equalsToText(CommonClassNames.JAVA_LANG_SHORT) ||
- type.equalsToText(CommonClassNames.JAVA_LANG_INTEGER)) {
+ if (type.equalsToText(CommonClassNames.JAVA_LANG_CHARACTER) || type.equalsToText(CommonClassNames.JAVA_LANG_BYTE) ||
+ type.equalsToText(CommonClassNames.JAVA_LANG_SHORT) || type.equalsToText(CommonClassNames.JAVA_LANG_INTEGER)) {
return true;
}
if (languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) {
@@ -187,30 +123,57 @@ public class SwitchUtils {
return true;
}
}
- if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7) &&
- type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7) && type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
return true;
}
}
return false;
}
- private static PsiExpression determinePossibleStringSwitchExpression(
- PsiExpression expression) {
+ private static PsiExpression determinePossibleSwitchExpressions(PsiExpression expression, LanguageLevel languageLevel) {
+ expression = ParenthesesUtils.stripParentheses(expression);
+ if (expression == null) {
+ return null;
+ }
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
+ final PsiExpression jdk17Expression = determinePossibleStringSwitchExpression(expression);
+ if (jdk17Expression != null) {
+ return jdk17Expression;
+ }
+ }
+ if (!(expression instanceof PsiPolyadicExpression)) {
+ return null;
+ }
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final IElementType operation = polyadicExpression.getOperationTokenType();
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ if (operation.equals(JavaTokenType.OROR) && operands.length > 0) {
+ return determinePossibleSwitchExpressions(operands[0], languageLevel);
+ }
+ else if (operation.equals(JavaTokenType.EQEQ) && operands.length == 2) {
+ final PsiExpression lhs = operands[0];
+ final PsiExpression rhs = operands[1];
+ if (canBeCaseLabel(lhs, languageLevel)) {
+ return rhs;
+ }
+ else if (canBeCaseLabel(rhs, languageLevel)) {
+ return lhs;
+ }
+ }
+ return null;
+ }
+
+ private static PsiExpression determinePossibleStringSwitchExpression(PsiExpression expression) {
if (!(expression instanceof PsiMethodCallExpression)) {
return null;
}
- final PsiMethodCallExpression methodCallExpression =
- (PsiMethodCallExpression)expression;
- final PsiReferenceExpression methodExpression =
- methodCallExpression.getMethodExpression();
- @NonNls final String referenceName =
- methodExpression.getReferenceName();
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+ final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+ @NonNls final String referenceName = methodExpression.getReferenceName();
if (!"equals".equals(referenceName)) {
return null;
}
- final PsiExpression qualifierExpression =
- methodExpression.getQualifierExpression();
+ final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
if (qualifierExpression == null) {
return null;
}
@@ -218,16 +181,14 @@ public class SwitchUtils {
if (type == null || !type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
return null;
}
- final PsiExpressionList argumentList =
- methodCallExpression.getArgumentList();
+ final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
if (arguments.length != 1) {
return null;
}
final PsiExpression argument = arguments[0];
final PsiType argumentType = argument.getType();
- if (argumentType == null ||
- !argumentType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
+ if (argumentType == null || !argumentType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
return null;
}
if (PsiUtil.isConstantExpression(qualifierExpression)) {
@@ -239,36 +200,23 @@ public class SwitchUtils {
return null;
}
- private static boolean canBeCaseLabel(PsiExpression expression,
- LanguageLevel languageLevel) {
+ private static boolean canBeCaseLabel(PsiExpression expression, LanguageLevel languageLevel) {
if (expression == null) {
return false;
}
- if (languageLevel.isAtLeast(LanguageLevel.JDK_1_5) &&
- expression instanceof PsiReferenceExpression) {
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_5) && expression instanceof PsiReferenceExpression) {
final PsiElement referent = ((PsiReference)expression).resolve();
if (referent instanceof PsiEnumConstant) {
return true;
}
}
final PsiType type = expression.getType();
- return type != null &&
- (PsiType.INT.equals(type) || PsiType.CHAR.equals(type) ||
- PsiType.SHORT.equals(type) || PsiType.BYTE.equals(type)) &&
+ return (PsiType.INT.equals(type) || PsiType.SHORT.equals(type) || PsiType.BYTE.equals(type) || PsiType.CHAR.equals(type)) &&
PsiUtil.isConstantExpression(expression);
}
- public static String findUniqueLabelName(PsiStatement statement,
- @NonNls String baseName) {
- PsiElement ancestor = statement;
- while (ancestor.getParent() != null) {
- if (ancestor instanceof PsiMethod
- || ancestor instanceof PsiClass
- || ancestor instanceof PsiFile) {
- break;
- }
- ancestor = ancestor.getParent();
- }
+ public static String findUniqueLabelName(PsiStatement statement, @NonNls String baseName) {
+ final PsiElement ancestor = PsiTreeUtil.getParentOfType(statement, PsiMember.class);
if (!checkForLabel(baseName, ancestor)) {
return baseName;
}
@@ -288,8 +236,7 @@ public class SwitchUtils {
return visitor.isUsed();
}
- private static class LabelSearchVisitor
- extends JavaRecursiveElementWalkingVisitor {
+ private static class LabelSearchVisitor extends JavaRecursiveElementWalkingVisitor {
private final String m_labelName;
private boolean m_used = false;
@@ -308,8 +255,7 @@ public class SwitchUtils {
@Override
public void visitLabeledStatement(PsiLabeledStatement statement) {
- final PsiIdentifier labelIdentifier =
- statement.getLabelIdentifier();
+ final PsiIdentifier labelIdentifier = statement.getLabelIdentifier();
final String labelText = labelIdentifier.getText();
if (labelText.equals(m_labelName)) {
m_used = true;
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
index a4045e144b5a..0d83164dff0e 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2012 Bas Leijdekkers
+ * Copyright 2008-2013 Bas Leijdekkers
*
* 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.siyeh.ig.psiutils;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -36,8 +35,7 @@ import java.util.*;
public class WeakestTypeFinder {
- private WeakestTypeFinder() {
- }
+ private WeakestTypeFinder() {}
@NotNull
public static Collection<PsiClass> calculateWeakestClassesNecessary(@NotNull PsiElement variableOrMethod,
@@ -56,7 +54,7 @@ public class WeakestTypeFinder {
}
}
else {
- throw new IllegalArgumentException( "PsiMethod or PsiVariable expected: " + variableOrMethod);
+ throw new IllegalArgumentException("PsiMethod or PsiVariable expected: " + variableOrMethod);
}
if (!(variableOrMethodType instanceof PsiClassType)) {
return Collections.emptyList();
@@ -66,16 +64,32 @@ public class WeakestTypeFinder {
if (variableOrMethodClass == null) {
return Collections.emptyList();
}
- final PsiManager manager = variableOrMethod.getManager();
+ Set<PsiClass> weakestTypeClasses = new HashSet<PsiClass>();
final GlobalSearchScope scope = variableOrMethod.getResolveScope();
- final Project project = manager.getProject();
- final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
- final PsiClass javaLangObjectClass = facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, scope);
- if (javaLangObjectClass == null || variableOrMethodClass.equals(javaLangObjectClass)) {
- return Collections.emptyList();
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(variableOrMethod.getProject());
+ final PsiClass lowerBoundClass;
+ if (variableOrMethod instanceof PsiResourceVariable) {
+ lowerBoundClass = facade.findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, scope);
+ if (lowerBoundClass == null || variableOrMethodClass.equals(lowerBoundClass)) {
+ return Collections.emptyList();
+ }
+ weakestTypeClasses.add(lowerBoundClass);
+ final PsiResourceVariable resourceVariable = (PsiResourceVariable)variableOrMethod;
+ @NonNls final String methodCallText = resourceVariable.getName() + ".close()";
+ final PsiMethodCallExpression methodCallExpression =
+ (PsiMethodCallExpression)facade.getElementFactory().createExpressionFromText(methodCallText, resourceVariable.getParent());
+ if (!findWeakestType(methodCallExpression, weakestTypeClasses)) {
+ return Collections.emptyList();
+ }
}
- Set<PsiClass> weakestTypeClasses = new HashSet<PsiClass>();
- weakestTypeClasses.add(javaLangObjectClass);
+ else {
+ lowerBoundClass = facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, scope);
+ if (lowerBoundClass == null || variableOrMethodClass.equals(lowerBoundClass)) {
+ return Collections.emptyList();
+ }
+ weakestTypeClasses.add(lowerBoundClass);
+ }
+
final Query<PsiReference> query = ReferencesSearch.search(variableOrMethod, variableOrMethod.getUseScope());
boolean hasUsages = false;
for (PsiReference reference : query) {
@@ -311,8 +325,7 @@ public class WeakestTypeFinder {
return checkType(type, substitutor, weakestTypeClasses);
}
- private static boolean checkType(@Nullable PsiType type,
- @NotNull PsiSubstitutor substitutor,
+ private static boolean checkType(@Nullable PsiType type, @NotNull PsiSubstitutor substitutor,
@NotNull Collection<PsiClass> weakestTypeClasses) {
if (!(type instanceof PsiClassType)) {
return false;
@@ -330,28 +343,19 @@ public class WeakestTypeFinder {
return true;
}
- private static boolean findWeakestType(PsiMethodCallExpression methodCallExpression,
- Set<PsiClass> weakestTypeClasses) {
+ private static boolean findWeakestType(PsiMethodCallExpression methodCallExpression, Set<PsiClass> weakestTypeClasses) {
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
final PsiElement target = methodExpression.resolve();
if (!(target instanceof PsiMethod)) {
return false;
}
- PsiClass autoClosable = null;
- final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
- if (qualifierExpression instanceof PsiReferenceExpression) {
- final PsiElement resolve = ((PsiReferenceExpression)qualifierExpression).resolve();
- if (resolve instanceof PsiResourceVariable) {
- autoClosable = JavaPsiFacade.getInstance(resolve.getProject()).findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, resolve.getResolveScope());
- }
- }
final PsiMethod method = (PsiMethod)target;
final PsiReferenceList throwsList = method.getThrowsList();
final PsiClassType[] classTypes = throwsList.getReferencedTypes();
final Collection<PsiClassType> thrownTypes = new HashSet<PsiClassType>(Arrays.asList(classTypes));
- final PsiMethod[] superMethods = method.findDeepestSuperMethods();
+ final List<PsiMethod> superMethods = findAllSuperMethods(method);
boolean checked = false;
- if (superMethods.length > 0) {
+ if (!superMethods.isEmpty()) {
final PsiType expectedType = ExpectedTypeUtils.findExpectedType(methodCallExpression, false);
for (PsiMethod superMethod : superMethods) {
final PsiType returnType = superMethod.getReturnType();
@@ -365,9 +369,6 @@ public class WeakestTypeFinder {
continue;
}
final PsiClass containingClass = superMethod.getContainingClass();
- if (autoClosable != null && !InheritanceUtil.isInheritorOrSelf(containingClass, autoClosable, true)) {
- continue;
- }
checkClass(containingClass, weakestTypeClasses);
checked = true;
}
@@ -382,18 +383,28 @@ public class WeakestTypeFinder {
}
}
final PsiClass containingClass = method.getContainingClass();
- if (autoClosable != null && !InheritanceUtil.isInheritorOrSelf(containingClass, autoClosable, true)) {
- return false;
- }
checkClass(containingClass, weakestTypeClasses);
}
return true;
}
- private static boolean findWeakestType(PsiElement referenceElement,
- PsiAssignmentExpression assignmentExpression,
- boolean useRighthandTypeAsWeakestTypeInAssignments,
- Set<PsiClass> weakestTypeClasses) {
+ private static List<PsiMethod> findAllSuperMethods(PsiMethod method) {
+ final List<PsiMethod> methods = findAllSuperMethods(method, new ArrayList());
+ Collections.reverse(methods);
+ return methods;
+ }
+
+ private static List<PsiMethod> findAllSuperMethods(PsiMethod method, List<PsiMethod> result) {
+ final PsiMethod[] superMethods = method.findSuperMethods();
+ Collections.addAll(result, superMethods);
+ for (PsiMethod superMethod : superMethods) {
+ findAllSuperMethods(superMethod, result);
+ }
+ return result;
+ }
+
+ private static boolean findWeakestType(PsiElement referenceElement, PsiAssignmentExpression assignmentExpression,
+ boolean useRighthandTypeAsWeakestTypeInAssignments, Set<PsiClass> weakestTypeClasses) {
final IElementType tokenType = assignmentExpression.getOperationTokenType();
if (JavaTokenType.EQ != tokenType) {
return false;
@@ -410,8 +421,7 @@ public class WeakestTypeFinder {
if (rhs == null) {
return false;
}
- if (!(rhs instanceof PsiNewExpression) ||
- !(rhs instanceof PsiTypeCastExpression)) {
+ if (!(rhs instanceof PsiNewExpression) || !(rhs instanceof PsiTypeCastExpression)) {
final PsiType rhsType = rhs.getType();
if (lhsType == null || lhsType.equals(rhsType)) {
return false;
@@ -431,13 +441,11 @@ public class WeakestTypeFinder {
return checkType(componentType, weakestTypeClasses);
}
- private static boolean findWeakestType(PsiThrowStatement throwStatement,
- PsiClass variableOrMethodClass,
+ private static boolean findWeakestType(PsiThrowStatement throwStatement, PsiClass variableOrMethodClass,
Set<PsiClass> weakestTypeClasses) {
final PsiClassType runtimeExceptionType = TypeUtils.getType(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, throwStatement);
final PsiClass runtimeExceptionClass = runtimeExceptionType.resolve();
- if (runtimeExceptionClass != null &&
- InheritanceUtil.isInheritorOrSelf(variableOrMethodClass, runtimeExceptionClass, true)) {
+ if (runtimeExceptionClass != null && InheritanceUtil.isInheritorOrSelf(variableOrMethodClass, runtimeExceptionClass, true)) {
if (!checkType(runtimeExceptionType, weakestTypeClasses)) {
return false;
}
@@ -472,9 +480,15 @@ public class WeakestTypeFinder {
private static boolean throwsIncompatibleException(PsiMethod method, Collection<PsiClassType> exceptionTypes) {
final PsiReferenceList superThrowsList = method.getThrowsList();
final PsiClassType[] superThrownTypes = superThrowsList.getReferencedTypes();
+ outer:
for (PsiClassType superThrownType : superThrownTypes) {
if (exceptionTypes.contains(superThrownType)) {
- return true;
+ continue;
+ }
+ for (PsiClassType exceptionType : exceptionTypes) {
+ if (InheritanceUtil.isInheritor(superThrownType, exceptionType.getCanonicalText())) {
+ continue outer;
+ }
}
final PsiClass aClass = superThrownType.resolve();
if (aClass == null) {
@@ -517,8 +531,7 @@ public class WeakestTypeFinder {
}
@Nullable
- private static PsiClass getVisibleInheritor(PsiClass superClass,
- PsiElement context) {
+ private static PsiClass getVisibleInheritor(PsiClass superClass, PsiElement context) {
final Query<PsiClass> search = DirectClassInheritorsSearch.search(superClass, context.getResolveScope());
for (PsiClass aClass : search) {
if (superClass.isInheritor(aClass, true)) {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
index 67246337c22b..cfa66387b071 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2012 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,6 @@ package com.siyeh.ig.style;
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.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -33,26 +32,20 @@ import java.util.Set;
public class UnnecessaryInterfaceModifierInspection extends BaseInspection {
private static final Set<String> INTERFACE_REDUNDANT_MODIFIERS =
- new HashSet<String>(Arrays.asList(PsiModifier.ABSTRACT,
- PsiModifier.STATIC));
+ new HashSet<String>(Arrays.asList(PsiModifier.ABSTRACT, PsiModifier.STATIC));
private static final Set<String> INNER_CLASS_REDUNDANT_MODIFIERS =
- new HashSet<String>(Arrays.asList(PsiModifier.PUBLIC,
- PsiModifier.STATIC));
+ new HashSet<String>(Arrays.asList(PsiModifier.PUBLIC, PsiModifier.STATIC));
private static final Set<String> INNER_INTERFACE_REDUNDANT_MODIFIERS =
- new HashSet<String>(Arrays.asList(PsiModifier.PUBLIC,
- PsiModifier.ABSTRACT, PsiModifier.STATIC));
+ new HashSet<String>(Arrays.asList(PsiModifier.PUBLIC, PsiModifier.ABSTRACT, PsiModifier.STATIC));
private static final Set<String> FIELD_REDUNDANT_MODIFIERS =
- new HashSet<String>(Arrays.asList(PsiModifier.PUBLIC,
- PsiModifier.STATIC, PsiModifier.FINAL));
+ new HashSet<String>(Arrays.asList(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL));
private static final Set<String> METHOD_REDUNDANT_MODIFIERS =
- new HashSet<String>(Arrays.asList(PsiModifier.PUBLIC,
- PsiModifier.ABSTRACT));
+ new HashSet<String>(Arrays.asList(PsiModifier.PUBLIC, PsiModifier.ABSTRACT));
@Override
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "unnecessary.interface.modifier.display.name");
+ return InspectionGadgetsBundle.message("unnecessary.interface.modifier.display.name");
}
@Override
@@ -65,32 +58,21 @@ public class UnnecessaryInterfaceModifierInspection extends BaseInspection {
final PsiClass containingClass = aClass.getContainingClass();
if (containingClass != null) {
if (aClass.isInterface()) {
- if (containingClass.isInterface()) {
- return InspectionGadgetsBundle.message(
- "unnecessary.interface.modifier.inner.interface.of.interface.problem.descriptor");
- }
- else {
- return InspectionGadgetsBundle.message(
- "unnecessary.interface.modifier.inner.interface.of.class.problem.descriptor");
- }
+ return InspectionGadgetsBundle.message("unnecessary.interface.modifier.inner.interface.of.interface.problem.descriptor");
}
else {
- return InspectionGadgetsBundle.message(
- "unnecessary.interface.modifier.problem.descriptor3");
+ return InspectionGadgetsBundle.message("unnecessary.interface.modifier.problem.descriptor3");
}
}
else {
- return InspectionGadgetsBundle.message(
- "unnecessary.interface.modifier.problem.descriptor");
+ return InspectionGadgetsBundle.message("unnecessary.interface.modifier.problem.descriptor");
}
}
else if (parent instanceof PsiMethod) {
- return InspectionGadgetsBundle.message(
- "unnecessary.interface.modifier.problem.descriptor2");
+ return InspectionGadgetsBundle.message("unnecessary.interface.modifier.problem.descriptor2");
}
else {
- return InspectionGadgetsBundle.message(
- "unnecessary.interface.modifier.problem.descriptor4");
+ return InspectionGadgetsBundle.message("unnecessary.interface.modifier.problem.descriptor4");
}
}
@@ -104,8 +86,7 @@ public class UnnecessaryInterfaceModifierInspection extends BaseInspection {
return new UnnecessaryInterfaceModifiersFix((String)infos[0]);
}
- private static class UnnecessaryInterfaceModifiersFix
- extends InspectionGadgetsFix {
+ private static class UnnecessaryInterfaceModifiersFix extends InspectionGadgetsFix {
private final String modifiersText;
@@ -115,13 +96,11 @@ public class UnnecessaryInterfaceModifierInspection extends BaseInspection {
@NotNull
public String getName() {
- return InspectionGadgetsBundle.message(
- "smth.unnecessary.remove.quickfix", modifiersText);
+ return InspectionGadgetsBundle.message("smth.unnecessary.remove.quickfix", modifiersText);
}
@Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ public void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiModifierList modifierList;
if (element instanceof PsiModifierList) {
@@ -142,8 +121,7 @@ public class UnnecessaryInterfaceModifierInspection extends BaseInspection {
if (aClass.isInterface()) {
modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
}
- final PsiClass containingClass =
- ClassUtils.getContainingClass(modifierOwner);
+ final PsiClass containingClass = ClassUtils.getContainingClass(modifierOwner);
if (containingClass != null && containingClass.isInterface()) {
// do the inner classes
modifierList.setModifierProperty(PsiModifier.PUBLIC, false);
@@ -160,8 +138,7 @@ public class UnnecessaryInterfaceModifierInspection extends BaseInspection {
}
}
- private static class UnnecessaryInterfaceModifierVisitor
- extends BaseInspectionVisitor {
+ private static class UnnecessaryInterfaceModifierVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
@@ -169,18 +146,15 @@ public class UnnecessaryInterfaceModifierInspection extends BaseInspection {
if (parent != null && parent.isInterface()) {
final PsiModifierList modifiers = aClass.getModifierList();
if (aClass.isInterface()) {
- checkForRedundantModifiers(modifiers,
- INNER_INTERFACE_REDUNDANT_MODIFIERS);
+ checkForRedundantModifiers(modifiers, INNER_INTERFACE_REDUNDANT_MODIFIERS);
}
else {
- checkForRedundantModifiers(modifiers,
- INNER_CLASS_REDUNDANT_MODIFIERS);
+ checkForRedundantModifiers(modifiers, INNER_CLASS_REDUNDANT_MODIFIERS);
}
}
else if (aClass.isInterface()) {
final PsiModifierList modifiers = aClass.getModifierList();
- checkForRedundantModifiers(modifiers,
- INTERFACE_REDUNDANT_MODIFIERS);
+ checkForRedundantModifiers(modifiers, INTERFACE_REDUNDANT_MODIFIERS);
}
}
@@ -212,8 +186,7 @@ public class UnnecessaryInterfaceModifierInspection extends BaseInspection {
checkForRedundantModifiers(modifiers, METHOD_REDUNDANT_MODIFIERS);
}
- public void checkForRedundantModifiers(PsiModifierList list,
- Set<String> modifiers) {
+ public void checkForRedundantModifiers(PsiModifierList list, Set<String> modifiers) {
if (list == null) {
return;
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java
index 88f78160511b..42e901e7c434 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryParenthesesInspection.java
@@ -108,48 +108,20 @@ public class UnnecessaryParenthesesInspection extends BaseInspection {
@Override
public void visitParenthesizedExpression(PsiParenthesizedExpression expression) {
final PsiElement parent = expression.getParent();
- final PsiExpression child = expression.getExpression();
- if (child == null) {
+ if (parent instanceof PsiParenthesizedExpression) {
return;
}
- if (!(parent instanceof PsiExpression) || parent instanceof PsiParenthesizedExpression
- || parent instanceof PsiArrayAccessExpression || parent instanceof PsiArrayInitializerExpression) {
- registerError(expression);
- return;
- }
- final int parentPrecedence = ParenthesesUtils.getPrecedence((PsiExpression)parent);
- final int childPrecedence = ParenthesesUtils.getPrecedence(child);
- if (parentPrecedence > childPrecedence) {
- if (ignoreClarifyingParentheses) {
- if (child instanceof PsiPolyadicExpression) {
- if (parent instanceof PsiPolyadicExpression ||
- parent instanceof PsiConditionalExpression ||
- parent instanceof PsiInstanceOfExpression) {
- return;
- }
- }
- else if (child instanceof PsiInstanceOfExpression) {
- return;
- }
- }
- if (ignoreParenthesesOnConditionals) {
- if (parent instanceof PsiConditionalExpression) {
- final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)parent;
- final PsiExpression condition = conditionalExpression.getCondition();
- if (expression == condition) {
- return;
- }
- }
+ if (ignoreParenthesesOnConditionals && parent instanceof PsiConditionalExpression) {
+ final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)parent;
+ final PsiExpression condition = conditionalExpression.getCondition();
+ if (expression == condition) {
+ return;
}
+ }
+ if (!ParenthesesUtils.areParenthesesNeeded(expression, ignoreClarifyingParentheses)) {
registerError(expression);
return;
}
- if (parentPrecedence == childPrecedence) {
- if (!ParenthesesUtils.areParenthesesNeeded(expression, ignoreClarifyingParentheses)) {
- registerError(expression);
- return;
- }
- }
super.visitParenthesizedExpression(expression);
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspection.java
index 527a239422f9..4d17db337536 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Bas Leijdekkers
+ * Copyright 2008-2012 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,8 +23,7 @@ import com.siyeh.InspectionGadgetsBundle;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
-public class SynchronizationOnLocalVariableOrMethodParameterInspection
- extends BaseInspection {
+public class SynchronizationOnLocalVariableOrMethodParameterInspection extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean reportLocalVariables = true;
@@ -34,8 +33,7 @@ public class SynchronizationOnLocalVariableOrMethodParameterInspection
@Nls
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "synchronization.on.local.variable.or.method.parameter.display.name");
+ return InspectionGadgetsBundle.message("synchronization.on.local.variable.or.method.parameter.display.name");
}
public boolean isEnabledByDefault() {
@@ -46,12 +44,10 @@ public class SynchronizationOnLocalVariableOrMethodParameterInspection
protected String buildErrorString(Object... infos) {
final Boolean localVariable = (Boolean)infos[0];
if (localVariable.booleanValue()) {
- return InspectionGadgetsBundle.message(
- "synchronization.on.local.variable.problem.descriptor");
+ return InspectionGadgetsBundle.message("synchronization.on.local.variable.problem.descriptor");
}
else {
- return InspectionGadgetsBundle.message(
- "synchronization.on.method.parameter.problem.descriptor");
+ return InspectionGadgetsBundle.message("synchronization.on.method.parameter.problem.descriptor");
}
}
@@ -59,11 +55,9 @@ public class SynchronizationOnLocalVariableOrMethodParameterInspection
return new SynchronizationOnLocalVariableVisitor();
}
- private class SynchronizationOnLocalVariableVisitor
- extends BaseInspectionVisitor {
+ private class SynchronizationOnLocalVariableVisitor extends BaseInspectionVisitor {
- public void visitSynchronizedStatement(
- PsiSynchronizedStatement statement) {
+ public void visitSynchronizedStatement(PsiSynchronizedStatement statement) {
super.visitSynchronizedStatement(statement);
if (!reportLocalVariables && !reportMethodParameters) {
return;
@@ -72,8 +66,7 @@ public class SynchronizationOnLocalVariableOrMethodParameterInspection
if (!(lockExpression instanceof PsiReferenceExpression)) {
return;
}
- final PsiReferenceExpression referenceExpression =
- (PsiReferenceExpression)lockExpression;
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lockExpression;
if (referenceExpression.isQualified()) {
return;
}
@@ -103,13 +96,16 @@ public class SynchronizationOnLocalVariableOrMethodParameterInspection
else {
return;
}
- final PsiClass parentClass =
- PsiTreeUtil.getParentOfType(statement, PsiClass.class);
- if (!PsiTreeUtil.isAncestor(parentClass, target, true)) {
- // different class, probably different thread.
+ final PsiElement statementScope = getScope(statement);
+ final PsiElement targetScope = getScope(target);
+ if (statementScope != targetScope) {
return;
}
registerError(referenceExpression, Boolean.valueOf(localVariable));
}
+
+ private PsiElement getScope(PsiElement element) {
+ return PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiLambdaExpression.class, PsiClassInitializer.class);
+ }
}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AnnotationNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AnnotationNamingConvention.html
index 5868ee95bce2..db2187b5aaa0 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/AnnotationNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AnnotationNamingConvention.html
@@ -4,7 +4,7 @@ Reports annotation classes whose names are either too short, too long, or do not
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for annotation names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for annotation names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassComplexity.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassComplexity.html
index ff78e208becc..ba9645bfc1ff 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassComplexity.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassComplexity.html
@@ -7,7 +7,7 @@ toward the total complexity. Anonymous classes with more than very low complexit
difficult to understand, and should probably be promoted to become named inner classes.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable complexity a class might have.
+Use the field below to specify the maximum complexity a class is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassMethodCount.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassMethodCount.html
index 6ba388da5fb1..562dcd0e56de 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassMethodCount.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AnonymousClassMethodCount.html
@@ -1,12 +1,11 @@
<html>
<body>
-Reports anonymous inner class with too many methods.
+Reports anonymous inner <b>class</b> with too many methods.
Anonymous classes with more than a very low number of methods may be
difficult to understand, and should probably be promoted to become named inner classes.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable number of methods
-an anonymous inner class might have.
+Use the field below to specify the maximum number of methods an anonymous inner <b>class</b> is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AssignmentToSuperclassField.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AssignmentToSuperclassField.html
new file mode 100644
index 000000000000..5a4a842cbcd8
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AssignmentToSuperclassField.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+Reports any assignments to fields from a superclass from within a constructor. It is usually better to call a constructor of the
+superclass to initialize the fields.
+<!-- tooltip end -->
+<p>
+<small>New in 12.1, Powered by InspectionGadgets</small>
+</body>
+</html> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassComplexity.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassComplexity.html
index 5545631e12d8..e57f1a74bfb3 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassComplexity.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassComplexity.html
@@ -1,12 +1,12 @@
<html>
<body>
-Reports class with too high of a total complexity. The
-total complexity of a class is the sum of the cyclomatic complexities of all the methods
-and initializers the class declares. Inherited methods and initializers are not counted
+Reports classes with too high of a total complexity. The
+total complexity of a <b>class</b> is the sum of the cyclomatic complexities of all the methods
+and initializers the <b>class</b> declares. Inherited methods and initializers are not counted
toward the total complexity.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable complexity a class might have.
+Use the field below to specify the maximum complexity a class is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassCoupling.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassCoupling.html
index 9a4dea6c0f21..0c5c3d5a1026 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassCoupling.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassCoupling.html
@@ -2,11 +2,10 @@
<body>
Reports classes which are highly coupled, i.e. that reference too many other classes.
Classes with too high a coupling can be very fragile, and should probably be broken up. References to system classes
-(those in the <b>java.</b>or <b>javax.</b> packages), are not
-counted for purposes of this inspection.
+(those in the <b>java.</b>or <b>javax.</b> packages), are not counted.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable coupling a class might have.
+Use the field below to specify the maximum coupling a class is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassInheritanceDepth.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassInheritanceDepth.html
index 01b74552b231..037a60410018 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassInheritanceDepth.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassInheritanceDepth.html
@@ -2,10 +2,10 @@
<body>
Reports class too deep in the inheritance hierarchy. Classes too deeply inherited
may be confusing, and are a good sign that refactoring may be necessary. This inspection counts all superclasses
-from a library as a single superclass (libraries are considered unmodifyable).
+from a library as a single superclass (libraries are considered unmodifiable).
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable inheritance depth a class might have.
+Use the field below to specify the maximum inheritance depth a class is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassNamingConvention.html
index 106143e562bb..fb9919e329bd 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassNamingConvention.html
@@ -4,7 +4,7 @@ Reports classes whose names are either too short, too long, or do not follow
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for class names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for class names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassNestingDepth.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassNestingDepth.html
index 5d19449ca9f3..bd8b314e0587 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassNestingDepth.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassNestingDepth.html
@@ -4,7 +4,7 @@ Reports inner classes too deeply nested. Nesting inner classes inside
inner classes is almost certain to be confusing, and is a good sign that refactoring may be necessary.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable nesting depth a class might have.
+Use the field below to specify the maximum nesting depth a class is allowed have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassWithoutNoArgConstructor.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassWithoutNoArgConstructor.html
index a6c1e99852a7..3b1d5e0dbfae 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassWithoutNoArgConstructor.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassWithoutNoArgConstructor.html
@@ -5,7 +5,7 @@ Such constructors are necessary in some contexts if a class is to be created ref
<!-- tooltip end -->
<p>
Use the checkbox below to indicate that this inspection should ignore classes which
-contain no explicit constructors, and thus are provided a default no-argument constructor
+contain no explicit constructors. These classes are provided a default no-argument constructor
by the compiler.
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ConstantNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ConstantNamingConvention.html
index 99c3c6b6201a..9bc0bdb2368a 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ConstantNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ConstantNamingConvention.html
@@ -4,9 +4,10 @@ Reports any constants whose names are either too short, too long, or do not foll
the specified regular expression pattern. Constants are fields declared <b>static final</b>.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for constant names
-(Regular expressions are in standard <b>java.util.regex</b> format). Use the
-checkbox below to specify that only immutable static final fields should be checked by this inspection.
+Use the fields below to specify minimum length, maximum length and regular expression expected for constant names
+(Regular expressions are in standard <b>java.util.regex</b> format).
+<p>
+Use the checkbox below to specify that only immutable static final fields should be checked by this inspection.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ConstructorCount.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ConstructorCount.html
index f6e8bb81050e..f5175b6ee095 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ConstructorCount.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ConstructorCount.html
@@ -5,7 +5,7 @@ too many constructors are prone to initialization errors, and may often be bette
multiple subclasses.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable number of constructors a class might have.
+Use the field below to specify the maximum number of constructors a class is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/CyclomaticComplexity.html b/plugins/InspectionGadgets/src/inspectionDescriptions/CyclomaticComplexity.html
index 96acc30811f5..9b486425fa77 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/CyclomaticComplexity.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/CyclomaticComplexity.html
@@ -5,7 +5,7 @@ complexity is basically a measurement of the number of branching points in a met
a cyclomatic complexity may be confusing and difficult to test.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable cyclomatic complexity a method might have.
+Use the field below to specify the maximum cyclomatic complexity a method is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/DuplicateCondition.html b/plugins/InspectionGadgets/src/inspectionDescriptions/DuplicateCondition.html
index 242fdae23897..f6fa1cc1b5a3 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/DuplicateCondition.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/DuplicateCondition.html
@@ -5,6 +5,9 @@ Reports on any duplicate conditions among different branches of an
desired semantics, duplicate conditions usually represent programmer oversight.
<!-- tooltip end -->
<p>
+Use the checkbox below to let this inspection ignore conditions containing method calls. Some method calls may return a different value
+on an identical invocation.
+<p>
<small>Powered by InspectionGadgets</small>
</body>
</html> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/EnumSwitchStatementWhichMissesCases.html b/plugins/InspectionGadgets/src/inspectionDescriptions/EnumSwitchStatementWhichMissesCases.html
index 827ef4f29c54..feeb593c8a5d 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/EnumSwitchStatementWhichMissesCases.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/EnumSwitchStatementWhichMissesCases.html
@@ -4,8 +4,7 @@ Reports <b>switch</b> statements
over enumerated types which do not include all of the enumerated type's elements as cases.
<!-- tooltip end -->
<p>
-Use the check box below to let this inspection ignore <b>switch</b>
-statements which include a <b>default</b> branch.
+Use the checkbox below to ignore <b>switch</b> statements which have a <b>default</b> branch.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedClassNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedClassNamingConvention.html
index cd55dc8db061..9f2382f5dbe6 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedClassNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedClassNamingConvention.html
@@ -4,7 +4,7 @@ Reports enumerated classes whose names are either too short, too long, or do not
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for enumerated class names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for enumerated class names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedConstantNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedConstantNamingConvention.html
index de47a9ed2ec9..c67aa6c5e14b 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedConstantNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/EnumeratedConstantNamingConvention.html
@@ -4,7 +4,7 @@ Reports enumerated constants whose names are either too short, too long, or do n
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for enumerated constant names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for enumerated constant names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/FieldCount.html b/plugins/InspectionGadgets/src/inspectionDescriptions/FieldCount.html
index 1053fda73f13..a6cb3d42f151 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/FieldCount.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/FieldCount.html
@@ -5,9 +5,10 @@ a large number of fields are often trying to 'do too much', and may need to be
refactored into multiple smaller classes.
<!-- tooltip end -->
<p>
-Use the controls below to specify the maximum acceptable number of fields a class might have, and
-to indicate whether constant fields count toward this number. Per default this inspection only counts
-immutable <b>static final</b> objects as constant. Use the checkbox below to
+Use the field below to specify the maximum number of fields a class is allowed to have.
+<p>
+Use the first checkbox below to indicate whether constant fields count toward this number.
+<p>Per default this inspection only counts immutable <b>static final</b> objects as constant. Use the second checkbox below to
count any <b>static final</b> field as constant.
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ForCanBeForeach.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ForCanBeForeach.html
index 2e6283893e0b..111adc7da74b 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ForCanBeForeach.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ForCanBeForeach.html
@@ -1,7 +1,7 @@
<html>
<body>
Reports <b>for</b> loops which iterate
-over collections or arrays, and can be replaced with the "for each" iteration syntax, available
+over collections or arrays, and can be replaced with the <b>foreach</b> iteration syntax, available
in Java 5 and newer.
<!-- tooltip end -->
<p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/IfStatementWithTooManyBranches.html b/plugins/InspectionGadgets/src/inspectionDescriptions/IfStatementWithTooManyBranches.html
index ba3b4cd5bf61..6ccaf0ffb7fb 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/IfStatementWithTooManyBranches.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/IfStatementWithTooManyBranches.html
@@ -5,7 +5,7 @@ Such statements may be confusing, and are often the sign of inadequate levels of
abstraction.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum number of branches expected.
+Use the field below to specify the maximum number of branches an <b>if</b> statement is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceMethodNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceMethodNamingConvention.html
index 6b5506a05232..2d43e9b5f64d 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceMethodNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceMethodNamingConvention.html
@@ -5,7 +5,7 @@ the specified regular expression pattern. Instance methods that override library
methods are ignored by this inspection.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for instance method names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for instance method names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceVariableNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceVariableNamingConvention.html
index 4f0efb6c957f..4a9c36f0490f 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceVariableNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/InstanceVariableNamingConvention.html
@@ -4,7 +4,7 @@ Reports instance variables whose names are either too short, too long, or do not
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for
+Use the fields below to specify minimum length, maximum length and regular expression expected for
instance variable names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceNamingConvention.html
index bd8d7e5ba8b5..8183383249e2 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceNamingConvention.html
@@ -4,7 +4,7 @@ Reports interfaces whose names are either too short, too long, or do not follow
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for interface names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for interface names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/JUnitAbstractTestClassNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/JUnitAbstractTestClassNamingConvention.html
index 6e9ed206f39e..8492d81e4a92 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/JUnitAbstractTestClassNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/JUnitAbstractTestClassNamingConvention.html
@@ -6,7 +6,7 @@ standard that abstract JUnit test classes follow a specific pattern, usually req
with "TestCase".
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for class names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for class names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/JUnitTestClassNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/JUnitTestClassNamingConvention.html
index 797ef090f0a5..431e0acf2563 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/JUnitTestClassNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/JUnitTestClassNamingConvention.html
@@ -6,7 +6,7 @@ standard that concrete JUnit test classes follow a specific pattern, usually req
with "Test".
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for class names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for class names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/LocalVariableNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/LocalVariableNamingConvention.html
index 449e387b2645..35fa839696c1 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/LocalVariableNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/LocalVariableNamingConvention.html
@@ -4,7 +4,7 @@ Reports local variables whose names are either too short, too long, or do not fo
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for local variables names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for local variables names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/LogStatementGuardedByLogCondition.html b/plugins/InspectionGadgets/src/inspectionDescriptions/LogStatementGuardedByLogCondition.html
index bc16a72efc06..dd4a0b561feb 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/LogStatementGuardedByLogCondition.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/LogStatementGuardedByLogCondition.html
@@ -1,17 +1,19 @@
<html>
<body>
-Reports log statements with non-constant arguments which are not
-surrounded by a guard condition.
-The evaluation of the arguments of a log statement can be expensive.
-Surrounding a log statement with a guard clause prevents that cost when the logging
-is disabled for the level used by the logging statement. This is especially for the
-least serious level (trace, debug, finest) of logging statements, because those are
+Reports logging calls with non-constant arguments which are not surrounded by a guard condition.
+The evaluation of the arguments of a logging call can be expensive.
+Surrounding a logging call with a guard clause prevents that cost, when the logging
+is disabled for the level used by the logging statement. This is especially useful for the
+least serious level (trace, debug, finest) of logging calls, because those are
most often disabled in a production environment.
<!-- tooltip end -->
<p>
-Use the text field below to specify the logger class name used. Use the table
-to specify the log methods this inspection should warn on, with the corresponding
-logging condition text.
+Use the text field below to specify the logger class name used.
+<p>
+Use the table to specify the logging methods this inspection should warn on, with the corresponding
+log condition text.
+<p>
+Use the checkbox below to let this inspection flag all unguarded log calls, not only those with non-constant arguments.
<p>
<small>New in 8, Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/LoggingConditionDisagreesWithLogStatement.html b/plugins/InspectionGadgets/src/inspectionDescriptions/LoggingConditionDisagreesWithLogStatement.html
index fa394dc4f1a3..ce67c059a7b7 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/LoggingConditionDisagreesWithLogStatement.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/LoggingConditionDisagreesWithLogStatement.html
@@ -1,7 +1,7 @@
<html>
<body>
Reports <em>is log enabled for</em> conditions of if statements which
-do not match the log level of the contained log statement.
+do not match the log level of the contained logging call.
<p>
For example:
<code><pre>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCanBeVariableArityMethod.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCanBeVariableArityMethod.html
index 62d61cd226cd..4445fa8fcb39 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCanBeVariableArityMethod.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCanBeVariableArityMethod.html
@@ -7,6 +7,10 @@ This inspection only reports if the project or module is configured to use a
language level of 5.0 or higher.
<!-- tooltip end -->
<p>
+Use the first checkbox below to not offer to convert byte[] or short[] parameters to vararg.
+<p>
+Use the second checkbox below to ignore methods overriding a method in a super class.
+<p>
<small>New in 10.5, Powered by InspectionGadgets</small>
</body>
</html> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCount.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCount.html
index 471915e3dc85..28724c52181d 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCount.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCount.html
@@ -5,11 +5,9 @@ a large number of methods are often trying to 'do too much', and may need to be
refactored into multiple smaller classes.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable number of methods
-a class might have.
+Use the field below to specify the maximum number of methods a class is allowed to have.
<p>
-Use the checkbox below to specify if simple getters and setters should be ignored
-in the method count.
+Use the checkbox below to specify that simple getters and setters should be ignored in the method count.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCoupling.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCoupling.html
index 121e7f960f29..4baba21ee9e1 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCoupling.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MethodCoupling.html
@@ -6,7 +6,7 @@ Methods with too high a coupling can be very fragile, and should probably be bro
counted for purposes of this inspection.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable coupling a method might have.
+Use the field below to specify the maximum coupling a method is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MultipleReturnPointsPerMethod.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MultipleReturnPointsPerMethod.html
index ab45f6242ca0..e7396f74045c 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/MultipleReturnPointsPerMethod.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MultipleReturnPointsPerMethod.html
@@ -1,12 +1,15 @@
<html>
<body>
-Reports methods with too many return points. Methods
-with too many return points may be confusing, and hard to refactor.
+Reports methods with too many <b>return</b> points. Methods with too many <b>return</b> points may be confusing,
+and hard to refactor. A <b>return</b> point is either a <b>return</b> statement or the falling through the bottom of a
+<b>void</b> method or constructor.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable number of return points a method might have.
-Use the check boxes below to specify if guard clause and/or return points inside
-<b>equals()</b> methods should be ignored.
+Use the field below to specify the maximum number of <b>return</b> points a method is allowed to have.
+<p>
+Use the first checkbox below to ignore guard clauses.
+<p>
+Use the second checkbox below to ignore <b>return</b> points inside <b>equals()</b> methods.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MultiplyOrDivideByPowerOfTwo.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MultiplyOrDivideByPowerOfTwo.html
index 89179a4fb58c..c2a8578868d8 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/MultiplyOrDivideByPowerOfTwo.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MultiplyOrDivideByPowerOfTwo.html
@@ -1,10 +1,10 @@
<html>
<body>
Reports multiplication of an integer value by a constant power of 2. These
-expressions may be replaced by right or left shift operations, to some possible performance improvement.
+expressions may be replaced by right or left shift operations, for a possible performance improvement.
<!-- tooltip end -->
<p>
-Use the check box below to enable the inspection for divisions by a power of two also. Note that replacing
+Use the checkbox below to enable the inspection for divisions by a power of two. Note that replacing
a power of two division by a shift does not work for negative numbers.
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/NegatedConditional.html b/plugins/InspectionGadgets/src/inspectionDescriptions/NegatedConditional.html
index 30cb00ed1326..ccd1b184ce12 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/NegatedConditional.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/NegatedConditional.html
@@ -4,8 +4,7 @@ Reports conditional expressions whose conditions are negated.
Flipping the order of the conditional expression branches will usually increase the clarity of such statements.
<!-- tooltip end -->
<p>
-Use the check box below to have comparisons of the form <b>!= null</b>
-ignored by this inspection
+Use the checkbox below to ignore comparisons of the form <b>!= null</b>.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/NegatedIfElse.html b/plugins/InspectionGadgets/src/inspectionDescriptions/NegatedIfElse.html
index 5029f07dcc69..63a12c216851 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/NegatedIfElse.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/NegatedIfElse.html
@@ -6,8 +6,7 @@ Flipping the order of the <b>if</b> and <b>else</b>
branches will usually increase the clarity of such statements.
<!-- tooltip end -->
<p>
-Use the check box below to have comparisons of the form <b>!= null</b>
-ignored by this inspection
+Use the checkbox below to ignore comparisons of the form <b>!= null</b>.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/NestingDepth.html b/plugins/InspectionGadgets/src/inspectionDescriptions/NestingDepth.html
index fa5fd1b7e41c..f658efd3a684 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/NestingDepth.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/NestingDepth.html
@@ -4,7 +4,7 @@ Reports methods whose bodies are too deeply nested. Methods with too much statem
nesting may be confusing, and are a good sign that refactoring may be necessary.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable nesting depth a method might have.
+Use the field below to specify the maximum nesting depth a method is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/NonCommentSourceStatements.html b/plugins/InspectionGadgets/src/inspectionDescriptions/NonCommentSourceStatements.html
index 5599d4592282..f1b6865cccd5 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/NonCommentSourceStatements.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/NonCommentSourceStatements.html
@@ -4,7 +4,7 @@ Reports methods that are too long. Methods that are too long
may be confusing, and are a good sign that refactoring is necessary.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable number of non-comment source statements a method might have.
+Use the field below to specify the maximum number of non-comment source statements a method is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexArithmeticExpression.html b/plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexArithmeticExpression.html
index b6d845c2f6a4..26c746a06c07 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexArithmeticExpression.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexArithmeticExpression.html
@@ -4,7 +4,7 @@ Reports arithmetic expressions with too many terms. Such
expressions may be confusing and bug-prone.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum number of terms allowed in an arithmetic expression.
+Use the field below to specify the maximum number of terms allowed in an arithmetic expression.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexBooleanExpression.html b/plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexBooleanExpression.html
index d92ae7b6e1ee..fc6f4a1314a0 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexBooleanExpression.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/OverlyComplexBooleanExpression.html
@@ -1,10 +1,11 @@
<html>
<body>
-Reports boolean expressions with too many terms. Such
-expressions may be confusing and bug-prone.
+Reports boolean expressions with too many terms. Such expressions may be confusing and bug-prone.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum number of terms allowed in a boolean expression.
+Use the field below to specify the maximum number of terms allowed in a boolean expression.
+<p>
+Use the checkbox below to ignore boolean expressions which use only a single boolean operator repeatedly.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/PackageNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/PackageNamingConvention.html
index 9eddb8328048..55fce2a987a0 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/PackageNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/PackageNamingConvention.html
@@ -4,7 +4,7 @@ This global inspection reports packages whose names are either too short, too lo
the specified regular expression pattern. Since this inspection requires global code analysis, it is only available in batch inspection mode.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for method parameter names
+Use the fields below to specify minimum length, maximum length and regular expression expected for method parameter names
(Regular expressions are in standard <b>java.util.regex</b> format).
<p>
<small>New in 11, Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ParameterNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ParameterNamingConvention.html
index ddd783ced5c6..9557e336ad5c 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ParameterNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ParameterNamingConvention.html
@@ -4,7 +4,7 @@ Reports method parameters whose names are either too short, too long, or do not
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for method parameter names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for method parameter names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerConstructor.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerConstructor.html
index 226c8ea0b002..97c9c4001e52 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerConstructor.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerConstructor.html
@@ -4,7 +4,7 @@ Reports constructors with too many parameters. Constructors
with too many parameters can be a good sign that refactoring is necessary.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable number of parameters a constructor might have.
+Use the field below to specify the maximum number of parameters a constructor is allowed to have.
<p>
Use the combobox below to specify if the inspection should ignore private, package local & private or protected, package local and
private constructors
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerMethod.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerMethod.html
index 67d3f8d3eb7b..6d6075e05e03 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerMethod.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ParametersPerMethod.html
@@ -5,7 +5,7 @@ can be a good sign that refactoring is necessary. Methods whose signatures are i
library classes are ignored by this inspection.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable number of parameters a method might have.
+Use the field below to specify the maximum number of parameters a method is allowed to have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/PlaceholderCountMatchesArgumentCount.html b/plugins/InspectionGadgets/src/inspectionDescriptions/PlaceholderCountMatchesArgumentCount.html
new file mode 100644
index 000000000000..a89605bed897
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/PlaceholderCountMatchesArgumentCount.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+Reports SLF4J logging calls where the number of {}-placeholders in the string constant argument
+does not match the number of other arguments to the logging call.
+<!-- tooltip end -->
+<p>
+<small>New in 12.1, Powered by InspectionGadgets</small>
+</body>
+</html> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/PointlessNullCheck.html b/plugins/InspectionGadgets/src/inspectionDescriptions/PointlessNullCheck.html
index e69e0d11d5b7..8d94468a2871 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/PointlessNullCheck.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/PointlessNullCheck.html
@@ -2,7 +2,7 @@
<body>
<p>Reports a <b>null</b> check followed by an <b>instanceof</b> check.
Since the <b>instanceof</b> operator always returns <b>false</b> for <b>null</b>,
-there is no need to also have a <b>null</b> check. </p>
+there is no need to have an additional <b>null</b> check. </p>
<p>Here is an example of a violation: </p>
<pre><code> if (x != null && x instanceof String) { ... }</code></pre>
<p>The quickfix changes this code to:</p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ReplaceAssignmentWithOperatorAssignment.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ReplaceAssignmentWithOperatorAssignment.html
index 1e2f9dea8373..0404e0fb7cfa 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ReplaceAssignmentWithOperatorAssignment.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ReplaceAssignmentWithOperatorAssignment.html
@@ -4,7 +4,7 @@ Reports assignment operations which can be replaced by operator-assignment. Code
using operator assignment may be clearer, and theoretically more performant.
<!-- tooltip end -->
<p>
-Use the check box below to ignore the conditional operators <b>&amp;&amp;</b>
+Use the checkbox below to ignore the conditional operators <b>&amp;&amp;</b>
and <b>||</b>. Replacing conditional operators with operator
assignment modifies the semantics of the expression.
<p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ResultOfObjectAllocationIgnored.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ResultOfObjectAllocationIgnored.html
index 077a8fb17157..a07bfe721c12 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ResultOfObjectAllocationIgnored.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ResultOfObjectAllocationIgnored.html
@@ -1,6 +1,6 @@
<html>
<body>
-Reports object allocation where the object allocated ignored.
+Reports object allocations where the object allocated is ignored, and not assigned to a variable or used in another way.
Such allocation expressions are legal Java, but are usually either inadvertent, or
evidence of a very odd object initialization strategy.
<!-- tooltip end -->
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StaticMethodNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StaticMethodNamingConvention.html
index 605ed476071b..be324e15ce8c 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/StaticMethodNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StaticMethodNamingConvention.html
@@ -1,10 +1,10 @@
<html>
<body>
-Reports static methods whose names are either too short, too long, or do not follow
+Reports <b>static</b> methods whose names are either too short, too long, or do not follow
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for static method names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for static method names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StaticVariableNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StaticVariableNamingConvention.html
index 27ef62898a9b..54040ee77476 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/StaticVariableNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StaticVariableNamingConvention.html
@@ -5,7 +5,7 @@ the specified regular expression pattern. Constants, i.e. variables of immutable
are not checked by this inspection
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for static variable names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for static variable names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html
index bdc568a2f3c7..5d8ebdfbab46 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html
@@ -1,14 +1,14 @@
<html>
<body>
-Reports string concatenations where the left literal does not
-end with whitespace and the right literal does not start with whitespace. For example:
+Reports string concatenations where the left-hand side does not
+end with whitespace or a symbol and the right-hand side does not start with whitespace or a symbol. For example:
<pre><code>
String sql = "SELECT column" +
"FROM table";
</code></pre>
<!-- tooltip end -->
<p>
-Use the checkbox below to have this inspection only report when both the left and right side of the concatenation are string literals.
+Use the checkbox below to have this inspection only report when both the left and right side of the concatenation are literals.
<p>
<small>New in 12, Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConstructor.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConstructor.html
index 3851033ebf56..a8ea2df6e63c 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConstructor.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConstructor.html
@@ -6,7 +6,7 @@ Constructing new <b>String</b> objects in this way
is rarely necessary, and may cause performance problems if done often enough.
<!-- tooltip end -->
<p>
-Use the check box below to ignore <b>String</b>
+Use the checkbox below to ignore <b>String</b>
constructor calls which have a <b>String.substring()</b>
call as parameter. A call to <b>substring()</b>
reuses the character array of the original string, which can cause a large
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StringReplaceableByStringBuffer.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StringReplaceableByStringBuffer.html
index 45e397e37d13..65299e00bf63 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/StringReplaceableByStringBuffer.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StringReplaceableByStringBuffer.html
@@ -5,7 +5,7 @@ repeatedly appended to. Such variables may be more efficiently declared as <b>ja
or <b>java.lang.StringBuilder</b>.
<!-- tooltip end -->
<p>
-Use the check box below to specify that this inspection should only warn when the variable is appended
+Use the checkbox below to specify that this inspection should only warn when the variable is appended
to in a loop.
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooFewBranches.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooFewBranches.html
index fcbd8e712f03..0832a5793d77 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooFewBranches.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooFewBranches.html
@@ -4,7 +4,7 @@ Reports <b>switch</b> statements with too few <b>case</b> labels.
Such statements may be more clearly expressed as <b>if</b> statements.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the minimum number of <b>case</b> labels expected.
+Use the field below to specify the minimum number of <b>case</b> labels expected.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooManyBranches.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooManyBranches.html
index 0ceee7b6fd87..d1853c9b399a 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooManyBranches.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SwitchStatementWithTooManyBranches.html
@@ -3,7 +3,7 @@
Reports <b>switch</b> statements with too many <b>case</b> labels.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum number of <b>case</b> labels expected.
+Use the field below to specify the maximum number of <b>case</b> labels expected.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ThrownExceptionsPerMethod.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ThrownExceptionsPerMethod.html
index 4a1d6db3543e..4c94a5df808a 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ThrownExceptionsPerMethod.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ThrownExceptionsPerMethod.html
@@ -5,7 +5,7 @@ different types of exceptions. Methods with too many exceptions declared
are a good sign that your error handling code is getting overly complex.
<!-- tooltip end -->
<p>
-Use the field provided below to specify the maximum acceptable number of throw clauses a method might have.
+Use the field below to specify the maximum number of <b>throws</b> clauses a method might have.
<p>
<small>Powered by InspectionGadgets</small>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TryFinallyCanBeTryWithResources.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TryFinallyCanBeTryWithResources.html
index 22533392f259..28b8411a23e5 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/TryFinallyCanBeTryWithResources.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TryFinallyCanBeTryWithResources.html
@@ -1,7 +1,7 @@
<html>
<body>
Reports <b>try finally</b> statements which can use Java 7
-Automatic Resource Management. A quickfix is provided to convert the <b>try finally</b>
+Automatic Resource Management. A quickfix is available to convert the <b>try finally</b>
statement into a <b>try</b> with resources statement.
<p>
This inspection only reports if the project or module is configured to use a
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html
index 79143fd4e68f..3b10d772375b 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TryWithIdenticalCatches.html
@@ -1,6 +1,6 @@
<html>
<body>
-Reports identical <b>catch</b> sections in <b>try</b> blocks under JDK 7. A quickfix is provided to collapse the sections into
+Reports identical <b>catch</b> sections in <b>try</b> blocks under JDK 7. A quickfix is available to collapse the sections into
a multi-catch section.
<p>
This inspection only reports if the project or module is configured to use a
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TypeParameterNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TypeParameterNamingConvention.html
index be4665aa3ba9..c305e8a67f9f 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/TypeParameterNamingConvention.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TypeParameterNamingConvention.html
@@ -4,7 +4,7 @@ Reports type parameters whose names are either too short, too long, or do not fo
the specified regular expression pattern.
<!-- tooltip end -->
<p>
-Use the fields provided below to specify minimum length, maximum length and regular expression expected for type parameter names.
+Use the fields below to specify minimum length, maximum length and regular expression expected for type parameter names.
(Regular expressions are in standard <b>java.util.regex</b> format.)
<p>
<small>Powered by InspectionGadgets</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/WhileCanBeForeach.html b/plugins/InspectionGadgets/src/inspectionDescriptions/WhileCanBeForeach.html
index 4bc193be7e3f..a5a7f944ff2a 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/WhileCanBeForeach.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/WhileCanBeForeach.html
@@ -1,7 +1,7 @@
<html>
<body>
Reports <b>while</b> loops which iterate
-over collections, and can be replaced with the "for each" iteration syntax,
+over collections, and can be replaced with the <b>foreach</b> iteration syntax,
which is available in Java 5 and newer.
<p>
This inspection only reports if the project or module is configured to use a
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/constant_if/Comment.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/constant_if/Comment.after.java
new file mode 100644
index 000000000000..ab585746b99e
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/constant_if/Comment.after.java
@@ -0,0 +1,6 @@
+class Test {
+ {
+ // this comment will be deleted.
+ System.out.println();
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/constant_if/Comment.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/constant_if/Comment.java
new file mode 100644
index 000000000000..21b1a2d973a3
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/constant_if/Comment.java
@@ -0,0 +1,8 @@
+class Test {
+ {
+ i<caret>f (true) {
+ // this comment will be deleted.
+ System.out.println();
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Negated.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Negated.after.java
new file mode 100644
index 000000000000..d1777e043eab
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Negated.after.java
@@ -0,0 +1,6 @@
+class Negated {
+
+ void check(String contentType) {
+ if (!"image/jpeg".equalsIgnoreCase(contentType)) {}
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Negated.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Negated.java
new file mode 100644
index 000000000000..d834fb67b7e1
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Negated.java
@@ -0,0 +1,6 @@
+class Negated {
+
+ void check(String contentType) {
+ if (contentType<caret> == null || !contentType.equalsIgnoreCase("image/jpeg")) {}
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Normal.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Normal.after.java
new file mode 100644
index 000000000000..79a55fd2112b
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Normal.after.java
@@ -0,0 +1,6 @@
+class Normal {
+
+ void check(String contentType) {
+ if ("image/jpeg".equals(contentType)) {}
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Normal.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Normal.java
new file mode 100644
index 000000000000..8b87e90495ef
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/simplifiable_equals_expression/Normal.java
@@ -0,0 +1,6 @@
+class Normal {
+
+ void check(String contentType) {
+ if ((contentType != <caret>null) && contentType.equals("image/jpeg")) {}
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/errorhandling/throws_runtime_exception/moveThrows.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/errorhandling/throws_runtime_exception/MoveThrows.java
index ea95fddcf155..ea95fddcf155 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igfixes/errorhandling/throws_runtime_exception/moveThrows.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/errorhandling/throws_runtime_exception/MoveThrows.java
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/logging/string_concatenation_argument_to_log_call/UseOfConstant.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/logging/string_concatenation_argument_to_log_call/UseOfConstant.after.java
new file mode 100644
index 000000000000..c7159d28aa56
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/logging/string_concatenation_argument_to_log_call/UseOfConstant.after.java
@@ -0,0 +1,11 @@
+import org.slf4j.*;
+
+class UseOfConstant {
+
+ void foo() {
+ Logger logger = LoggerFactory.getLogger(UseOfConstant.class);
+ final String CONST = "const";
+ String var = "var";
+ logger.info("string {}" + CONST, var);
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/logging/string_concatenation_argument_to_log_call/UseOfConstant.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/logging/string_concatenation_argument_to_log_call/UseOfConstant.java
new file mode 100644
index 000000000000..9861dfd6f0ac
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/logging/string_concatenation_argument_to_log_call/UseOfConstant.java
@@ -0,0 +1,11 @@
+import org.slf4j.*;
+
+class UseOfConstant {
+
+ void foo() {
+ Logger logger = LoggerFactory.getLogger(UseOfConstant.class);
+ final String CONST = "const";
+ String var = "var";
+ logger.in<caret>fo("string " + (var) + CONST);
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/if_can_be_switch/Comment.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/if_can_be_switch/Comment.after.java
new file mode 100644
index 000000000000..c6dc251371e5
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/if_can_be_switch/Comment.after.java
@@ -0,0 +1,15 @@
+class Comment {
+
+ String foo(int par) {
+ switch (par) {
+ case 11:
+ return "ciao";//case 1 bla bla
+ case 14:
+ return "fourteen";//case 2 bla bla
+ case 15:
+ return "fifteen"; //case 3 chchah
+ default:
+ return "default";
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/if_can_be_switch/Comment.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/if_can_be_switch/Comment.java
new file mode 100644
index 000000000000..00a181784e5d
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/migration/if_can_be_switch/Comment.java
@@ -0,0 +1,13 @@
+class Comment {
+
+ String foo(int par) {
+ i<caret>f(par == 11)
+ return "ciao";//case 1 bla bla
+ else if(par == 14)
+ return "fourteen";//case 2 bla bla
+ else if(par == 15)
+ return "fifteen"; //case 3 chchah
+ else
+ return "default";
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
index a5fe62bbe18c..3d9b0a2fd811 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
@@ -35,4 +35,10 @@ class AutoClosableTest2
bar.go();
}
}
+
+ void dodo() throws java.io.IOException {
+ try (java.io.Reader reader = new java.io.FileReader("/home/steve/foo.txt")) {
+ System.out.println(reader);
+ }
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/expected.xml
index 807c8ea762c3..599595a7163a 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/expected.xml
@@ -28,4 +28,11 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Type may be weakened</problem_class>
<description>Type of variable &lt;code&gt;bar&lt;/code&gt; may be weakened to 'com.siyeh.igtest.abstraction.weaken_type.AutoClosableTest2.Foo' #loc</description>
</problem>
+
+ <problem>
+ <file>AutoClosableTest.java</file>
+ <line>40</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Type may be weakened</problem_class>
+ <description>Type of variable &lt;code&gt;reader&lt;/code&gt; may be weakened to 'java.io.Closeable' #loc</description>
+ </problem>
</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/assignment/assignment_to_superclass_field/AssignmentToSuperclassField.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/assignment/assignment_to_superclass_field/AssignmentToSuperclassField.java
new file mode 100644
index 000000000000..c3b0fb0380f8
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/assignment/assignment_to_superclass_field/AssignmentToSuperclassField.java
@@ -0,0 +1,25 @@
+package com.siyeh.igtest.assignment.assignment_to_superclass_field;
+
+class AssignmentToSuperclassField {
+ int i = 1;
+ int j = 2;
+ int k = 0;
+
+ AssignmentToSuperclassField() {}
+
+ AssignmentToSuperclassField(int i, int j, int k) {
+ this.i = i;
+ this.j = j;
+ this.k = k;
+ }
+}
+class B extends AssignmentToSuperclassField {
+ int z;
+
+ B() {
+ i += 3;
+ this.j = 4;
+ super.k++;
+ z = 100;
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/assignment/assignment_to_superclass_field/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/assignment/assignment_to_superclass_field/expected.xml
new file mode 100644
index 000000000000..a7aa39856153
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/assignment/assignment_to_superclass_field/expected.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+
+ <problem>
+ <file>AssignmentToSuperclassField.java</file>
+ <line>20</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Constructor assigns value to field defined in superclass</problem_class>
+ <description>Assignment to field 'i' defined in superclass 'AssignmentToSuperclassField'</description>
+ </problem>
+
+ <problem>
+ <file>AssignmentToSuperclassField.java</file>
+ <line>21</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Constructor assigns value to field defined in superclass</problem_class>
+ <description>Assignment to field 'j' defined in superclass 'AssignmentToSuperclassField'</description>
+ </problem>
+
+ <problem>
+ <file>AssignmentToSuperclassField.java</file>
+ <line>22</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Constructor assigns value to field defined in superclass</problem_class>
+ <description>Assignment to field 'k' defined in superclass 'AssignmentToSuperclassField'</description>
+ </problem>
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/IgnoreResultsOfReadInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/IgnoreResultsOfReadInspection.java
deleted file mode 100644
index 010b97103504..000000000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/IgnoreResultsOfReadInspection.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.siyeh.igtest.bugs;
-
-import java.io.*;
-
-public class IgnoreResultsOfReadInspection
-{
- private void foo()
- {
- try
- {
- final FileInputStream stream = new FileInputStream("FOO");
- final byte[] buffer = new byte[10];
- stream.read(buffer);
- }
- catch(FileNotFoundException e)
- {
- }
- catch(IOException e)
- {
- }
-
- }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ignore_result_of_call/IgnoreResultOfCall.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ignore_result_of_call/IgnoreResultOfCall.java
new file mode 100644
index 000000000000..6dbce04ce831
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ignore_result_of_call/IgnoreResultOfCall.java
@@ -0,0 +1,10 @@
+package com.siyeh.igtest.bugs.ignore_result_of_call;
+
+class IgnoreResultOfCall {
+
+ void foo(Object o, String s) {
+ o.equals(s);
+ o.equals()
+ }
+
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ignore_result_of_call/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ignore_result_of_call/expected.xml
new file mode 100644
index 000000000000..7f64be4f9ef0
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ignore_result_of_call/expected.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>IgnoreResultOfCall.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Result of method call ignored</problem_class>
+ <description>Result of &lt;code&gt;Object.equals()&lt;/code&gt; is ignored #loc</description>
+ </problem>
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ResultOfObjectAllocationIgnoredInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/result_of_object_allocation_ignored/ResultOfObjectAllocationIgnored.java
index 4f76d187ba20..1185f4ddb2ca 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ResultOfObjectAllocationIgnoredInspection.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/result_of_object_allocation_ignored/ResultOfObjectAllocationIgnored.java
@@ -1,8 +1,8 @@
-package com.siyeh.igtest.bugs;
+package com.siyeh.igtest.bugs.result_of_object_allocation_ignored;
-public class ResultOfObjectAllocationIgnoredInspection {
+public class ResultOfObjectAllocationIgnored {
- private ResultOfObjectAllocationIgnoredInspection() {
+ private ResultOfObjectAllocationIgnored() {
super();
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/result_of_object_allocation_ignored/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/result_of_object_allocation_ignored/expected.xml
new file mode 100644
index 000000000000..319a29ac85b1
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/result_of_object_allocation_ignored/expected.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>ResultOfObjectAllocationIgnored.java</file>
+ <line>14</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Result of object allocation ignored</problem_class>
+ <description>Result of &lt;code&gt;new Comparable&lt;String&gt;()&lt;/code&gt; is ignored #loc</description>
+ </problem>
+
+ <problem>
+ <file>ResultOfObjectAllocationIgnored.java</file>
+ <line>10</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Result of object allocation ignored</problem_class>
+ <description>Result of &lt;code&gt;new Integer()&lt;/code&gt; is ignored #loc</description>
+ </problem>
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java
index c3f495333a7f..5d709ccd8b4b 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java
@@ -8,5 +8,7 @@ class Concatenations {
System.out.println("no:" + i);
System.out.println("i" + i);
System.out.println("i" + ((String)"j"));
+ System.out.println('{' + "a" + '\'');
+ String.format("aaaa%n" + "bbbb");
}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/PrimitiveArrayArgumnetToVariableArgMethod.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/PrimitiveArrayArgumentToVariableArgMethod.java
index 1c62329ea804..aa8620ac34c1 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/PrimitiveArrayArgumnetToVariableArgMethod.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/PrimitiveArrayArgumentToVariableArgMethod.java
@@ -1,6 +1,6 @@
package com.siyeh.igtest.bugs.var_arg;
-public class PrimitiveArrayArgumnetToVariableArgMethod
+public class PrimitiveArrayArgumentToVariableArgMethod
{
public static void main(String[] arg)
{
@@ -15,4 +15,14 @@ public class PrimitiveArrayArgumnetToVariableArgMethod
private static void methodVarArgByteArray(byte[]... bytes)
{
}
+
+ class X<T> {
+ void method(T... t) {
+ }
+ }
+
+ void foo(byte[] bs) {
+ final X<byte[]> x = new X<byte[]>();
+ x.method(bs);
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/expected.xml
index c308de6db0a5..cee36b29eb4e 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/var_arg/expected.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
- <file>PrimitiveArrayArgumnetToVariableArgMethod.java</file>
+ <file>PrimitiveArrayArgumentToVariableArgMethod.java</file>
<line>7</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Confusing primitive array argument to var-arg method</problem_class>
<description>Confusing primitive array argument to var-arg method #loc</description>
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/non_final_utility_class/NonFinalUtilityClass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/non_final_utility_class/NonFinalUtilityClass.java
index d77cc0ebe49e..9d49e02351ff 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/non_final_utility_class/NonFinalUtilityClass.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/non_final_utility_class/NonFinalUtilityClass.java
@@ -7,4 +7,7 @@ class NonFinalUtilityClass {
}
final class FinalUtilityClass {
public static void foo() {}
+}
+abstract class NoUtilityClass {
+ public static void foo() {}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_boolean_branch/DuplicateBooleanBranch.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_boolean_branch/DuplicateBooleanBranch.java
new file mode 100644
index 000000000000..d68b1d43e167
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_boolean_branch/DuplicateBooleanBranch.java
@@ -0,0 +1,8 @@
+package com.siyeh.igtest.controlflow.duplicate_boolean_branch;
+
+public class DuplicateBooleanBranch {
+
+ boolean x(boolean b, boolean c){
+ return b && b && c;
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_boolean_branch/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_boolean_branch/expected.xml
new file mode 100644
index 000000000000..f59e83b86cf3
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_boolean_branch/expected.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>DuplicateBooleanBranch.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition on '&amp;&amp;' or '||'</problem_class>
+ <description>Duplicate branch &lt;code&gt;b&lt;/code&gt; #loc</description>
+ </problem>
+
+ <problem>
+ <file>DuplicateBooleanBranch.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition on '&amp;&amp;' or '||'</problem_class>
+ <description>Duplicate branch &lt;code&gt;b&lt;/code&gt; #loc</description>
+ </problem>
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_condition/DuplicateCondition.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_condition/DuplicateCondition.java
new file mode 100644
index 000000000000..ef047398e14f
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_condition/DuplicateCondition.java
@@ -0,0 +1,12 @@
+package com.siyeh.igtest.controlflow.duplicate_condition;
+
+public class DuplicateCondition {
+
+ void x(boolean b) {
+ if (b || b || b ) {
+
+ } else if (b) {
+
+ } else if (b) {}
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_condition/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_condition/expected.xml
new file mode 100644
index 000000000000..47f1e352b5e6
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/duplicate_condition/expected.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>DuplicateCondition.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
+ <description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
+ </problem>
+
+ <problem>
+ <file>DuplicateCondition.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
+ <description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
+ </problem>
+
+ <problem>
+ <file>DuplicateCondition.java</file>
+ <line>8</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
+ <description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
+ </problem>
+
+ <problem>
+ <file>DuplicateCondition.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
+ <description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
+ </problem>
+
+ <problem>
+ <file>DuplicateCondition.java</file>
+ <line>10</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Duplicate condition in 'if' statement</problem_class>
+ <description>Duplicate condition &lt;code&gt;b&lt;/code&gt; #loc</description>
+ </problem>
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/FallthruInSwitch.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/FallthruInSwitch.java
index ed8501e48045..6ce4e6a7d4f1 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/FallthruInSwitch.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/FallthruInSwitch.java
@@ -20,7 +20,7 @@ public class FallthruInSwitch
case (4):
System.out.println("3");
case (5):
- case (6):
+ case (6): // don't warn here
System.out.println("4");
}
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/expected.xml
index fa39d92753c6..4017e6ccf8c8 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/fallthru_in_switch_statement/expected.xml
@@ -8,11 +8,4 @@
<description>&lt;code&gt;case (5):&lt;/code&gt; fall-through in 'switch' statement #loc</description>
</problem>
- <problem>
- <file>FallthruInSwitch.java</file>
- <line>23</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Fall-through in 'switch' statement</problem_class>
- <description>&lt;code&gt;case (6):&lt;/code&gt; fall-through in 'switch' statement #loc</description>
- </problem>
-
</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/overly_complex_boolean_expression/OverlyComplexBooleanExpression.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/overly_complex_boolean_expression/OverlyComplexBooleanExpression.java
new file mode 100644
index 000000000000..0bd94cfb6f81
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/overly_complex_boolean_expression/OverlyComplexBooleanExpression.java
@@ -0,0 +1,13 @@
+package com.siyeh.igtest.controlflow.overly_complex_boolean_expression;
+
+public class OverlyComplexBooleanExpression {
+
+ boolean x(boolean b) {
+ return b && b || b && b;
+ }
+
+ boolean ignore(boolean b) {
+ return b || b || b || b;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/overly_complex_boolean_expression/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/overly_complex_boolean_expression/expected.xml
new file mode 100644
index 000000000000..5af2080fb042
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/overly_complex_boolean_expression/expected.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>OverlyComplexBooleanExpression.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Overly complex boolean expression</problem_class>
+ <description>Overly complex boolean expression (4 terms) #loc</description>
+ </problem>
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression_ignore_cont_const/PointlessBooleanExpression.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression/PointlessBooleanExpression.java
index 15020be28068..0cfd2f6840ba 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression_ignore_cont_const/PointlessBooleanExpression.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression/PointlessBooleanExpression.java
@@ -28,4 +28,11 @@ class PointlessBooleanExpression {
boolean y = false || c;
boolean z = b != true;
}
+}
+class Presley {
+ void elvis(Object king) {
+ if (true && king != null && king.hashCode() > 1) {
+ // blah
+ }
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression_ignore_cont_const/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression/expected.xml
index 1d0a66df6e32..32f91701b161 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression_ignore_cont_const/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_boolean_expression/expected.xml
@@ -42,4 +42,11 @@
<description>&lt;code&gt;b != true&lt;/code&gt; can be simplified to '!b' #loc</description>
</problem>
+ <problem>
+ <file>PointlessBooleanExpression.java</file>
+ <line>34</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless boolean expression</problem_class>
+ <description>&lt;code&gt;true &amp;&amp; king != null &amp;&amp; king.hashCode() &gt; 1&lt;/code&gt; can be simplified to 'king != null &amp;&amp; king.hashCode() &gt; 1' #loc</description>
+ </problem>
+
</problems>
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_null_check/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_null_check/expected.xml
index 6805724ab1d6..de2c46db9665 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_null_check/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/pointless_null_check/expected.xml
@@ -4,48 +4,48 @@
<file>PointlessNullCheck.java</file>
<line>6</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless null check</problem_class>
- <description>Pointless null check can be removed</description>
+ <description>Unnecessary 'null' check</description>
</problem>
<problem>
<file>PointlessNullCheck.java</file>
<line>10</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless null check</problem_class>
- <description>Pointless null check can be removed</description>
+ <description>Unnecessary 'null' check</description>
</problem>
<problem>
<file>PointlessNullCheck.java</file>
<line>14</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless null check</problem_class>
- <description>Pointless null check can be removed</description>
+ <description>Unnecessary 'null' check</description>
</problem>
<problem>
<file>PointlessNullCheck.java</file>
<line>18</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless null check</problem_class>
- <description>Pointless null check can be removed</description>
+ <description>Unnecessary 'null' check</description>
</problem>
<problem>
<file>PointlessNullCheck.java</file>
<line>22</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless null check</problem_class>
- <description>Pointless null check can be removed</description>
+ <description>Unnecessary 'null' check</description>
</problem>
<problem>
<file>PointlessNullCheck.java</file>
<line>26</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless null check</problem_class>
- <description>Pointless null check can be removed</description>
+ <description>Unnecessary 'null' check</description>
</problem>
<problem>
<file>PointlessNullCheck.java</file>
<line>30</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless null check</problem_class>
- <description>Pointless null check can be removed</description>
+ <description>Unnecessary 'null' check</description>
</problem>
<problem>
<file>PointlessNullCheck.java</file>
<line>33</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless 'null' check</problem_class>
- <description>Pointless 'null' check can be removed</description>
+ <description>Unnecessary 'null' check</description>
</problem>
</problems>
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/AutoBoxing.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/AutoBoxing.java
index 796470be95c7..883b3e2e5a46 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/AutoBoxing.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/AutoBoxing.java
@@ -45,4 +45,12 @@ public class AutoBoxing {
Byte s = 8;
Short j = (byte)7;
}
+
+ void polyadic() {
+ Integer i = 1 + 2 + 3;
+ }
+
+ void doInstanceof(Object o) {
+ Boolean b = o instanceof String;
+ }
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/expected.xml
index 2f40755387dc..c5867eeadea1 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/jdk/auto_boxing/expected.xml
@@ -79,4 +79,18 @@
<description>Auto-boxing &lt;code&gt;(byte)7&lt;/code&gt; #loc</description>
</problem>
+ <problem>
+ <file>AutoBoxing.java</file>
+ <line>50</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Auto-boxing</problem_class>
+ <description>Auto-boxing &lt;code&gt;1 + 2 + 3&lt;/code&gt; #loc</description>
+ </problem>
+
+ <problem>
+ <file>AutoBoxing.java</file>
+ <line>54</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Auto-boxing</problem_class>
+ <description>Auto-boxing &lt;code&gt;o instanceof String&lt;/code&gt; #loc</description>
+ </problem>
+
</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/LogStatementGuardedByLogCondition.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/LogStatementGuardedByLogCondition.java
index b8f4f8c43443..dfb8c65cc7e0 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/LogStatementGuardedByLogCondition.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/LogStatementGuardedByLogCondition.java
@@ -32,6 +32,10 @@ public class LogStatementGuardedByLogCondition {
}
}
+ void alternativeDebugMethodSignature(int i) {
+ LOG.debug(i, "asdfasdf");
+ }
+
static class Logger {
public Logger(String log) {
@@ -40,6 +44,8 @@ public class LogStatementGuardedByLogCondition {
public void debug(String s) {
}
+ public void debug(int i, String s) {}
+
public void trace(String s) {}
public boolean isDebug() {
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/expected.xml
index e04e666cf360..701ef7837e72 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/log_statement_guarded_by_log_condition/expected.xml
@@ -14,4 +14,11 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Log statement not guarded by log condition</problem_class>
<description>&lt;code&gt;debug()&lt;/code&gt; log statement not guarded by log condition #loc</description>
</problem>
+
+ <problem>
+ <file>LogStatementGuardedByLogCondition.java</file>
+ <line>36</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Log statement not guarded by log condition</problem_class>
+ <description>&lt;code&gt;debug()&lt;/code&gt; log statement not guarded by log condition #loc</description>
+ </problem>
</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/IfCanBeSwitch.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/IfCanBeSwitch.java
index 8260653742c9..4b65e91cb8f2 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/IfCanBeSwitch.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/IfCanBeSwitch.java
@@ -1,4 +1,6 @@
-class C {
+import org.jetbrains.annotations.Nullable;
+
+class IfCanBeSwitch {
void m1(int i) { // ok
if (i == 0) System.out.println("zero"); else if (i == 1) System.out.println("one"); else System.out.println("many");
}
@@ -11,11 +13,36 @@ class C {
if (i == (byte)0) System.out.println("zero"); else if (i == (byte)1) System.out.println("one"); else System.out.println("many");
}
- void m1(int i) { // bad, long literals
+ void m2(int i) { // bad, long literals
if (i == 0L) System.out.println("zero"); else if (i == 1L) System.out.println("one"); else System.out.println("many");
}
void m2(long l) { // bad, long expression
if (l == 0) System.out.println("zero"); else if (l == 1) System.out.println("one"); else System.out.println("many");
}
+
+ void polyadic() {
+ String s = null;
+ if ("asdf".equals(s) || "addd".equals(s) || "lkjh".equals(s)) {
+ System.out.println("asdf");
+
+ } else if ("null".equals(s)) {
+ System.out.println("null");
+
+ } else {
+ System.out.println("default");
+ }
+ }
+
+ void nullable(@Nullable String s) {
+ if ("a".equals(s)) {
+ System.out.println(1);
+ } else if ("b".equals(s)) {
+ System.out.println(2);
+ } else if ("c".equals(s)) {
+ System.out.println(3);
+ } else {
+ System.out.println(4);
+ }
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/expected.xml
index 197819a78333..af78b4213567 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/if_switch/expected.xml
@@ -2,21 +2,28 @@
<problems>
<problem>
<file>IfCanBeSwitch.java</file>
- <line>3</line>
+ <line>5</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'if' replaceable with 'switch'</problem_class>
<description>&lt;code&gt;if&lt;/code&gt; statement replaceable with 'switch' statement #loc</description>
</problem>
<problem>
<file>IfCanBeSwitch.java</file>
- <line>7</line>
+ <line>9</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'if' replaceable with 'switch'</problem_class>
<description>&lt;code&gt;if&lt;/code&gt; statement replaceable with 'switch' statement #loc</description>
</problem>
<problem>
<file>IfCanBeSwitch.java</file>
- <line>11</line>
+ <line>13</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'if' replaceable with 'switch'</problem_class>
+ <description>&lt;code&gt;if&lt;/code&gt; statement replaceable with 'switch' statement #loc</description>
+ </problem>
+
+ <problem>
+ <file>IfCanBeSwitch.java</file>
+ <line>26</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'if' replaceable with 'switch'</problem_class>
<description>&lt;code&gt;if&lt;/code&gt; statement replaceable with 'switch' statement #loc</description>
</problem>
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java
index 4fd8268a94fe..db74d0cfc230 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java
@@ -17,4 +17,11 @@ abstract class MyInputStream extends Reader {
public int read(char[] cbuf) throws IOException {
return super.read(cbuf);
}
+}
+class Sub extends MethodCanBeVariableArity {
+
+ @Override
+ public void convertMe(String[] ss) {
+ super.convertMe(ss);
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/divide_by_zero/DivideByZero.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/divide_by_zero/DivideByZero.java
new file mode 100644
index 000000000000..9f24ebf109ee
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/divide_by_zero/DivideByZero.java
@@ -0,0 +1,13 @@
+package com.siyeh.igtest.numeric.divide_by_zero;
+
+public class DivideByZero {
+
+ int divide(int num) {
+ return num / 3 / 0;
+ }
+
+ int rest(int num) {
+ return num % 0 % 1;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/divide_by_zero/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/divide_by_zero/expected.xml
new file mode 100644
index 000000000000..3a07cc5477ef
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/divide_by_zero/expected.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>DivideByZero.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Division by zero</problem_class>
+ <description>Division by zero #loc</description>
+ </problem>
+
+ <problem>
+ <file>DivideByZero.java</file>
+ <line>10</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Division by zero</problem_class>
+ <description>Division by zero #loc</description>
+ </problem>
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/ImplicitNumericConversion.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/ImplicitNumericConversion.java
index 9aa5a5a2dde8..09ee0ed4b595 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/ImplicitNumericConversion.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/ImplicitNumericConversion.java
@@ -79,4 +79,8 @@ public class ImplicitNumericConversion
int a[] = new int[b];
a[b] = (byte)1;
}
+
+ private void polyadic() {
+ long l = 1 + 2 + 3;
+ }
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/expected.xml
index 3b9e14d34212..833457e3f0cb 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/implicit_numeric_conversion/expected.xml
@@ -168,4 +168,11 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Implicit numeric conversion</problem_class>
<description>Implicit numeric conversion of &lt;code&gt;(byte)1&lt;/code&gt; from 'byte' to 'int' #loc</description>
</problem>
+
+ <problem>
+ <file>ImplicitNumericConversion.java</file>
+ <line>84</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Implicit numeric conversion</problem_class>
+ <description>Implicit numeric conversion of &lt;code&gt;1 + 2 + 3&lt;/code&gt; from 'int' to 'long' #loc</description>
+ </problem>
</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java
index 60d67f02003f..9468de1baf32 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java
@@ -48,4 +48,9 @@ public class UnnecessaryExplicitNumericCast {
void target(int c) {}
void target(char c) {}
void target2(int d) {}
+
+ void foo() {
+ float x = 2;
+ target((int) x); // this line complains: 'x' unnecessarily cast to 'int'
+ }
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_parentheses/UnnecessaryParenthesesInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_parentheses/UnnecessaryParenthesesInspection.java
index ce6022abc44f..70695c4e1fff 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_parentheses/UnnecessaryParenthesesInspection.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_parentheses/UnnecessaryParenthesesInspection.java
@@ -107,4 +107,9 @@ public class UnnecessaryParenthesesInspection
final Object[] objects = {(args.length - 1), 1};
return args.length > 0 && place.equals(args[(args.length - 1)]);// here are unnecessary parentheses inside args[...]
}
+
+ void uu() {
+ Object info = new Object[]{"abc"};
+ String s = (String)((Object[])info)[0];
+ }
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter/SynchronizationOnLocalVariableOrMethodParameter.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter/SynchronizationOnLocalVariableOrMethodParameter.java
new file mode 100644
index 000000000000..6eaff9ad5acd
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter/SynchronizationOnLocalVariableOrMethodParameter.java
@@ -0,0 +1,34 @@
+package com.siyeh.igtest.threading.synchronization_on_local_variable_or_method_parameter;
+
+class SynchronizationOnLocalVariableOrMethodParameter {
+
+ static {
+ final Object lock = new Object();
+ new Object(){{
+ synchronized (lock) {} // no warning
+ }};
+ }
+
+ interface IntegerMath {
+ int operation(int a, int b);
+ }
+ public int operateBinary(int a, int b, IntegerMath op) {
+ return op.operation(a, b);
+ }
+ public static void foo() {
+ final Object lock = new Object();
+ final SynchronizationOnLocalVariableOrMethodParameter x = new SynchronizationOnLocalVariableOrMethodParameter();
+ IntegerMath addition = (a, b) -> {
+ synchronized(lock) {return a + b;} // no warning
+ };
+ System.out.println("40 + 2 = " +
+ x.operateBinary(40, 2, addition));
+ }
+
+ void bar() {
+ final Object lock = new Object();
+ synchronized (lock) {
+
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter/expected.xml
new file mode 100644
index 000000000000..efee019926d2
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter/expected.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>SynchronizationOnLocalVariableOrMethodParameter.java</file>
+ <line>30</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Synchronization on local variable or method parameter</problem_class>
+ <description>Synchronization on local variable &lt;code&gt;lock&lt;/code&gt; #loc</description>
+ </problem>
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java
new file mode 100644
index 000000000000..3760b2f16d8f
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java
@@ -0,0 +1,73 @@
+/*
+ * 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.siyeh.ig;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import org.intellij.lang.annotations.Language;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public abstract class LightInspectionTestCase extends LightCodeInsightFixtureTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ for (String environmentClass : getEnvironmentClasses()) {
+ myFixture.addClass(environmentClass);
+ }
+ myFixture.enableInspections(getInspection());
+ }
+
+ protected abstract LocalInspectionTool getInspection();
+
+ @NonNls
+ protected String[] getEnvironmentClasses() {
+ return new String[]{};
+ }
+
+ protected final void doTest(@Language("JAVA") @NotNull @NonNls String classText) {
+ @NonNls final StringBuilder newText = new StringBuilder();
+ int start = 0;
+ int end = classText.indexOf("/*");
+ while (end >= 0) {
+ newText.append(classText, start, end);
+ start = end + 2;
+ end = classText.indexOf("*/", end);
+ if (end < 0) {
+ throw new IllegalArgumentException("invalid class text");
+ }
+ final String warning = classText.substring(start, end);
+ if (warning.isEmpty()) {
+ newText.append("</warning>");
+ } else {
+ newText.append("<warning descr=\"").append(warning).append("\">");
+ }
+ start = end + 2;
+ end = classText.indexOf("/*", end + 1);
+ }
+ newText.append(classText, start, classText.length());
+ myFixture.configureByText("X.java", newText.toString());
+ myFixture.testHighlighting(true, false, false);
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/assignment/AssignmentToSuperclassFieldInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/assignment/AssignmentToSuperclassFieldInspectionTest.java
new file mode 100644
index 000000000000..c872e143c188
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/assignment/AssignmentToSuperclassFieldInspectionTest.java
@@ -0,0 +1,25 @@
+/*
+ * 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.siyeh.ig.assignment;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class AssignmentToSuperclassFieldInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/assignment/assignment_to_superclass_field", new AssignmentToSuperclassFieldInspection());
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.java
new file mode 100644
index 000000000000..9e575efebbac
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionTest.java
@@ -0,0 +1,10 @@
+package com.siyeh.ig.bugs;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class IgnoreResultOfCallInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/bugs/ignore_result_of_call", new IgnoreResultOfCallInspection());
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspectionTest.java
new file mode 100644
index 000000000000..505385d32ca2
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/PrimitiveArrayArgumentToVariableArgMethodInspectionTest.java
@@ -0,0 +1,10 @@
+package com.siyeh.ig.bugs;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class PrimitiveArrayArgumentToVariableArgMethodInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/bugs/var_arg", new PrimitiveArrayArgumentToVariableArgMethodInspection());
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/PrimitiveArrayArgumnetToVariableArgMethodInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/PrimitiveArrayArgumnetToVariableArgMethodInspectionTest.java
deleted file mode 100644
index f2b0ef1277a0..000000000000
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/PrimitiveArrayArgumnetToVariableArgMethodInspectionTest.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.siyeh.ig.bugs;
-
-import com.siyeh.ig.IGInspectionTestCase;
-
-public class PrimitiveArrayArgumnetToVariableArgMethodInspectionTest extends IGInspectionTestCase {
-
- public void test() throws Exception {
- doTest("com/siyeh/igtest/bugs/var_arg",
- new PrimitiveArrayArgumentToVariableArgMethodInspection());
- }
-} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspectionTest.java
new file mode 100644
index 000000000000..51e31a55987f
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ResultOfObjectAllocationIgnoredInspectionTest.java
@@ -0,0 +1,25 @@
+/*
+ * 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.siyeh.ig.bugs;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class ResultOfObjectAllocationIgnoredInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/bugs/result_of_object_allocation_ignored", new ResultOfObjectAllocationIgnoredInspection());
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspectionTest.java
new file mode 100644
index 000000000000..2eae159f3403
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/DuplicateBooleanBranchInspectionTest.java
@@ -0,0 +1,10 @@
+package com.siyeh.ig.controlflow;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class DuplicateBooleanBranchInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/controlflow/duplicate_boolean_branch", new DuplicateBooleanBranchInspection());
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/DuplicateConditionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/DuplicateConditionInspectionTest.java
new file mode 100644
index 000000000000..aaa379cf6ad1
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/DuplicateConditionInspectionTest.java
@@ -0,0 +1,10 @@
+package com.siyeh.ig.controlflow;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class DuplicateConditionInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/controlflow/duplicate_condition", new DuplicateConditionInspection());
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspectionTest.java
new file mode 100644
index 000000000000..bca8529d1ed7
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/OverlyComplexBooleanExpressionInspectionTest.java
@@ -0,0 +1,13 @@
+package com.siyeh.ig.controlflow;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class OverlyComplexBooleanExpressionInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ final OverlyComplexBooleanExpressionInspection tool = new OverlyComplexBooleanExpressionInspection();
+ tool.m_limit = 3;
+ tool.m_ignorePureConjunctionsDisjunctions = true;
+ doTest("com/siyeh/igtest/controlflow/overly_complex_boolean_expression", tool);
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspectionTest.java
index 5c213bf5c00e..fb1751dc2d55 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspectionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,6 @@ public class PointlessBooleanExpressionInspectionTest extends IGInspectionTestCa
public void test() throws Exception {
final PointlessBooleanExpressionInspection inspection = new PointlessBooleanExpressionInspection();
inspection.m_ignoreExpressionsContainingConstants = true;
- doTest("com/siyeh/igtest/controlflow/pointless_boolean_expression_ignore_cont_const", inspection);
+ doTest("com/siyeh/igtest/controlflow/pointless_boolean_expression", inspection);
}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessBooleanExpressionFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessBooleanExpressionFixTest.java
index f3ace921a257..30a81c245adb 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessBooleanExpressionFixTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessBooleanExpressionFixTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,9 +26,10 @@ public class PointlessBooleanExpressionFixTest extends IGQuickFixesTestCase {
super.setUp();
myFixture.enableInspections(new PointlessBooleanExpressionInspection());
myRelativePath = "pointlessboolean";
- myDefaultHint = InspectionGadgetsBundle.message("pointless.nullcheck.simplify.quickfix");
+ myDefaultHint = InspectionGadgetsBundle.message("pointless.bitwise.expression.simplify.quickfix");
}
+
public void testNegation() {
doTest();
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessNullCheckFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessNullCheckFixTest.java
index bafeb45518b2..e101a9a3e1de 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessNullCheckFixTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/PointlessNullCheckFixTest.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
- *pointless.nullcheck.quickfix
+ * 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
@@ -26,10 +26,9 @@ public class PointlessNullCheckFixTest extends IGQuickFixesTestCase {
super.setUp();
myFixture.enableInspections(new PointlessNullCheckInspection());
myRelativePath = "pointlessnullcheck";
- myDefaultHint = InspectionGadgetsBundle.message("pointless.nullcheck.simplify.quickfix");
}
public void testScenario1() {
- doTest();
+ doTest(InspectionGadgetsBundle.message("pointless.nullcheck.simplify.quickfix", "arg != null"));
}
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/ConstantIfFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/ConstantIfFixTest.java
new file mode 100644
index 000000000000..7613d1818b14
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/ConstantIfFixTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.siyeh.ig.fixes.controlflow;
+
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.controlflow.ConstantIfStatementInspection;
+
+public class ConstantIfFixTest extends IGQuickFixesTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.enableInspections(new ConstantIfStatementInspection());
+ myRelativePath = "controlflow/constant_if";
+ myDefaultHint = InspectionGadgetsBundle.message("constant.conditional.expression.simplify.quickfix");
+ }
+
+ public void testComment() { doTest(); }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/SimplifiableEqualsExpressionFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/SimplifiableEqualsExpressionFixTest.java
new file mode 100644
index 000000000000..1ec9847167d1
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/SimplifiableEqualsExpressionFixTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ig.fixes.controlflow;
+
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.controlflow.ConstantIfStatementInspection;
+import com.siyeh.ig.controlflow.SimplifiableEqualsExpressionInspection;
+
+public class SimplifiableEqualsExpressionFixTest extends IGQuickFixesTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.enableInspections(new SimplifiableEqualsExpressionInspection());
+ myRelativePath = "controlflow/simplifiable_equals_expression";
+ }
+
+ public void testNormal() { doTest(InspectionGadgetsBundle.message("simplifiable.equals.expression.quickfix", "equals")); }
+ public void testNegated() { doTest(InspectionGadgetsBundle.message("simplifiable.equals.expression.quickfix", "equalsIgnoreCase")); }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/errorhandling/ThrowsRuntimeExceptionInspectionFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/errorhandling/ThrowsRuntimeExceptionInspectionFixTest.java
index 500d8244adad..0b29ddfd081a 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/errorhandling/ThrowsRuntimeExceptionInspectionFixTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/errorhandling/ThrowsRuntimeExceptionInspectionFixTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@ package com.siyeh.ig.fixes.errorhandling;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.IGQuickFixesTestCase;
-import com.siyeh.ig.errorhandling.CaughtExceptionImmediatelyRethrownInspection;
-import com.siyeh.ig.errorhandling.EmptyFinallyBlockInspection;
import com.siyeh.ig.errorhandling.ThrowsRuntimeExceptionInspection;
public class ThrowsRuntimeExceptionInspectionFixTest extends IGQuickFixesTestCase {
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/logging/StringConcatenationArgumentToLogCallFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/logging/StringConcatenationArgumentToLogCallFixTest.java
new file mode 100644
index 000000000000..9257d3e29062
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/logging/StringConcatenationArgumentToLogCallFixTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.siyeh.ig.fixes.logging;
+
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.logging.StringConcatenationArgumentToLogCallInspection;
+
+public class StringConcatenationArgumentToLogCallFixTest extends IGQuickFixesTestCase {
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myDefaultHint = InspectionGadgetsBundle.message("string.concatenation.in.format.call.quickfix");
+ myFixture.addClass("package org.slf4j; public interface Logger { void info(String format); }");
+ myFixture.addClass("package org.slf4j; public class LoggerFactory { public static Logger getLogger(Class clazz) { return null; }}");
+ myFixture.enableInspections(new StringConcatenationArgumentToLogCallInspection());
+ }
+
+ public void testUseOfConstant() {
+ doTest();
+ }
+
+ @Override
+ protected String getRelativePath() {
+ return "logging/string_concatenation_argument_to_log_call";
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/migration/IfCanBeSwitchFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/migration/IfCanBeSwitchFixTest.java
new file mode 100644
index 000000000000..bc14f28ee9c5
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/migration/IfCanBeSwitchFixTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.siyeh.ig.fixes.migration;
+
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.migration.IfCanBeSwitchInspection;
+
+public class IfCanBeSwitchFixTest extends IGQuickFixesTestCase {
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ final IfCanBeSwitchInspection inspection = new IfCanBeSwitchInspection();
+ inspection.suggestIntSwitches = true;
+ myFixture.enableInspections(inspection);
+ myRelativePath = "migration/if_can_be_switch";
+ myDefaultHint = InspectionGadgetsBundle.message("if.can.be.switch.quickfix");
+ }
+
+ public void testComment() {
+ doTest();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java
new file mode 100644
index 000000000000..a5a246170b43
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java
@@ -0,0 +1,62 @@
+package com.siyeh.ig.logging;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.siyeh.ig.LightInspectionTestCase;
+
+public class PlaceholderCountMatchesArgumentCountInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected LocalInspectionTool getInspection() {
+ return new PlaceholderCountMatchesArgumentCountInspection();
+ }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[]{
+ "package org.slf4j; public interface Logger { void info(String format, Object... arguments); }",
+ "package org.slf4j; public class LoggerFactory { public static Logger getLogger(Class clazz) { return null; }}"};
+ }
+
+ public void testNoWarn() {
+ doTest("import org.slf4j.*;\n" +
+ "class X {\n" +
+ " void foo() {\n" +
+ " Logger logger = LoggerFactory.getLogger(X.class);\n" +
+ " logger.info(\"string {}\", 1);\n" +
+ " }\n" +
+ "}"
+ );
+ }
+
+ public void testMorePlaceholders() {
+ doTest("import org.slf4j.*;\n" +
+ "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" +
+ " }\n" +
+ "}"
+ );
+ }
+
+ public void testFewerPlaceholders() {
+ doTest("import org.slf4j.*;\n" +
+ "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" +
+ " }\n" +
+ "}"
+ );
+ }
+
+ public void testThrowable() {
+ doTest("import org.slf4j.*;\n" +
+ "class X {\n" +
+ " void foo() {\n" +
+ " Logger logger = LoggerFactory.getLogger(X.class);\n" +
+ " logger.info(\"string {}\", 1, new RuntimeException());\n" +
+ " }\n" +
+ "}"
+ );
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspectionTest.java
new file mode 100644
index 000000000000..442a2fc8d2b9
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspectionTest.java
@@ -0,0 +1,31 @@
+package com.siyeh.ig.logging;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.siyeh.ig.LightInspectionTestCase;
+
+public class StringConcatenationArgumentToLogCallInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected LocalInspectionTool getInspection() {
+ return new StringConcatenationArgumentToLogCallInspection();
+ }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[]{
+ "package org.slf4j; public interface Logger { void debug(String format); }",
+ "package org.slf4j; public class LoggerFactory { public static Logger getLogger(Class clazz) { return null; }}"};
+ }
+
+ public void testBasic() {
+ doTest("import org.slf4j.*;\n" +
+ "class X {\n" +
+ " void foo() {\n" +
+ " Logger logger = LoggerFactory.getLogger(X.class);\n" +
+ " final String CONST = \"const\";\n" +
+ " String var = \"var\";\n" +
+ " logger./*Non-constant string concatenation as argument to 'debug()' logging call*/debug/**/(\"string \" + var + CONST);\n" +
+ " }\n" +
+ "}"
+ );
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/IfCanBeSwitchInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/IfCanBeSwitchInspectionTest.java
index 07adab51d884..bf9dced7682a 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/IfCanBeSwitchInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/IfCanBeSwitchInspectionTest.java
@@ -16,12 +16,23 @@
package com.siyeh.ig.migration;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.roots.LanguageLevelProjectExtension;
+import com.intellij.pom.java.LanguageLevel;
+import com.intellij.testFramework.IdeaTestUtil;
import com.siyeh.ig.IGInspectionTestCase;
public class IfCanBeSwitchInspectionTest extends IGInspectionTestCase {
+
+ @Override
+ protected Sdk getTestProjectSdk() {
+ LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
+ return IdeaTestUtil.getMockJdk17();
+ }
+
public void test() throws Exception {
final IfCanBeSwitchInspection inspection = new IfCanBeSwitchInspection();
inspection.suggestIntSwitches = true;
- doTest("com/siyeh/igtest/migration/if_switch", new LocalInspectionToolWrapper(inspection));
+ doTest("com/siyeh/igtest/migration/if_switch", new LocalInspectionToolWrapper(inspection));
}
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java
index b07f6920fb2e..a54bd64d3b47 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java
@@ -5,10 +5,9 @@ import com.siyeh.ig.IGInspectionTestCase;
public class MethodCanBeVariableArityMethodInspectionTest extends IGInspectionTestCase {
public void test() throws Exception {
- final MethodCanBeVariableArityMethodInspection tool =
- new MethodCanBeVariableArityMethodInspection();
+ final MethodCanBeVariableArityMethodInspection tool = new MethodCanBeVariableArityMethodInspection();
tool.ignoreByteAndShortArrayParameters = true;
- doTest("com/siyeh/igtest/migration/method_can_be_variable_arity_method",
- tool);
+ tool.ignoreOverridingMethods = true;
+ doTest("com/siyeh/igtest/migration/method_can_be_variable_arity_method", tool);
}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/DivideByZeroInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/DivideByZeroInspectionTest.java
new file mode 100644
index 000000000000..7fb38a3f579d
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/DivideByZeroInspectionTest.java
@@ -0,0 +1,10 @@
+package com.siyeh.ig.numeric;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class DivideByZeroInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/numeric/divide_by_zero", new DivideByZeroInspection());
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspectionTest.java
new file mode 100644
index 000000000000..da714c2abbad
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/SynchronizationOnLocalVariableOrMethodParameterInspectionTest.java
@@ -0,0 +1,21 @@
+package com.siyeh.ig.threading;
+
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.roots.LanguageLevelProjectExtension;
+import com.intellij.pom.java.LanguageLevel;
+import com.intellij.testFramework.IdeaTestUtil;
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class SynchronizationOnLocalVariableOrMethodParameterInspectionTest extends IGInspectionTestCase {
+
+ @Override
+ protected Sdk getTestProjectSdk() {
+ LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_8);
+ return IdeaTestUtil.getMockJdk17();
+ }
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/threading/synchronization_on_local_variable_or_method_parameter",
+ new SynchronizationOnLocalVariableOrMethodParameterInspection());
+ }
+}
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomErrorElementFilter.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomErrorElementFilter.java
index b54d59f90b07..5a01e38a63fd 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomErrorElementFilter.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/CustomErrorElementFilter.java
@@ -19,7 +19,6 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoFilter;
import com.intellij.codeInsight.highlighting.HighlightErrorFilter;
import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
@@ -30,12 +29,9 @@ import org.jetbrains.annotations.Nullable;
* @author Gregory.Shrago
*/
public class CustomErrorElementFilter extends HighlightErrorFilter implements HighlightInfoFilter {
- public boolean shouldHighlightErrorElement(@NotNull final PsiErrorElement element) {
- return !value(element);
- }
- public static boolean value(final PsiErrorElement psiErrorElement) {
- return isFrankenstein(psiErrorElement.getContainingFile());
+ public boolean shouldHighlightErrorElement(@NotNull PsiErrorElement element) {
+ return !isFrankenstein(element.getContainingFile());
}
@Override
@@ -45,12 +41,11 @@ public class CustomErrorElementFilter extends HighlightErrorFilter implements Hi
if (!isFrankenstein(file)) return true;
int start = highlightInfo.getStartOffset();
int end = highlightInfo.getEndOffset();
- // the bad news are: offsets may be in host file or in injected file
- String text = (end < file.getTextLength() ? file.getText() : file.getContext().getContainingFile().getText()).substring(start, end);
+ String text = file.getText().substring(start, end);
return !"missingValue".equals(text);
}
- private static boolean isFrankenstein(PsiFile file) {
+ private static boolean isFrankenstein(@Nullable PsiFile file) {
return file != null && Boolean.TRUE.equals(file.getUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION));
}
}
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
index 2f7059153f37..f5876f4d69af 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
@@ -18,6 +18,7 @@ package org.intellij.plugins.intelliLang.inject;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.Language;
+import com.intellij.lang.LanguageUtil;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
@@ -79,12 +80,12 @@ public class InjectLanguageAction implements IntentionAction {
}
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
- doChooseLanguageToInject(editor, new Processor<String>() {
- public boolean process(final String languageId) {
+ doChooseLanguageToInject(editor, new Processor<Language>() {
+ public boolean process(final Language language) {
if (project.isDisposed()) return false;
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
- invokeImpl(project, editor, file, languageId);
+ invokeImpl(project, editor, file, language);
}
});
return false;
@@ -92,12 +93,10 @@ public class InjectLanguageAction implements IntentionAction {
});
}
- private static void invokeImpl(Project project, Editor editor, PsiFile file, String languageId) {
+ private static void invokeImpl(Project project, Editor editor, PsiFile file, Language language) {
final PsiLanguageInjectionHost host = findInjectionHost(editor, file);
if (host == null) return;
- if (defaultFunctionalityWorked(host, languageId)) return;
- Language language = InjectedLanguage.findLanguageById(languageId);
- if (language == null) return;
+ if (defaultFunctionalityWorked(host, language)) return;
try {
for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) {
if (support.addInjectionInPlace(language, host)) return;
@@ -109,20 +108,18 @@ public class InjectLanguageAction implements IntentionAction {
}
}
- private static boolean defaultFunctionalityWorked(final PsiLanguageInjectionHost host, final String languageId) {
- return Configuration.getProjectInstance(host.getProject()).setHostInjectionEnabled(host, Collections.singleton(languageId), true);
+ private static boolean defaultFunctionalityWorked(final PsiLanguageInjectionHost host, final Language language) {
+ return Configuration.getProjectInstance(host.getProject()).setHostInjectionEnabled(host, Collections.singleton(language.getID()), true);
}
- private static boolean doChooseLanguageToInject(Editor editor, final Processor<String> onChosen) {
- final String[] langIds = InjectedLanguage.getAvailableLanguageIDs();
- Arrays.sort(langIds);
+ private static boolean doChooseLanguageToInject(Editor editor, final Processor<Language> onChosen) {
+ final Language[] languages = InjectedLanguage.getAvailableLanguages();
+ Arrays.sort(languages, LanguageUtil.LANGUAGE_COMPARATOR);
- final JList list = new JBList(langIds);
- list.setCellRenderer(new ListCellRendererWrapper<String>() {
+ final JList list = new JBList(languages);
+ list.setCellRenderer(new ListCellRendererWrapper<Language>() {
@Override
- public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) {
- final Language language = InjectedLanguage.findLanguageById(value);
- assert language != null;
+ public void customize(JList list, Language language, int index, boolean selected, boolean hasFocus) {
final FileType ft = language.getAssociatedFileType();
setIcon(ft != null ? ft.getIcon() : EmptyIcon.ICON_16);
setText(language.getDisplayName() + (ft != null ? " (" + ft.getDescription() + ")" : ""));
@@ -130,10 +127,14 @@ public class InjectLanguageAction implements IntentionAction {
});
new PopupChooserBuilder(list).setItemChoosenCallback(new Runnable() {
public void run() {
- final String string = (String)list.getSelectedValue();
- onChosen.process(string);
+ onChosen.process((Language)list.getSelectedValue());
}
- }).setFilteringEnabled(new Function.Self<Object, String>())
+ }).setFilteringEnabled(new Function<Object, String>() {
+ @Override
+ public String fun(Object language) {
+ return ((Language)language).getDisplayName();
+ }
+ })
.createPopup().showInBestPositionFor(editor);
return true;
}
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectedLanguage.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectedLanguage.java
index 6f151f7953cd..f9013e5a7087 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectedLanguage.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectedLanguage.java
@@ -119,7 +119,7 @@ public final class InjectedLanguage {
}
private static boolean isInjectableLanguage(Language language) {
- if (language == Language.ANY || language == FileTypes.PLAIN_TEXT.getLanguage()) {
+ if (language == Language.ANY) {
return false;
}
if (language.getID().startsWith("$")) {
diff --git a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java
index 78d443bd4773..a05a24426dc9 100644
--- a/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java
+++ b/plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/xml/XmlLanguageInjector.java
@@ -41,6 +41,7 @@ import org.intellij.plugins.intelliLang.inject.config.AbstractTagInjection;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.intellij.plugins.intelliLang.inject.config.InjectionPlace;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.regex.Pattern;
@@ -227,8 +228,8 @@ public final class XmlLanguageInjector implements MultiHostInjector {
private static boolean areThereInjectionsWithText(final String text, Trinity<Long, Pattern, Collection<String>> index) {
if (text == null) return false;
if (index.third.contains(text)) return true;
- if (index.second.matcher(text).matches()) return true;
- return false;
+ Pattern pattern = index.second;
+ return pattern != null && pattern.matcher(text).matches();
}
private Trinity<Long, Pattern, Collection<String>> getXmlAnnotatedElementsValue() {
@@ -248,6 +249,7 @@ public final class XmlLanguageInjector implements MultiHostInjector {
return index;
}
+ @Nullable
private static Pattern buildPattern(Collection<String> stringSet) {
final StringBuilder sb = new StringBuilder();
for (String s : stringSet) {
@@ -255,7 +257,7 @@ public final class XmlLanguageInjector implements MultiHostInjector {
if (sb.length() > 0) sb.append('|');
sb.append("(?:").append(s).append(")");
}
- return Pattern.compile(sb.toString());
+ return sb.length() == 0 ? null : Pattern.compile(sb.toString());
}
}
diff --git a/plugins/IntentionPowerPak/src/META-INF/plugin.xml b/plugins/IntentionPowerPak/src/META-INF/plugin.xml
index 004627a131a7..ae2854a2d131 100644
--- a/plugins/IntentionPowerPak/src/META-INF/plugin.xml
+++ b/plugins/IntentionPowerPak/src/META-INF/plugin.xml
@@ -409,7 +409,7 @@
<categoryKey>intention.category.other</categoryKey>
</intentionAction>
<intentionAction>
- <className>com.siyeh.ipp.exceptions.SplitMulticatchIntention</className>
+ <className>com.siyeh.ipp.exceptions.SplitMultiCatchIntention</className>
<categoryKey>intention.category.other</categoryKey>
</intentionAction>
<intentionAction>
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
index a9784380e471..a75c3359d232 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
+++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
@@ -149,8 +149,8 @@ expand.to.normal.annotation.name=Expand to ''{0}''
annotate.overridden.methods.intention.family.name=Annotate overriding methods and their parameters
annotate.overridden.methods.intention.method.name=Annotate overriding methods as ''@{0}''
annotate.overridden.methods.intention.parameters.name=Annotate same parameter of overriding methods as ''@{0}''
-split.multicatch.intention.name=Split multi-catch into separate 'catch' blocks
-split.multicatch.intention.family.name=Split Multi-Catch into Separate Catch Blocks
+split.multi.catch.intention.name=Split multi-catch into separate 'catch' blocks
+split.multi.catch.intention.family.name=Split Multi-Catch into Separate Catch Blocks
replace.arm.with.try.finally.intention.name=Replace 'try-with-resources' with 'try finally'
replace.arm.with.try.finally.intention.family.name=Replace Try-With-Resources with Try-Finally
merge.nested.try.statements.intention.name=Merge nested 'try' statements
@@ -181,7 +181,7 @@ change.variable.type.to.rhs.type.intention.family.name=Change Variable Type to T
demorgans.intention.name1=Replace '\\&\\&' with '||'
demorgans.intention.name2=Replace '||' with '\\&\\&'
flip.smth.intention.name=Flip ''{0}''
-flip.smth.intention.name1=Flip ''{0}'' (may change semantics)
+flip.smth.intention.name1=Flip ''{0}'' (changes semantics)
flip.comparison.intention.name=Flip ''{0}'' to ''{1}''
negate.comparison.intention.name=Negate ''{0}''
negate.comparison.intention.name1=Negate ''{0}'' to ''{1}''
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsPredicate.java
index 9d4dfac96170..dd7e88a49121 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Bas Leijdekkers
+ * Copyright 2007-2013 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,27 +16,20 @@
package com.siyeh.ipp.exceptions;
import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.ipp.base.PsiElementPredicate;
class ConvertCatchToThrowsPredicate implements PsiElementPredicate {
public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiKeyword)) {
- return false;
- }
- final PsiJavaToken javaToken = (PsiJavaToken)element;
- final IElementType tokenType = javaToken.getTokenType();
- if (!tokenType.equals(JavaTokenType.CATCH_KEYWORD)) {
+ final PsiElement parent = element.getParent();
+ if (!(parent instanceof PsiCatchSection)) {
return false;
}
- final PsiElement parent = javaToken.getParent();
- if (!(parent instanceof PsiCatchSection)) {
+ if (element instanceof PsiCodeBlock) {
return false;
}
- final PsiMethod method =
- PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
+ final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class, true, PsiClass.class);
return method != null;
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java
index e7645c9685a5..092ff01be0a5 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -35,14 +35,15 @@ public class DetailExceptionsIntention extends Intention {
@Override
public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
final PsiJavaToken token = (PsiJavaToken)element;
- final PsiTryStatement tryStatement = (PsiTryStatement)token.getParent();
- if (tryStatement == null) {
+ PsiElement parent = token.getParent();
+ if (parent instanceof PsiCatchSection) {
+ parent = parent.getParent();
+ }
+ if (!(parent instanceof PsiTryStatement)) {
return;
}
- final String text = tryStatement.getText();
- final int length = text.length();
- @NonNls final StringBuilder newTryStatement = new StringBuilder(length);
- newTryStatement.append("try");
+ final PsiTryStatement tryStatement = (PsiTryStatement)parent;
+ @NonNls final StringBuilder newTryStatement = new StringBuilder("try");
final Set<PsiType> exceptionsThrown = new HashSet<PsiType>();
final PsiResourceList resourceList = tryStatement.getResourceList();
if (resourceList != null) {
@@ -74,24 +75,15 @@ public class DetailExceptionsIntention extends Intention {
exceptionsToExpand.removeAll(exceptionsAlreadyEmitted);
Collections.sort(exceptionsToExpand, comparator);
for (PsiType thrownType : exceptionsToExpand) {
- newTryStatement.append("catch(");
- final String exceptionType = thrownType.getCanonicalText();
- newTryStatement.append(exceptionType);
- newTryStatement.append(' ');
- final String parameterName = parameter.getName();
- newTryStatement.append(parameterName);
- newTryStatement.append(')');
- final String blockText = block.getText();
- newTryStatement.append(blockText);
+ newTryStatement.append("catch(").append(thrownType.getCanonicalText()).append(' ').append(parameter.getName()).append(')');
+ newTryStatement.append(block.getText());
exceptionsAlreadyEmitted.add(thrownType);
}
}
}
final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
if (finallyBlock != null) {
- newTryStatement.append("finally");
- final String finallyBlockText = finallyBlock.getText();
- newTryStatement.append(finallyBlockText);
+ newTryStatement.append("finally").append(finallyBlock.getText());
}
final String newStatement = newTryStatement.toString();
replaceStatementAndShorten(newStatement, tryStatement);
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsPredicate.java
index 6281ba230e73..9979821b5290 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -31,10 +31,13 @@ class DetailExceptionsPredicate implements PsiElementPredicate {
return false;
}
final IElementType tokenType = ((PsiJavaToken)element).getTokenType();
- if (!JavaTokenType.TRY_KEYWORD.equals(tokenType)) {
+ if (!JavaTokenType.TRY_KEYWORD.equals(tokenType) && !JavaTokenType.CATCH_KEYWORD.equals(tokenType)) {
return false;
}
- final PsiElement parent = element.getParent();
+ PsiElement parent = element.getParent();
+ if (parent instanceof PsiCatchSection) {
+ parent = parent.getParent();
+ }
if (!(parent instanceof PsiTryStatement)) {
return false;
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ExceptionUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ExceptionUtils.java
index 2cf500c07020..fb8431b4fd05 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ExceptionUtils.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ExceptionUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -339,9 +339,9 @@ class ExceptionUtils {
final PsiPostfixExpression postfixExpression = (PsiPostfixExpression)expression;
calculateExceptionsThrownForPostfixExpression(postfixExpression, exceptionTypes);
}
- else if (expression instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression;
- calculateExceptionsThrownForBinaryExpression(binaryExpression, exceptionTypes);
+ else if (expression instanceof PsiPolyadicExpression) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ calculateExceptionsThrownForPolyadicExpression(polyadicExpression, exceptionTypes);
}
else if (expression instanceof PsiAssignmentExpression) {
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)expression;
@@ -351,6 +351,11 @@ class ExceptionUtils {
final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)expression;
calculateExceptionsThrownForConditionalExpression(conditionalExpression, exceptionTypes);
}
+ else if (expression instanceof PsiParenthesizedExpression) {
+ final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
+ final PsiExpression innerExpression = parenthesizedExpression.getExpression();
+ calculateExceptionsThrownForExpression(innerExpression, exceptionTypes);
+ }
}
private static void calculateExceptionsThrownForTypeCast(PsiTypeCastExpression typeCastExpression, Set<PsiType> exceptionTypes) {
@@ -414,11 +419,11 @@ class ExceptionUtils {
calculateExceptionsThrownForExpression(thenExpression, exceptionTypes);
}
- private static void calculateExceptionsThrownForBinaryExpression(PsiBinaryExpression binaryExpression, Set<PsiType> exceptionTypes) {
- final PsiExpression lOperand = binaryExpression.getLOperand();
- calculateExceptionsThrownForExpression(lOperand, exceptionTypes);
- final PsiExpression rhs = binaryExpression.getROperand();
- calculateExceptionsThrownForExpression(rhs, exceptionTypes);
+ private static void calculateExceptionsThrownForPolyadicExpression(PsiPolyadicExpression polyadicExpression, Set<PsiType> exceptionTypes) {
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ for (PsiExpression operand : operands) {
+ calculateExceptionsThrownForExpression(operand, exceptionTypes);
+ }
}
private static void calculateExceptionsThrownForAssignmentExpression(PsiAssignmentExpression assignmentExpression,
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MulticatchPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MulticatchPredicate.java
index 878df78fed76..5866835ccd43 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MulticatchPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MulticatchPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Bas Leijdekkers
+ * Copyright 2011-2013 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,21 +16,15 @@
package com.siyeh.ipp.exceptions;
import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
import com.siyeh.ipp.base.PsiElementPredicate;
class MulticatchPredicate implements PsiElementPredicate {
public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiKeyword)) {
+ if (element instanceof PsiCodeBlock) {
return false;
}
- final PsiJavaToken javaToken = (PsiJavaToken)element;
- final IElementType tokenType = javaToken.getTokenType();
- if (!tokenType.equals(JavaTokenType.CATCH_KEYWORD)) {
- return false;
- }
- final PsiElement parent = javaToken.getParent();
+ final PsiElement parent = element.getParent();
if (!(parent instanceof PsiCatchSection)) {
return false;
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMulticatchIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMultiCatchIntention.java
index 1a0eab9992db..f0288078a691 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMulticatchIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitMultiCatchIntention.java
@@ -16,14 +16,15 @@
package com.siyeh.ipp.exceptions;
import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
-import java.util.List;
+import static com.intellij.psi.PsiAnnotation.TargetType;
-public class SplitMulticatchIntention extends Intention {
+public class SplitMultiCatchIntention extends Intention {
@NotNull
@Override
@@ -32,8 +33,7 @@ public class SplitMulticatchIntention extends Intention {
}
@Override
- protected void processIntention(@NotNull PsiElement element)
- throws IncorrectOperationException {
+ protected void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
final PsiElement parent = element.getParent();
if (!(parent instanceof PsiCatchSection)) {
return;
@@ -51,22 +51,28 @@ public class SplitMulticatchIntention extends Intention {
if (!(type instanceof PsiDisjunctionType)) {
return;
}
- final PsiDisjunctionType disjunctionType = (PsiDisjunctionType)type;
- final List<PsiType> disjunctions = disjunctionType.getDisjunctions();
- final PsiElementFactory factory =
- JavaPsiFacade.getElementFactory(element.getProject());
- for (PsiType disjunction : disjunctions) {
+
+ final PsiModifierList modifierList = parameter.getModifierList();
+ if (modifierList != null) {
+ for (PsiAnnotation annotation : modifierList.getAnnotations()) {
+ if (PsiImplUtil.findApplicableTarget(annotation, TargetType.TYPE_USE) == TargetType.TYPE_USE) {
+ annotation.delete();
+ }
+ }
+ }
+
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject());
+ for (PsiType disjunction : ((PsiDisjunctionType)type).getDisjunctions()) {
final PsiCatchSection copy = (PsiCatchSection)catchSection.copy();
final PsiParameter copyParameter = copy.getParameter();
- if (copyParameter == null) {
- continue;
- }
+ assert copyParameter != null : copy.getText();
final PsiTypeElement typeElement = copyParameter.getTypeElement();
- final PsiTypeElement newTypeElement =
- factory.createTypeElement(disjunction);
+ assert typeElement != null : copyParameter.getText();
+ final PsiTypeElement newTypeElement = factory.createTypeElement(disjunction);
typeElement.replace(newTypeElement);
grandParent.addBefore(copy, catchSection);
}
+
catchSection.delete();
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java
index c836078fdd87..2683504a0646 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -41,7 +42,7 @@ public class SplitTryWithMultipleResourcesIntention extends Intention {
if (resourceList == null) {
return;
}
- final StringBuilder newTryStatementText = new StringBuilder();
+ @NonNls final StringBuilder newTryStatementText = new StringBuilder();
final List<PsiResourceVariable> variables = resourceList.getResourceVariables();
boolean braces = false;
for (PsiResourceVariable variable : variables) {
@@ -60,6 +61,10 @@ public class SplitTryWithMultipleResourcesIntention extends Intention {
for (int i = 1; i < variables.size(); i++) {
newTryStatementText.append("\n}");
}
+ final PsiCatchSection[] catchSections = tryStatement.getCatchSections();
+ for (PsiCatchSection catchSection : catchSections) {
+ newTryStatementText.append(catchSection.getText());
+ }
replaceStatement(newTryStatementText.toString(), tryStatement);
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java
index 1dfdf84476da..647b56b28a8f 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,12 +28,15 @@ class TryWithMultipleResourcesPredicate implements PsiElementPredicate {
@Override
public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiJavaToken)) {
- return false;
+
+ if (element instanceof PsiJavaToken) {
+ final PsiJavaToken javaToken = (PsiJavaToken)element;
+ final IElementType tokenType = javaToken.getTokenType();
+ if (!JavaTokenType.TRY_KEYWORD.equals(tokenType)) {
+ return false;
+ }
}
- final PsiJavaToken javaToken = (PsiJavaToken)element;
- final IElementType tokenType = javaToken.getTokenType();
- if (!JavaTokenType.TRY_KEYWORD.equals(tokenType)) {
+ else if (!(element instanceof PsiResourceList)) {
return false;
}
final PsiElement parent = element.getParent();
@@ -41,10 +44,6 @@ class TryWithMultipleResourcesPredicate implements PsiElementPredicate {
return false;
}
final PsiTryStatement tryStatement = (PsiTryStatement)parent;
- final PsiCodeBlock[] catchBlocks = tryStatement.getCatchBlocks();
- if (catchBlocks.length > 0) {
- return false;
- }
final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
if (finallyBlock != null) {
return false;
@@ -57,7 +56,6 @@ class TryWithMultipleResourcesPredicate implements PsiElementPredicate {
if (tryBlock == null) {
return false;
}
- final List<PsiResourceVariable> variables = resourceList.getResourceVariables();
- return variables.size() > 1;
+ return resourceList.getResourceVariables().size() > 1;
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java
index b543fabb9e37..7055f691077e 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Dave Griffith, Bas Leijdekkers
+ * Copyright 2007-2013 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.
@@ -15,24 +15,36 @@
*/
package com.siyeh.ipp.expression;
-import com.intellij.psi.PsiBinaryExpression;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiExpression;
+import com.intellij.psi.*;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.ComparisonUtils;
-import com.siyeh.ipp.psiutils.ErrorUtil;
class ExpressionPredicate implements PsiElementPredicate {
public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiBinaryExpression)) {
+ if (!(element instanceof PsiJavaToken)) {
return false;
}
- final PsiBinaryExpression expression = (PsiBinaryExpression)element;
- final PsiExpression rhs = expression.getROperand();
- if (rhs == null) {
+ final PsiElement parent = element.getParent();
+ if (!(parent instanceof PsiPolyadicExpression)) {
return false;
}
- return !ComparisonUtils.isComparison((PsiExpression)element);
+ final PsiPolyadicExpression expression = (PsiPolyadicExpression)parent;
+ final PsiExpression[] operands = expression.getOperands();
+ if (operands.length < 2) {
+ return false;
+ }
+ PsiExpression prevOperand = null;
+ for (PsiExpression operand : operands) {
+ final PsiJavaToken token = expression.getTokenBeforeOperand(operand);
+ if (element == token) {
+ if (prevOperand == null || operand.getText().equals(prevOperand.getText())) {
+ return false;
+ }
+ break;
+ }
+ prevOperand = operand;
+ }
+ return !ComparisonUtils.isComparison(expression);
}
} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java
index e2dfc021dcba..5c992ad66f37 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2010 Dave Griffith, Bas Leijdekkers
+ * Copyright 2007-2013 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.
@@ -15,15 +15,17 @@
*/
package com.siyeh.ipp.expression;
-import com.intellij.psi.PsiBinaryExpression;
+import com.intellij.openapi.editor.CaretModel;
+import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiJavaToken;
+import com.intellij.psi.PsiPolyadicExpression;
import com.intellij.psi.tree.IElementType;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
+import com.siyeh.ipp.psiutils.ConcatenationUtils;
import com.siyeh.ipp.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
@@ -31,19 +33,17 @@ public class FlipExpressionIntention extends MutablyNamedIntention {
@Override
public String getTextForElement(PsiElement element) {
- final PsiBinaryExpression expression = (PsiBinaryExpression)element;
- final PsiJavaToken sign = expression.getOperationSign();
- final String operatorText = sign.getText();
- final IElementType token = sign.getTokenType();
- final boolean commutative =
- ParenthesesUtils.isCommutativeBinaryOperator(token);
- if (commutative) {
- return IntentionPowerPackBundle.message("flip.smth.intention.name",
- operatorText);
+ final PsiPolyadicExpression expression = (PsiPolyadicExpression)element.getParent();
+ final PsiExpression[] operands = expression.getOperands();
+ final PsiJavaToken sign = expression.getTokenBeforeOperand(operands[1]);
+ final String operatorText = sign == null ? "" : sign.getText();
+ final IElementType tokenType = expression.getOperationTokenType();
+ final boolean commutative = ParenthesesUtils.isCommutativeOperator(tokenType);
+ if (commutative && !ConcatenationUtils.isConcatenation(expression)) {
+ return IntentionPowerPackBundle.message("flip.smth.intention.name", operatorText);
}
else {
- return IntentionPowerPackBundle.message("flip.smth.intention.name1",
- operatorText);
+ return IntentionPowerPackBundle.message("flip.smth.intention.name1", operatorText);
}
}
@@ -54,24 +54,37 @@ public class FlipExpressionIntention extends MutablyNamedIntention {
}
@Override
- public void processIntention(@NotNull PsiElement element)
- throws IncorrectOperationException {
- final PsiBinaryExpression expression = (PsiBinaryExpression)element;
- final PsiExpression lhs = expression.getLOperand();
- final PsiExpression rhs = expression.getROperand();
- final PsiJavaToken sign = expression.getOperationSign();
- if (rhs == null) {
+ public void processIntention(@NotNull PsiElement element) {
+ final PsiJavaToken token = (PsiJavaToken)element;
+ final PsiElement parent = token.getParent();
+ if (!(parent instanceof PsiPolyadicExpression)) {
return;
}
- final String signText = sign.getText();
- final String lhsText = lhs.getText();
- final String rhsText = rhs.getText();
- final StringBuilder newExpression = new StringBuilder(rhsText);
- newExpression.append(signText);
- if (lhsText.startsWith(signText)) {
- newExpression.append(' ');
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)parent;
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ final StringBuilder newExpression = new StringBuilder();
+ String prevOperand = null;
+ final String tokenText = token.getText() + ' '; // 2- -1 without the space is not legal
+ for (PsiExpression operand : operands) {
+ final PsiJavaToken token1 = polyadicExpression.getTokenBeforeOperand(operand);
+ if (token == token1) {
+ newExpression.append(operand.getText()).append(tokenText);
+ continue;
+ }
+ if (prevOperand != null) {
+ newExpression.append(prevOperand).append(tokenText);
+ }
+ prevOperand = operand.getText();
}
- newExpression.append(lhsText);
- replaceExpression(newExpression.toString(), expression);
+ newExpression.append(prevOperand);
+ replaceExpression(newExpression.toString(), polyadicExpression);
+ }
+
+ @Override
+ protected void processIntention(Editor editor, @NotNull PsiElement element) {
+ final CaretModel caretModel = editor.getCaretModel();
+ final int offset = caretModel.getOffset();
+ super.processIntention(editor, element);
+ caretModel.moveToOffset(offset);
}
} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/IterableForEachLoopPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/IterableForEachLoopPredicate.java
index c9780104203c..e925b5c0ba67 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/IterableForEachLoopPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/IterableForEachLoopPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2006 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.siyeh.ipp.forloop;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.ErrorUtil;
@@ -35,13 +36,15 @@ class IterableForEachLoopPredicate implements PsiElementPredicate {
if (!(parent instanceof PsiForeachStatement)) {
return false;
}
- final PsiForeachStatement foreachStatement =
- (PsiForeachStatement)parent;
+ final PsiForeachStatement foreachStatement = (PsiForeachStatement)parent;
final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
if (iteratedValue == null) {
return false;
}
final PsiType type = iteratedValue.getType();
- return type instanceof PsiClassType && !ErrorUtil.containsError(parent);
+ if (!InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ITERABLE)) {
+ return false;
+ }
+ return !ErrorUtil.containsError(foreachStatement);
}
} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java
index d9af9bba12e7..ea69411b0db1 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2012 Bas Leijdekkers
+ * Copyright 2007-2013 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.ipp.opassign;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -28,22 +27,23 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
-public class ReplaceOperatorAssignmentWithAssignmentIntention
- extends MutablyNamedIntention {
+public class ReplaceOperatorAssignmentWithAssignmentIntention extends MutablyNamedIntention {
- private static final Map<IElementType, IElementType> tokenMap = new HashMap<IElementType, IElementType>() {{
- put(JavaTokenType.PLUSEQ, JavaTokenType.PLUS);
- put(JavaTokenType.MINUSEQ, JavaTokenType.MINUS);
- put(JavaTokenType.ASTERISKEQ, JavaTokenType.ASTERISK);
- put(JavaTokenType.DIVEQ, JavaTokenType.DIV);
- put(JavaTokenType.ANDEQ, JavaTokenType.AND);
- put(JavaTokenType.OREQ, JavaTokenType.OR);
- put(JavaTokenType.XOREQ, JavaTokenType.XOR);
- put(JavaTokenType.PERCEQ, JavaTokenType.PERC);
- put(JavaTokenType.LTLTEQ, JavaTokenType.LTLT);
- put(JavaTokenType.GTGTEQ, JavaTokenType.GTGT);
- put(JavaTokenType.GTGTGTEQ, JavaTokenType.GTGTGT);
- }};
+ private static final Map<IElementType, IElementType> tokenMap = new HashMap<IElementType, IElementType>();
+
+ static {
+ tokenMap.put(JavaTokenType.PLUSEQ, JavaTokenType.PLUS);
+ tokenMap.put(JavaTokenType.MINUSEQ, JavaTokenType.MINUS);
+ tokenMap.put(JavaTokenType.ASTERISKEQ, JavaTokenType.ASTERISK);
+ tokenMap.put(JavaTokenType.DIVEQ, JavaTokenType.DIV);
+ tokenMap.put(JavaTokenType.ANDEQ, JavaTokenType.AND);
+ tokenMap.put(JavaTokenType.OREQ, JavaTokenType.OR);
+ tokenMap.put(JavaTokenType.XOREQ, JavaTokenType.XOR);
+ tokenMap.put(JavaTokenType.PERCEQ, JavaTokenType.PERC);
+ tokenMap.put(JavaTokenType.LTLTEQ, JavaTokenType.LTLT);
+ tokenMap.put(JavaTokenType.GTGTEQ, JavaTokenType.GTGT);
+ tokenMap.put(JavaTokenType.GTGTGTEQ, JavaTokenType.GTGTGT);
+ }
@Override
@NotNull
@@ -53,17 +53,14 @@ public class ReplaceOperatorAssignmentWithAssignmentIntention
@Override
protected String getTextForElement(PsiElement element) {
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)element;
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)element;
final PsiJavaToken sign = assignmentExpression.getOperationSign();
final String operator = sign.getText();
- return IntentionPowerPackBundle.message(
- "replace.operator.assignment.with.assignment.intention.name",
- operator);
+ return IntentionPowerPackBundle.message("replace.operator.assignment.with.assignment.intention.name", operator);
}
@Override
- protected void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
+ protected void processIntention(@NotNull PsiElement element) {
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)element;
final PsiJavaToken sign = assignmentExpression.getOperationSign();
final PsiExpression lhs = assignmentExpression.getLExpression();
@@ -73,13 +70,13 @@ public class ReplaceOperatorAssignmentWithAssignmentIntention
final String lhsText = lhs.getText();
final String rhsText = (rhs == null) ? "" : rhs.getText();
final boolean parentheses;
- if (rhs instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)rhs;
+ if (rhs instanceof PsiPolyadicExpression) {
+ final PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression)rhs;
final int precedence1 = ParenthesesUtils.getPrecedenceForOperator(binaryExpression.getOperationTokenType());
final IElementType signTokenType = sign.getTokenType();
final IElementType newOperatorToken = tokenMap.get(signTokenType);
final int precedence2 = ParenthesesUtils.getPrecedenceForOperator(newOperatorToken);
- parentheses = precedence1 >= precedence2 || !ParenthesesUtils.isCommutativeBinaryOperator(newOperatorToken);
+ parentheses = precedence1 >= precedence2 || !ParenthesesUtils.isCommutativeOperator(newOperatorToken);
}
else {
parentheses = false;
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java
index 6e61e4dfe77a..f4d0397fcc93 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,50 +17,53 @@ package com.siyeh.ipp.opassign;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
-public class ReplaceWithOperatorAssignmentIntention
- extends MutablyNamedIntention {
+public class ReplaceWithOperatorAssignmentIntention extends MutablyNamedIntention {
public String getTextForElement(PsiElement element) {
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)element;
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)element;
final PsiExpression rhs = assignmentExpression.getRExpression();
- final PsiBinaryExpression expression =
- (PsiBinaryExpression)PsiUtil.deparenthesizeExpression(rhs);
+ final PsiPolyadicExpression expression = (PsiPolyadicExpression)PsiUtil.deparenthesizeExpression(rhs);
assert expression != null;
- final PsiJavaToken sign = expression.getOperationSign();
+ final PsiJavaToken sign = expression.getTokenBeforeOperand(expression.getOperands()[1]);
+ assert sign != null;
final String operator = sign.getText();
- return IntentionPowerPackBundle.message(
- "replace.assignment.with.operator.assignment.intention.name",
- operator);
+ return IntentionPowerPackBundle.message("replace.assignment.with.operator.assignment.intention.name", operator);
}
@NotNull
public PsiElementPredicate getElementPredicate() {
- return new AssignmentExpressionReplaceableWithOperatorAssigment();
+ return new ReplaceableWithOperatorAssignmentPredicate();
}
- public void processIntention(@NotNull PsiElement element)
- throws IncorrectOperationException {
- final PsiAssignmentExpression expression =
- (PsiAssignmentExpression)element;
- final PsiExpression rhs =
- expression.getRExpression();
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)PsiUtil.deparenthesizeExpression(rhs);
+ public void processIntention(@NotNull PsiElement element){
+ final PsiAssignmentExpression expression = (PsiAssignmentExpression)element;
+ final PsiExpression rhs = expression.getRExpression();
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)PsiUtil.deparenthesizeExpression(rhs);
+ assert polyadicExpression != null;
final PsiExpression lhs = expression.getLExpression();
assert rhs != null;
- final PsiJavaToken sign = binaryExpression.getOperationSign();
- final String operand = sign.getText();
- final PsiExpression binaryRhs = binaryExpression.getROperand();
- assert binaryRhs != null;
- final String newExpression =
- lhs.getText() + operand + '=' + binaryRhs.getText();
- replaceExpression(newExpression, expression);
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ final PsiJavaToken sign = polyadicExpression.getTokenBeforeOperand(operands[1]);
+ assert sign != null;
+ final String signText = sign.getText();
+ final StringBuilder newExpression = new StringBuilder();
+ newExpression.append(lhs.getText()).append(signText).append('=');
+ boolean token = false;
+ for (int i = 1; i < operands.length; i++) {
+ final PsiExpression operand = operands[i];
+ if (token) {
+ newExpression.append(signText);
+ }
+ else {
+ token = true;
+ }
+ newExpression.append(operand.getText());
+ }
+ replaceExpression(newExpression.toString(), expression);
}
} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/AssignmentExpressionReplaceableWithOperatorAssigment.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceableWithOperatorAssignmentPredicate.java
index ca0f09e7ef42..1f397a5a57bf 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/AssignmentExpressionReplaceableWithOperatorAssigment.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceableWithOperatorAssignmentPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -23,45 +23,37 @@ import com.siyeh.ipp.psiutils.EquivalenceChecker;
import com.siyeh.ipp.psiutils.ErrorUtil;
import com.siyeh.ipp.psiutils.SideEffectChecker;
-class AssignmentExpressionReplaceableWithOperatorAssigment
- implements PsiElementPredicate {
+class ReplaceableWithOperatorAssignmentPredicate implements PsiElementPredicate {
public boolean satisfiedBy(PsiElement element) {
if (!(element instanceof PsiAssignmentExpression)) {
return false;
}
- final PsiAssignmentExpression assignment =
- (PsiAssignmentExpression)element;
+ final PsiAssignmentExpression assignment = (PsiAssignmentExpression)element;
final IElementType tokenType = assignment.getOperationTokenType();
if (!JavaTokenType.EQ.equals(tokenType)) {
return false;
}
final PsiExpression rhs = assignment.getRExpression();
final PsiExpression expression = PsiUtil.deparenthesizeExpression(rhs);
- if (expression == null) {
+ if (!(expression instanceof PsiPolyadicExpression)) {
return false;
}
- if (!(expression instanceof PsiBinaryExpression)) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ if (operands.length < 2) {
return false;
}
- final PsiBinaryExpression binaryRhs = (PsiBinaryExpression)expression;
- final PsiExpression rhsRhs = binaryRhs.getROperand();
- final PsiExpression rhsLhs = binaryRhs.getLOperand();
- if (rhsRhs == null) {
- return false;
- }
- final IElementType rhsTokenType = binaryRhs.getOperationTokenType();
- if (JavaTokenType.OROR.equals(rhsTokenType) ||
- JavaTokenType.ANDAND.equals(rhsTokenType) ||
- JavaTokenType.EQEQ.equals(rhsTokenType) ||
- JavaTokenType.NE.equals(rhsTokenType)) {
+ final IElementType rhsTokenType = polyadicExpression.getOperationTokenType();
+ if (JavaTokenType.OROR.equals(rhsTokenType) || JavaTokenType.ANDAND.equals(rhsTokenType) ||
+ JavaTokenType.EQEQ.equals(rhsTokenType) || JavaTokenType.NE.equals(rhsTokenType)) {
return false;
}
final PsiExpression lhs = assignment.getLExpression();
if (SideEffectChecker.mayHaveSideEffects(lhs)) {
return false;
}
- if (!EquivalenceChecker.expressionsAreEquivalent(lhs, rhsLhs)) {
+ if (!EquivalenceChecker.expressionsAreEquivalent(lhs, operands[0])) {
return false;
}
return !ErrorUtil.containsError(element);
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConcatenationUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConcatenationUtils.java
index c2766e595967..0a62b3181b88 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConcatenationUtils.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConcatenationUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -20,9 +20,7 @@ import com.intellij.psi.tree.IElementType;
public class ConcatenationUtils {
- private ConcatenationUtils() {
- super();
- }
+ private ConcatenationUtils() {}
public static boolean isConcatenation(PsiElement element) {
if (!(element instanceof PsiPolyadicExpression)) {
@@ -33,20 +31,24 @@ public class ConcatenationUtils {
if (!tokenType.equals(JavaTokenType.PLUS)) {
return false;
}
- PsiExpression[] operands = expression.getOperands();
- if (operands.length <= 1) return false;
+ final PsiExpression[] operands = expression.getOperands();
+ if (operands.length <= 1) {
+ return false;
+ }
final PsiType type = expression.getType();
if (type == null) {
for (PsiExpression operand : operands) {
- if (hasStringType(operand)) return true;
+ if (hasStringType(operand)) {
+ return true;
+ }
}
return false;
}
- return type.equalsToText("java.lang.String");
+ return type.equalsToText(CommonClassNames.JAVA_LANG_STRING);
}
private static boolean hasStringType(PsiExpression expression) {
final PsiType type = expression.getType();
- return type != null && type.equalsToText("java.lang.String");
+ return type != null && type.equalsToText(CommonClassNames.JAVA_LANG_STRING);
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ParenthesesUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ParenthesesUtils.java
index b4d97f52687d..ab2971af6b81 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ParenthesesUtils.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ParenthesesUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -81,7 +81,7 @@ public class ParenthesesUtils {
return expression;
}
- public static boolean isCommutativeBinaryOperator(@NotNull IElementType token) {
+ public static boolean isCommutativeOperator(@NotNull IElementType token) {
return !(token.equals(JavaTokenType.MINUS) ||
token.equals(JavaTokenType.DIV) ||
token.equals(JavaTokenType.PERC) ||
@@ -185,8 +185,8 @@ public class ParenthesesUtils {
removeParensFromPostfixExpression(postfixExpression, ignoreClarifyingParentheses);
}
if (expression instanceof PsiPolyadicExpression) {
- final PsiPolyadicExpression binaryExpression = (PsiPolyadicExpression)expression;
- removeParensFromPolyadicExpression(binaryExpression, ignoreClarifyingParentheses);
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ removeParensFromPolyadicExpression(polyadicExpression, ignoreClarifyingParentheses);
}
if (expression instanceof PsiInstanceOfExpression) {
final PsiInstanceOfExpression instanceofExpression = (PsiInstanceOfExpression)expression;
@@ -225,12 +225,15 @@ public class ParenthesesUtils {
return;
}
else if (parent instanceof PsiArrayAccessExpression) {
- // use addAfter() + delete() instead of replace() to
- // workaround automatic insertion of parentheses by psi
- final PsiExpression newExpression = (PsiExpression)parent.addAfter(body, parenthesizedExpression);
- parenthesizedExpression.delete();
- removeParentheses(newExpression, ignoreClarifyingParentheses);
- return;
+ final PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression)parent;
+ if (parenthesizedExpression == arrayAccessExpression.getIndexExpression()) {
+ // use addAfter() + delete() instead of replace() to
+ // workaround automatic insertion of parentheses by psi
+ final PsiExpression newExpression = (PsiExpression)parent.addAfter(body, parenthesizedExpression);
+ parenthesizedExpression.delete();
+ removeParentheses(newExpression, ignoreClarifyingParentheses);
+ return;
+ }
}
final PsiExpression parentExpression = (PsiExpression)parent;
final int parentPrecedence = getPrecedence(parentExpression);
@@ -245,15 +248,15 @@ public class ParenthesesUtils {
}
else if (parentPrecedence == childPrecedence) {
if (parentExpression instanceof PsiPolyadicExpression && body instanceof PsiPolyadicExpression) {
- final PsiPolyadicExpression parentBinaryExpression = (PsiPolyadicExpression)parentExpression;
- final IElementType parentOperator = parentBinaryExpression.getOperationTokenType();
- final PsiPolyadicExpression bodyBinaryExpression = (PsiPolyadicExpression)body;
- final IElementType bodyOperator = bodyBinaryExpression.getOperationTokenType();
- final PsiType parentType = parentBinaryExpression.getType();
+ final PsiPolyadicExpression parentPolyadicExpression = (PsiPolyadicExpression)parentExpression;
+ final IElementType parentOperator = parentPolyadicExpression.getOperationTokenType();
+ final PsiPolyadicExpression bodyPolyadicExpression = (PsiPolyadicExpression)body;
+ final IElementType bodyOperator = bodyPolyadicExpression.getOperationTokenType();
+ final PsiType parentType = parentPolyadicExpression.getType();
final PsiType bodyType = body.getType();
if (parentType != null && parentType.equals(bodyType) && parentOperator.equals(bodyOperator)) {
- final PsiExpression[] parentOperands = parentBinaryExpression.getOperands();
- if (PsiTreeUtil.isAncestor(parentOperands[0], body, true) || isCommutativeBinaryOperator(bodyOperator)) {
+ final PsiExpression[] parentOperands = parentPolyadicExpression.getOperands();
+ if (PsiTreeUtil.isAncestor(parentOperands[0], body, true) || isCommutativeOperator(bodyOperator)) {
// use addAfter() + delete() instead of replace() to
// workaround automatic insertion of parentheses by psi
final PsiExpression newExpression = (PsiExpression)parent.addAfter(body, parenthesizedExpression);
@@ -407,12 +410,18 @@ public class ParenthesesUtils {
if (child == null) {
return true;
}
+ if (parent instanceof PsiArrayAccessExpression) {
+ final PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression)parent;
+ final PsiExpression indexExpression = arrayAccessExpression.getIndexExpression();
+ if (expression == indexExpression) {
+ return false;
+ }
+ }
return areParenthesesNeeded(child, (PsiExpression)parent);
}
public static boolean areParenthesesNeeded(PsiExpression expression, PsiExpression parentExpression) {
- if (parentExpression instanceof PsiParenthesizedExpression || parentExpression instanceof PsiArrayAccessExpression ||
- parentExpression instanceof PsiArrayInitializerExpression) {
+ if (parentExpression instanceof PsiParenthesizedExpression || parentExpression instanceof PsiArrayInitializerExpression) {
return false;
}
final int parentPrecedence = getPrecedence(parentExpression);
@@ -451,7 +460,7 @@ public class ParenthesesUtils {
final PsiExpression[] parentOperands = parentPolyadicExpression.getOperands();
if (!PsiTreeUtil.isAncestor(parentOperands[0], expression, false)) {
final IElementType parentOperator = parentPolyadicExpression.getOperationTokenType();
- if (!isCommutativeBinaryOperator(parentOperator)) {
+ if (!isCommutativeOperator(parentOperator)) {
return true;
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/IfStatementBranch.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/IfStatementBranch.java
index 218ddf50fb5e..598809d5e25a 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/IfStatementBranch.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/IfStatementBranch.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -24,7 +24,7 @@ class IfStatementBranch {
private final Set<String> topLevelVariables = new HashSet<String>(3);
private final LinkedList<String> comments = new LinkedList<String>();
private final LinkedList<String> statementComments = new LinkedList<String>();
- private final List<String> conditions = new ArrayList<String>(3);
+ private final List<PsiExpression> caseExpressions = new ArrayList<PsiExpression>(3);
private final PsiStatement statement;
private final boolean elseBranch;
@@ -42,30 +42,28 @@ class IfStatementBranch {
statementComments.addFirst(comment);
}
- public void addCondition(String conditionString) {
- conditions.add(conditionString);
+ public void addCaseExpression(PsiExpression expression) {
+ caseExpressions.add(expression);
}
public PsiStatement getStatement() {
return statement;
}
- public List<String> getConditions() {
- return Collections.unmodifiableList(conditions);
+ public List<PsiExpression> getCaseExpressions() {
+ return Collections.unmodifiableList(caseExpressions);
}
public boolean isElse() {
return elseBranch;
}
- public boolean topLevelDeclarationsConflictWith(
- IfStatementBranch testBranch) {
+ public boolean topLevelDeclarationsConflictWith(IfStatementBranch testBranch) {
final Set<String> topLevel = testBranch.topLevelVariables;
return intersects(topLevelVariables, topLevel);
}
- private static boolean intersects(Set<String> set1,
- Set<String> set2) {
+ private static boolean intersects(Set<String> set1, Set<String> set2) {
for (final String s : set1) {
if (set2.contains(s)) {
return true;
@@ -87,10 +85,8 @@ class IfStatementBranch {
return;
}
if (statement instanceof PsiDeclarationStatement) {
- final PsiDeclarationStatement declarationStatement =
- (PsiDeclarationStatement)statement;
- final PsiElement[] elements =
- declarationStatement.getDeclaredElements();
+ final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)statement;
+ final PsiElement[] elements = declarationStatement.getDeclaredElements();
for (PsiElement element : elements) {
final PsiVariable variable = (PsiVariable)element;
final String varName = variable.getName();
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LabelSearchVisitor.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LabelSearchVisitor.java
index ac7987373ded..5ab51566d190 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LabelSearchVisitor.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LabelSearchVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2005 Dave Griffith
+ * Copyright 2003-2013 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.
@@ -15,10 +15,7 @@
*/
package com.siyeh.ipp.switchtoif;
-import com.intellij.psi.JavaRecursiveElementWalkingVisitor;
-import com.intellij.psi.PsiIdentifier;
-import com.intellij.psi.PsiLabeledStatement;
-import com.intellij.psi.PsiReferenceExpression;
+import com.intellij.psi.*;
class LabelSearchVisitor extends JavaRecursiveElementWalkingVisitor {
@@ -26,12 +23,15 @@ class LabelSearchVisitor extends JavaRecursiveElementWalkingVisitor {
private boolean m_used = false;
LabelSearchVisitor(String name) {
- super();
m_labelName = name;
}
@Override
- public void visitReferenceExpression(PsiReferenceExpression expression) {
+ public void visitElement(PsiElement element) {
+ if (m_used) {
+ return;
+ }
+ super.visitElement(element);
}
@Override
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LocalVariableUsageVisitor.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LocalVariableUsageVisitor.java
deleted file mode 100644
index 4fc5a2c32c64..000000000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/LocalVariableUsageVisitor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2003-2005 Dave Griffith
- *
- * 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.switchtoif;
-
-import com.intellij.psi.JavaRecursiveElementWalkingVisitor;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLocalVariable;
-import com.intellij.psi.PsiReferenceExpression;
-
-class LocalVariableUsageVisitor extends JavaRecursiveElementWalkingVisitor {
-
- private final PsiLocalVariable m_var;
- private boolean m_used = false;
-
- LocalVariableUsageVisitor(PsiLocalVariable name) {
- super();
- m_var = name;
- }
-
- @Override
- public void visitReferenceExpression(PsiReferenceExpression expression) {
- final PsiElement reference = expression.resolve();
- if (m_var.equals(reference)) {
- m_used = true;
- }
- super.visitReferenceElement(expression);
- }
-
- public boolean isUsed() {
- return m_used;
- }
-} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java
index 4d7e34bc3834..cfd5406bec1d 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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,6 @@ package com.siyeh.ipp.switchtoif;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.ControlFlowUtils;
@@ -39,8 +38,7 @@ public class ReplaceIfWithSwitchIntention extends Intention {
}
@Override
- public void processIntention(@NotNull PsiElement element)
- throws IncorrectOperationException {
+ public void processIntention(@NotNull PsiElement element) {
final PsiJavaToken switchToken = (PsiJavaToken)element;
PsiIfStatement ifStatement = (PsiIfStatement)switchToken.getParent();
if (ifStatement == null) {
@@ -50,67 +48,37 @@ public class ReplaceIfWithSwitchIntention extends Intention {
PsiStatement breakTarget = null;
String labelString = "";
if (ControlFlowUtils.statementContainsNakedBreak(ifStatement)) {
- breakTarget = PsiTreeUtil.getParentOfType(ifStatement,
- PsiLoopStatement.class, PsiSwitchStatement.class);
+ breakTarget = PsiTreeUtil.getParentOfType(ifStatement, PsiLoopStatement.class, PsiSwitchStatement.class);
if (breakTarget != null) {
final PsiElement parent = breakTarget.getParent();
if (parent instanceof PsiLabeledStatement) {
- final PsiLabeledStatement labeledStatement =
- (PsiLabeledStatement)parent;
- labelString =
- labeledStatement.getLabelIdentifier().getText();
+ final PsiLabeledStatement labeledStatement = (PsiLabeledStatement)parent;
+ labelString = labeledStatement.getLabelIdentifier().getText();
breakTarget = labeledStatement;
breaksNeedRelabeled = true;
}
else {
- labelString = SwitchUtils.findUniqueLabelName(ifStatement,
- "label");
+ labelString = SwitchUtils.findUniqueLabelName(ifStatement, "label");
breaksNeedRelabeled = true;
}
}
}
final PsiIfStatement statementToReplace = ifStatement;
- final PsiExpression switchExpression =
- SwitchUtils.getSwitchExpression(ifStatement);
- assert switchExpression != null;
-
- final List<IfStatementBranch> branches =
- new ArrayList<IfStatementBranch>(20);
+ final PsiExpression switchExpression = SwitchUtils.getSwitchExpression(ifStatement);
+ if (switchExpression == null) {
+ return;
+ }
+ final List<IfStatementBranch> branches = new ArrayList<IfStatementBranch>(20);
while (true) {
final PsiExpression condition = ifStatement.getCondition();
- final List<PsiExpression> labels =
- getValuesFromExpression(condition, switchExpression,
- new ArrayList());
final PsiStatement thenBranch = ifStatement.getThenBranch();
- final IfStatementBranch ifBranch =
- new IfStatementBranch(thenBranch, false);
+ final IfStatementBranch ifBranch = new IfStatementBranch(thenBranch, false);
+ extractCaseExpressions(condition, switchExpression, ifBranch);
if (!branches.isEmpty()) {
extractIfComments(ifStatement, ifBranch);
}
extractStatementComments(thenBranch, ifBranch);
- for (final PsiExpression label : labels) {
- if (label instanceof PsiReferenceExpression) {
- final PsiReferenceExpression reference =
- (PsiReferenceExpression)label;
- final PsiElement referent = reference.resolve();
- if (referent instanceof PsiEnumConstant) {
- final PsiEnumConstant constant =
- (PsiEnumConstant)referent;
- final String constantName = constant.getName();
- ifBranch.addCondition(constantName);
- }
- else {
- final String labelText = label.getText();
- ifBranch.addCondition(labelText);
- }
- }
- else {
- final String labelText = label.getText();
- ifBranch.addCondition(labelText);
- }
- }
branches.add(ifBranch);
-
final PsiStatement elseBranch = ifStatement.getElseBranch();
if (elseBranch instanceof PsiIfStatement) {
ifStatement = (PsiIfStatement)elseBranch;
@@ -119,8 +87,7 @@ public class ReplaceIfWithSwitchIntention extends Intention {
break;
}
else {
- final IfStatementBranch elseIfBranch =
- new IfStatementBranch(elseBranch, true);
+ final IfStatementBranch elseIfBranch = new IfStatementBranch(elseBranch, true);
final PsiKeyword elseKeyword = ifStatement.getElseElement();
extractIfComments(elseKeyword, elseIfBranch);
extractStatementComments(elseBranch, elseIfBranch);
@@ -129,11 +96,10 @@ public class ReplaceIfWithSwitchIntention extends Intention {
}
}
- @NonNls final StringBuilder switchStatementText =
- new StringBuilder();
- switchStatementText.append("switch(");
- switchStatementText.append(switchExpression.getText());
- switchStatementText.append("){");
+ @NonNls final StringBuilder switchStatementText = new StringBuilder();
+ switchStatementText.append("switch(").append(switchExpression.getText()).append("){");
+ final PsiType type = switchExpression.getType();
+ final boolean castToInt = type != null && type.equalsToText(CommonClassNames.JAVA_LANG_INTEGER);
for (IfStatementBranch branch : branches) {
boolean hasConflicts = false;
for (IfStatementBranch testBranch : branches) {
@@ -144,39 +110,30 @@ public class ReplaceIfWithSwitchIntention extends Intention {
hasConflicts = true;
}
}
- dumpBranch(branch, hasConflicts, breaksNeedRelabeled, labelString,
- switchStatementText);
+ dumpBranch(branch, castToInt, hasConflicts, breaksNeedRelabeled, labelString, switchStatementText);
}
switchStatementText.append('}');
- final JavaPsiFacade psiFacade =
- JavaPsiFacade.getInstance(element.getProject());
+ final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(element.getProject());
final PsiElementFactory factory = psiFacade.getElementFactory();
if (breaksNeedRelabeled) {
final StringBuilder out = new StringBuilder();
if (!(breakTarget instanceof PsiLabeledStatement)) {
- out.append(labelString);
- out.append(':');
+ out.append(labelString).append(':');
}
- termReplace(breakTarget, statementToReplace, switchStatementText,
- out);
+ termReplace(breakTarget, statementToReplace, switchStatementText, out);
final String newStatementText = out.toString();
- final PsiStatement newStatement =
- factory.createStatementFromText(newStatementText, element);
+ final PsiStatement newStatement = factory.createStatementFromText(newStatementText, element);
breakTarget.replace(newStatement);
}
else {
- final PsiStatement newStatement =
- factory.createStatementFromText(
- switchStatementText.toString(), element);
+ final PsiStatement newStatement = factory.createStatementFromText(switchStatementText.toString(), element);
statementToReplace.replace(newStatement);
}
}
@Nullable
- public static <T extends PsiElement> T getPrevSiblingOfType(
- @Nullable PsiElement element,
- @NotNull Class<T> aClass,
- @NotNull Class<? extends PsiElement>... stopAt) {
+ public static <T extends PsiElement> T getPrevSiblingOfType(@Nullable PsiElement element, @NotNull Class<T> aClass,
+ @NotNull Class<? extends PsiElement>... stopAt) {
if (element == null) {
return null;
}
@@ -192,18 +149,15 @@ public class ReplaceIfWithSwitchIntention extends Intention {
return (T)sibling;
}
- private static void extractIfComments(PsiElement element,
- IfStatementBranch out) {
- PsiComment comment = getPrevSiblingOfType(element,
- PsiComment.class, PsiStatement.class);
+ private static void extractIfComments(PsiElement element, IfStatementBranch out) {
+ PsiComment comment = getPrevSiblingOfType(element, PsiComment.class, PsiStatement.class);
while (comment != null) {
final PsiElement sibling = comment.getPrevSibling();
final String commentText;
if (sibling instanceof PsiWhiteSpace) {
final String whiteSpaceText = sibling.getText();
if (whiteSpaceText.startsWith("\n")) {
- commentText = whiteSpaceText.substring(1) +
- comment.getText();
+ commentText = whiteSpaceText.substring(1) + comment.getText();
}
else {
commentText = comment.getText();
@@ -213,23 +167,19 @@ public class ReplaceIfWithSwitchIntention extends Intention {
commentText = comment.getText();
}
out.addComment(commentText);
- comment = getPrevSiblingOfType(comment, PsiComment.class,
- PsiStatement.class);
+ comment = getPrevSiblingOfType(comment, PsiComment.class, PsiStatement.class);
}
}
- private static void extractStatementComments(PsiElement element,
- IfStatementBranch out) {
- PsiComment comment = getPrevSiblingOfType(element,
- PsiComment.class, PsiStatement.class, PsiKeyword.class);
+ private static void extractStatementComments(PsiElement element, IfStatementBranch out) {
+ PsiComment comment = getPrevSiblingOfType(element, PsiComment.class, PsiStatement.class, PsiKeyword.class);
while (comment != null) {
final PsiElement sibling = comment.getPrevSibling();
final String commentText;
if (sibling instanceof PsiWhiteSpace) {
final String whiteSpaceText = sibling.getText();
if (whiteSpaceText.startsWith("\n")) {
- commentText = whiteSpaceText.substring(1) +
- comment.getText();
+ commentText = whiteSpaceText.substring(1) + comment.getText();
}
else {
commentText = comment.getText();
@@ -239,14 +189,11 @@ public class ReplaceIfWithSwitchIntention extends Intention {
commentText = comment.getText();
}
out.addStatementComment(commentText);
- comment = getPrevSiblingOfType(comment, PsiComment.class,
- PsiStatement.class, PsiKeyword.class);
+ comment = getPrevSiblingOfType(comment, PsiComment.class, PsiStatement.class, PsiKeyword.class);
}
}
- private static void termReplace(
- PsiElement target, PsiElement replace,
- StringBuilder stringToReplaceWith, StringBuilder out) {
+ private static void termReplace(PsiElement target, PsiElement replace, StringBuilder stringToReplaceWith, StringBuilder out) {
if (target.equals(replace)) {
out.append(stringToReplaceWith);
}
@@ -261,120 +208,118 @@ public class ReplaceIfWithSwitchIntention extends Intention {
}
}
- private static List<PsiExpression> getValuesFromExpression(
- PsiExpression expression, PsiExpression caseExpression,
- List<PsiExpression> values) {
+ private static void extractCaseExpressions(PsiExpression expression, PsiExpression switchExpression, IfStatementBranch values) {
if (expression instanceof PsiMethodCallExpression) {
- final PsiMethodCallExpression methodCallExpression =
- (PsiMethodCallExpression)expression;
- final PsiExpressionList argumentList =
- methodCallExpression.getArgumentList();
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+ final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
final PsiExpression argument = arguments[0];
- final PsiReferenceExpression methodExpression =
- methodCallExpression.getMethodExpression();
- final PsiExpression qualifierExpression =
- methodExpression.getQualifierExpression();
- if (EquivalenceChecker.expressionsAreEquivalent(caseExpression,
- argument)) {
- values.add(qualifierExpression);
+ final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+ final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
+ if (EquivalenceChecker.expressionsAreEquivalent(switchExpression, argument)) {
+ values.addCaseExpression(qualifierExpression);
}
else {
- values.add(argument);
+ values.addCaseExpression(argument);
}
}
- else if (expression instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final PsiExpression lhs = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
- final IElementType tokenType = binaryExpression.getOperationTokenType();
+ else if (expression instanceof PsiPolyadicExpression) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ final IElementType tokenType = polyadicExpression.getOperationTokenType();
if (JavaTokenType.OROR.equals(tokenType)) {
- getValuesFromExpression(lhs, caseExpression,
- values);
- getValuesFromExpression(rhs, caseExpression,
- values);
+ for (PsiExpression operand : operands) {
+ extractCaseExpressions(operand, switchExpression, values);
+ }
}
- else {
- if (EquivalenceChecker.expressionsAreEquivalent(caseExpression,
- rhs)) {
- values.add(lhs);
+ else if (JavaTokenType.EQEQ.equals(tokenType) && operands.length == 2) {
+ final PsiExpression lhs = operands[0];
+ final PsiExpression rhs = operands[1];
+ if (EquivalenceChecker.expressionsAreEquivalent(switchExpression, rhs)) {
+ values.addCaseExpression(lhs);
}
- else {
- values.add(rhs);
+ else if (EquivalenceChecker.expressionsAreEquivalent(switchExpression, lhs)){
+ values.addCaseExpression(rhs);
}
}
}
else if (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- final PsiExpression contents =
- parenthesizedExpression.getExpression();
- getValuesFromExpression(contents, caseExpression, values);
+ final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
+ final PsiExpression contents = parenthesizedExpression.getExpression();
+ extractCaseExpressions(contents, switchExpression, values);
}
- return values;
}
- private static void dumpBranch(IfStatementBranch branch,
- boolean wrap,
- boolean renameBreaks,
- String breakLabelName,
- StringBuilder switchStatementText) {
+ private static void dumpBranch(IfStatementBranch branch, boolean castToInt, boolean wrap, boolean renameBreaks, String breakLabelName,
+ @NonNls StringBuilder switchStatementText) {
dumpComments(branch.getComments(), switchStatementText);
if (branch.isElse()) {
switchStatementText.append("default: ");
}
else {
- for (String label : branch.getConditions()) {
- switchStatementText.append("case ");
- switchStatementText.append(label);
- switchStatementText.append(": ");
+ for (PsiExpression caseExpression : branch.getCaseExpressions()) {
+ switchStatementText.append("case ").append(getCaseLabelText(caseExpression, castToInt)).append(": ");
}
}
dumpComments(branch.getStatementComments(), switchStatementText);
- dumpBody(branch.getStatement(), wrap, renameBreaks, breakLabelName,
- switchStatementText
- );
+ dumpBody(branch.getStatement(), wrap, renameBreaks, breakLabelName, switchStatementText);
}
- private static void dumpComments(List<String> comments,
- StringBuilder switchStatementText) {
- if (!comments.isEmpty()) {
- switchStatementText.append('\n');
- for (String comment : comments) {
- switchStatementText.append(comment);
- switchStatementText.append('\n');
+ @NonNls
+ private static String getCaseLabelText(PsiExpression expression, boolean castToInt) {
+ if (expression instanceof PsiReferenceExpression) {
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
+ final PsiElement target = referenceExpression.resolve();
+ if (target instanceof PsiEnumConstant) {
+ final PsiEnumConstant enumConstant = (PsiEnumConstant)target;
+ return enumConstant.getName();
}
}
+ if (castToInt) {
+ final PsiType type = expression.getType();
+ if (!PsiType.INT.equals(type)) {
+ /*
+ because
+ Integer a = 1;
+ switch (a) {
+ case (byte)7:
+ }
+ does not compile with javac (but does with Eclipse)
+ */
+ return "(int)" + expression.getText();
+ }
+ }
+ return expression.getText();
+ }
+
+ private static void dumpComments(List<String> comments, StringBuilder switchStatementText) {
+ if (comments.isEmpty()) {
+ return;
+ }
+ switchStatementText.append('\n');
+ for (String comment : comments) {
+ switchStatementText.append(comment).append('\n');
+ }
}
- private static void dumpBody(PsiStatement bodyStatement,
- boolean wrap,
- boolean renameBreaks,
- String breakLabelName,
+ private static void dumpBody(PsiStatement bodyStatement, boolean wrap, boolean renameBreaks, String breakLabelName,
@NonNls StringBuilder switchStatementText) {
if (wrap) {
switchStatementText.append('{');
}
if (bodyStatement instanceof PsiBlockStatement) {
- final PsiCodeBlock codeBlock =
- ((PsiBlockStatement)bodyStatement).getCodeBlock();
+ final PsiCodeBlock codeBlock = ((PsiBlockStatement)bodyStatement).getCodeBlock();
final PsiElement[] children = codeBlock.getChildren();
//skip the first and last members, to unwrap the block
for (int i = 1; i < children.length - 1; i++) {
final PsiElement child = children[i];
- appendElement(child, renameBreaks, breakLabelName,
- switchStatementText
- );
+ appendElement(child, renameBreaks, breakLabelName, switchStatementText);
}
}
else {
- appendElement(bodyStatement, renameBreaks, breakLabelName,
- switchStatementText
- );
+ appendElement(bodyStatement, renameBreaks, breakLabelName, switchStatementText);
}
- if (ControlFlowUtils.statementMayCompleteNormally(
- bodyStatement)) {
+ if (ControlFlowUtils.statementMayCompleteNormally(bodyStatement)) {
switchStatementText.append("break;");
}
if (wrap) {
@@ -382,39 +327,43 @@ public class ReplaceIfWithSwitchIntention extends Intention {
}
}
- private static void appendElement(PsiElement element,
- boolean renameBreakElements,
- String breakLabelString,
+ private static void appendElement(PsiElement element, boolean renameBreakElements, String breakLabelString,
@NonNls StringBuilder switchStatementText) {
final String text = element.getText();
if (!renameBreakElements) {
switchStatementText.append(text);
}
else if (element instanceof PsiBreakStatement) {
- final PsiBreakStatement breakStatement =
- (PsiBreakStatement)element;
- final PsiIdentifier identifier =
- breakStatement.getLabelIdentifier();
+ final PsiBreakStatement breakStatement = (PsiBreakStatement)element;
+ final PsiIdentifier identifier = breakStatement.getLabelIdentifier();
if (identifier == null) {
- switchStatementText.append("break ");
- switchStatementText.append(breakLabelString);
- switchStatementText.append(';');
+ switchStatementText.append("break ").append(breakLabelString).append(';');
}
else {
switchStatementText.append(text);
}
}
- else if (element instanceof PsiBlockStatement ||
- element instanceof PsiCodeBlock ||
- element instanceof PsiIfStatement) {
+ else if (element instanceof PsiBlockStatement || element instanceof PsiCodeBlock || element instanceof PsiIfStatement) {
final PsiElement[] children = element.getChildren();
for (final PsiElement child : children) {
- appendElement(child, renameBreakElements, breakLabelString,
- switchStatementText);
+ appendElement(child, renameBreakElements, breakLabelString, switchStatementText);
}
}
else {
switchStatementText.append(text);
}
+ final PsiElement lastChild = element.getLastChild();
+ if (isEndOfLineComment(lastChild)) {
+ switchStatementText.append('\n');
+ }
+ }
+
+ private static boolean isEndOfLineComment(PsiElement element) {
+ if (!(element instanceof PsiComment)) {
+ return false;
+ }
+ final PsiComment comment = (PsiComment)element;
+ final IElementType tokenType = comment.getTokenType();
+ return JavaTokenType.END_OF_LINE_COMMENT.equals(tokenType);
}
-}
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/SwitchUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/SwitchUtils.java
index b48e8b8526ca..4ca574870472 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/SwitchUtils.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/SwitchUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2013 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.
@@ -21,136 +21,117 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ipp.psiutils.EquivalenceChecker;
+import com.siyeh.ipp.psiutils.ParenthesesUtils;
import com.siyeh.ipp.psiutils.SideEffectChecker;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
-import java.util.List;
-
class SwitchUtils {
- private SwitchUtils() {
- }
+ private SwitchUtils() {}
- private static boolean canBeCaseLabel(PsiExpression expression,
- LanguageLevel languageLevel) {
- if (expression == null) {
- return false;
+ @Nullable
+ public static PsiExpression getSwitchExpression(PsiIfStatement statement) {
+ final PsiExpression condition = statement.getCondition();
+ final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(statement);
+ final PsiExpression possibleSwitchExpression = determinePossibleSwitchExpressions(condition, languageLevel);
+ if (!canBeSwitchExpression(possibleSwitchExpression, languageLevel)) {
+ return null;
}
- if (languageLevel.compareTo(LanguageLevel.JDK_1_5) >= 0
- && expression instanceof PsiReferenceExpression) {
- final PsiElement referent = ((PsiReference)expression).resolve();
- if (referent instanceof PsiEnumConstant) {
- return true;
+ while (true) {
+ if (!canBeMadeIntoCase(statement.getCondition(), possibleSwitchExpression, languageLevel)) {
+ break;
+ }
+ final PsiStatement elseBranch = statement.getElseBranch();
+ if (!(elseBranch instanceof PsiIfStatement)) {
+ return possibleSwitchExpression;
}
+ statement = (PsiIfStatement)elseBranch;
}
- final PsiType type = expression.getType();
- return type != null &&
- (type.equals(PsiType.INT) ||
- type.equals(PsiType.CHAR) ||
- type.equals(PsiType.LONG) ||
- type.equals(PsiType.SHORT)) &&
- PsiUtil.isConstantExpression(expression);
+ return null;
}
- public static boolean isUsedByStatementList(PsiLocalVariable variable,
- List<PsiElement> elements) {
- for (PsiElement element : elements) {
- if (isUsedByStatement(variable, element)) {
+ private static boolean canBeMadeIntoCase(PsiExpression expression, PsiExpression switchExpression, LanguageLevel languageLevel) {
+ expression = ParenthesesUtils.stripParentheses(expression);
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
+ final PsiExpression stringSwitchExpression = determinePossibleStringSwitchExpression(expression);
+ if (EquivalenceChecker.expressionsAreEquivalent(switchExpression, stringSwitchExpression)) {
return true;
}
}
- return false;
- }
-
- private static boolean isUsedByStatement(PsiLocalVariable variable,
- PsiElement statement) {
- final LocalVariableUsageVisitor visitor =
- new LocalVariableUsageVisitor(variable);
- statement.accept(visitor);
- return visitor.isUsed();
- }
-
- public static String findUniqueLabelName(PsiStatement statement,
- @NonNls String baseName) {
- final PsiElement ancestor =
- PsiTreeUtil.getParentOfType(statement, PsiMember.class);
- if (!checkForLabel(baseName, ancestor)) {
- return baseName;
+ if (!(expression instanceof PsiPolyadicExpression)) {
+ return false;
}
- int val = 1;
- while (true) {
- final String name = baseName + val;
- if (!checkForLabel(name, ancestor)) {
- return name;
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final IElementType operation = polyadicExpression.getOperationTokenType();
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ if (operation.equals(JavaTokenType.OROR)) {
+ for (PsiExpression operand : operands) {
+ if (!canBeMadeIntoCase(operand, switchExpression, languageLevel)) {
+ return false;
+ }
}
- val++;
+ return true;
+ }
+ else if (operation.equals(JavaTokenType.EQEQ) && operands.length == 2) {
+ return (canBeCaseLabel(operands[0], languageLevel) && EquivalenceChecker.expressionsAreEquivalent(switchExpression, operands[1])) ||
+ (canBeCaseLabel(operands[1], languageLevel) && EquivalenceChecker.expressionsAreEquivalent(switchExpression, operands[0]));
+ }
+ else {
+ return false;
}
}
- private static boolean checkForLabel(String name, PsiElement ancestor) {
- final LabelSearchVisitor visitor = new LabelSearchVisitor(name);
- ancestor.accept(visitor);
- return visitor.isUsed();
- }
-
- @Nullable
- public static PsiExpression getSwitchExpression(PsiIfStatement statement) {
- final PsiExpression condition = statement.getCondition();
- final LanguageLevel languageLevel =
- PsiUtil.getLanguageLevel(statement);
- final PsiExpression possibleSwitchExpression =
- determinePossibleSwitchExpressions(condition, languageLevel);
- if (possibleSwitchExpression == null) {
- return null;
+ private static boolean canBeSwitchExpression(PsiExpression expression, LanguageLevel languageLevel) {
+ if (expression == null || SideEffectChecker.mayHaveSideEffects(expression)) {
+ return false;
}
- if (SideEffectChecker.mayHaveSideEffects(possibleSwitchExpression)) {
- return null;
+ final PsiType type = expression.getType();
+ if (PsiType.CHAR.equals(type) || PsiType.BYTE.equals(type) || PsiType.SHORT.equals(type) || PsiType.INT.equals(type)) {
+ return true;
}
- while (true) {
- final PsiExpression caseCondition = statement.getCondition();
- if (!canBeMadeIntoCase(caseCondition, possibleSwitchExpression,
- languageLevel)) {
- break;
+ else if (type instanceof PsiClassType) {
+ if (type.equalsToText(CommonClassNames.JAVA_LANG_CHARACTER) || type.equalsToText(CommonClassNames.JAVA_LANG_BYTE) ||
+ type.equalsToText(CommonClassNames.JAVA_LANG_SHORT) || type.equalsToText(CommonClassNames.JAVA_LANG_INTEGER)) {
+ return true;
}
- final PsiStatement elseBranch = statement.getElseBranch();
- if (!(elseBranch instanceof PsiIfStatement)) {
- return possibleSwitchExpression;
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) {
+ final PsiClassType classType = (PsiClassType)type;
+ final PsiClass aClass = classType.resolve();
+ if (aClass != null && aClass.isEnum()) {
+ return true;
+ }
+ }
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7) && type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
+ return true;
}
- statement = (PsiIfStatement)elseBranch;
}
- return null;
+ return false;
}
- private static PsiExpression determinePossibleSwitchExpressions(
- PsiExpression expression, LanguageLevel languageLevel) {
- while (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- expression = parenthesizedExpression.getExpression();
- }
+ private static PsiExpression determinePossibleSwitchExpressions(PsiExpression expression, LanguageLevel languageLevel) {
+ expression = ParenthesesUtils.stripParentheses(expression);
if (expression == null) {
return null;
}
- if (languageLevel.compareTo(LanguageLevel.JDK_1_7) >= 0) {
- final PsiExpression jdk17Expression =
- determinePossibleStringSwitchExpression(expression);
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
+ final PsiExpression jdk17Expression = determinePossibleStringSwitchExpression(expression);
if (jdk17Expression != null) {
return jdk17Expression;
}
}
- if (!(expression instanceof PsiBinaryExpression)) {
+ if (!(expression instanceof PsiPolyadicExpression)) {
return null;
}
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final IElementType operation = binaryExpression.getOperationTokenType();
- final PsiExpression lhs = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
- if (operation.equals(JavaTokenType.OROR)) {
- return determinePossibleSwitchExpressions(lhs, languageLevel);
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
+ final IElementType operation = polyadicExpression.getOperationTokenType();
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ if (operation.equals(JavaTokenType.OROR) && operands.length > 0) {
+ return determinePossibleSwitchExpressions(operands[0], languageLevel);
}
- else if (operation.equals(JavaTokenType.EQEQ)) {
+ else if (operation.equals(JavaTokenType.EQEQ) && operands.length == 2) {
+ final PsiExpression lhs = operands[0];
+ final PsiExpression rhs = operands[1];
if (canBeCaseLabel(lhs, languageLevel)) {
return rhs;
}
@@ -161,39 +142,32 @@ class SwitchUtils {
return null;
}
- private static PsiExpression determinePossibleStringSwitchExpression(
- PsiExpression expression) {
+ private static PsiExpression determinePossibleStringSwitchExpression(PsiExpression expression) {
if (!(expression instanceof PsiMethodCallExpression)) {
return null;
}
- final PsiMethodCallExpression methodCallExpression =
- (PsiMethodCallExpression)expression;
- final PsiReferenceExpression methodExpression =
- methodCallExpression.getMethodExpression();
- @NonNls final String referenceName =
- methodExpression.getReferenceName();
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+ final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+ @NonNls final String referenceName = methodExpression.getReferenceName();
if (!"equals".equals(referenceName)) {
return null;
}
- final PsiExpression qualifierExpression =
- methodExpression.getQualifierExpression();
+ final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
if (qualifierExpression == null) {
return null;
}
final PsiType type = qualifierExpression.getType();
- if (type == null || !type.equalsToText("java.lang.String")) {
+ if (type == null || !type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
return null;
}
- final PsiExpressionList argumentList =
- methodCallExpression.getArgumentList();
+ final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
if (arguments.length != 1) {
return null;
}
final PsiExpression argument = arguments[0];
final PsiType argumentType = argument.getType();
- if (argumentType == null ||
- !argumentType.equalsToText("java.lang.String")) {
+ if (argumentType == null || !argumentType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
return null;
}
if (PsiUtil.isConstantExpression(qualifierExpression)) {
@@ -205,45 +179,39 @@ class SwitchUtils {
return null;
}
- private static boolean canBeMadeIntoCase(
- PsiExpression expression, PsiExpression caseExpression,
- LanguageLevel languageLevel) {
- while (expression instanceof PsiParenthesizedExpression) {
- final PsiParenthesizedExpression parenthesizedExpression =
- (PsiParenthesizedExpression)expression;
- expression = parenthesizedExpression.getExpression();
- }
- if (languageLevel.compareTo(LanguageLevel.JDK_1_7) >= 0) {
- final PsiExpression stringCaseExpression =
- determinePossibleStringSwitchExpression(expression);
- if (EquivalenceChecker.expressionsAreEquivalent(caseExpression,
- stringCaseExpression)) {
+ private static boolean canBeCaseLabel(PsiExpression expression, LanguageLevel languageLevel) {
+ if (expression == null) {
+ return false;
+ }
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_5) && expression instanceof PsiReferenceExpression) {
+ final PsiElement referent = ((PsiReference)expression).resolve();
+ if (referent instanceof PsiEnumConstant) {
return true;
}
}
- if (!(expression instanceof PsiBinaryExpression)) {
- return false;
- }
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final IElementType operation = binaryExpression.getOperationTokenType();
- final PsiExpression lOperand = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
- if (operation.equals(JavaTokenType.OROR)) {
- return canBeMadeIntoCase(lOperand, caseExpression, languageLevel) &&
- canBeMadeIntoCase(rhs, caseExpression, languageLevel);
- }
- else if (operation.equals(JavaTokenType.EQEQ)) {
- return (canBeCaseLabel(lOperand, languageLevel) &&
- EquivalenceChecker.expressionsAreEquivalent(
- caseExpression, rhs))
- ||
- (canBeCaseLabel(rhs, languageLevel) &&
- EquivalenceChecker.expressionsAreEquivalent(
- caseExpression, lOperand));
+ final PsiType type = expression.getType();
+ return (PsiType.INT.equals(type) || PsiType.SHORT.equals(type) || PsiType.BYTE.equals(type) || PsiType.CHAR.equals(type)) &&
+ PsiUtil.isConstantExpression(expression);
+ }
+
+ public static String findUniqueLabelName(PsiStatement statement, @NonNls String baseName) {
+ final PsiElement ancestor = PsiTreeUtil.getParentOfType(statement, PsiMember.class);
+ if (!checkForLabel(baseName, ancestor)) {
+ return baseName;
}
- else {
- return false;
+ int val = 1;
+ while (true) {
+ final String name = baseName + val;
+ if (!checkForLabel(name, ancestor)) {
+ return name;
+ }
+ val++;
}
}
+
+ private static boolean checkForLabel(String name, PsiElement ancestor) {
+ final LabelSearchVisitor visitor = new LabelSearchVisitor(name);
+ ancestor.accept(visitor);
+ return visitor.isUsed();
+ }
} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java
index f0d54848106c..8ffc5eebfbe0 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceMethodRefWithLambdaIntention.java
@@ -82,15 +82,18 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention {
buf.append("{");
}
final PsiElement qualifier = referenceExpression.getQualifier();
- boolean isReceiver = false;
+ PsiClass containingClass = null;
if (resolveElement instanceof PsiMethod) {
- final PsiClass containingClass = ((PsiMember)resolveElement).getContainingClass();
+ containingClass = ((PsiMember)resolveElement).getContainingClass();
LOG.assertTrue(containingClass != null);
- isReceiver = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, containingClass, (PsiMethod)resolveElement);
} else if (resolveElement instanceof PsiClass) {
- isReceiver = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, (PsiClass)resolveElement, (PsiMethod)null);
+ containingClass = (PsiClass)resolveElement;
}
+ final boolean onArrayRef =
+ JavaPsiFacade.getElementFactory(element.getProject()).getArrayClass(PsiUtil.getLanguageLevel(element)) == containingClass;
+ boolean isReceiver = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, containingClass, resolveElement instanceof PsiMethod ? (PsiMethod)resolveElement : null);
+
final PsiElement referenceNameElement = referenceExpression.getReferenceNameElement();
if (isReceiver){
buf.append(parameters[0].getName()).append(".");
@@ -113,43 +116,52 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention {
if (referenceNameElement instanceof PsiKeyword) {
//class name
buf.append(" ");
- buf.append(((PsiMember)resolveElement).getName());
-
- final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
-
- PsiClass containingClass;
- if (resolveElement instanceof PsiClass) {
- containingClass = (PsiClass)resolveElement;
- } else {
- containingClass = ((PsiMember)resolveElement).getContainingClass();
- }
-
- LOG.assertTrue(containingClass != null);
- if (containingClass.hasTypeParameters() && !PsiUtil.isRawSubstitutor(containingClass, substitutor)) {
- buf.append("<").append(StringUtil.join(containingClass.getTypeParameters(), new Function<PsiTypeParameter, String>() {
- @Override
- public String fun(PsiTypeParameter parameter) {
- final PsiType psiType = substitutor.substitute(parameter);
- LOG.assertTrue(psiType != null);
- return psiType.getCanonicalText();
+ if (onArrayRef) {
+ if (qualifier instanceof PsiTypeElement) {
+ final PsiType type = ((PsiTypeElement)qualifier).getType();
+ int dim = type.getArrayDimensions();
+ buf.append(type.getDeepComponentType().getCanonicalText());
+ buf.append("[");
+ buf.append(map.get(parameters[0]));
+ buf.append("]");
+ while (--dim > 0) {
+ buf.append("[]");
}
- }, ", ")).append(">");
+ }
+ } else {
+ buf.append(((PsiMember)resolveElement).getName());
+
+ final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
+
+ LOG.assertTrue(containingClass != null);
+ if (containingClass.hasTypeParameters() && !PsiUtil.isRawSubstitutor(containingClass, substitutor)) {
+ buf.append("<").append(StringUtil.join(containingClass.getTypeParameters(), new Function<PsiTypeParameter, String>() {
+ @Override
+ public String fun(PsiTypeParameter parameter) {
+ final PsiType psiType = substitutor.substitute(parameter);
+ LOG.assertTrue(psiType != null);
+ return psiType.getCanonicalText();
+ }
+ }, ", ")).append(">");
+ }
}
}
- //param list
- buf.append("(");
- boolean first = true;
- for (int i = isReceiver ? 1 : 0; i < parameters.length; i++) {
- PsiParameter parameter = parameters[i];
- if (!first) {
- buf.append(", ");
- } else {
- first = false;
+ if (!onArrayRef || isReceiver) {
+ //param list
+ buf.append("(");
+ boolean first = true;
+ for (int i = isReceiver ? 1 : 0; i < parameters.length; i++) {
+ PsiParameter parameter = parameters[i];
+ if (!first) {
+ buf.append(", ");
+ } else {
+ first = false;
+ }
+ buf.append(map.get(parameter));
}
- buf.append(map.get(parameter));
+ buf.append(")");
}
- buf.append(")");
if (needBraces) {
buf.append(";}");
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/after.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/after.java.template
index 8a3ba03bb373..8a3ba03bb373 100644
--- a/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/after.java.template
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/after.java.template
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/before.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/before.java.template
index 8d08a5453a3b..8d08a5453a3b 100644
--- a/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/before.java.template
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/before.java.template
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/description.html b/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/description.html
new file mode 100644
index 000000000000..16d16cd35c2b
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMultiCatchIntention/description.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+This intention splits a multi-catch section into separate <b>catch</b> blocks.
+<br><br>
+<small>New in 10.5</small>
+</body>
+</html>
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/description.html b/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/description.html
deleted file mode 100644
index 35896b35a538..000000000000
--- a/plugins/IntentionPowerPak/src/intentionDescriptions/SplitMulticatchIntention/description.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<body>
-This intention splits a multicatch section into
-separate <b>catch</b> blocks.
-<br><br>
-<small>New in 10.5</small>
-</body>
-</html>
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/catchToThrows/SingleCatch.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/catchToThrows/SingleCatch.java
index e4b20b45496f..d584d799a779 100644
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/catchToThrows/SingleCatch.java
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/catchToThrows/SingleCatch.java
@@ -21,6 +21,6 @@ class C {
/* important comment */
f();
// another comment
- } <caret>catch (Exception ignore) { }
+ } catch (Exception <caret>ignore) { }
}
} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/detail/PolyadicParentheses.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/detail/PolyadicParentheses.java
new file mode 100644
index 000000000000..750abe1ab026
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/detail/PolyadicParentheses.java
@@ -0,0 +1,20 @@
+package com.siyeh.ipp.exceptions.detail;
+
+import java.io.IOException;
+
+public class PolyadicParentheses {
+
+ void box() {
+ try {
+ System.out.println(one() && (two()) && one());
+ } c<caret>atch (Exception e) {}
+ }
+
+ boolean one() throws IOException {
+ return false;
+ }
+
+ boolean two() throws NoSuchFieldException {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/detail/PolyadicParentheses_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/detail/PolyadicParentheses_after.java
new file mode 100644
index 000000000000..b52f62c1691c
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/detail/PolyadicParentheses_after.java
@@ -0,0 +1,22 @@
+package com.siyeh.ipp.exceptions.detail;
+
+import java.io.IOException;
+
+public class PolyadicParentheses {
+
+ void box() {
+ try {
+ System.out.println(one() && (two()) && one());
+ } catch (IOException e) {
+ } catch (NoSuchFieldException e) {
+ }
+ }
+
+ boolean one() throws IOException {
+ return false;
+ }
+
+ boolean two() throws NoSuchFieldException {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/Simple.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/Simple.java
new file mode 100644
index 000000000000..78110c3af48d
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/Simple.java
@@ -0,0 +1,12 @@
+package com.siyeh.ipp.exceptions.splitMultiCatch;
+
+import java.io.*;
+
+public class Simple {
+ void foo() {
+ try {
+ Reader reader = new FileReader("");
+ } <caret>catch (IndexOutOfBoundsException | FileNotFoundException e) {
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/Simple_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/Simple_after.java
new file mode 100644
index 000000000000..f10a40928fda
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/Simple_after.java
@@ -0,0 +1,13 @@
+package com.siyeh.ipp.exceptions.splitMultiCatch;
+
+import java.io.*;
+
+public class Simple {
+ void foo() {
+ try {
+ Reader reader = new FileReader("");
+ } catch (IndexOutOfBoundsException e) {
+ } catch (FileNotFoundException e) {
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/TypeAnno.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/TypeAnno.java
new file mode 100644
index 000000000000..9768360bedb6
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/TypeAnno.java
@@ -0,0 +1,16 @@
+package com.siyeh.ipp.exceptions.splitMultiCatch;
+
+import java.io.*;
+import java.lang.annotation.*;
+
+public class Simple {
+ void foo() {
+ try {
+ Reader reader = new FileReader("");
+ } <caret>catch (@A @TA IndexOutOfBoundsException | @TA FileNotFoundException e) {
+ }
+ }
+}
+
+@Target(ElementType.PARAMETER) @interface A { }
+@Target(ElementType.TYPE_USE) @interface TA { } \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/TypeAnno_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/TypeAnno_after.java
new file mode 100644
index 000000000000..d8d23ae53a2a
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitMultiCatch/TypeAnno_after.java
@@ -0,0 +1,17 @@
+package com.siyeh.ipp.exceptions.splitMultiCatch;
+
+import java.io.*;
+import java.lang.annotation.*;
+
+public class Simple {
+ void foo() {
+ try {
+ Reader reader = new FileReader("");
+ } catch (@A @TA IndexOutOfBoundsException e) {
+ } catch (@A @TA FileNotFoundException e) {
+ }
+ }
+}
+
+@Target(ElementType.PARAMETER) @interface A { }
+@Target(ElementType.TYPE_USE) @interface TA { } \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch.java
new file mode 100644
index 000000000000..3bdb9a4db5ad
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch.java
@@ -0,0 +1,13 @@
+package com.siyeh.ipp.exceptions.splitTry;
+
+import java.io.*;
+
+public class WithCatch {
+ void foo(File file1, File file2) {
+ try (FileInputStream in = new FileInputStream(file1); <caret>FileOutputStream out = new FileOutputStream(file2)) {
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch_after.java
new file mode 100644
index 000000000000..08442f0a7203
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch_after.java
@@ -0,0 +1,15 @@
+package com.siyeh.ipp.exceptions.splitTry;
+
+import java.io.*;
+
+public class WithCatch {
+ void foo(File file1, File file2) {
+ try (FileInputStream in = new FileInputStream(file1)) {
+ try (FileOutputStream out = new FileOutputStream(file2)) {
+
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/NoChange.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/NoChange.java
new file mode 100644
index 000000000000..258e196f0910
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/NoChange.java
@@ -0,0 +1,7 @@
+package com.siyeh.ipp.expression.flip_expression;
+
+public class NoChange {
+ int x() {
+ return 1 <caret>+ 1;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/NoException.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/NoException.java
new file mode 100644
index 000000000000..307a095981c4
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/NoException.java
@@ -0,0 +1,8 @@
+package com.siyeh.ipp.expression.flip_expression;
+
+public class NoException {
+
+ void x() {
+ int i = 1 <caret>+ ;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Polyadic.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Polyadic.java
new file mode 100644
index 000000000000..258cebec8bce
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Polyadic.java
@@ -0,0 +1,8 @@
+package com.siyeh.ipp.expression.flip_expression;
+
+public class Polyadic {
+ int x() {
+ return 1 - 2 <caret>- 3;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Polyadic_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Polyadic_after.java
new file mode 100644
index 000000000000..f7acdf929318
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Polyadic_after.java
@@ -0,0 +1,8 @@
+package com.siyeh.ipp.expression.flip_expression;
+
+public class Polyadic {
+ int x() {
+ return 1 - 3 - 2;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Prefix.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Prefix.java
new file mode 100644
index 000000000000..7a4712faa429
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Prefix.java
@@ -0,0 +1,7 @@
+package com.siyeh.ipp.expression.flip_expression;
+
+class Prefix {
+ int x() {
+ return 1 <caret>- -1;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Prefix_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Prefix_after.java
new file mode 100644
index 000000000000..b4b147aff359
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/expression/flip_expression/Prefix_after.java
@@ -0,0 +1,7 @@
+package com.siyeh.ipp.expression.flip_expression;
+
+class Prefix {
+ int x() {
+ return -1 - 1;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods.java
index 394e20bbf423..8e5a6597500e 100644
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods.java
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods.java
@@ -1,21 +1,5 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
public interface I<caret> {
- void m() default {
+ default void m() {
System.out.println("Hi there.");
}
} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods_after.java
index d616bc7ead37..14b7e5555bf9 100644
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods_after.java
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/interfaceToClass/ExtensionMethods_after.java
@@ -1,19 +1,3 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
public abstract class I {
public void m() {
System.out.println("Hi there.");
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/PolyadicAssignment.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/PolyadicAssignment.java
new file mode 100644
index 000000000000..c9248c1d4f42
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/PolyadicAssignment.java
@@ -0,0 +1,7 @@
+package com.siyeh.ipp.opassign.assignment;
+
+class PolyadicAssignment {
+ void x(int i) {
+ i *= 1<caret> + 2 + 3;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/PolyadicAssignment_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/PolyadicAssignment_after.java
new file mode 100644
index 000000000000..e378f5b21dfd
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/assignment/PolyadicAssignment_after.java
@@ -0,0 +1,7 @@
+package com.siyeh.ipp.opassign.assignment;
+
+class PolyadicAssignment {
+ void x(int i) {
+ i = i * (1 + 2 + 3);
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/Excluded.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/Excluded.java
new file mode 100644
index 000000000000..fd14af215d5f
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/Excluded.java
@@ -0,0 +1,8 @@
+package com.siyeh.ipp.opassign.operator_assignment;
+
+class Excluded {
+ void bug() {
+ boolean b = true;
+ b = b<caret> != false;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/PolyadicExpression.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/PolyadicExpression.java
new file mode 100644
index 000000000000..e6bf75c6a695
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/PolyadicExpression.java
@@ -0,0 +1,8 @@
+package com.siyeh.ipp.opassign.operator_assignment;
+
+class PolyadicExpression {
+
+ void foo(int i) {
+ i = i <caret>+ 1 + 2;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/PolyadicExpression_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/PolyadicExpression_after.java
new file mode 100644
index 000000000000..fc172e9a04dd
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/opassign/operator_assignment/PolyadicExpression_after.java
@@ -0,0 +1,8 @@
+package com.siyeh.ipp.opassign.operator_assignment;
+
+class PolyadicExpression {
+
+ void foo(int i) {
+ i += 1 + 2;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression2.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression2.java
new file mode 100644
index 000000000000..dc079b930859
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression2.java
@@ -0,0 +1,8 @@
+package com.siyeh.ipp.parentheses;
+
+class ArrayAccessExpression2 {
+ private static void x() {
+ Object info = new Object[]{"abc"};
+ String s = (String)(((Object[])info)[0]<caret>);
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression2_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression2_after.java
new file mode 100644
index 000000000000..438ea8db9782
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ArrayAccessExpression2_after.java
@@ -0,0 +1,8 @@
+package com.siyeh.ipp.parentheses;
+
+class ArrayAccessExpression2 {
+ private static void x() {
+ Object info = new Object[]{"abc"};
+ String s = (String) ((Object[])info)[0];
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Comments.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Comments.java
new file mode 100644
index 000000000000..5a42a37ef3b0
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Comments.java
@@ -0,0 +1,14 @@
+class Comments {
+
+ String foo(int par) {
+ if<caret>(par == 11)
+ return "ciao";/* case 1 bla bla */
+ else if(par == 14)
+ return "fourteen";//case 2 bla bla
+ else if(par == 15)
+ return "fifteen"; //case 3 chchah
+ else
+ return "default";
+
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Comments_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Comments_after.java
new file mode 100644
index 000000000000..3922f442af44
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Comments_after.java
@@ -0,0 +1,16 @@
+class Comments {
+
+ String foo(int par) {
+ switch (par) {
+ case 11:
+ return "ciao";/* case 1 bla bla */
+ case 14:
+ return "fourteen";//case 2 bla bla
+ case 15:
+ return "fifteen"; //case 3 chchah
+ default:
+ return "default";
+ }
+
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Long.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Long.java
new file mode 100644
index 000000000000..14113e62e520
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Long.java
@@ -0,0 +1,10 @@
+package com.siyeh.ipp.switchtoif.replace_if_with_switch;
+
+public class Long {
+ void x(long l) {
+ <caret>if (l == 1) {
+ } else if (l == 2) {
+ } else if (l == 3) {
+ } else if (l == 4) {}
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Polyadic.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Polyadic.java
new file mode 100644
index 000000000000..8bb02a29e15c
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Polyadic.java
@@ -0,0 +1,13 @@
+package com.siyeh.ipp.switchtoif.replace_if_with_switch;
+
+public class Polyadic {
+ void x(int i) {
+ <caret>if (i == 1 || i == 2 || i == 3) {
+
+ } else if (i == 5) {
+
+ } else {
+
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Polyadic_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Polyadic_after.java
new file mode 100644
index 000000000000..1c6313bb0e21
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/switchtoif/replace_if_with_switch/Polyadic_after.java
@@ -0,0 +1,19 @@
+package com.siyeh.ipp.switchtoif.replace_if_with_switch;
+
+public class Polyadic {
+ void x(int i) {
+ switch (i) {
+ case 1:
+ case 2:
+ case 3:
+
+ break;
+ case 5:
+
+ break;
+ default:
+
+ break;
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef.java
new file mode 100644
index 000000000000..cd14ddf1f7f2
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef.java
@@ -0,0 +1,12 @@
+public class Foo {
+ static void foo() {
+ Ar<String> a = Stri<caret>ng[]::new;
+ }
+
+ interface Ar<T> {
+ T[] jjj(int p);
+ }
+}
+
+
+
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef2Dim.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef2Dim.java
new file mode 100644
index 000000000000..b4c1520b142d
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef2Dim.java
@@ -0,0 +1,12 @@
+public class Foo {
+ static void foo() {
+ Ar<String> a = Str<caret>ing[][]::new;
+ }
+
+ interface Ar<T> {
+ T[][] jjj(int p);
+ }
+}
+
+
+
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef2Dim_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef2Dim_after.java
new file mode 100644
index 000000000000..f12bd0757c40
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef2Dim_after.java
@@ -0,0 +1,12 @@
+public class Foo {
+ static void foo() {
+ Ar<String> a = (p) -> new String[p][];
+ }
+
+ interface Ar<T> {
+ T[][] jjj(int p);
+ }
+}
+
+
+
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRefUniqueParamName.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRefUniqueParamName.java
new file mode 100644
index 000000000000..9c22e194ce6c
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRefUniqueParamName.java
@@ -0,0 +1,14 @@
+public class Foo {
+ public void test() {
+ Object i = null;
+ long[][] avg = collect(long[][]:<caret>:new);
+ }
+
+ interface P<T> {
+ T _(int i);
+ }
+
+ <T> T collect(P<T> h) {
+ return null;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRefUniqueParamName_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRefUniqueParamName_after.java
new file mode 100644
index 000000000000..a97db7b453f1
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRefUniqueParamName_after.java
@@ -0,0 +1,14 @@
+public class Foo {
+ public void test() {
+ Object i = null;
+ long[][] avg = collect((i1) -> new long[i1][]);
+ }
+
+ interface P<T> {
+ T _(int i);
+ }
+
+ <T> T collect(P<T> h) {
+ return null;
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef_after.java
new file mode 100644
index 000000000000..7d38741a60ab
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayConstructorRef_after.java
@@ -0,0 +1,12 @@
+public class Foo {
+ static void foo() {
+ Ar<String> a = (p) -> new String[p];
+ }
+
+ interface Ar<T> {
+ T[] jjj(int p);
+ }
+}
+
+
+
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayMethodRef.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayMethodRef.java
new file mode 100644
index 000000000000..a59bb6d2041c
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayMethodRef.java
@@ -0,0 +1,9 @@
+public class Foo {
+ static void foo() {
+ Cln j = i<caret>nt[]::clone;
+ }
+
+ interface Cln {
+ Object _(int[] p);
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayMethodRef_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayMethodRef_after.java
new file mode 100644
index 000000000000..65a55a55e8aa
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/methodRefs2lambda/ArrayMethodRef_after.java
@@ -0,0 +1,9 @@
+public class Foo {
+ static void foo() {
+ Cln j = (p) -> p.clone();
+ }
+
+ interface Cln {
+ Object _(int[] p);
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/DetailExceptionsIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/DetailExceptionsIntentionTest.java
index 57dd548f5d15..4aa2832b772f 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/DetailExceptionsIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/DetailExceptionsIntentionTest.java
@@ -4,6 +4,7 @@ import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.IPPTestCase;
/**
+ * @see DetailExceptionsIntention
* @author Bas Leijdekkers
*/
public class DetailExceptionsIntentionTest extends IPPTestCase {
@@ -12,6 +13,7 @@ public class DetailExceptionsIntentionTest extends IPPTestCase {
public void testSimple() { doTest(); }
public void testForeach() { doTest(); }
public void testTryWithResources() { doTest(); }
+ public void testPolyadicParentheses() { doTest(); }
@Override
protected String getIntentionName() {
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitMultiCatchIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitMultiCatchIntentionTest.java
new file mode 100644
index 000000000000..360ea156ba14
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitMultiCatchIntentionTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ipp.exceptions;
+
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ipp.IPPTestCase;
+
+public class SplitMultiCatchIntentionTest extends IPPTestCase {
+ public void testSimple() { doTest(); }
+ public void testTypeAnno() { doTest(); }
+
+ @Override
+ protected String getIntentionName() {
+ return IntentionPowerPackBundle.message("split.multi.catch.intention.name");
+ }
+
+ @Override
+ protected String getRelativePath() {
+ return "exceptions/splitMultiCatch";
+ }
+}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java
index cce64b4edcd8..61a1fa54a6b2 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java
@@ -9,6 +9,7 @@ import com.siyeh.ipp.IPPTestCase;
public class SplitTryWithMultipleResourcesIntentionTest extends IPPTestCase {
public void testSimple() { doTest(); }
+ public void testWithCatch() { doTest(); }
@Override
protected String getIntentionName() {
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/FlipExpressionIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/FlipExpressionIntentionTest.java
new file mode 100644
index 000000000000..e1ec6b467380
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/expression/FlipExpressionIntentionTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.siyeh.ipp.expression;
+
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ipp.IPPTestCase;
+
+/**
+ * @see com.siyeh.ipp.expression.FlipExpressionIntention
+ */
+public class FlipExpressionIntentionTest extends IPPTestCase {
+ public void testPrefix() { doTest(); }
+ public void testPolyadic() { doTest(); }
+ public void testNoChange() { assertIntentionNotAvailable(); }
+ public void testNoException() { assertIntentionNotAvailable(); }
+
+ @Override
+ protected String getIntentionName() {
+ return IntentionPowerPackBundle.message("flip.smth.intention.name1", "-");
+ }
+
+ @Override
+ protected String getRelativePath() {
+ return "expression/flip_expression";
+ }
+}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntentionTest.java
index d3decdebc342..026351e96ddf 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntentionTest.java
@@ -3,12 +3,16 @@ package com.siyeh.ipp.opassign;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.IPPTestCase;
+/**
+ * @see ReplaceOperatorAssignmentWithAssignmentIntention
+ */
public class ReplaceOperatorAssignmentWithAssignmentIntentionTest extends IPPTestCase {
public void testOperatorAssignment1() { doTest(); }
public void testDoubleOpAssign() { doTest(); }
public void testStringOpAssign() { doTest(); }
public void testByteOpAssign() { doTest(); }
public void testPrecedence() { doTest(); }
+ public void testPolyadicAssignment() { doTest(IntentionPowerPackBundle.message("replace.operator.assignment.with.assignment.intention.name", "*=")); }
@Override
protected String getIntentionName() {
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntentionTest.java
new file mode 100644
index 000000000000..0a109e5af5c4
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntentionTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.siyeh.ipp.opassign;
+
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ipp.IPPTestCase;
+
+/**
+ * @see ReplaceWithOperatorAssignmentIntention
+ */
+public class ReplaceWithOperatorAssignmentIntentionTest extends IPPTestCase {
+ public void testPolyadicExpression() { doTest(); }
+ public void testExcluded() { assertIntentionNotAvailable(); }
+
+ @Override
+ protected String getIntentionName() {
+ return IntentionPowerPackBundle.message("replace.assignment.with.operator.assignment.intention.name", "+");
+ }
+
+ @Override
+ protected String getRelativePath() {
+ return "opassign/operator_assignment";
+ }
+}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/parenthesis/UnnecessaryParenthesesIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/parenthesis/UnnecessaryParenthesesIntentionTest.java
index 720442fc883d..d373c6c46d6c 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/parenthesis/UnnecessaryParenthesesIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/parenthesis/UnnecessaryParenthesesIntentionTest.java
@@ -17,6 +17,7 @@ public class UnnecessaryParenthesesIntentionTest extends IPPTestCase {
public void testNotCommutative2() { doTest(); }
public void testArrayInitializer() { doTest(); }
public void testArrayAccessExpression() { doTest(); }
+ public void testArrayAccessExpression2() { doTest(); }
public void testSimplePrecedence() { assertIntentionNotAvailable(); }
@Override
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchlIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchlIntentionTest.java
new file mode 100644
index 000000000000..f6692ab4e2c6
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/switchtoif/ReplaceIfWithSwitchlIntentionTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.siyeh.ipp.switchtoif;
+
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ipp.IPPTestCase;
+
+/**
+ * @see ReplaceIfWithSwitchIntention
+ */
+public class ReplaceIfWithSwitchlIntentionTest extends IPPTestCase {
+
+ public void testComments() { doTest(); }
+ public void testLong() { assertIntentionNotAvailable(); }
+ public void testPolyadic() { doTest(); }
+
+ @Override
+ protected String getIntentionName() {
+ return IntentionPowerPackBundle.message("replace.if.with.switch.intention.name");
+ }
+
+ @Override
+ protected String getRelativePath() {
+ return "switchtoif/replace_if_with_switch";
+ }
+}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceMethodReferenceWithLambdaIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceMethodReferenceWithLambdaIntentionTest.java
index 0a4dc30371f2..650a2d8a5266 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceMethodReferenceWithLambdaIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceMethodReferenceWithLambdaIntentionTest.java
@@ -89,4 +89,20 @@ public class ReplaceMethodReferenceWithLambdaIntentionTest extends IPPTestCase {
public void testNewDefaultConstructor() throws Exception {
doTest();
}
+
+ public void testArrayConstructorRef() throws Exception {
+ doTest();
+ }
+
+ public void testArrayConstructorRef2Dim() throws Exception {
+ doTest();
+ }
+
+ public void testArrayMethodRef() throws Exception {
+ doTest();
+ }
+
+ public void testArrayConstructorRefUniqueParamName() throws Exception {
+ doTest();
+ }
}
diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/RootView.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/RootView.java
index bda836ac10fd..6483149d2c01 100644
--- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/RootView.java
+++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/RootView.java
@@ -15,7 +15,6 @@
*/
package com.intellij.android.designer.designSurface;
-import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
@@ -26,13 +25,23 @@ import java.util.List;
*/
public class RootView extends com.intellij.designer.designSurface.RootView {
private List<EmptyRegion> myEmptyRegions;
+ private boolean myAlphaChannelImage;
public RootView(int x, int y, BufferedImage image) {
super(x, y, image);
}
- public void setImage(BufferedImage image) {
- super.setImage(image);
+ public boolean isAlphaChannelImage() {
+ return myAlphaChannelImage;
+ }
+
+ public void setAlphaChannelImage(boolean alphaChannelImage) {
+ myAlphaChannelImage = alphaChannelImage;
+ }
+
+ @Override
+ public void setImage(BufferedImage image, int x, int y, int width, int height) {
+ super.setImage(image, x, y, width, height);
myEmptyRegions = new ArrayList<EmptyRegion>();
}
diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidDexBuildTarget.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidDexBuildTarget.java
index cf0c6704527e..6b6b2c860af1 100644
--- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidDexBuildTarget.java
+++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidDexBuildTarget.java
@@ -10,10 +10,10 @@ import org.jetbrains.jps.android.AndroidJpsUtil;
import org.jetbrains.jps.android.AndroidPlatform;
import org.jetbrains.jps.android.model.JpsAndroidModuleExtension;
import org.jetbrains.jps.builders.BuildRootDescriptor;
-import org.jetbrains.jps.builders.BuildRootIndex;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.ModuleBuildTarget;
import org.jetbrains.jps.indices.IgnoredFileIndex;
@@ -34,9 +34,8 @@ public class AndroidDexBuildTarget extends AndroidBuildTarget {
}
@Override
- public void writeConfiguration(PrintWriter out, BuildDataPaths dataPaths, BuildRootIndex buildRootIndex) {
- super.writeConfiguration(out, dataPaths, buildRootIndex);
-
+ public void writeConfiguration(ProjectDescriptor pd, PrintWriter out) {
+ super.writeConfiguration(pd, out);
// todo: write compiler settings
}
diff --git a/plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/JpsAntExtensionService.java b/plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/JpsAntExtensionService.java
index 22668a1c6bc0..d39f6ff79c28 100644
--- a/plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/JpsAntExtensionService.java
+++ b/plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/JpsAntExtensionService.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.jps.ant.model;
+import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -28,8 +29,6 @@ import org.jetbrains.jps.model.JpsGlobal;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.artifact.JpsArtifact;
-import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
-import org.jetbrains.jps.model.serialization.PathMacroUtil;
import java.io.File;
import java.util.Collections;
@@ -69,10 +68,10 @@ public class JpsAntExtensionService {
}
@Nullable
- private static JpsAntInstallation getBundledAntInstallation(@NotNull JpsGlobal global) {
- String appHome = JpsGlobalLoader.getPathVariable(global, PathMacroUtil.APPLICATION_HOME_DIR);
+ private static JpsAntInstallation getBundledAntInstallation() {
+ final String appHome = PathManager.getHomePath();
if (appHome == null) {
- LOG.debug(PathMacroUtil.APPLICATION_HOME_DIR + " path variable not found, bundled Ant won't be configured");
+ LOG.debug("IDEA home path is null, bundled Ant won't be configured");
return null;
}
@@ -104,7 +103,7 @@ public class JpsAntExtensionService {
antInstallationName = options.getAntInstallationName();
}
- if (antInstallationName == null) return getBundledAntInstallation(model.getGlobal());
+ if (antInstallationName == null) return getBundledAntInstallation();
return findAntInstallation(model, antInstallationName);
}
diff --git a/plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/impl/JpsAntInstallationImpl.java b/plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/impl/JpsAntInstallationImpl.java
index 1db18840e793..ca5dc045265f 100644
--- a/plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/impl/JpsAntInstallationImpl.java
+++ b/plugins/ant/jps-plugin/src/org/jetbrains/jps/ant/model/impl/JpsAntInstallationImpl.java
@@ -34,7 +34,7 @@ public class JpsAntInstallationImpl extends JpsElementBase<JpsAntInstallationImp
private final String myName;
private final List<String> myClasspath;
private final List<String> myJarDirectories;
- public static final JpsElementChildRoleBase<JpsAntInstallation> ROLE = JpsElementChildRoleBase.create("ant installation");
+ private static final JpsElementChildRoleBase<JpsAntInstallation> ROLE = JpsElementChildRoleBase.create("ant installation");
public static final JpsElementCollectionRole<JpsAntInstallation> COLLECTION_ROLE = JpsElementCollectionRole.create(ROLE);
public JpsAntInstallationImpl(File antHome, String name, final List<String> classpath, List<String> jarDirectories) {
diff --git a/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java b/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
index a2b43bb75b03..426604fdfe97 100644
--- a/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
+++ b/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
@@ -21,11 +21,11 @@ import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderTestCase;
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
+import org.jetbrains.jps.model.serialization.JpsModelSerializationDataService;
import org.jetbrains.jps.model.serialization.PathMacroUtil;
import java.io.File;
import java.io.IOException;
-import java.util.Collections;
import java.util.Map;
import static com.intellij.util.io.TestFileSystemBuilder.fs;
@@ -43,8 +43,8 @@ public class JpsAntArtifactBuilderTaskTest extends ArtifactBuilderTestCase {
}
public void testSimple() throws IOException {
- Map<String, String> pathVariables = Collections.singletonMap(PathMacroUtil.APPLICATION_HOME_DIR, PathManager.getHomePath());
- JpsGlobalLoader.loadGlobalSettings(myModel.getGlobal(), pathVariables, getTestDataRootPath() + "/config/options");
+ JpsModelSerializationDataService.getOrCreatePathVariablesConfiguration(myModel.getGlobal()).addPathVariable(PathMacroUtil.APPLICATION_HOME_DIR, PathManager.getHomePath());
+ JpsGlobalLoader.loadGlobalSettings(myModel.getGlobal(), getTestDataRootPath() + "/config/options");
addJdk("1.6");
loadProject("ant-project");
rebuildAll();
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/InputRequestHandler.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/InputRequestHandler.java
index 5bd77dff3b4e..5acc761f9c3f 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/execution/InputRequestHandler.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/InputRequestHandler.java
@@ -53,14 +53,17 @@ class InputRequestHandler {
private static String askUser(SegmentReader reader, Project project) {
String prompt = reader.readLimitedString();
+ String defaultValue = reader.readLimitedString();
String[] choices = reader.readStringArray();
MessagesEx.BaseInputInfo question;
if (choices.length == 0) {
- question = new MessagesEx.InputInfo(project);
+ MessagesEx.InputInfo inputInfo = new MessagesEx.InputInfo(project);
+ inputInfo.setDefaultValue(defaultValue);
+ question = inputInfo;
}
else {
MessagesEx.ChoiceInfo choiceInfo = new MessagesEx.ChoiceInfo(project);
- choiceInfo.setChoices(choices, 0);
+ choiceInfo.setChoices(choices, defaultValue);
question = choiceInfo;
}
question.setIcon(Messages.getQuestionIcon());
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBuildFileImpl.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBuildFileImpl.java
index f6dd78d892b7..3078230bfbe3 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBuildFileImpl.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntBuildFileImpl.java
@@ -34,8 +34,6 @@ import com.intellij.psi.xml.XmlFile;
import com.intellij.util.NewInstanceFactory;
import com.intellij.util.SystemProperties;
import com.intellij.util.config.*;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.HashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -119,11 +117,12 @@ public class AntBuildFileImpl implements AntBuildFileBase {
public static final BooleanProperty VERBOSE = new BooleanProperty("verbose", true);
public static final BooleanProperty TREE_VIEW = new BooleanProperty("treeView", true);
public static final BooleanProperty CLOSE_ON_NO_ERRORS = new BooleanProperty("viewClosedWhenNoErrors", false);
- public static final AbstractProperty<String> CUSTOM_JDK_NAME = new StringProperty("customJdkName", "");
+ public static final StringProperty CUSTOM_JDK_NAME = new StringProperty("customJdkName", "");
public static final ListProperty<TargetFilter> TARGET_FILTERS = ListProperty.create("targetFilters");
public static final ListProperty<BuildFileProperty> ANT_PROPERTIES = ListProperty.create("properties");
- public static final AbstractProperty<String> ANT_COMMAND_LINE_PARAMETERS = new StringProperty("antCommandLine", "");
- public static final AbstractProperty<AntReference> ANT_REFERENCE = new ValueProperty<AntReference>("antReference", AntReference.PROJECT_DEFAULT);
+ public static final StringProperty ANT_COMMAND_LINE_PARAMETERS = new StringProperty("antCommandLine", "");
+ public static final AbstractProperty<AntReference> ANT_REFERENCE =
+ new ValueProperty<AntReference>("antReference", AntReference.PROJECT_DEFAULT);
public static final ListProperty<AntClasspathEntry> ADDITIONAL_CLASSPATH = ListProperty.create("additionalClassPath");
public static final AbstractProperty<AntInstallation> RUN_WITH_ANT = new AbstractProperty<AntInstallation>() {
public String getName() {
@@ -164,21 +163,20 @@ public class AntBuildFileImpl implements AntBuildFileBase {
myWorkspaceOptions.registerProperty(TREE_VIEW);
myWorkspaceOptions.registerProperty(VERBOSE);
myWorkspaceOptions.registerProperty(TARGET_FILTERS, "filter", NewInstanceFactory.fromClass(TargetFilter.class));
- myWorkspaceOptions.registerProperty((StringProperty)ANT_COMMAND_LINE_PARAMETERS);
myWorkspaceOptions.rememberKey(RUN_WITH_ANT);
myProjectOptions = new ExternalizablePropertyContainer();
myProjectOptions.registerProperty(MAX_HEAP_SIZE);
myProjectOptions.registerProperty(MAX_STACK_SIZE);
- myProjectOptions.registerProperty((StringProperty)CUSTOM_JDK_NAME);
+ myProjectOptions.registerProperty(CUSTOM_JDK_NAME);
+ myProjectOptions.registerProperty(ANT_COMMAND_LINE_PARAMETERS);
myProjectOptions.registerProperty(ANT_PROPERTIES, "property", NewInstanceFactory.fromClass(BuildFileProperty.class));
myProjectOptions.registerProperty(ADDITIONAL_CLASSPATH, "entry", SinglePathEntry.EXTERNALIZER);
myProjectOptions.registerProperty(ANT_REFERENCE, AntReference.EXTERNALIZER);
- myAllOptions = new CompositePropertyContainer(new AbstractProperty.AbstractPropertyContainer[]{
- myWorkspaceOptions, myProjectOptions, GlobalAntConfiguration.getInstance().getProperties(getProject())
- });
+ myAllOptions = new CompositePropertyContainer(new AbstractProperty.AbstractPropertyContainer[]{myWorkspaceOptions, myProjectOptions,
+ GlobalAntConfiguration.getInstance().getProperties(getProject())});
myClassloaderHolder = new AntBuildFileClassLoaderHolder(myAllOptions);
}
@@ -203,7 +201,7 @@ public class AntBuildFileImpl implements AntBuildFileBase {
@Nullable
public String getName() {
final VirtualFile vFile = getVirtualFile();
- return vFile != null? vFile.getName() : null;
+ return vFile != null ? vFile.getName() : null;
}
@@ -222,12 +220,12 @@ public class AntBuildFileImpl implements AntBuildFileBase {
@Nullable
public XmlFile getAntFile() {
- final PsiFile psiFile = myVFile.isValid()? PsiManager.getInstance(getProject()).findFile(myVFile) : null;
+ final PsiFile psiFile = myVFile.isValid() ? PsiManager.getInstance(getProject()).findFile(myVFile) : null;
if (!(psiFile instanceof XmlFile)) {
return null;
}
final XmlFile xmlFile = (XmlFile)psiFile;
- return AntDomFileDescription.isAntFile(xmlFile)? xmlFile : null;
+ return AntDomFileDescription.isAntFile(xmlFile) ? xmlFile : null;
}
public Project getProject() {
@@ -274,18 +272,20 @@ public class AntBuildFileImpl implements AntBuildFileBase {
}
public void updateProperties() {
- final Map<String, AntBuildTarget> targetByName =
- ContainerUtil.newMapFromValues(Arrays.asList(getModel().getTargets()).iterator(), new Convertor<AntBuildTarget, String>() {
- public String convert(AntBuildTarget target) {
- return target.getName();
- }
- });
- targetByName.remove(null); // ensure there are no targets with 'null' name
+ // do not change position
+ final AntBuildTarget[] targets = getModel().getTargets();
+ final Map<String, AntBuildTarget> targetByName = new LinkedHashMap<String, AntBuildTarget>(targets.length);
+ for (AntBuildTarget target : targets) {
+ String targetName = target.getName();
+ if(targetName != null) {
+ targetByName.put(targetName, target);
+ }
+ }
synchronized (myOptionsLock) {
myCachedExternalProperties = null;
final ArrayList<TargetFilter> filters = TARGET_FILTERS.getModifiableList(myAllOptions);
- for (Iterator<TargetFilter> iterator = filters.iterator(); iterator.hasNext();) {
+ for (Iterator<TargetFilter> iterator = filters.iterator(); iterator.hasNext(); ) {
final TargetFilter filter = iterator.next();
final String name = filter.getTargetName();
if (name == null) {
@@ -333,6 +333,12 @@ public class AntBuildFileImpl implements AntBuildFileBase {
if (expanded != null) {
myShouldExpand = Boolean.valueOf(expanded.getAttributeValue("value"));
}
+
+ // don't lose old command line parameters
+ final Element antCommandLine = parentNode.getChild("antCommandLine");
+ if (antCommandLine != null) {
+ ANT_COMMAND_LINE_PARAMETERS.set(myProjectOptions, antCommandLine.getAttributeValue("value"));
+ }
}
}
@@ -375,7 +381,7 @@ public class AntBuildFileImpl implements AntBuildFileBase {
result = myCachedExternalProperties;
if (result == null) {
result = new HashMap<String, String>();
-
+
final DataContext context = SimpleDataContext.getProjectContext(myProject);
final MacroManager macroManager = MacroManager.getInstance();
Iterator<BuildFileProperty> properties = ANT_PROPERTIES.getIterator(myAllOptions);
@@ -391,13 +397,13 @@ public class AntBuildFileImpl implements AntBuildFileBase {
LOG.debug(e);
}
}
- myCachedExternalProperties = result;
+ myCachedExternalProperties = result;
}
}
}
return result;
}
-
+
private void bindAnt() {
ANT_REFERENCE.set(getAllOptions(), ANT_REFERENCE.get(getAllOptions()).bind(GlobalAntConfiguration.getInstance()));
}
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java
index d748495ef6e5..3b4a28971f13 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java
@@ -24,6 +24,7 @@ import com.intellij.util.containers.Convertor;
import com.intellij.util.lang.UrlClassLoader;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
@@ -125,6 +126,7 @@ public class AntInstallation {
return myProperties;
}
+ @NotNull
public ClassLoader getClassLoader() {
return myClassLoaderHolder.getClassloader();
}
@@ -164,7 +166,7 @@ public class AntInstallation {
Properties properties = new Properties();
InputStream stream = null;
try {
- stream = new UrlClassLoader(Collections.singletonList(antJar.toURL()), null, false, false, true).getResourceAsStream(VERSION_RESOURCE);
+ stream = new UrlClassLoader(Collections.singletonList(antJar.toURL()), null, false, false, true, false).getResourceAsStream(VERSION_RESOURCE);
properties.load(stream);
}
catch (MalformedURLException e) {
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java
index 4ff2b85c8b2a..feb9356add33 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java
@@ -17,9 +17,9 @@ package com.intellij.lang.ant.config.impl;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.util.lang.UrlClassLoader;
+import gnu.trove.THashSet;
import java.net.URL;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -28,15 +28,20 @@ import java.util.Set;
* Date: Oct 21, 2008
*/
public class AntResourcesClassLoader extends UrlClassLoader {
- private final Set<String> myMisses = new HashSet<String>();
+ private final Set<String> myMisses = new THashSet<String>();
public AntResourcesClassLoader(final List<URL> urls, final ClassLoader parentLoader, final boolean canLockJars, final boolean canUseCache) {
- super(urls, parentLoader, canLockJars, canUseCache, true);
+ super(urls, parentLoader, canLockJars, canUseCache, true, false);
}
protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
if (myMisses.contains(name)) {
- throw new ClassNotFoundException(name);
+ throw new ClassNotFoundException(name) {
+ @Override
+ public synchronized Throwable fillInStackTrace() {
+ return this;
+ }
+ };
}
return super.loadClass(name, resolve);
}
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntClasspathEditorPanel.form b/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntClasspathEditorPanel.form
index 0acb741d97e5..21b11258cb75 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntClasspathEditorPanel.form
+++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntClasspathEditorPanel.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="com.intellij.lang.ant.config.impl.configuration.AntClasspathEditorPanel$Form">
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.lang.ant.config.impl.configuration.AntClasspathEditorPanel.Form">
<grid id="e8f1e" binding="myWholePanel" layout-manager="GridLayoutManager" row-count="6" 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>
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntUIUtil.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntUIUtil.java
index a97e29839421..d252433b4399 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntUIUtil.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AntUIUtil.java
@@ -27,6 +27,7 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ui.OrderEntryAppearanceService;
import com.intellij.openapi.ui.FixedSizeButton;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
@@ -177,7 +178,10 @@ public class AntUIUtil {
if (jdk == null) {
if (myProjectJdkName.length() > 0) {
setIcon(AllIcons.General.Jdk);
- append(AntBundle.message("project.jdk.project.jdk.name.list.column.value", myProjectJdkName), selected ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES);
+ append(AntBundle.message("project.jdk.project.jdk.name.list.column.value", myProjectJdkName),
+ selected && !(SystemInfo.isWinVistaOrNewer && UIManager.getLookAndFeel().getName().contains("Windows"))
+ ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES
+ : SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES);
}
else {
setIcon(PlatformIcons.INVALID_ENTRY_ICON);
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java
index d9de2a4d0aac..7f17f40faa2f 100644
--- a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java
+++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java
@@ -145,19 +145,21 @@ public abstract class AntDomProject extends AntDomNamedElement implements Proper
@NotNull
public final ClassLoader getClassLoader() {
- if (myClassLoader == null) {
+ ClassLoader loader = myClassLoader;
+ if (loader == null) {
final XmlTag tag = getXmlTag();
final PsiFile containingFile = tag.getContainingFile();
final AntBuildFileImpl buildFile = (AntBuildFileImpl)AntConfigurationBase.getInstance(containingFile.getProject()).getAntBuildFile(containingFile);
if (buildFile != null) {
- myClassLoader = buildFile.getClassLoader();
+ loader = buildFile.getClassLoader();
}
else {
AntInstallation antInstallation = getAntInstallation();
- myClassLoader = antInstallation.getClassLoader();
+ loader = antInstallation.getClassLoader();
}
+ myClassLoader = loader;
}
- return myClassLoader;
+ return loader;
}
public AntInstallation getAntInstallation() {
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomRefIdConverter.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomRefIdConverter.java
index d0da497ef33e..e84b21f31068 100644
--- a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomRefIdConverter.java
+++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomRefIdConverter.java
@@ -103,7 +103,7 @@ public class AntDomRefIdConverter extends Converter<AntDomElement> implements Cu
}
public void visitAntDomElement(AntDomElement element) {
- if (result.get() != null || element instanceof AntDomCustomElement) {
+ if (result.get() != null) {
return;
}
if (id.equals(element.getId().getRawText())) {
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/ClassProvider.java b/plugins/ant/src/com/intellij/lang/ant/dom/ClassProvider.java
new file mode 100644
index 000000000000..6335987d2875
--- /dev/null
+++ b/plugins/ant/src/com/intellij/lang/ant/dom/ClassProvider.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.lang.ant.dom;
+
+import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+* @author Eugene Zhuravlev
+* Date: 3/4/13
+*/
+abstract class ClassProvider {
+ static final ClassProvider EMPTY = new ClassProvider() {
+ @Nullable
+ @Override
+ public Class lookupClass() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public String getError() {
+ return null;
+ }
+ };
+ @Nullable
+ abstract Class lookupClass();
+
+ @Nullable
+ abstract String getError();
+
+ static ClassProvider create(Class clazz) {
+ return clazz == null? EMPTY : new LoadedClassProvider(clazz);
+ }
+
+ static ClassProvider create(@Nullable String className, @NotNull ClassLoader loader) {
+ return className == null? EMPTY : new LazyLoadClassProvider(className, loader);
+ }
+
+ private static final class LoadedClassProvider extends ClassProvider {
+ private final Class myClass;
+
+ LoadedClassProvider(Class clazz) {
+ myClass = clazz;
+ }
+
+ @Nullable
+ @Override
+ public Class lookupClass() {
+ return myClass;
+ }
+
+ @Nullable
+ @Override
+ public String getError() {
+ return null;
+ }
+ }
+
+ private static final class LazyLoadClassProvider extends ClassProvider {
+ private final String myClassName;
+ private final ClassLoader myClassLoader;
+ private Pair<Class, String> myResult;
+
+ LazyLoadClassProvider(String className, ClassLoader classLoader) {
+ myClassName = className;
+ myClassLoader = classLoader;
+ }
+
+ @Override
+ @Nullable
+ public Class lookupClass() {
+ return getResult().getFirst();
+ }
+
+ @Override
+ @Nullable
+ public String getError() {
+ return getResult().getSecond();
+ }
+
+ @NotNull
+ private Pair<Class, String> getResult() {
+ Pair<Class, String> result = myResult;
+ if (result == null) {
+ Class clazz = null;
+ String error = null;
+ try {
+ clazz = myClassLoader.loadClass(myClassName);
+ }
+ catch (ClassNotFoundException e) {
+ error = "Class not found " + e.getMessage();
+ }
+ catch (NoClassDefFoundError e) {
+ error = "Class definition not found " + e.getMessage();
+ }
+ catch (UnsupportedClassVersionError e) {
+ error = "Unsupported class version " + e.getMessage();
+ }
+ myResult = result = Pair.create(clazz, error);
+ }
+ return result;
+ }
+ }
+
+}
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java b/plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java
index bc34389263b6..c8b64fe1d5b1 100644
--- a/plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java
+++ b/plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java
@@ -38,6 +38,7 @@ import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.xml.XmlName;
+import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,11 +66,10 @@ public class CustomAntElementsRegistry {
private static final Logger LOG = Logger.getInstance("#com.intellij.lang.ant.dom.CustomAntElementsRegistry");
private static final Key<CustomAntElementsRegistry> REGISTRY_KEY = Key.create("_custom_element_registry_");
- private final Map<XmlName, Class> myCustomElements = new HashMap<XmlName, Class>();
- private final Map<XmlName, String> myErrors = new HashMap<XmlName, String>();
- private final Map<AntDomNamedElement, String> myTypeDefErrors = new HashMap<AntDomNamedElement, String>();
- private final Map<XmlName, AntDomNamedElement> myDeclarations = new HashMap<XmlName, AntDomNamedElement>();
- private final Map<String, ClassLoader> myNamedLoaders = new HashMap<String, ClassLoader>();
+ private final Map<XmlName, ClassProvider> myCustomElements = new THashMap<XmlName, ClassProvider>();
+ private final Map<AntDomNamedElement, String> myTypeDefErrors = new THashMap<AntDomNamedElement, String>();
+ private final Map<XmlName, AntDomNamedElement> myDeclarations = new THashMap<XmlName, AntDomNamedElement>();
+ private final Map<String, ClassLoader> myNamedLoaders = new THashMap<String, ClassLoader>();
private CustomAntElementsRegistry(final AntDomProject antProject) {
antProject.accept(new CustomTagDefinitionFinder(antProject));
@@ -122,7 +122,7 @@ public class CustomAntElementsRegistry {
}
if (declaringElement instanceof AntDomTypeDef) {
final AntDomTypeDef typedef = (AntDomTypeDef)declaringElement;
- final Class clazz = myCustomElements.get(xmlName);
+ final Class clazz = lookupClass(xmlName);
if (clazz != null && typedef.isTask(clazz)) {
continue;
}
@@ -183,12 +183,14 @@ public class CustomAntElementsRegistry {
@Nullable
public Class lookupClass(XmlName xmlName) {
- return myCustomElements.get(xmlName);
+ final ClassProvider provider = myCustomElements.get(xmlName);
+ return provider == null ? null : provider.lookupClass();
}
@Nullable
public String lookupError(XmlName xmlName) {
- return myErrors.get(xmlName);
+ final ClassProvider provider = myCustomElements.get(xmlName);
+ return provider == null ? null : provider.getError();
}
public boolean hasTypeLoadingErrors(AntDomTypeDef typedef) {
@@ -198,7 +200,7 @@ public class CustomAntElementsRegistry {
}
for (Map.Entry<XmlName, AntDomNamedElement> entry : myDeclarations.entrySet()) {
if (typedef.equals(entry.getValue())) {
- if (myErrors.containsKey(entry.getKey())) {
+ if (lookupError(entry.getKey()) != null) {
return true;
}
}
@@ -214,15 +216,12 @@ public class CustomAntElementsRegistry {
List<String> errors = null;
for (Map.Entry<XmlName, AntDomNamedElement> entry : myDeclarations.entrySet()) {
if (typedef.equals(entry.getValue())) {
- final XmlName xmlName = entry.getKey();
- if (myErrors.containsKey(xmlName)) {
- final String err = myErrors.get(xmlName);
- if (err != null) {
- if (errors == null) {
- errors = new ArrayList<String>();
- }
- errors.add(err);
+ final String err = lookupError(entry.getKey());
+ if (err != null) {
+ if (errors == null) {
+ errors = new ArrayList<String>();
}
+ errors.add(err);
}
}
}
@@ -238,11 +237,14 @@ public class CustomAntElementsRegistry {
}
}
- @Nullable
+ @NotNull
private ClassLoader getClassLoader(AntDomCustomClasspathComponent customComponent, AntDomProject antProject) {
final String loaderRef = customComponent.getLoaderRef().getStringValue();
- if (loaderRef != null && myNamedLoaders.containsKey(loaderRef)) {
- return myNamedLoaders.get(loaderRef);
+ if (loaderRef != null) {
+ final ClassLoader loader = myNamedLoaders.get(loaderRef);
+ if (loader != null) {
+ return loader;
+ }
}
return createClassLoader(collectUrls(customComponent), antProject);
}
@@ -277,42 +279,9 @@ public class CustomAntElementsRegistry {
return factory.createFileFromText("_ant_dummy__." + fileType.getDefaultExtension(), fileType, builder, LocalTimeCounter.currentTime(), false, false);
}
- private void registerElement(AntDomNamedElement declaringElement, String customTagName, String nsUri, String classname, ClassLoader loader) {
- Class clazz = null;
- String error = null;
- try {
- clazz = loader.loadClass(classname);
- }
- catch (ClassNotFoundException e) {
- error = "Class not found " + e.getMessage();
- if (error == null) {
- error = "";
- }
- clazz = null;
- }
- catch (NoClassDefFoundError e) {
- error = "Class definition not found " + e.getMessage();
- if (error == null) {
- error = "";
- }
- clazz = null;
- }
- catch (UnsupportedClassVersionError e) {
- error = "Unsupported class version " + e.getMessage();
- if (error == null) {
- error = "";
- }
- clazz = null;
- }
- addCustomDefinition(declaringElement, customTagName, nsUri, clazz, error);
- }
-
- private void addCustomDefinition(@NotNull AntDomNamedElement declaringTag, String customTagName, String nsUri, Class clazz, String error) {
+ private void addCustomDefinition(@NotNull AntDomNamedElement declaringTag, String customTagName, String nsUri, ClassProvider classProvider) {
final XmlName xmlName = new XmlName(customTagName, nsUri == null? "" : nsUri);
- if (error != null) {
- myErrors.put(xmlName, error);
- }
- myCustomElements.put(xmlName, clazz);
+ myCustomElements.put(xmlName, classProvider);
myDeclarations.put(xmlName, declaringTag);
}
@@ -328,7 +297,7 @@ public class CustomAntElementsRegistry {
return StringUtil.endsWithIgnoreCase(resourceOrFileName, ".xml");
}
- @Nullable
+ @NotNull
public static ClassLoader createClassLoader(final List<URL> urls, final AntDomProject antProject) {
final ClassLoader parentLoader = antProject.getClassLoader();
if (urls.size() == 0) {
@@ -461,11 +430,11 @@ public class CustomAntElementsRegistry {
final String customTagName = macrodef.getName().getStringValue();
if (customTagName != null) {
final String nsUri = macrodef.getUri().getStringValue();
- addCustomDefinition(macrodef, customTagName, nsUri, null, null);
+ addCustomDefinition(macrodef, customTagName, nsUri, ClassProvider.EMPTY);
for (AntDomMacrodefElement element : macrodef.getMacroElements()) {
final String customSubTagName = element.getName().getStringValue();
if (customSubTagName != null) {
- addCustomDefinition(element, customSubTagName, nsUri, null, null);
+ addCustomDefinition(element, customSubTagName, nsUri, ClassProvider.EMPTY);
}
}
}
@@ -477,7 +446,7 @@ public class CustomAntElementsRegistry {
final String nsUri = scriptdef.getUri().getStringValue();
final ClassLoader classLoader = getClassLoader(scriptdef, myAntProject);
// register the scriptdef
- addCustomDefinition(scriptdef, customTagName, nsUri, null, null);
+ addCustomDefinition(scriptdef, customTagName, nsUri, ClassProvider.EMPTY);
// registering nested elements
ReflectedProject reflectedProject = null;
for (AntDomScriptdefElement element : scriptdef.getScriptdefElements()) {
@@ -485,13 +454,13 @@ public class CustomAntElementsRegistry {
if (customSubTagName != null) {
final String classname = element.getClassname().getStringValue();
if (classname != null) {
- registerElement(element, customTagName, nsUri, classname, classLoader);
+ addCustomDefinition(element, customTagName, nsUri, ClassProvider.create(classname, classLoader));
}
else {
Class clazz = null;
final String typeName = element.getElementType().getStringValue();
if (typeName != null) {
- clazz = myCustomElements.get(new XmlName(typeName));
+ clazz = lookupClass(new XmlName(typeName));
if (clazz == null) {
if (reflectedProject == null) { // lazy init
reflectedProject = ReflectedProject.getProject(myAntProject.getClassLoader());
@@ -508,7 +477,7 @@ public class CustomAntElementsRegistry {
}
}
}
- addCustomDefinition(element, customSubTagName, nsUri, clazz, null);
+ addCustomDefinition(element, customSubTagName, nsUri, ClassProvider.create(clazz));
}
}
}
@@ -519,7 +488,7 @@ public class CustomAntElementsRegistry {
final String customTagName = presetdef.getName().getStringValue();
if (customTagName != null) {
final String nsUri = presetdef.getUri().getStringValue();
- addCustomDefinition(presetdef, customTagName, nsUri, null, null);
+ addCustomDefinition(presetdef, customTagName, nsUri, ClassProvider.EMPTY);
}
}
@@ -553,7 +522,7 @@ public class CustomAntElementsRegistry {
final String classname = typedef.getClassName().getStringValue();
if (classname != null && customTagName != null) {
- registerElement(typedef, customTagName, uri, classname, getClassLoader(typedef, antProject));
+ addCustomDefinition(typedef, customTagName, uri, ClassProvider.create(classname, getClassLoader(typedef, antProject)));
}
else {
defineCustomElementsFromResources(typedef, uri, antProject, null);
@@ -574,25 +543,23 @@ public class CustomAntElementsRegistry {
if (loader == null) {
loader = getClassLoader(typedef, antProject);
}
- if (loader != null) {
- final InputStream stream = loader.getResourceAsStream(resource);
- if (stream != null) {
- try {
- if (isXmlFormat(typedef, resource)) {
- xmlFile = (XmlFile)loadContentAsFile(project, stream, StdFileTypes.XML);
- }
- else {
- propFile = (PropertiesFile)loadContentAsFile(project, stream, StdFileTypes.PROPERTIES);
- }
+ final InputStream stream = loader.getResourceAsStream(resource);
+ if (stream != null) {
+ try {
+ if (isXmlFormat(typedef, resource)) {
+ xmlFile = (XmlFile)loadContentAsFile(project, stream, StdFileTypes.XML);
}
- catch (IOException e) {
- LOG.info(e);
+ else {
+ propFile = (PropertiesFile)loadContentAsFile(project, stream, StdFileTypes.PROPERTIES);
}
}
- else {
- myTypeDefErrors.put(typedef, "Resource \"" + resource + "\" not found in the classpath");
+ catch (IOException e) {
+ LOG.info(e);
}
}
+ else {
+ myTypeDefErrors.put(typedef, "Resource \"" + resource + "\" not found in the classpath");
+ }
}
else {
final PsiFileSystemItem file = typedef.getFile().getValue();
@@ -611,7 +578,7 @@ public class CustomAntElementsRegistry {
loader = getClassLoader(typedef, antProject);
}
for (final IProperty property : propFile.getProperties()) {
- registerElement(typedef, property.getUnescapedKey(), uri, property.getValue(), loader);
+ addCustomDefinition(typedef, property.getUnescapedKey(), uri, ClassProvider.create(property.getValue(), loader));
}
}
@@ -634,7 +601,8 @@ public class CustomAntElementsRegistry {
final String tagName = def.getName().getStringValue();
final String className = def.getClassName().getStringValue();
if (tagName != null && className != null) {
- registerElement(typedef != null? typedef : def, tagName, uri, className, loader);
+ AntDomNamedElement declaringElement = typedef != null? typedef : def;
+ addCustomDefinition(declaringElement, tagName, uri, ClassProvider.create(className, loader));
}
else {
defineCustomElementsFromResources(def, uri, antProject, loader);
diff --git a/plugins/ant/tests/data/highlighting/RefidInCustomDomElement.xml b/plugins/ant/tests/data/highlighting/RefidInCustomDomElement.xml
new file mode 100644
index 000000000000..bcce3746ccba
--- /dev/null
+++ b/plugins/ant/tests/data/highlighting/RefidInCustomDomElement.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="javafxapplication">
+ <target name="artifact.unnamed">
+ <<error descr="Cannot resolve symbol 'application'">application</error> id="unnamed_id"/>
+ <<error descr="Cannot resolve symbol 'application'">application</error> refid="unnamed_id"/>
+ </target>
+</project> \ No newline at end of file
diff --git a/plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java b/plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java
index 8feb3e204a3c..b07836b5df8a 100644
--- a/plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java
+++ b/plugins/ant/tests/src/com/intellij/lang/ant/AntHighlightingTest.java
@@ -80,6 +80,10 @@ public class AntHighlightingTest extends DaemonAnalyzerTestCase {
public void testRefid() throws Exception {
doTest();
}
+
+ public void testRefidInCustomDomElement() throws Exception {
+ doTest();
+ }
public void testExternalValidator() throws Exception {
doTest();
diff --git a/plugins/cucumber-jvm-formatter/cucumber-jvm-formatter.iml b/plugins/cucumber-jvm-formatter/cucumber-jvm-formatter.iml
new file mode 100644
index 000000000000..acf56ba72944
--- /dev/null
+++ b/plugins/cucumber-jvm-formatter/cucumber-jvm-formatter.iml
@@ -0,0 +1,13 @@
+<?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="library" name="cucumber-jvm" level="project" />
+ </component>
+</module>
+
diff --git a/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatter.java b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatter.java
new file mode 100644
index 000000000000..6fc3befcb1b2
--- /dev/null
+++ b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatter.java
@@ -0,0 +1,349 @@
+package org.jetbrains.plugins.cucumber.java.run;
+
+import gherkin.formatter.Formatter;
+import gherkin.formatter.Reporter;
+import gherkin.formatter.model.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayDeque;
+import java.util.Date;
+import java.util.List;
+import java.util.Queue;
+
+/**
+ * User: Andrey.Vokin
+ * Date: 8/10/12
+ */
+public class CucumberJvmSMFormatter implements Formatter, Reporter {
+ private int scenarioCount;
+ private int passedScenarioCount;
+ private boolean scenarioPassed = true;
+
+ private int stepCount;
+ private int passedStepCount;
+ private int skippedStepCount;
+ private int pendingStepCount;
+ private int failedStepCount;
+ private int undefinedStepCount;
+
+ private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ");
+
+ private static final String TEMPLATE_TEST_STARTED =
+ "##teamcity[testStarted timestamp = '%s' locationHint = 'file:///%s' captureStandardOutput = 'true' name = '%s']";
+ private static final String TEMPLATE_TEST_FAILED =
+ "##teamcity[testFailed timestamp = '%s' details = '%s' message = '%s' name = '%s' %s]";
+ private static final String TEMPLATE_SCENARIO_FAILED = "##teamcity[customProgressStatus timestamp='%s' type='testFailed']";
+ private static final String TEMPLATE_TEST_PENDING =
+ "##teamcity[testIgnored name = '%s' message = 'Skipped step' timestamp = '%s']";
+
+ private static final String TEMPLATE_TEST_FINISHED =
+ "##teamcity[testFinished timestamp = '%s' diagnosticInfo = 'cucumber f/s=(1344855950447, 1344855950447), duration=0, time.now=%s' duration = '0' name = '%s']";
+
+ private static final String TEMPLATE_ENTER_THE_MATRIX = "##teamcity[enteredTheMatrix timestamp = '%s']";
+
+ private static final String TEMPLATE_TEST_SUITE_STARTED =
+ "##teamcity[testSuiteStarted timestamp = '%s' locationHint = 'file://%s' name = '%s']";
+ private static final String TEMPLATE_TEST_SUITE_FINISHED = "##teamcity[testSuiteFinished timestamp = '%s' name = '%s']";
+
+ private static final String TEMPLATE_SCENARIO_COUNTING_STARTED =
+ "##teamcity[customProgressStatus testsCategory = 'Scenarios' count = '0' timestamp = '%s']";
+ private static final String TEMPLATE_SCENARIO_COUNTING_FINISHED =
+ "##teamcity[customProgressStatus testsCategory = '' count = '0' timestamp = '%s']";
+ private static final String TEMPLATE_SCENARIO_STARTED = "##teamcity[customProgressStatus type = 'testStarted' timestamp = '%s']";
+
+ public static final String RESULT_STATUS_PENDING = "pending";
+
+ private Appendable appendable;
+
+ private Queue<String> queue;
+
+ private String uri;
+ private String currentFeatureName;
+
+ private boolean beforeExampleSection;
+
+ private ScenarioOutline currentScenarioOutline;
+
+ private Scenario currentScenario;
+
+ private Queue<Step> currentSteps;
+
+ @SuppressWarnings("UnusedDeclaration")
+ public CucumberJvmSMFormatter(Appendable appendable) {
+ this.appendable = System.err;
+ queue = new ArrayDeque<String>();
+ currentSteps = new ArrayDeque<Step>();
+ outCommand(String.format(TEMPLATE_ENTER_THE_MATRIX, getCurrentTime()));
+ outCommand(String.format(TEMPLATE_SCENARIO_COUNTING_STARTED, getCurrentTime()));
+ }
+
+ @Override
+ public void feature(Feature feature) {
+ if (currentFeatureName != null) {
+ done();
+ }
+ currentFeatureName = "Feature: " + getName(feature);
+ outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), uri + ":" + feature.getLine(), currentFeatureName));
+ }
+
+ private boolean isRealScenario(final Scenario scenario) {
+ return scenario.getKeyword().equals("Scenario");
+ }
+
+ @Override
+ public void scenario(Scenario scenario) {
+ closeScenario();
+ if (isRealScenario(scenario)) {
+ scenarioCount++;
+ outCommand(String.format(TEMPLATE_SCENARIO_STARTED, getCurrentTime()));
+ closeScenarioOutline();
+ currentSteps.clear();
+ }
+ currentScenario = scenario;
+ beforeExampleSection = false;
+ outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), uri + ":" + scenario.getLine(), getName(currentScenario)));
+
+ while (queue.size() > 0) {
+ String smMessage = queue.poll();
+ outCommand(smMessage);
+ }
+ }
+
+ @Override
+ public void scenarioOutline(ScenarioOutline outline) {
+ scenarioCount++;
+ outCommand(String.format(TEMPLATE_SCENARIO_STARTED, getCurrentTime()));
+ queue.clear();
+ currentSteps.clear();
+
+ closePreviousScenarios();
+ currentScenarioOutline = outline;
+ currentScenario = null;
+ beforeExampleSection = true;
+ outCommand(
+ String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), uri + ":" + outline.getLine(), getName(currentScenarioOutline)));
+ }
+
+ @Override
+ public void examples(Examples examples) {
+ beforeExampleSection = false;
+ outCommand(String.format(TEMPLATE_TEST_SUITE_STARTED, getCurrentTime(), uri + ":" + examples.getLine(), "Examples:"));
+ }
+
+ @Override
+ public void step(Step step) {
+ if (beforeExampleSection) {
+ return;
+ }
+ currentSteps.add(step);
+ }
+
+ @Override
+ public void result(Result result) {
+ stepCount++;
+ Step currentStep = currentSteps.poll();
+ outCommand(String.format(TEMPLATE_TEST_STARTED, getCurrentTime(), uri + ":" + currentStep.getLine(), getName(currentStep)), true);
+ String stepFullName = getName(currentStep);
+ if (result.getStatus().equals(Result.FAILED)) {
+ failedStepCount++;
+ scenarioPassed = false;
+ String fullMessage = result.getErrorMessage().replace("\r", "").replace("\t", " ");
+ String[] messageInfo = fullMessage.split("\n", 2);
+ final String message;
+ final String details;
+ if (messageInfo.length == 2) {
+ message = messageInfo[0].trim();
+ details = messageInfo[1].trim();
+ }
+ else {
+ message = fullMessage;
+ details = "";
+ }
+
+ outCommand(String.format(TEMPLATE_TEST_FAILED, getCurrentTime(), escape(details), escape(message), stepFullName, ""), true);
+ outCommand(String.format(TEMPLATE_SCENARIO_FAILED, getCurrentTime()), true);
+ }
+ else if (result.getStatus().equals(RESULT_STATUS_PENDING)) {
+ pendingStepCount++;
+ scenarioPassed = false;
+ outCommand(String.format(TEMPLATE_TEST_PENDING, stepFullName, getCurrentTime()), true);
+ }
+ else if (result.equals(Result.UNDEFINED)) {
+ undefinedStepCount++;
+ scenarioPassed = false;
+ String message = "Undefined step: " + getName(currentStep);
+ String details = "";
+ outCommand(String.format(TEMPLATE_TEST_FAILED, getCurrentTime(), escape(details), escape(message), stepFullName, "error = 'true'"), true);
+ outCommand(String.format(TEMPLATE_SCENARIO_FAILED, getCurrentTime()), true);
+ }
+ else if (result.equals(Result.SKIPPED)) {
+ skippedStepCount++;
+ scenarioPassed = false;
+ outCommand(String.format(TEMPLATE_TEST_PENDING, stepFullName, getCurrentTime()), true);
+ }
+ else {
+ passedStepCount++;
+ }
+
+ String currentTime = getCurrentTime();
+ outCommand(String.format(TEMPLATE_TEST_FINISHED, currentTime, currentTime, stepFullName), true);
+ }
+
+ private void closeScenario() {
+ if (currentScenario != null) {
+ if (isRealScenario(currentScenario)) {
+ if (scenarioPassed) {
+ passedScenarioCount++;
+ }
+ }
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), getName(currentScenario)));
+ }
+ currentScenario = null;
+ }
+
+ private void closeScenarioOutline() {
+ if (currentScenarioOutline != null) {
+ if (scenarioPassed) {
+ passedScenarioCount++;
+ }
+ if (!beforeExampleSection) {
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), "Examples:"));
+ }
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), getName(currentScenarioOutline)));
+ }
+ currentScenarioOutline = null;
+ }
+
+ private void closePreviousScenarios() {
+ closeScenario();
+ closeScenarioOutline();
+ }
+
+ @Override
+ public void background(Background background) {
+ closeScenario();
+ currentScenario = null;
+ }
+
+ @Override
+ public void done() {
+ closePreviousScenarios();
+ outCommand(String.format(TEMPLATE_TEST_SUITE_FINISHED, getCurrentTime(), currentFeatureName));
+ }
+
+ @Override
+ public void uri(String s) {
+ String currentDir = System.getenv().get("current_dir");
+ if (currentDir != null) {
+ uri = currentDir + File.separator + s;
+ }
+ else {
+ uri = s;
+ }
+ }
+
+ @Override
+ public void eof() {
+ }
+
+ @Override
+ public void syntaxError(String s, String s1, List<String> strings, String s2, Integer integer) {
+ outCommand("Syntax error\n");
+ }
+
+ @Override
+ public void after(Match match, Result result) {
+ outCommand("after\n");
+ }
+
+ @Override
+ public void match(Match match) {
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public void embedding(String mimeType, byte[] data) {
+ outCommand("embedding\n");
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public void embedding(String s, InputStream inputStream) {
+ outCommand("embedding\n");
+ }
+
+ @Override
+ public void write(String s) {
+ out(s);
+ }
+
+ @Override
+ public void close() {
+ outCommand(String.format(TEMPLATE_SCENARIO_COUNTING_FINISHED, getCurrentTime()));
+
+ outCommand(scenarioCount + " scenario (" + passedScenarioCount + " passed)\n");
+ outCommand(stepCount + " steps (" + passedStepCount + " passed)\n");
+ }
+
+ @Override
+ public void before(Match match, Result result) {
+ outCommand("before\n");
+ }
+
+ private String getCurrentTime() {
+ return DATE_FORMAT.format(new Date());
+ }
+
+ private String escape(String source) {
+ return source.replace("|", "||").replace("\n", "|n").replace("\r", "|r").replace("'", "|'").replace("[", "|[").replace("]", "|]");
+ }
+
+ private void outCommand(String s) {
+ outCommand(s, false);
+ }
+
+ private void outCommand(String s, boolean waitForScenario) {
+ if (currentScenario == null && waitForScenario) {
+ queue.add(s);
+ }
+ else {
+ try {
+ appendable.append("\n");
+ appendable.append(s);
+ appendable.append("\n");
+ }
+ catch (IOException ignored) {
+ }
+ }
+ }
+
+ private void out(String s) {
+ try {
+ appendable.append(s);
+ }
+ catch (IOException ignored) {
+ }
+ }
+
+ private String getName(Scenario scenario) {
+ if (scenario.getKeyword().equals("Scenario Outline")) {
+ return escape("Scenario: Line: " + scenario.getLine());
+ }
+ else {
+ return escape("Scenario: " + scenario.getName());
+ }
+ }
+
+ private String getName(ScenarioOutline outline) {
+ return escape("Scenario Outline: " + outline.getName());
+ }
+
+ private String getName(Step step) {
+ return escape(step.getKeyword() + " " + step.getName());
+ }
+
+ private String getName(Feature feature) {
+ return escape(feature.getName());
+ }
+}
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java
index 3f6c6f976b81..cf8dccc44d3a 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsUtil.java
@@ -181,12 +181,12 @@ public class CvsUtil {
public static boolean fileIsLocallyAdded(File file) {
Entry entry = getEntryFor(file);
- return entry == null ? false : entry.isAddedFile();
+ return entry != null && entry.isAddedFile();
}
public static boolean fileIsLocallyDeleted(File file) {
Entry entry = getEntryFor(file);
- return entry == null ? false : entry.isRemoved();
+ return entry != null && entry.isRemoved();
}
public static boolean fileIsLocallyAdded(VirtualFile file) {
@@ -209,9 +209,9 @@ public class CvsUtil {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
final String entriesFileRelativePath = CVS + File.separatorChar + ENTRIES;
- Messages
- .showErrorDialog(CvsBundle.message("message.error.invalid.entries", entriesFileRelativePath, dir.getAbsolutePath(), entries),
- CvsBundle.message("message.error.invalid.entries.title"));
+ Messages.showErrorDialog(
+ CvsBundle.message("message.error.invalid.entries", entriesFileRelativePath, dir.getAbsolutePath(), entries),
+ CvsBundle.message("message.error.invalid.entries.title"));
}
});
}
@@ -520,7 +520,7 @@ public class CvsUtil {
if (storedRevisionFile.isFile()) return;
try {
FileUtil.writeToFile(storedRevisionFile, bytes);
- storedRevisionFile.setLastModified(file.getModificationStamp());
+ storedRevisionFile.setLastModified(file.getTimeStamp());
}
catch (IOException e) {
LOG.info(e);
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java
index 9c3e60b4b5be..04d7771ed6d4 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/application/CvsEntriesManager.java
@@ -34,6 +34,7 @@ import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.*;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
@@ -41,7 +42,6 @@ import org.jetbrains.annotations.Nullable;
import org.netbeans.lib.cvsclient.admin.Entry;
import java.io.File;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
@@ -57,7 +57,7 @@ public class CvsEntriesManager extends VirtualFileAdapter {
private static final String CVS_ADMIN_DIRECTORY_NAME = CvsUtil.CVS;
- private final Collection<CvsEntriesListener> myEntriesListeners = new ArrayList<CvsEntriesListener>();
+ private final Collection<CvsEntriesListener> myEntriesListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private int myIsActive = 0;
private final Collection<String> myFilesToRefresh = new HashSet<String>();
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsContentRevision.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsContentRevision.java
index 4c0e6472486d..10788cb563e6 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsContentRevision.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsContentRevision.java
@@ -38,6 +38,7 @@ import com.intellij.openapi.vcs.actions.VcsContextFactory;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.encoding.EncodingRegistry;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -72,7 +73,7 @@ public class CvsContentRevision implements ContentRevision {
byte[] content = loadContent();
if (content != null) {
final Charset charset = myLocalFile.getCharset();
- myContent = charset == null ? CharsetToolkit.bytesToString(content) : CharsetToolkit.bytesToString(content, charset);
+ myContent = charset == null ? CharsetToolkit.bytesToString(content, EncodingRegistry.getInstance().getDefaultCharset()) : CharsetToolkit.bytesToString(content, charset);
}
}
return myContent;
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsRootAsStringConfigurationPanel.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsRootAsStringConfigurationPanel.java
index 08aeca23a90a..42c033c0b47e 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsRootAsStringConfigurationPanel.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsRootAsStringConfigurationPanel.java
@@ -22,12 +22,12 @@ import com.intellij.cvsSupport2.ui.CvsRootChangeListener;
import com.intellij.cvsSupport2.ui.FormUtils;
import com.intellij.openapi.util.Ref;
import com.intellij.ui.DocumentAdapter;
+import com.intellij.util.containers.ContainerUtil;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.ArrayList;
import java.util.Collection;
/**
@@ -38,7 +38,7 @@ public class CvsRootAsStringConfigurationPanel {
private JTextField myCvsRoot;
private JButton myEditFieldByFieldButton;
private final Ref<Boolean> myIsUpdating;
- private final Collection<CvsRootChangeListener> myCvsRootListeners = new ArrayList<CvsRootChangeListener>();
+ private final Collection<CvsRootChangeListener> myCvsRootListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private JPanel myPanel;
public CvsRootAsStringConfigurationPanel(boolean readOnly, Ref<Boolean> isUpdating) {
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java
index 07c28e52c050..fec365a48bdf 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CvsTree.java
@@ -28,6 +28,7 @@ import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.TreeUIHelper;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NonNls;
@@ -160,7 +161,7 @@ public class CvsTree extends JPanel implements CvsTabbedWindow.DeactivateListene
}
}
- private final List<CvsTabbedWindow.DeactivateListener> myListeners = new ArrayList<CvsTabbedWindow.DeactivateListener>();
+ private final List<CvsTabbedWindow.DeactivateListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
public void addListener(final CvsTabbedWindow.DeactivateListener listener) {
synchronized (myListeners) {
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsMessages/CvsCompositeListener.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsMessages/CvsCompositeListener.java
index 50cd23b4ec64..25bfa6acc65c 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsMessages/CvsCompositeListener.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsMessages/CvsCompositeListener.java
@@ -15,13 +15,13 @@
*/
package com.intellij.cvsSupport2.cvsoperations.cvsMessages;
+import com.intellij.util.containers.ContainerUtil;
import org.netbeans.lib.cvsclient.file.ICvsFileSystem;
-import java.util.ArrayList;
import java.util.Collection;
public class CvsCompositeListener implements CvsListenersCollection, CvsMessagesListener {
- private final Collection<CvsMessagesListener> myListeners = new ArrayList<CvsMessagesListener>();
+ private final Collection<CvsMessagesListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
public void addCvsListener(CvsMessagesListener listener) {
myListeners.add(listener);
diff --git a/plugins/devkit/devkit.iml b/plugins/devkit/devkit.iml
index a4dfa50b500e..cfc7dad256db 100644
--- a/plugins/devkit/devkit.iml
+++ b/plugins/devkit/devkit.iml
@@ -28,6 +28,16 @@
<orderEntry type="library" scope="TEST" name="Groovy" level="project" />
<orderEntry type="module" module-name="jps-builders" />
<orderEntry type="library" name="Guava" level="project" />
+ <orderEntry type="library" name="Xerces" level="project" />
+ <orderEntry type="module-library">
+ <library name="DTDParser">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/dtdparser113.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
</component>
</module>
diff --git a/plugins/devkit/lib/dtdparser113.jar b/plugins/devkit/lib/dtdparser113.jar
new file mode 100644
index 000000000000..4172640cb9d8
--- /dev/null
+++ b/plugins/devkit/lib/dtdparser113.jar
Binary files differ
diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml
index 099b9b23dfb4..667fcd76911f 100644
--- a/plugins/devkit/resources/META-INF/plugin.xml
+++ b/plugins/devkit/resources/META-INF/plugin.xml
@@ -140,6 +140,10 @@
<action internal="true" class="org.jetbrains.idea.devkit.actions.ShowSerializedXmlAction" text="Show Serialized XML for Class"
id="ShowSerializedXml"/>
+
+ <action internal="true" class="org.jetbrains.idea.devkit.dom.generator.GenerateDomModelAction" text="Generate Dom Model"
+ id="GenerateDomModel"/>
+
<add-to-group group-id="Internal" anchor="last"/>
</group>
diff --git a/plugins/devkit/src/build/PluginModuleBuildScopeProvider.java b/plugins/devkit/src/build/PluginModuleBuildScopeProvider.java
index d4899785a7f7..79bccac2c71e 100644
--- a/plugins/devkit/src/build/PluginModuleBuildScopeProvider.java
+++ b/plugins/devkit/src/build/PluginModuleBuildScopeProvider.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.devkit.module.PluginModuleType;
+import org.jetbrains.jps.api.CmdlineProtoUtil;
import org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTargetType;
@@ -35,7 +36,8 @@ import java.util.List;
public class PluginModuleBuildScopeProvider extends BuildTargetScopeProvider {
@NotNull
@Override
- public List<TargetTypeBuildScope> getBuildTargetScopes(@NotNull CompileScope baseScope, @NotNull CompilerFilter filter, @NotNull Project project) {
+ public List<TargetTypeBuildScope> getBuildTargetScopes(@NotNull CompileScope baseScope, @NotNull CompilerFilter filter,
+ @NotNull Project project, boolean forceBuild) {
List<String> pluginArtifactTargetIds = new ArrayList<String>();
for (Module module : baseScope.getAffectedModules()) {
if (PluginModuleType.isOfType(module)) {
@@ -46,6 +48,6 @@ public class PluginModuleBuildScopeProvider extends BuildTargetScopeProvider {
if (pluginArtifactTargetIds.isEmpty()) {
return Collections.emptyList();
}
- return Collections.singletonList(TargetTypeBuildScope.newBuilder().setTypeId(ArtifactBuildTargetType.INSTANCE.getTypeId()).addAllTargetId(pluginArtifactTargetIds).build());
+ return Collections.singletonList(CmdlineProtoUtil.createTargetsScope(ArtifactBuildTargetType.INSTANCE.getTypeId(), pluginArtifactTargetIds, forceBuild));
}
}
diff --git a/plugins/devkit/src/dom/generator/DTDModelLoader.java b/plugins/devkit/src/dom/generator/DTDModelLoader.java
new file mode 100644
index 000000000000..4a49d6eacbcf
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/DTDModelLoader.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import com.wutka.dtd.*;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author Gregory.Shrago
+ * @author Konstantin Bulenkov
+ */
+public class DTDModelLoader implements ModelLoader {
+ private ModelDesc model;
+
+ public void loadModel(ModelDesc model, Collection<File> schemas, XMLEntityResolver resolver) throws Exception {
+ this.model = model;
+ for (File dtdFile : schemas) {
+ String fileName = dtdFile.getPath();
+ if (dtdFile.isDirectory() || !fileName.endsWith(".dtd") || fileName.endsWith("datatypes.dtd")) {
+ Util.log("skipping " + fileName);
+ continue;
+ }
+ Util.log("loading " + fileName+"..");
+ String ns = fileName.substring(fileName.lastIndexOf(File.separatorChar) + 1);
+ //loadDTDByXerces(ns, dtdFile, resolver);
+
+ loadDTDByWutka(ns, dtdFile);
+
+ }
+ }
+
+ private NamespaceDesc ensureNamespaceExists(String ns) {
+ if (!model.nsdMap.containsKey(ns)) {
+ Util.log("Adding default ns desc for: " + ns);
+ NamespaceDesc nsd = new NamespaceDesc(ns, model.nsdMap.get(""));
+ model.nsdMap.put(ns, nsd);
+ }
+ return model.nsdMap.get(ns);
+ }
+
+
+ private void loadDTDByWutka(String ns, File dtdFile) throws Exception {
+ DTDParser parser = new DTDParser(dtdFile, false);
+ // Parse the DTD and ask the parser to guess the root element
+ DTD dtd = parser.parse(true);
+ checkDTDRootElement(dtd);
+ processDTD(ns, dtd, model.jtMap, model.nsdMap);
+ }
+
+
+ private void processDTD(String namespace, DTD dtd, Map<String, TypeDesc> jtMap, Map<String, NamespaceDesc> nsdMap) {
+ final NamespaceDesc nsd = ensureNamespaceExists(namespace);
+ if (nsd.skip) return;
+ final ArrayList<String> resultQNames = new ArrayList<String>();
+ final DTDElement[] elements = new DTDElement[dtd.elements.size()];
+ int ptr = 1;
+
+ final HashSet<DTDElement> visitedElements = new HashSet<DTDElement>();
+ elements[0] = dtd.rootElement;
+
+ while (--ptr > -1) {
+ final DTDElement el = elements[ptr];
+ visitedElements.add(el);
+ final String typeName = model.toJavaTypeName(el.name, namespace);
+ final String typeQName = model.toJavaQualifiedTypeName(namespace, typeName, false);
+ if (resultQNames.contains(typeQName)) {
+ continue;
+ } else {
+ resultQNames.add(typeQName);
+ }
+ final TypeDesc td = new TypeDesc(el.name, namespace, typeName, TypeDesc.TypeEnum.CLASS);
+ boolean duplicates = false;
+ if ((el.content instanceof DTDAny) || (el.content instanceof DTDMixed)) {
+ FieldDesc fd = new FieldDesc(FieldDesc.SIMPLE, "value", "String", null, "null", false);
+ fd.realIndex = td.fdMap.size();
+ td.fdMap.put(fd.name, fd);
+ }
+ for (Object o : el.attributes.keySet()) {
+ String attrName = (String) o;
+ DTDAttribute attr = (DTDAttribute) el.attributes.get(attrName);
+ if (attr.decl == DTDDecl.FIXED || "ID".equals(attr.type)) {
+ continue;
+ }
+ boolean required = attr.decl == DTDDecl.REQUIRED;
+ FieldDesc fd1 = new FieldDesc(FieldDesc.ATTR, Util.toJavaFieldName(attrName), "String", null, "\"\"", required);
+ fd1.tagName = attrName;
+ fd1.documentation = "Attribute " + attrName + "";
+ fd1.realIndex = td.fdMap.size();
+ duplicates = Util.addToNameMap(td.fdMap, fd1, false) || duplicates;
+ }
+ final ArrayList<List<DTDItem>> choiceList = new ArrayList<List<DTDItem>>();
+ final LinkedList<Entry> plist = new LinkedList<Entry>();
+ if (el.content instanceof DTDContainer) {
+ //if ((el.content instanceof DTDChoice) || (el.content instanceof DTDSequence)) {
+ plist.add(new Entry(el.content, false, true));
+ }
+ while (!plist.isEmpty()) {
+ final Entry pentry = plist.removeFirst();
+
+ final DTDItem p = pentry.p;
+
+ if (p instanceof DTDName) {
+ final DTDName n = (DTDName) p;
+ final DTDElement nel = (DTDElement) dtd.elements.get(n.value);
+ final String pName = n.value;
+ final FieldDesc fd1 = new FieldDesc(FieldDesc.STR, Util.toJavaFieldName(pName), pName, null, "null", pentry.required && (n.cardinal == DTDCardinal.ONEMANY || n.cardinal == DTDCardinal.NONE));
+ fd1.tagName = pName;
+ if (nel != null) {
+ fd1.documentation = parseDTDItemDocumentation(dtd, nel, "Type " + nel.name + " documentation");
+ }
+ if (nel == null) {
+ fd1.type = model.toJavaTypeName(fd1.tagName, namespace);
+ } else if (nel.content instanceof DTDEmpty || nel.content instanceof DTDAny) {
+ boolean hasAttrFields = false;
+ boolean hasTextContents = nel.content instanceof DTDAny;
+ for (Object o : nel.attributes.values()) {
+ DTDAttribute attr = (DTDAttribute) o;
+ if (attr.decl != DTDDecl.FIXED && !"ID".equals(attr.type)) {
+ hasAttrFields = true;
+ break;
+ }
+ }
+ if (hasAttrFields || hasTextContents) {
+ fd1.clType = FieldDesc.OBJ;
+ fd1.type = model.toJavaTypeName(fd1.tagName, namespace);
+ fd1.contentQualifiedName = model.toJavaQualifiedTypeName(namespace, fd1.name, false);
+ fd1.def = "null";
+ // next type
+ if (!visitedElements.contains(nel)) {
+ elements[ptr++] = nel;
+ }
+ } else if (hasTextContents) {
+ fd1.clType = FieldDesc.STR;
+ fd1.type = "String";
+ fd1.def = "null";
+ } else {
+ fd1.clType = FieldDesc.BOOL;
+ fd1.type = "boolean";
+ fd1.def = "false";
+ }
+ } else if (nel.content instanceof DTDContainer) {
+ boolean hasAttrFields = false;
+ boolean hasTextField = false;
+ if ((nel.content instanceof DTDMixed) && ((DTDMixed) nel.content).getItemsVec().size() == 1) {
+ hasTextField = true;
+ for (Object o : nel.attributes.values()) {
+ final DTDAttribute attr = (DTDAttribute) o;
+ if (attr.decl != DTDDecl.FIXED && !"ID".equals(attr.type)) {
+ hasAttrFields = true;
+ break;
+ }
+ }
+ }
+ if (hasTextField && !hasAttrFields) {
+ fd1.clType = FieldDesc.STR;
+ fd1.type = "String";
+ fd1.def = "null";
+ } else {
+ fd1.clType = FieldDesc.OBJ;
+ fd1.type = model.toJavaTypeName(fd1.tagName, namespace);
+ fd1.contentQualifiedName = model.toJavaQualifiedTypeName(namespace, fd1.tagName, false);
+ // next type
+ if (!visitedElements.contains(nel)) {
+ elements[ptr++] = nel;
+ }
+ }
+ } else {
+ fd1.type = "ERROR:Name";
+ }
+ if ((pentry.many || n.cardinal.type >= 2) && fd1.clType != FieldDesc.BOOL) {
+ fd1.elementType = fd1.type;
+ fd1.elementName = fd1.name;
+ fd1.type = "List<" + fd1.elementType + ">";
+ fd1.name = Util.pluralize(fd1.name);
+ fd1.def = "new ArrayList(0)";
+ fd1.clType = -fd1.clType;
+ fd1.comment = "array of " + fd1.elementType;
+ }
+ fd1.realIndex = td.fdMap.size();
+ duplicates = Util.addToNameMap(td.fdMap, fd1, false) || duplicates;
+ } else if (p instanceof DTDContainer) {
+ final DTDContainer cont = (DTDContainer) p;
+ final boolean isChoice = cont instanceof DTDChoice;
+ // 0 - NONE, 1 - OPT, 2 - ZEROMANY, 3 - ONEMANY
+ final boolean required = !isChoice && pentry.required && p.cardinal != DTDCardinal.ZEROMANY && p.cardinal != DTDCardinal.OPTIONAL;
+ final boolean many = p.cardinal == DTDCardinal.ONEMANY || p.cardinal == DTDCardinal.ZEROMANY;
+ List<DTDItem> l = cont.getItemsVec();
+ if (!many && isChoice) {
+ choiceList.add(l);
+ }
+ for (DTDItem aL : l) {
+ plist.add(new Entry(aL, many, required));
+ }
+ } else {
+ Util.logerr("unknown item " + p);
+ }
+ }
+ td.duplicates = duplicates;
+ td.documentation = parseDTDItemDocumentation(dtd, el, "Type " + el.name + " documentation");
+ jtMap.put(model.toJavaQualifiedTypeName(namespace, td.name, false), td);
+ int i = 0;
+ for (FieldDesc fd : td.fdMap.values()) {
+ fd.idx = i++;
+ }
+ for (List<DTDItem> l : choiceList) {
+ ArrayList<DTDItem> clist = new ArrayList<DTDItem>();
+ LinkedList<DTDItem> elist = new LinkedList<DTDItem>();
+ for (i = 0; i < l.size(); i++) {
+ elist.add(l.get(i));
+ }
+ while (!elist.isEmpty()) {
+ DTDItem p = elist.removeFirst();
+ if (p instanceof DTDContainer) {
+ List<DTDItem> l2 = ((DTDContainer) p).getItemsVec();
+ for (DTDItem aL2 : l2) {
+ elist.addFirst(aL2);
+ }
+ } else if (p instanceof DTDName) {
+ clist.add(p);
+ }
+ }
+ boolean choiceOpt = true;
+ FieldDesc[] choice = new FieldDesc[clist.size()];
+ for (i = 0; i < choice.length; i++) {
+ DTDName p = (DTDName) clist.get(i);
+ String s = Util.toJavaFieldName(p.value);
+ FieldDesc fd = td.fdMap.get(s);
+ if (fd == null) {
+ fd = td.fdMap.get(Util.pluralize(s));
+ if (fd == null) {
+ Util.logerr("uknown choice element: " + s);
+ continue;
+ }
+ }
+ choice[i] = fd;
+ choice[i].choice = choice;
+ if (fd.required) choiceOpt = false;
+ }
+ for (i = 0; i < choice.length; i++) {
+ choice[i].choiceOpt = choiceOpt;
+ }
+ }
+ }
+ List<DTDEntity> entList = dtd.getItemsByType(DTDEntity.class);
+ for (DTDEntity entity : entList) {
+ String value = entity.value;
+ if (!value.startsWith("(") || !value.endsWith(")")) {
+ continue;
+ }
+ String typeName = model.toJavaTypeName(entity.name, namespace);
+ TypeDesc td = new TypeDesc(entity.name, namespace, typeName, TypeDesc.TypeEnum.ENUM);
+ StringTokenizer st = new StringTokenizer(value, "(|)");
+ while (st.hasMoreTokens()) {
+ final String s = st.nextToken();
+ td.fdMap.put(s, new FieldDesc(Util.computeEnumConstantName(s, td.name), s));
+ }
+ td.documentation = parseDTDItemDocumentation(dtd, entity, "Type " + entity.name + " documentation");
+ jtMap.put(model.toJavaQualifiedTypeName(namespace, td.name, true), td);
+ }
+ }
+
+ private static String parseDTDItemDocumentation(DTD dtd, DTDOutput obj, String title) {
+ int elementIndex = dtd.items.indexOf(obj);
+ if (elementIndex < 1) return null;
+ Object prev = dtd.items.get(elementIndex - 1);
+ if (!(prev instanceof DTDComment)) return null;
+ DTDComment comment = (DTDComment) prev;
+ return title + "\n" + "<pre>\n" + comment.getText() + "\n</pre>";
+ }
+
+ static class Entry {
+ boolean required;
+ boolean many;
+ DTDItem p;
+
+ Entry(DTDItem p, boolean many, boolean required) {
+ this.required = required;
+ this.many = many;
+ this.p = p;
+ }
+
+ Entry parent;
+ DTDItem it;
+ Vector choice;
+ int num;
+
+ Entry(Entry parent, DTDItem it, Vector choice, int num) {
+ this.parent = parent;
+ this.it = it;
+ this.choice = choice;
+ this.num = num;
+ }
+ }
+
+
+ private static void checkDTDRootElement(DTD dtd) throws Exception {
+ if (dtd.rootElement == null) {
+ StringBuffer sb = new StringBuffer("Empty root: possible elements: ");
+ HashMap map = new HashMap(dtd.elements);
+ for (Object o : dtd.elements.values()) {
+ DTDElement el = (DTDElement) o;
+ if (el.content instanceof DTDContainer) {
+ for (Object obj : ((DTDContainer) el.content).getItemsVec()) {
+ if (obj instanceof DTDName) {
+ map.remove(((DTDName) obj).value);
+ }
+ }
+ }
+ }
+ if (dtd.rootElement != null) return;
+ sb.append(map.size()).append(map.keySet());
+ throw new Exception(sb.toString());
+ }
+ }
+
+}
diff --git a/plugins/devkit/src/dom/generator/DomGenDialog.java b/plugins/devkit/src/dom/generator/DomGenDialog.java
new file mode 100644
index 000000000000..52d2675e0ea3
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/DomGenDialog.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+
+import javax.swing.*;
+import java.io.File;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DomGenDialog extends DialogWrapper{
+ final DomGenPanel panel;
+ final JComponent comp;
+
+ protected DomGenDialog(Project project) {
+ super(project);
+ panel = new DomGenPanel(project);
+ comp = panel.getComponent();
+ panel.restore();
+ setTitle("Generate Dom Model from XSD or DTD");
+ init();
+ getOKAction().putValue(Action.NAME, "Generate");
+ }
+
+ @Override
+ protected JComponent createCenterPanel() {
+ return comp;
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (!panel.validate()) return;
+ final String location = panel.getLocation();
+ ModelLoader loader = location.toLowerCase().endsWith(".xsd") ? new XSDModelLoader() : new DTDModelLoader();
+ final JetBrainsEmitter emitter = new JetBrainsEmitter();
+ final MergingFileManager fileManager = new MergingFileManager();
+ if (panel.getAuthor().trim().length() > 0) {
+ emitter.setAuthor(panel.getAuthor());
+ }
+ final ModelGen modelGen = new ModelGen(loader, emitter, fileManager);
+ final NamespaceDesc desc = panel.getNamespaceDescriptor();
+ modelGen.setConfig(desc.name, location, desc, panel.getSkippedSchemas());
+ try {
+ final File output = new File(panel.getOutputDir());
+ modelGen.perform(output, new File(location).getParentFile());
+ } catch (Exception e) {
+ e.printStackTrace(System.err);
+ }
+ panel.saveAll();
+ super.doOKAction();
+ }
+
+ @Override
+ public void doCancelAction() {
+ panel.saveAll();
+ super.doCancelAction();
+ }
+
+ @Override
+ protected String getDimensionServiceKey() {
+ return getClass().getName();
+ }
+}
diff --git a/plugins/devkit/src/dom/generator/DomGenPanel.form b/plugins/devkit/src/dom/generator/DomGenPanel.form
new file mode 100644
index 000000000000..1cc5978d395b
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/DomGenPanel.form
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.devkit.dom.generator.DomGenPanel">
+ <grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="8" 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="424" height="262"/>
+ </constraints>
+ <properties/>
+ <clientProperties>
+ <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
+ </clientProperties>
+ <border type="none" title="Dom Generator Config"/>
+ <children>
+ <component id="29b47" class="javax.swing.JLabel">
+ <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="Namespace:"/>
+ </properties>
+ </component>
+ <vspacer id="e8ccd">
+ <constraints>
+ <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="f5680" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="3" 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="Super Class:"/>
+ </properties>
+ </component>
+ <component id="20f66" class="javax.swing.JTextField" binding="mySuperClass">
+ <constraints>
+ <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="327" height="22"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="com.intellij.util.xml.DomElement"/>
+ </properties>
+ </component>
+ <component id="4a359" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="2" 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="Package:"/>
+ </properties>
+ </component>
+ <component id="afd05" class="javax.swing.JTextField" binding="myPackage">
+ <constraints>
+ <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="327" height="22"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="com.intellij.myFramework.model"/>
+ </properties>
+ </component>
+ <component id="d62dc" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="4" 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="Output Dir:"/>
+ </properties>
+ </component>
+ <component id="6a48b" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myOutputDir" custom-create="true">
+ <constraints>
+ <grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="327" height="22"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="7fb9d" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="mySchemaLocation" custom-create="true">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="327" height="22"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="7940e" 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 value="Scheme File:"/>
+ </properties>
+ </component>
+ <component id="833b2" class="javax.swing.JTextField" binding="myNamespace">
+ <constraints>
+ <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="327" height="22"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="bdaaf" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="6" 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>
+ <text value="Skip schemes:"/>
+ </properties>
+ </component>
+ <component id="f4732" class="javax.swing.JTextArea" binding="mySkipSchemas">
+ <constraints>
+ <grid row="6" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="50"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="54b59" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="5" 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="@author:"/>
+ </properties>
+ </component>
+ <component id="b033e" class="javax.swing.JTextField" binding="myAuthor">
+ <constraints>
+ <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/plugins/devkit/src/dom/generator/DomGenPanel.java b/plugins/devkit/src/dom/generator/DomGenPanel.java
new file mode 100644
index 000000000000..df2a6d8e8701
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/DomGenPanel.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.fileChooser.FileTypeDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.IdeFocusManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.ArrayList;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DomGenPanel {
+ private JPanel mainPanel;
+ private JTextField myNamespace;
+ private JTextField mySuperClass;
+ private TextFieldWithBrowseButton mySchemaLocation;
+ private JTextField myPackage;
+ private TextFieldWithBrowseButton myOutputDir;
+ private JTextArea mySkipSchemas;
+ private JTextField myAuthor;
+ private final Project myProject;
+
+ public DomGenPanel(Project project) {
+ myProject = project;
+ }
+
+ private void createUIComponents() {
+ mySchemaLocation = new TextFieldWithBrowseButton();
+ final String title = "Choose XSD or DTD schema";
+ mySchemaLocation.addBrowseFolderListener(title, "Make sure there are only necessary schemes in directory where your XSD or DTD schema is located", myProject, new FileTypeDescriptor(title, "xsd", "dtd"));
+ mySchemaLocation.getTextField().setEditable(false);
+ mySchemaLocation.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ final File file = new File(mySchemaLocation.getText());
+ if (file.exists() && file.getName().toLowerCase().endsWith(".xsd")) {
+ final VirtualFile vf = LocalFileSystem.getInstance().findFileByIoFile(file);
+ if (vf != null) {
+ final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(vf);
+ if (psiFile instanceof XmlFile) {
+ final XmlDocument xml = ((XmlFile)psiFile).getDocument();
+ if (xml != null) {
+ final XmlTag rootTag = xml.getRootTag();
+ if (rootTag != null) {
+ String target = null;
+ ArrayList<String> ns = new ArrayList<String>();
+ for (XmlAttribute attr : rootTag.getAttributes()) {
+ if ("targetNamespace".equals(attr.getName())) {
+ target = attr.getValue();
+ }
+ else if (attr.getName().startsWith("xmlns")) {
+ ns.add(attr.getValue());
+ }
+ }
+
+ ns.remove(target);
+ if (target != null) {
+ myNamespace.setText(target);
+ }
+ mySkipSchemas.setText(StringUtil.join(ArrayUtil.toStringArray(ns), "\n"));
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+ myOutputDir = new TextFieldWithBrowseButton();
+ myOutputDir.addBrowseFolderListener("Select Output For Generated Files", "", myProject, FileChooserDescriptorFactory.getDirectoryChooserDescriptor("Output For Generated Files"));
+ }
+
+ public JComponent getComponent() {
+ return mainPanel;
+ }
+
+ public NamespaceDesc getNamespaceDescriptor() {
+ return new NamespaceDesc(myNamespace.getText().trim(), myPackage.getText().trim(), mySuperClass.getText().trim(), "", null, null, null, null);
+ }
+
+ public String getLocation() {
+ return mySchemaLocation.getText();
+ }
+
+ public String getOutputDir() {
+ return myOutputDir.getText();
+ }
+
+ private static final String PREFIX = "DomGenPanel.";
+ public void restore() {
+ myNamespace.setText(getValue("namespace", ""));
+ myPackage.setText(getValue("package", "com.intellij.myframework.model"));
+ mySchemaLocation.setText(getValue("schemaLocation", ""));
+ mySuperClass.setText(getValue("superClass", "com.intellij.util.xml.DomElement"));
+ myOutputDir.setText(getValue("output", ""));
+ mySkipSchemas.setText(getValue("skipSchemas", "http://www.w3.org/2001/XMLSchema\nhttp://www.w3.org/2001/XMLSchema-instance"));
+ myAuthor.setText(getValue("author", ""));
+ }
+
+ private static String getValue(String name, String defaultValue) {
+ return PropertiesComponent.getInstance().getOrInit(PREFIX + name, defaultValue);
+ }
+
+ private static void setValue(String name, String value) {
+ PropertiesComponent.getInstance().setValue(PREFIX + name, value);
+ }
+
+ public void saveAll() {
+ setValue("namespace", myNamespace.getText());
+ setValue("package", myPackage.getText());
+ setValue("schemaLocation", mySchemaLocation.getText());
+ setValue("superClass", mySuperClass.getText());
+ setValue("output", myOutputDir.getText());
+ setValue("skipSchemas", mySkipSchemas.getText());
+ setValue("author", myAuthor.getText());
+ }
+
+ public boolean validate() {
+ if (!new File(mySchemaLocation.getText()).exists()) {
+ Messages.showErrorDialog(myProject, "Schema location doesn't exist", "Error");
+ IdeFocusManager.getInstance(myProject).requestFocus(mySchemaLocation, true);
+ return false;
+ }
+
+ if (!new File(myOutputDir.getText()).exists()) {
+ Messages.showErrorDialog(myProject, "Output dir doesn't exist", "Error");
+ IdeFocusManager.getInstance(myProject).requestFocus(myOutputDir, true);
+ return false;
+ }
+
+ return true;
+ }
+
+ public String[] getSkippedSchemas() {
+ final String schemes = mySkipSchemas.getText().replaceAll("\r\n", "\n").trim();
+ if (schemes.length() > 0) {
+ return schemes.split("\n");
+ }
+ return new String[0];
+ }
+
+ public String getAuthor() {
+ return myAuthor.getText();
+ }
+}
diff --git a/plugins/devkit/src/dom/generator/Emitter.java b/plugins/devkit/src/dom/generator/Emitter.java
new file mode 100644
index 000000000000..4bc212f8a242
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/Emitter.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public interface Emitter {
+ String JDOC_OPEN = "/**";
+ String JDOC_CONT = " * ";
+ String JDOC_CLOSE = " */";
+
+ void emit(FileManager fileManager, ModelDesc model, File outputRoot);
+}
diff --git a/plugins/devkit/src/dom/generator/FieldDesc.java b/plugins/devkit/src/dom/generator/FieldDesc.java
new file mode 100644
index 000000000000..13f3bf6e065f
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/FieldDesc.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class FieldDesc implements Comparable<FieldDesc> {
+ final static int STR = 1;
+ final static int BOOL = 2;
+ final static int OBJ = 3;
+ final static int ATTR = 4;
+ final static int DOUBLE = 5;
+ final static int SIMPLE = 6;
+
+ public FieldDesc(String name, String def) {
+ this.name = name;
+ this.def = def;
+ }
+
+ public FieldDesc(int clType, String name, String type, String elementType, String def, boolean required) {
+ this.clType = clType;
+ this.name = name;
+ this.type = type;
+ this.elementType = elementType;
+ this.def = def;
+ this.required = required;
+ }
+
+ int clType = STR;
+ String name;
+ String type;
+ String elementType;
+ String def;
+ boolean required;
+
+ int idx;
+ String tagName;
+ String elementName;
+ String comment;
+ FieldDesc[] choice;
+ boolean choiceOpt;
+
+ String documentation;
+ String simpleTypesString;
+ int duplicateIndex = -1;
+ int realIndex;
+ String contentQualifiedName;
+
+ public int compareTo(FieldDesc o) {
+ return name.compareTo(o.name);
+ }
+
+ public String toString() {
+ return "Field: " + name + ";" + type + ";" + elementName + ";" + elementType;
+ }
+
+}
diff --git a/plugins/devkit/src/dom/generator/FileManager.java b/plugins/devkit/src/dom/generator/FileManager.java
new file mode 100644
index 000000000000..8ad5c711a6c4
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/FileManager.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public interface FileManager {
+ public File releaseOutputFile(File outFile);
+ public File getOutputFile(File target);
+}
diff --git a/plugins/devkit/src/dom/generator/GenerateDomModelAction.java b/plugins/devkit/src/dom/generator/GenerateDomModelAction.java
new file mode 100644
index 000000000000..fb8efd87244c
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/GenerateDomModelAction.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.project.Project;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class GenerateDomModelAction extends AnAction {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
+ if (project != null) {
+ new DomGenDialog(project).show();
+ }
+ }
+}
diff --git a/plugins/devkit/src/dom/generator/JetBrainsEmitter.java b/plugins/devkit/src/dom/generator/JetBrainsEmitter.java
new file mode 100644
index 000000000000..bf3c3bc35565
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/JetBrainsEmitter.java
@@ -0,0 +1,679 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.*;
+
+/**
+ * @author Gregory.Shrago
+ * @author Konstantin Bulenkov
+ */
+public class JetBrainsEmitter implements Emitter {
+ static final boolean NOT_COMPARE_MODE = true; // compare mode: skip package decl & all comments/javadoc
+ static final boolean JB_OFF = false;
+ static final boolean REPLACE_TYPES_WITH_INTERFACES = true;
+ private String AUTHOR = null;
+
+
+ public void emit(FileManager fileManager, ModelDesc model, File outputRoot) {
+ final NamespaceDesc nsdDef = model.nsdMap.get("");
+ final Set<String> simpleTypes = new TreeSet<String>();
+ for (TypeDesc td : model.jtMap.values()) {
+ generateClass(fileManager, td, model, outputRoot, simpleTypes);
+ }
+// for (Iterator it = nsdMap.values().iterator(); it.hasNext(); ) {
+// NamespaceDesc nsd = (NamespaceDesc) it.next();
+// generateSuper(nsd, outputRoot);
+// generateHelper(nsd, jtMap, outputRoot);
+// }
+ generateSuper(fileManager, nsdDef, model, outputRoot);
+ generateHelper(fileManager, nsdDef, model, outputRoot);
+
+ Util.log("SimpleTypes log:");
+ for (String s : simpleTypes) {
+ Util.log(" " + s);
+ }
+ }
+
+ public void generateClass(FileManager fileManager, TypeDesc td, ModelDesc model, File outDir, Set<String> simpleTypes) {
+ final Map<String, TypeDesc> jtMap = model.jtMap;
+ final Map<String, NamespaceDesc> nsdMap = model.nsdMap;
+ final NamespaceDesc nsd = nsdMap.get(nsdMap.containsKey(td.xsNamespace) ? td.xsNamespace : "");
+ final String typeName = td.name;
+ final String typeQName = model.getNSDPrefix(td) + typeName;
+ final String pkgName = typeQName.lastIndexOf('.') > -1 ? typeQName.substring(0, typeQName.lastIndexOf('.')) : "";
+
+ final File outFile = fileManager.getOutputFile(new File(outDir, toJavaFileName(typeQName)));
+ PrintWriter out = null;
+ try {
+ TreeSet<String> externalClasses = new TreeSet<String>();
+ if (td.type != TypeDesc.TypeEnum.ENUM) {
+ if (nsd.imports != null) {
+ StringTokenizer st = new StringTokenizer(nsd.imports, ";");
+ while (st.hasMoreTokens()) {
+ externalClasses.add(st.nextToken());
+ }
+ }
+ if (!model.getNSDPrefix("", nsd.superClass, false).equals(model.getNSDPrefix(td))) {
+ externalClasses
+ .add(model.getNSDPrefix("", nsd.superClass, false) + nsd.superClass.substring(nsd.superClass.lastIndexOf(".") + 1));
+ }
+ if (td.supers != null) {
+ for (TypeDesc tds : td.supers) {
+ String pkg1 = model.getNSDPrefix(tds);
+ String pkg2 = model.getNSDPrefix(td);
+ if (!pkg1.equals(pkg2)) {
+ externalClasses.add(model.getNSDPrefix(tds) + tds.name);
+ }
+ }
+ }
+ for (FieldDesc fd : td.fdMap.values()) {
+ if (fd.simpleTypesString != null && fd.simpleTypesString.indexOf(":fully-qualified-classType;") != -1) {
+ externalClasses.add("com.intellij.psi.PsiClass");
+ }
+ if (fd.contentQualifiedName != null && fd.contentQualifiedName.indexOf('.') > 0) {
+ String pkgNameFD = fd.contentQualifiedName.substring(0, fd.contentQualifiedName.lastIndexOf('.'));
+ if (!pkgNameFD.equals(pkgName)) {
+ externalClasses.add(fd.contentQualifiedName);
+ }
+ }
+ if (fd.clType < 0) {
+ externalClasses.add("java.util.List");
+ }
+ externalClasses.add("org.jetbrains.annotations.NotNull");
+ externalClasses.add("com.intellij.util.xml.*");
+ }
+ }
+
+ Util.log("Generating type: " + typeName + "..");
+ out = new PrintWriter(new FileWriter(outFile));
+ if (NOT_COMPARE_MODE) {
+ out.println("// Generated on " + new Date());
+ out.println("// DTD/Schema : " + nsd.name);
+ }
+ out.println("");
+ if (NOT_COMPARE_MODE && pkgName != null && pkgName.length() > 0) {
+ out.println("package " + pkgName + ";");
+ }
+ out.println();
+ if (td.type != TypeDesc.TypeEnum.ENUM) {
+ boolean javaLang = false;
+ boolean external = false;
+ for (String s : externalClasses) {
+ if (s.startsWith("java.")) {
+ javaLang = true;
+ continue;
+ }
+ external = true;
+ out.println("import " + s + ";");
+ }
+ if (javaLang) {
+ if (external) out.println();
+ for (String s : externalClasses) {
+ if (!s.startsWith("java.")) continue;
+ out.println("import " + s + ";");
+ }
+ }
+ out.println();
+ }
+ if (td.type == TypeDesc.TypeEnum.ENUM) {
+ boolean text = false;
+ for (Map.Entry<String, FieldDesc> e : td.fdMap.entrySet()) {
+ if (!e.getKey().equals(e.getValue().name)) {
+ text = true;
+ break;
+ }
+ }
+ if (NOT_COMPARE_MODE) {
+ out.println(JDOC_OPEN);
+ out.println(JDOC_CONT + td.xsNamespace + ":" + td.xsName + " enumeration.");
+ if (AUTHOR != null) out.println(JDOC_CONT + AUTHOR);
+ printDocumentation(out, td.documentation, JDOC_CONT);
+
+ out.println(JDOC_CLOSE);
+ }
+ out.print("public enum " + typeName + (text ? (JB_OFF ? "" : " implements com.intellij.util.xml.NamedEnum") : ""));
+ out.print(" {");
+ boolean first = true;
+ for (Map.Entry<String, FieldDesc> e : td.fdMap.entrySet()) {
+ String val = e.getKey();
+ FieldDesc id = e.getValue();
+ if (first) {
+ first = false;
+ out.println("");
+ }
+ else {
+ out.println(",");
+ }
+ if (text) {
+ out.print("\t" + id.name + " (\"" + val + "\")");
+ }
+ else {
+ out.print("\t" + id.name);
+ }
+ }
+ if (text) {
+ out.println(";");
+ out.println();
+ out.println("\tprivate final String value;");
+ out.println("\tprivate " + typeName + "(String value) { this.value = value; }");
+ out.println("\tpublic String getValue() { return value; }");
+ }
+ out.println();
+ out.println("}");
+ return;
+ }
+ if (NOT_COMPARE_MODE) {
+ out.println(JDOC_OPEN);
+ if (td.type == TypeDesc.TypeEnum.GROUP_INTERFACE) {
+ out.println(JDOC_CONT + td.xsNamespace + ":" + td.xsName + " model group interface.");
+ }
+ else {
+ out.println(JDOC_CONT + td.xsNamespace + ":" + td.xsName + " interface.");
+ }
+ printDocumentation(out, td.documentation, JDOC_CONT);
+ if (AUTHOR != null) out.println(JDOC_CONT + AUTHOR);
+ out.println(JDOC_CLOSE);
+ }
+ out.print("public interface " + typeName);
+ if (nsd.superClass != null || (td.supers != null && td.supers.length > 1)) {
+ boolean comma = false;
+ if (td.type != TypeDesc.TypeEnum.GROUP_INTERFACE) {
+ if (nsd.superClass != null) {
+ out.print(" extends " + nsd.superClass.substring(nsd.superClass.lastIndexOf(".") + 1));
+ comma = true;
+ }
+ }
+ if (td.supers != null && td.supers.length > 0) {
+ if (!comma) out.print(" extends ");
+ for (TypeDesc aSuper : td.supers) {
+ if (comma) {
+ out.print(", ");
+ }
+ else {
+ comma = true;
+ }
+ out.print(aSuper.name);
+ }
+ }
+ }
+ out.println(" {");
+
+ FieldDesc[] fields = td.fdMap.values().toArray(new FieldDesc[td.fdMap.size()]);
+ if (fields.length == 0) {
+ Util.logwarn("no fields in: " + td.xsName);
+ }
+ Arrays.sort(fields, new Comparator<FieldDesc>() {
+ public int compare(FieldDesc o1, FieldDesc o2) {
+ return o1.realIndex - o2.realIndex;
+ }
+ });
+ out.println("");
+ for (FieldDesc field : fields) {
+ String tagName = field.tagName;
+ String type = field.type;
+ String elementType = field.elementType;
+ String name = field.name;
+ String paramName = toJavaIdName(field.clType > 0 ? name : field.elementName);
+ String javaDocTagName = field.clType < 0 ? tagName + " children" : tagName != null ? tagName + " child" : "simple content";
+ boolean isAttr = field.clType == FieldDesc.ATTR;
+ boolean isList = field.clType < 0;
+
+ if (name.equals("class")) { // getClass method prohibited
+ name = "clazz";
+ }
+ boolean nameChanged = field.tagName != null &&
+ !name
+ .equals(isList ? Util.pluralize(Util.toJavaFieldName(field.tagName)) : Util.toJavaFieldName(field.tagName));
+
+ // annotations
+ // types replacement
+ String newType = field.clType < 0 ? elementType : type;
+ String converterString = null;
+ if (field.simpleTypesString != null) {
+ if (field.simpleTypesString.indexOf(":fully-qualified-classType;") != -1) { // localType, remoteType, etc.
+ newType = "PsiClass";
+ //converterString = (JB_OFF ? "//" : "")+"\t@Convert (PsiClassReferenceConverter.class)";
+ }
+ else if (field.simpleTypesString.indexOf(":ejb-linkType;") != -1) {
+ }
+ else if (field.simpleTypesString.indexOf(":ejb-ref-nameType;") != -1) { // jndi-nameType
+ }
+ else if (field.simpleTypesString.indexOf(":pathType;") != -1) {
+ }
+ else if (field.simpleTypesString.indexOf(":java-identifierType;") != -1) {
+ //out.println((JB_OFF ? "//" : "") +"\t@Convert (JavaIdentifierConverter.class)");
+ }
+ else if (field.simpleTypesString.indexOf(":QName;") != -1) {
+ // ???
+ }
+ else if (field.simpleTypesString.indexOf(":integer;") != -1) { // BigDecimal
+ newType = REPLACE_TYPES_WITH_INTERFACES ? "Integer" : "int";
+ }
+ else if (field.simpleTypesString.indexOf(":int;") != -1) {
+ newType = REPLACE_TYPES_WITH_INTERFACES ? "Integer" : "int";
+ }
+ else if (field.simpleTypesString.indexOf(":byte;") != -1) {
+ newType = REPLACE_TYPES_WITH_INTERFACES ? "Byte" : "byte";
+ }
+ else if (field.simpleTypesString.indexOf(":short;") != -1) {
+ newType = REPLACE_TYPES_WITH_INTERFACES ? "Short" : "short";
+ }
+ else if (field.simpleTypesString.indexOf(":long;") != -1) {
+ newType = REPLACE_TYPES_WITH_INTERFACES ? "Long" : "long";
+ }
+ else if (field.simpleTypesString.indexOf(":float;") != -1) {
+ newType = REPLACE_TYPES_WITH_INTERFACES ? "Float" : "float";
+ }
+ else if (field.simpleTypesString.indexOf(":double;") != -1) {
+ newType = REPLACE_TYPES_WITH_INTERFACES ? "Double" : "double";
+ }
+ else if (field.simpleTypesString.indexOf(":boolean;") != -1) { // true-falseType
+ newType = REPLACE_TYPES_WITH_INTERFACES ? "Boolean" : "boolean";
+ }
+ for (int idx = 0; idx != -1;) {
+ simpleTypes.add(field.simpleTypesString.substring(idx));
+ idx = field.simpleTypesString.indexOf(';', idx) + 1;
+ if (idx == 0) break;
+ }
+ }
+ if (REPLACE_TYPES_WITH_INTERFACES) {
+ switch (Math.abs(field.clType)) {
+ case FieldDesc.ATTR:
+ newType = "GenericAttributeValue<" + newType + ">";
+ break;
+ case FieldDesc.BOOL:
+ newType = "GenericDomValue<Boolean>";
+ break;
+ case FieldDesc.SIMPLE:
+ break;
+ case FieldDesc.STR:
+ newType = "GenericDomValue<" + newType + ">";
+ break;
+ case FieldDesc.OBJ: {
+ TypeDesc ftd = jtMap.get(field.contentQualifiedName);
+ if (ftd != null && ftd.type == TypeDesc.TypeEnum.ENUM) {
+ newType = "GenericDomValue<" + ftd.name + ">";
+ }
+ break;
+ }
+ }
+ }
+ if (newType != null && isList) {
+ elementType = newType;
+ }
+ else if (newType != null) {
+ type = newType;
+ }
+ if (isList) {
+ type = "List<" + elementType + ">";
+ }
+
+ StringBuffer sbAnnotations = new StringBuffer();
+ if (field.clType == FieldDesc.SIMPLE) {
+ // sbAnnotations.append((JB_OFF ? "//" : "") +"\t@TagValue");
+ }
+ else if (isAttr && nameChanged) {
+ sbAnnotations.append((JB_OFF ? "//" : "") + "\t@Attribute (\"").append(tagName).append("\")");
+ }
+ else if (isList) {
+ // sbAnnotations.append((JB_OFF ? "//" : "") +"\t@SubTagList (\"" + tagName + "\")");
+ if (nameChanged) {
+ sbAnnotations.append((JB_OFF ? "//" : "") + "\t@SubTag (\"").append(tagName).append("\")");
+ }
+ else {
+ if (isBadTagName(tagName)) {
+ sbAnnotations.append((JB_OFF ? "//" : "") + "\t@SubTagList (\"").append(tagName).append("\")");
+ }
+ }
+ }
+ else {
+ if (field.duplicateIndex >= 0) {
+ sbAnnotations.append((JB_OFF ? "//" : "") + "\t@SubTag (value = \"").append(tagName).append("\", index = ")
+ .append(field.duplicateIndex - 1).append(")");
+ }
+ else if (field.clType == FieldDesc.BOOL) {
+ sbAnnotations.append((JB_OFF ? "//" : "") + "\t@SubTag (value = \"").append(tagName).append("\", indicator = true)");
+ }
+ else if (!name.equals(field.name)) {
+ sbAnnotations.append((JB_OFF ? "//" : "") + "\t@SubTag (\"").append(tagName).append("\")");
+ }
+ }
+ if (converterString != null) {
+ sbAnnotations.append("\n").append(converterString);
+ }
+ if (NOT_COMPARE_MODE && td.type != TypeDesc.TypeEnum.GROUP_INTERFACE) {
+ out.println("\t" + JDOC_OPEN);
+ final String text;
+ if (isList) {
+ text = "the list of " + javaDocTagName;
+ }
+ else {
+ text = "the value of the " + javaDocTagName;
+ }
+ out.println("\t" + JDOC_CONT + "Returns " + text + ".");
+ printDocumentation(out, field.documentation, "\t" + JDOC_CONT);
+ out.println("\t" + JDOC_CONT + "@return " + text + ".");
+ out.println("\t" + JDOC_CLOSE);
+ }
+ out.println((JB_OFF ? "//" : "") + "\t@NotNull");
+ if (td.type != TypeDesc.TypeEnum.GROUP_INTERFACE) {
+ if (sbAnnotations.length() > 0) out.println(sbAnnotations);
+ if (field.required) {
+ out.println((JB_OFF ? "//" : "") + "\t@Required");
+ }
+ }
+ out.print("\t");
+ //out.print("public ");
+ out.print(type);
+ out.print(" ");
+ out.print("get");
+ out.print(Util.capitalize(name));
+ out.println("();");
+
+ final boolean genAddRemoveInsteadOfSet = true;
+ if (!genAddRemoveInsteadOfSet || field.clType > 0) {
+ if (field.clType == FieldDesc.SIMPLE) {
+ if (NOT_COMPARE_MODE && td.type != TypeDesc.TypeEnum.GROUP_INTERFACE) {
+ out.println("\t" + JDOC_OPEN);
+ if (field.clType < 0) {
+ out.println("\t" + JDOC_CONT + "Sets the list of " + javaDocTagName + ".");
+ }
+ else {
+ out.println("\t" + JDOC_CONT + "Sets the value of the " + javaDocTagName + ".");
+ }
+ out.println("\t" + JDOC_CONT + "@param " + paramName + " the new value to set");
+ out.println("\t" + JDOC_CLOSE);
+ if (sbAnnotations.length() > 0) out.println(sbAnnotations);
+ }
+ out.print("\t");
+ //out.print("public ");
+ out.print("void set");
+ out.print(Util.capitalize(name));
+ out.print("(");
+ if (field.required) {
+ out.print((JB_OFF ? "" : "@NotNull "));
+ }
+ out.print(type);
+ out.print(" ");
+ out.print(paramName);
+ out.println(");");
+ }
+ }
+ else {
+ if (NOT_COMPARE_MODE && td.type != TypeDesc.TypeEnum.GROUP_INTERFACE) {
+ out.println("\t" + JDOC_OPEN);
+ out.println("\t" + JDOC_CONT + "Adds new child to the list of " + javaDocTagName + ".");
+ out.println("\t" + JDOC_CONT + "@return created child");
+ out.println("\t" + JDOC_CLOSE);
+ if (sbAnnotations.length() > 0) out.println(sbAnnotations);
+ }
+ out.print("\t");
+ //out.print("public ");
+ out.print(elementType + " add");
+ out.print(Util.capitalize(field.elementName));
+ out.println("();");
+ }
+
+ out.println("");
+ out.println("");
+ }
+ out.println("}");
+ }
+ catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ finally {
+ try {
+ out.close();
+ }
+ catch (Exception ex) {
+ }
+ fileManager.releaseOutputFile(outFile);
+ }
+ }
+
+ private static boolean isBadTagName(String tagName) {
+ if (Character.isUpperCase(tagName.charAt(0))) return false;
+ final char[] chars = tagName.toCharArray();
+ for (int i = 1; i < chars.length; i++) {
+ if (Character.isUpperCase(chars[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void generateSuper(FileManager fileManager, NamespaceDesc nsd, ModelDesc model, File outDir) {
+ if (nsd.superClass == null || nsd.superClass.length() == 0) return;
+ final String typeName = nsd.superClass.substring(nsd.superClass.lastIndexOf(".") + 1);
+ final String typeQName = model.toJavaQualifiedTypeName("", nsd.superClass, false);
+ String pkgName = typeQName.substring(0, typeQName.lastIndexOf('.'));
+ File outFile = new File(outDir, toJavaFileName(typeQName));
+ outFile = fileManager.getOutputFile(outFile);
+ PrintWriter out = null;
+ try {
+ Util.log("Generating type: " + typeName + "..");
+ out = new PrintWriter(new FileWriter(outFile));
+ out.println("// Generated on " + new Date());
+ out.println("// DTD/Schema : " + nsd.name);
+ out.println("");
+ if (pkgName != null) {
+ out.println("package " + pkgName + ";");
+ }
+ out.println("");
+ out.println("");
+ out.println(JDOC_OPEN);
+ out.println(JDOC_CONT + nsd.name + " base interface.");
+ if (AUTHOR != null) out.println(JDOC_CONT + AUTHOR);
+ out.println(JDOC_CLOSE);
+ out.print("public interface " + typeName + " ");
+ out.println("{");
+
+
+ out.println("}");
+ }
+ catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ }
+ catch (Exception ex) {
+ }
+ fileManager.releaseOutputFile(outFile);
+ }
+ }
+
+ private void generateHelper(FileManager fileManager, NamespaceDesc nsd, ModelDesc model, File outDir) {
+ final Map<String, TypeDesc> jtMap = model.jtMap;
+ final Map<String, NamespaceDesc> nsdMap = model.nsdMap;
+ if (nsd.helperClass == null || nsd.helperClass.length() == 0) return;
+ ArrayList<TypeDesc> jtList = new ArrayList<TypeDesc>();
+ for (TypeDesc td : jtMap.values()) {
+ if (td.type != TypeDesc.TypeEnum.CLASS) continue;
+// if (!nsd.name.equals(td.xsNamespace)) {
+// continue;
+// }
+ jtList.add(td);
+ }
+ if (jtList.size() == 0) return;
+
+ String typeName = nsd.helperClass.substring(nsd.helperClass.lastIndexOf(".") + 1);
+ final String typeQName = model.toJavaQualifiedTypeName("", nsd.helperClass, false);
+ String pkgName = typeQName.substring(0, typeQName.lastIndexOf('.'));
+ File outFile = new File(outDir, toJavaFileName(typeQName));
+ outFile = fileManager.getOutputFile(outFile);
+ PrintWriter out = null;
+ try {
+ Util.log("Generating type: " + typeName + "..");
+ out = new PrintWriter(new FileWriter(outFile));
+ out.println("// Generated on " + new Date());
+ out.println("// DTD/Schema : " + nsd.name);
+ out.println("");
+ if (pkgName != null) {
+ out.println("package " + pkgName + ";");
+ }
+ out.println("");
+ out.println("");
+ out.println(JDOC_OPEN);
+ out.println(JDOC_CONT + nsd.name + " helper class.");
+ if (AUTHOR != null) out.println(JDOC_CONT + AUTHOR);
+ out.println(JDOC_CLOSE);
+ out.print("public class " + typeName + " ");
+ out.println("{");
+ out.println("");
+ out.println("\tprivate interface GetName { String getName(Object o); }");
+ out.println("\tprivate static java.util.HashMap<Class, GetName> nameMap = new java.util.HashMap();");
+ out.println("\tstatic {");
+
+ for (TypeDesc td : jtList) {
+ ArrayList<FieldDesc> fields = new ArrayList<FieldDesc>(td.fdMap.values());
+ Collections.sort(fields, new Comparator<FieldDesc>() {
+ public int compare(FieldDesc o1, FieldDesc o2) {
+ return o1.realIndex - o2.realIndex;
+ }
+ });
+ int guessPriority = 0;
+ FieldDesc guessedField = null;
+ for (FieldDesc fd : fields) {
+ if (fd.clType == FieldDesc.STR || fd.clType == FieldDesc.SIMPLE || fd.clType == FieldDesc.ATTR) {
+ if (fd.name.equals("name") && guessPriority < 10) {
+ guessPriority = 10;
+ guessedField = fd;
+ }
+ else if (fd.name.endsWith("Name")) {
+ if ((fd.name.endsWith(Util.decapitalize(td.name + "Name")) || fd.realIndex < 2) && guessPriority < 10) {
+ guessPriority = 10;
+ guessedField = fd;
+ }
+ else if (fd.name.endsWith(Util.decapitalize("DisplayName")) && guessPriority < 5) {
+ guessPriority = 5;
+ guessedField = fd;
+ }
+ else if (guessPriority < 3) {
+ guessPriority = 3;
+ guessedField = fd;
+ }
+ }
+ else if (fd.name.equals("value") && guessPriority < 1) {
+ guessPriority = 1;
+ guessedField = fd;
+ }
+ }
+ else if ((fd.clType == -FieldDesc.OBJ || fd.clType == -FieldDesc.STR) && fd.name.endsWith("displayNames") && guessPriority < 5) {
+ guessPriority = 5;
+ guessedField = fd;
+ }
+ }
+ out.println();
+ String qname = model.getNSDPrefix(td) + td.name;
+ String tdNameString = "\"" + toPresentationName(td.name) + "\"";
+ out.println("\t\tnameMap.put(" + qname + ".class, new GetName() {");
+ out.println("\t\t\tpublic String getName(Object o) {");
+ if (guessedField != null) {
+ out.println("\t\t\t\t" + qname + " my = (" + qname + ") o;");
+ String getter = "my.get" + Util.capitalize(guessedField.name) + "()";
+ if (guessedField.clType > 0) {
+ out.println("\t\t\t\tString s = o==null? null:" + getter +
+ (guessedField.clType == FieldDesc.STR || guessedField.clType == FieldDesc.ATTR ? ".getValue();" : ";"));
+ out.println("\t\t\t\treturn s==null?" + tdNameString + ":s;");
+ }
+ else {
+ out.println("\t\t\t\treturn (o!=null && " + getter + "!=null && " + getter + ".size()>0)?");
+ out.println("\t\t\t\t\tgetPresentationName(" + getter + ".get(0), null):" + tdNameString + ";");
+ }
+ }
+ else {
+ out.println("\t\t\t\treturn " + tdNameString + ";");
+ }
+ out.println("\t\t\t}");
+ out.println("\t\t});");
+ }
+ out.println("\t}");
+
+ out.println("\tpublic static String getPresentationName(Object o, String def) {");
+ out.println("\t\tGetName g = o!=null? nameMap.get(o.getClass().getInterfaces()[0]):null;");
+ out.println("\t\treturn g != null?g.getName(o):def;");
+ out.println("\t}");
+ out.println("}");
+ }
+ catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ finally {
+ try {
+ out.close();
+ }
+ catch (Exception ex) {
+ }
+ fileManager.releaseOutputFile(outFile);
+ }
+ }
+
+ public static void printDocumentation(PrintWriter out, String str, String prefix) {
+ if (str == null) return;
+ StringTokenizer st = new StringTokenizer(str, "\n\r");
+ while (st.hasMoreTokens()) {
+ String line = prefix + st.nextToken();
+ out.println(line);
+ }
+ }
+
+ public static String toPresentationName(String typeName) {
+ StringBuffer sb = new StringBuffer(typeName.length() + 10);
+ boolean prevUp = true;
+ for (int i = 0; i < typeName.length(); i++) {
+ char c = typeName.charAt(i);
+ if (Character.isUpperCase(c) && !prevUp) {
+ sb.append(' ');
+ }
+ sb.append(c);
+ prevUp = Character.isUpperCase(c);
+ }
+ return sb.toString();
+ }
+
+ private static String toJavaFileName(String typeName) {
+ return typeName.replace('.', File.separatorChar) + ".java";
+ }
+
+ public static String toJavaIdName(String javaFieldName) {
+ if (Util.RESERVED_NAMES_MAP.containsKey(javaFieldName)) {
+ javaFieldName += "_";
+ }
+ return javaFieldName;
+ }
+
+
+ public void setAuthor(String author) {
+ AUTHOR = "@author " + author;
+ }
+}
diff --git a/plugins/devkit/src/dom/generator/Main.java b/plugins/devkit/src/dom/generator/Main.java
new file mode 100644
index 000000000000..e164a89dcbff
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/Main.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import java.io.File;
+
+/**
+ * @author Gregory.Shrago
+ * @author Konstantin Bulenkov
+ */
+public class Main {
+
+
+ public static void main(String argv[]) throws Exception {
+ if (argv.length != 4) {
+ System.out.println("Usage: Main <XSD or DTD> <input folder> <output folder> <config xml>");
+ }
+ String mode = argv[0];
+ final ModelLoader loader;
+ if (mode.equalsIgnoreCase("xsd")) {
+ loader = new XSDModelLoader();
+ }
+ else if (mode.equalsIgnoreCase("dtd")) {
+ loader = new DTDModelLoader();
+ }
+ else {
+ System.out.println("'"+mode+"' format not supported");
+ System.exit(-1);
+ return;
+ }
+ final File modelRoot = new File(argv[1]);
+ final File outputRoot = new File(argv[2]);
+ final File configXml = new File(argv[3]);
+
+ outputRoot.mkdirs();
+ final ModelGen modelGen = new ModelGen(loader);
+ modelGen.loadConfig(configXml);
+ modelGen.perform(outputRoot, modelRoot);
+ }
+
+}
diff --git a/plugins/devkit/src/dom/generator/MergingFileManager.java b/plugins/devkit/src/dom/generator/MergingFileManager.java
new file mode 100644
index 000000000000..1076eedb9d06
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/MergingFileManager.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import com.intellij.util.ArrayUtil;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.TreeSet;
+
+/**
+ * @author Gregory.Shrago
+ * @author Konstantin Bulenkov
+ */
+public class MergingFileManager implements FileManager {
+
+ public File getOutputFile(File target) {
+ File outFile = target;
+ if (!outFile.getParentFile().exists() && !outFile.getParentFile().mkdirs()) {
+ Util.logerr("parent mkdirs failed: " + outFile);
+ return null;
+ }
+ for (int i = 0; outFile.exists(); i++) {
+ outFile = new File(target.getParentFile(), target.getName() + ".tmp." + i);
+ }
+ return outFile;
+ }
+
+ public File releaseOutputFile(File outFile) {
+ int idx = outFile.getName().indexOf(".tmp.");
+ File target = outFile;
+ if (idx > -1) {
+ target = new File(outFile.getParentFile(), outFile.getName().substring(0, idx));
+ String[] curLines = loadFile(outFile);
+ String[] prevLines = loadFile(target);
+ String[] mergedLines = mergeLines(curLines, prevLines);
+ if (mergedLines != prevLines) {
+ if (mergedLines == curLines) {
+ if (target.exists() && !target.delete()) {
+ Util.logerr("file replace failed: " + target);
+ outFile.delete();
+ } else {
+ outFile.renameTo(target);
+ Util.logwarn("file replaced: " + target);
+ }
+ } else {
+ outFile.delete();
+ if (target.exists() && !target.delete()) {
+ Util.logerr("file replace failed: " + target);
+ } else {
+ writeFile(target, mergedLines);
+ Util.logwarn("file merged: " + target);
+ }
+ }
+ } else {
+ outFile.delete();
+ }
+ }
+ return target;
+ }
+
+ private static String[] mergeLines(String[] curLines, String[] prevLines) {
+ if (prevLines.length == 0) return curLines;
+ ArrayList<String> merged = new ArrayList<String>();
+ int curIdx = 0, prevIdx = 0;
+ String cur, prev;
+ boolean classScope = false;
+ boolean importMerged = false;
+ for (int i = 0; i < Math.max(curLines.length, prevLines.length); i++) {
+ cur = curIdx < curLines.length ? curLines[curIdx] : "";
+ prev = prevIdx < prevLines.length ? prevLines[prevIdx] : "";
+ if (classScope) {
+ merged.addAll(Arrays.asList(curLines).subList(curIdx, curLines.length));
+ break;
+ } else if (prev.trim().startsWith("import ") || cur.trim().startsWith("import ")) {
+ if (importMerged) continue;
+ importMerged = true;
+ int[] indices = new int[]{curIdx, prevIdx};
+ mergeImports(merged, curLines, prevLines, indices);
+ curIdx = indices[0];
+ prevIdx = indices[1];
+ } else if (cur.equals(prev)) {
+ if (cur.trim().startsWith("public interface ")
+ || cur.trim().startsWith("public enum ")) classScope = true;
+ merged.add(cur);
+ curIdx++;
+ prevIdx++;
+ } else if (prev.trim().startsWith("@")) {
+ merged.add(prev);
+ prevIdx++;
+ } else if (cur.trim().startsWith("@")) {
+ merged.add(cur);
+ curIdx++;
+ } else if (cur.trim().startsWith("package ") && prev.trim().startsWith("package ")) {
+ merged.add(prev);
+ curIdx++;
+ prevIdx++;
+ } else if (cur.trim().startsWith("public interface ") && prev.trim().startsWith("public interface ")) {
+ classScope = true;
+ prevIdx = addAllStringsUpTo(merged, prevLines, prevIdx, "{");
+ curIdx = addAllStringsUpTo(null, curLines, curIdx, "{");
+ } else if (cur.trim().startsWith("* ")) {
+ curIdx = addAllStringsUpTo(merged, curLines, curIdx, "*/");
+ if (prev.trim().startsWith("* ") || prev.trim().endsWith("*/")) {
+ prevIdx = addAllStringsUpTo(null, prevLines, prevIdx, "*/");
+ }
+ } else {
+ merged.add(cur);
+ curIdx++;
+ prevIdx++;
+ }
+ }
+ String[] mergedLines = ArrayUtil.toStringArray(merged);
+ if (compareLines(mergedLines, prevLines, 2) == 0) {
+ return prevLines;
+ } else if (compareLines(mergedLines, curLines, 2) == 0) {
+ return curLines;
+ } else {
+ return mergedLines;
+ }
+ }
+
+ private static void mergeImports(ArrayList<String> merged, String[] curLines, String[] prevLines, int[] indices) {
+ TreeSet<String> externalClasses = new TreeSet<String>();
+ for (int i = 0; i < curLines.length; i++) {
+ String line = curLines[i].trim();
+ if (line.startsWith("import ") && line.endsWith(";")) {
+ indices[0] = i + 1;
+ final String name = line.substring("import ".length(), line.length() - 1).trim();
+ if (name.endsWith("*")) continue;
+ externalClasses.add(name);
+ }
+ }
+ for (int i = 0; i < prevLines.length; i++) {
+ String line = prevLines[i].trim();
+ if (line.startsWith("import ") && line.endsWith(";")) {
+ indices[1] = i + 1;
+ final String name = line.substring("import ".length(), line.length() - 1).trim();
+ if (name.endsWith("*")) continue;
+ externalClasses.add(name);
+ }
+ }
+ boolean javaLang = false;
+ for (String s : externalClasses) {
+ if (s.startsWith("java.")) {
+ javaLang = true;
+ continue;
+ }
+ merged.add("import " + s + ";");
+ }
+ if (javaLang) {
+ merged.add("");
+ for (String s : externalClasses) {
+ if (!s.startsWith("java.")) continue;
+ merged.add("import " + s + ";");
+ }
+ }
+ }
+
+ private static int addAllStringsUpTo(ArrayList<String> merged, String[] lines, int startIdx, String upTo) {
+ String str;
+ do {
+ str = startIdx < lines.length ? lines[startIdx] : upTo;
+ if (merged != null) merged.add(str);
+ startIdx++;
+ } while (!str.trim().endsWith(upTo) && startIdx < lines.length);
+ return startIdx;
+ }
+
+ private static int compareLines(String[] mergedLines, String[] curLines, int start) {
+ if (mergedLines.length < curLines.length) return -1;
+ if (mergedLines.length > curLines.length) return 1;
+ for (int i = start; i < mergedLines.length; i++) {
+ final int comp = mergedLines[i].compareTo(curLines[i]);
+ if (comp != 0) return comp;
+ }
+ return 0;
+ }
+
+
+ private static void writeFile(File target, String[] mergedLines) {
+ PrintWriter out = null;
+ try {
+ int lineCount = mergedLines.length;
+ while (lineCount > 0 && mergedLines[lineCount - 1].length() == 0) lineCount--;
+ out = new PrintWriter(new FileWriter(target));
+ for (int i = 0; i < lineCount; i++) {
+ String mergedLine = mergedLines[i];
+ out.println(mergedLine);
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+
+ private static String[] loadFile(File f1) {
+ if (!f1.exists()) return ArrayUtil.EMPTY_STRING_ARRAY;
+ ArrayList<String> list = new ArrayList<String>();
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new FileReader(f1));
+ String str;
+ while ((str = in.readLine()) != null) {
+ list.add(str);
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return ArrayUtil.toStringArray(list);
+ }
+
+}
diff --git a/plugins/devkit/src/dom/generator/ModelDesc.java b/plugins/devkit/src/dom/generator/ModelDesc.java
new file mode 100644
index 000000000000..e940fd24b733
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/ModelDesc.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import org.apache.xerces.xs.XSObject;
+
+import javax.xml.namespace.QName;
+import java.io.PrintWriter;
+import java.util.*;
+
+/**
+ * @author Gregory.Shrago
+ * @author Konstantin Bulenkov
+ */
+public class ModelDesc {
+ final Map<String, String> name2replaceMap = new HashMap<String, String>();
+ final Map<QName, String> qname2FileMap = new HashMap<QName, String>();
+ final Map<String, NamespaceDesc> nsdMap = new HashMap<String, NamespaceDesc>();
+ final Map<String, TypeDesc> jtMap = new TreeMap<String, TypeDesc>();
+
+
+ public String getNSDPrefix(TypeDesc td) {
+ return getNSDPrefix(td.xsNamespace, td.name, td.type == TypeDesc.TypeEnum.ENUM);
+ }
+
+ public String getNSDPrefix(String namespace, String name, boolean isEnum) {
+ final int lastIdx = name.lastIndexOf(".");
+ if (lastIdx > -1) return name.substring(0, lastIdx + 1);
+ final NamespaceDesc nsd = getNSD(namespace);
+ if (isEnum && nsd.enumPkg != null) {
+ return nsd.enumPkg + ".";
+ }
+ if (nsd.pkgNames != null) {
+ final QName qname = new QName(namespace, name);
+ final String files = qname2FileMap.get(qname);
+ if (files != null) {
+ for (int i = 0; i < nsd.pkgNames.length; i += 2) {
+ String file = nsd.pkgNames[i];
+ String pkg = nsd.pkgNames[i + 1];
+ if (files.contains(":" + file + ":")) {
+ return pkg + ".";
+ }
+ }
+ }
+ }
+ return nsd.pkgName != null && nsd.pkgName.length() > 0 ? nsd.pkgName + "." : "";
+ }
+
+ public NamespaceDesc getNSD(String namespace) {
+ NamespaceDesc nsd = nsdMap.get(namespace);
+ if (nsd == null) {
+ nsd = nsdMap.get("");
+ }
+ return nsd;
+ }
+
+
+ public String toJavaTypeName(String tname, String ns) {
+ final int lastIndex = tname.lastIndexOf('.');
+ String xmlName = lastIndex>-1? tname.substring(lastIndex+1): tname;
+ NamespaceDesc nsd = getNSD(ns);
+ if (ns == null || !ns.endsWith(".dtd")) {
+ if (xmlName.endsWith(Util.ANONYMOUS_ELEM_TYPE_SUFFIX)) xmlName = xmlName.substring(0, xmlName.length() - Util.ANONYMOUS_ELEM_TYPE_SUFFIX.length());
+ else if (xmlName.endsWith(Util.ANONYMOUS_ATTR_TYPE_SUFFIX)) xmlName = xmlName.substring(0, xmlName.length() - Util.ANONYMOUS_ATTR_TYPE_SUFFIX.length());
+ else if (xmlName.endsWith(Util.TYPE_SUFFIX)) xmlName = xmlName.substring(0, xmlName.length() - Util.TYPE_SUFFIX.length());
+ }
+ String rc = Util.capitalize(Util.toJavaName(xmlName));
+ if (nsd.prefix != null && nsd.prefix.length()>0 && !rc.startsWith(nsd.prefix)) {
+ rc = nsd.prefix + rc;
+ }
+ if (Util.RESERVED_NAMES_MAP.containsKey(rc)) {
+ rc = Util.RESERVED_NAMES_MAP.get(rc);
+ }
+ if (name2replaceMap.containsKey(rc)) {
+ rc = Util.expandProperties(name2replaceMap.get(rc), nsd.props);
+ }
+
+ return rc;
+ }
+
+ public String toJavaQualifiedTypeName(XSObject xs, Map<String, NamespaceDesc> nsdMap, boolean isEnum) {
+ String typeName = toJavaTypeName(xs.getName(), xs.getNamespace());
+ return getNSDPrefix(xs.getNamespace(), xs.getName(), isEnum) + typeName;
+ }
+
+ public String toJavaQualifiedTypeName(String namespace, String xmlname, boolean isEnum) {
+ return getNSDPrefix(namespace, xmlname, isEnum) + toJavaTypeName(xmlname, namespace);
+ }
+
+ void dump(final PrintWriter out) {
+// out.println("-- qname2FileMap ---");
+// out.println(qname2FileMap);
+ out.println("-- nsdMap ---");
+ for (Map.Entry<String, NamespaceDesc> entry : nsdMap.entrySet()) {
+ out.println("namespace key: "+entry.getKey());
+ dumpNamespace(entry.getValue(), out);
+ }
+ out.println("-- jtMap ---");
+ for (Map.Entry<String, TypeDesc> entry : jtMap.entrySet()) {
+ out.println("type key: "+entry.getKey());
+ dumpTypeDesc(entry.getValue(), out);
+ }
+ }
+
+ private void dumpTypeDesc(TypeDesc td, PrintWriter out) {
+ final ArrayList<String> superList;
+ if (td.supers !=null) {
+ superList = new ArrayList<String>();
+ for (TypeDesc aSuper : td.supers) {
+ superList.add(getNSDPrefix(aSuper)+aSuper.name);
+ }
+ } else superList = null;
+ out.println(" name " + td.name);
+ out.println(" type " + td.type);
+ out.println(" xsName " + td.xsName);
+ out.println(" xsNS " + td.xsNamespace);
+ out.println(" dups " + td.duplicates);
+ out.println(" supers " + (superList!=null?superList:"null"));
+ out.println(" doc " + (td.documentation != null ? td.documentation.length() : "null"));
+ for (Map.Entry<String, FieldDesc> entry : td.fdMap.entrySet()) {
+ out.println(" field key: " + entry.getKey());
+ dumpFieldDesc(td, entry.getValue(), out);
+ }
+ }
+
+ private void dumpFieldDesc(TypeDesc td, FieldDesc fd, PrintWriter out) {
+ out.println(" name " + fd.name);
+ if (td.type == TypeDesc.TypeEnum.ENUM) return;
+ out.println(" clType " + fd.clType);
+ out.println(" required " + fd.required);
+ out.println(" index " + fd.idx+"/"+fd.realIndex);
+ out.println(" choiceOpt " + fd.choiceOpt);
+ out.println(" choice " + (fd.choice!=null?fd.choice.length:"null"));
+ out.println(" content " + fd.contentQualifiedName);
+ out.println(" dupIdx " + fd.duplicateIndex);
+ out.println(" elName " + fd.elementName);
+ out.println(" elType " + fd.elementType);
+ out.println(" def " + fd.def);
+ out.println(" doc " + (fd.documentation != null? fd.documentation.length(): "null"));
+ }
+
+ private void dumpNamespace(NamespaceDesc value, PrintWriter out) {
+ if (value.skip) return;
+ out.println(" name "+value.name);
+ out.println(" prefix "+value.prefix);
+ out.println(" pkgName "+value.pkgName);
+ out.println(" pkgNames "+(value.pkgNames != null?Arrays.asList(value.pkgNames):"null"));
+ out.println(" enumPkg "+value.enumPkg);
+ out.println(" super "+value.superClass);
+ }
+}
diff --git a/plugins/devkit/src/dom/generator/ModelGen.java b/plugins/devkit/src/dom/generator/ModelGen.java
new file mode 100644
index 000000000000..8f1f709a6906
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/ModelGen.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLInputSource;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import java.io.CharArrayReader;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Gregory.Shrago
+ * @author Konstantin Bulenkov
+ */
+public class ModelGen {
+ private final ModelDesc model = new ModelDesc();
+ private final Map<String, String> schemaLocationMap = new HashMap<String, String>();
+ private final ModelLoader loader;
+ private final Emitter emitter;
+ private final FileManager fileManager;
+
+
+ public ModelGen(ModelLoader loader) {
+ this(loader, new JetBrainsEmitter(), new MergingFileManager());
+ }
+
+ public ModelGen(ModelLoader loader, Emitter emitter, FileManager fileManager) {
+ this.loader = loader;
+ this.emitter = emitter;
+ this.fileManager = fileManager;
+ }
+
+ public ModelDesc getModel() {
+ return model;
+ }
+
+ public static Element loadXml(File configXml) throws Exception {
+ SAXBuilder saxBuilder = new SAXBuilder();
+ saxBuilder.setEntityResolver(new EntityResolver() {
+ public InputSource resolveEntity(String publicId,
+ String systemId)
+ throws SAXException, IOException {
+ return new InputSource(new CharArrayReader(new char[0]));
+ }
+ });
+ final Document document = saxBuilder.build(configXml);
+ return document.getRootElement();
+ }
+
+ public void loadConfig(File configXml) throws Exception {
+ loadConfig(loadXml(configXml));
+ }
+
+ public void setConfig(String schema, String location, NamespaceDesc desc, String... schemasToSkip) {
+ schemaLocationMap.put(schema, location);
+ for (String sch : schemasToSkip) {
+ if (sch != null && sch.length() > 0) {
+ model.nsdMap.put(sch, new NamespaceDesc(sch));
+ }
+ }
+ model.nsdMap.put("", new NamespaceDesc("", "", "com.intellij.util.xml.DomElement", "", null, null, null, null));
+ model.nsdMap.put(desc.name, desc);
+ }
+
+ public void loadConfig(Element element) {
+ final Element namespaceEl = element.getChild("namespaces");
+ for (Element e : (List<Element>) namespaceEl.getChildren("schemaLocation")) {
+ final String name = e.getAttributeValue("name");
+ final String file = e.getAttributeValue("file");
+ schemaLocationMap.put(name, file);
+ }
+ for (Element e : (List<Element>) namespaceEl.getChildren("reserved-name")) {
+ final String name = e.getAttributeValue("name");
+ final String replacement = e.getAttributeValue("replace-with");
+ model.name2replaceMap.put(name, replacement);
+ }
+ NamespaceDesc def = new NamespaceDesc("", "generated", "java.lang.Object", "", null, null, null, null);
+ for (Element nsElement : (List<Element>) namespaceEl.getChildren("namespace")) {
+ final String name = nsElement.getAttributeValue("name");
+ final NamespaceDesc nsDesc = new NamespaceDesc(name, def);
+
+ final String skip = nsElement.getAttributeValue("skip");
+ final String prefix = nsElement.getAttributeValue("prefix");
+ final String superC = nsElement.getAttributeValue("super");
+ final String imports = nsElement.getAttributeValue("imports");
+ final String packageS = nsElement.getAttributeValue("package");
+ final String packageEnumS = nsElement.getAttributeValue("enums");
+ final String interfaces = nsElement.getAttributeValue("interfaces");
+ final ArrayList<String> list = new ArrayList<String>();
+ for (Element pkgElement : (List<Element>) nsElement.getChildren("package")) {
+ final String pkgName = pkgElement.getAttributeValue("name");
+ final String fileName = pkgElement.getAttributeValue("file");
+ list.add(fileName);
+ list.add(pkgName);
+ }
+ for (Element pkgElement : (List<Element>) nsElement.getChildren("property")) {
+ final String propertyName = pkgElement.getAttributeValue("name");
+ final String propertyValue = pkgElement.getAttributeValue("value");
+ nsDesc.props.put(propertyName, propertyValue);
+ }
+
+ if (skip != null) nsDesc.skip = skip.equalsIgnoreCase("true");
+ if (prefix != null) nsDesc.prefix = prefix;
+ if (superC != null) nsDesc.superClass = superC;
+ if (imports != null) nsDesc.imports = imports;
+ if (packageS != null) nsDesc.pkgName = packageS;
+ if (packageEnumS != null) nsDesc.enumPkg = packageEnumS;
+ if (interfaces != null) nsDesc.intfs = interfaces;
+ if (!list.isEmpty()) nsDesc.pkgNames = ArrayUtil.toStringArray(list);
+ if (name.length() == 0) def = nsDesc;
+ model.nsdMap.put(name, nsDesc);
+ }
+ }
+
+ public void perform(final File outputRoot, final File... modelRoots) throws Exception {
+ loadModel(modelRoots);
+ emitter.emit(fileManager, model, outputRoot);
+
+ Util.log("Done.");
+ }
+
+ public void loadModel(final File... modelRoots) throws Exception {
+ XMLEntityResolver resolver = new XMLEntityResolver() {
+ public XMLInputSource resolveEntity(XMLResourceIdentifier xmlResourceIdentifier) throws XNIException, IOException {
+ String esid = xmlResourceIdentifier.getExpandedSystemId();
+ if (esid == null) {
+ final String location = schemaLocationMap.get(xmlResourceIdentifier.getNamespace());
+ if (location != null) {
+ esid = location;
+ } else {
+ return null;
+ }
+ }
+ // Util.log("resolving "+esid);
+ File f = null;
+ for (File root : modelRoots) {
+ if (root == null) continue;
+ if (root.isDirectory()) {
+ final String fileName = esid.substring(esid.lastIndexOf('/') + 1);
+ f = new File(root, fileName);
+ } else {
+ f = root;
+ }
+ }
+ if (f == null || !f.exists()) {
+ Util.logerr("unable to resolve: " + esid);
+ return null;
+ }
+ esid = f.getPath();
+ return new XMLInputSource(null, esid, null);
+ }
+ };
+ ArrayList<File> files = new ArrayList<File>();
+ for (File root : modelRoots) {
+ ContainerUtil.addAll(files, root.listFiles());
+ }
+ loader.loadModel(model, files, resolver);
+ Util.log(model.jtMap.size() + " java types loaded");
+ }
+
+}
diff --git a/plugins/devkit/src/dom/generator/ModelLoader.java b/plugins/devkit/src/dom/generator/ModelLoader.java
new file mode 100644
index 000000000000..cf71534b473d
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/ModelLoader.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public interface ModelLoader {
+ void loadModel(ModelDesc model, Collection<File> files, XMLEntityResolver resolver) throws Exception;
+}
diff --git a/plugins/devkit/src/dom/generator/NamespaceDesc.java b/plugins/devkit/src/dom/generator/NamespaceDesc.java
new file mode 100644
index 000000000000..f73d16ad2cee
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/NamespaceDesc.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class NamespaceDesc {
+ public NamespaceDesc(String name,
+ String pkgName,
+ String superClass,
+ String prefix,
+ String factoryClass,
+ String helperClass,
+ String imports,
+ String intfs) {
+ this.name = name;
+ this.pkgName = pkgName;
+ this.superClass = superClass;
+ this.prefix = prefix;
+ this.factoryClass = factoryClass;
+ this.helperClass = helperClass;
+ this.imports = imports;
+ this.intfs = intfs;
+ }
+
+ public NamespaceDesc(String name) {
+ this(name, "generated", "java.lang.Object", "", null, null, null, null);
+ skip = true;
+ }
+
+
+ public NamespaceDesc(String name, NamespaceDesc def) {
+ this.name = name;
+ this.pkgName = def.pkgName;
+ this.superClass = def.superClass;
+ this.prefix = def.prefix;
+ this.factoryClass = def.factoryClass;
+ this.helperClass = def.helperClass;
+ this.imports = def.imports;
+ this.intfs = def.intfs;
+ }
+
+ final Map<String, String> props = new HashMap<String, String>();
+ final String name;
+ String pkgName;
+ String superClass;
+ String prefix;
+ String factoryClass;
+ String helperClass;
+ String imports;
+ String intfs;
+ boolean skip;
+ String[] pkgNames;
+ String enumPkg;
+
+
+ public String toString() {
+ return "NS:"+name+" "+(skip?"skip":"")+pkgName;
+ }
+}
diff --git a/plugins/devkit/src/dom/generator/TypeDesc.java b/plugins/devkit/src/dom/generator/TypeDesc.java
new file mode 100644
index 000000000000..c644fd73124a
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/TypeDesc.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class TypeDesc {
+ public enum TypeEnum {
+ CLASS, ENUM, GROUP_INTERFACE
+ }
+
+ public TypeDesc(String xsName, String xsNamespace, String name, TypeEnum type) {
+ this.xsName = xsName;
+ this.xsNamespace = xsNamespace;
+ this.name = name;
+ this.type = type;
+ }
+
+ TypeEnum type;
+ final String xsName;
+ final String xsNamespace;
+ final String name;
+ final Map<String, FieldDesc> fdMap = new TreeMap<String, FieldDesc>();
+ boolean duplicates;
+ String documentation;
+ TypeDesc[] supers;
+
+ public String toString() {
+ return (type == TypeEnum.ENUM ? "enum" : "type") + ": " + name + ";" + xsName + ";";
+ }
+}
diff --git a/plugins/devkit/src/dom/generator/Util.java b/plugins/devkit/src/dom/generator/Util.java
new file mode 100644
index 000000000000..a393bb143602
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/Util.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import org.apache.xerces.xs.XSObject;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class Util {
+ public static final String ANONYMOUS_ELEM_TYPE_SUFFIX = "ElemType";
+ public static final String ANONYMOUS_ATTR_TYPE_SUFFIX = "AttrType";
+ public static final String TYPE_SUFFIX = "Type";
+
+ //
+ // Constants
+ //
+ public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
+
+ // reserved names map
+ public static final String[] RESERVED_NAMES_TABLE = {
+ "abstract", "default", "if", "private", "this",
+ "boolean", "do", "implements", "protected", "throw",
+ "break", "double", "import", "public", "throws",
+ "byte", "else", "instanceof", "return", "transient",
+ "case", "extends", "int", "short", "try",
+ "catch", "final", "interface", "static", "void",
+ "char", "finally", "long", "strictfp", "volatile",
+ "class", "float", "native", "super", "while",
+ "const", "for", "new", "switch",
+ "continue", "goto", "package", "synchronized"
+ };
+ public static final HashMap<String, String> RESERVED_NAMES_MAP;
+
+ static {
+ RESERVED_NAMES_MAP = new HashMap<String, String>();
+ for (String aRESERVED_NAMES_TABLE : RESERVED_NAMES_TABLE) {
+ // RESERVED_NAMES_MAP.put(RESERVED_NAMES_TABLE[i], RESERVED_NAMES_TABLE[i]+"_");
+ // as far as there is no actual field but setters/getters:
+ RESERVED_NAMES_MAP.put(aRESERVED_NAMES_TABLE, aRESERVED_NAMES_TABLE);
+ }
+ //RESERVED_NAMES_MAP.put("class", "clazz");
+ }
+
+
+ static void log(String str) {
+ System.out.println(str);
+ }
+
+ static void logwarn(String str) {
+ System.out.println("[warn] " + str);
+ }
+
+ static void logerr(String str) {
+ System.out.println("[error] " + str);
+ }
+
+ public static String pluralize(String suggestion) {
+ // return suggestion+"List";
+ final String VOWELS = "aeiouy";
+ if (suggestion.endsWith("s") || suggestion.endsWith("x") ||
+ suggestion.endsWith("ch")) {
+ suggestion += "es";
+ } else {
+ int len = suggestion.length();
+ if (suggestion.endsWith("y") && len > 1 && VOWELS.indexOf(suggestion.charAt(len - 2)) < 0) {
+ suggestion = suggestion.substring(0, len - 1) + "ies";
+ } else {
+ suggestion += "s";
+ }
+ }
+ return suggestion;
+ }
+
+ public static String toJavaFieldName(String xmlName) {
+ String rc = toJavaName(xmlName);
+ if (RESERVED_NAMES_MAP.containsKey(rc)) {
+ rc = RESERVED_NAMES_MAP.get(rc);
+ }
+ return rc;
+ }
+
+
+ public static String computeEnumConstantName(String val, String typeName) {
+ String id = val;
+ for (int i = 1; i < id.length(); i++) {
+ if (Character.isUpperCase(id.charAt(i))
+ && Character.isLowerCase(id.charAt(i - 1))) {
+ id = id.substring(0, i) + "_" + id.substring(i);
+ i++;
+ }
+ }
+ id = id.toUpperCase();
+ id = id.replace('.', '_').replace('-', '_');
+ if (id.length() < 2 || !Character.isJavaIdentifierStart(id.charAt(0))) {
+ id = typeName + "_" + id;
+ }
+ return id;
+ }
+
+
+ public static String capitalize(String str) {
+ return Character.toUpperCase(str.charAt(0)) + str.substring(1);
+ }
+
+ public static String decapitalize(String str) {
+ return Character.toLowerCase(str.charAt(0)) + str.substring(1);
+ }
+
+ public static String toJavaName(String xmlName) {
+ xmlName = xmlName.substring(xmlName.lastIndexOf(':') + 1);
+ StringTokenizer st = new StringTokenizer(xmlName, "-");
+ StringBuffer sb = new StringBuffer(st.nextToken());
+ while (st.hasMoreTokens()) {
+ sb.append(capitalize(st.nextToken()));
+ }
+ return sb.toString();
+ }
+
+ public static String toDefXmlTagName(XSObject xs) {
+ String xmlName = xs.getName();
+ if (xmlName.endsWith(TYPE_SUFFIX)) xmlName = xmlName.substring(0, xmlName.length() - 4);
+ return xmlName;
+ }
+
+ public static String toDefXmlTagName(String tname) {
+ String xmlName = tname;
+ if (xmlName.endsWith(TYPE_SUFFIX)) xmlName = xmlName.substring(0, xmlName.length() - TYPE_SUFFIX.length());
+ return xmlName;
+ }
+
+
+ public static boolean addToNameMap(Map<String, FieldDesc> fdMap, FieldDesc fd1, boolean merge) {
+ boolean duplicates = false;
+ FieldDesc fd2;
+ if ((fd2 = fdMap.remove(fd1.name)) != null) {
+ if (fd2.clType == FieldDesc.ATTR) {
+ // attr <-> field
+ fd2.name = fd1.name + "Attr";
+ fdMap.put(fd2.name, fd2);
+ } else if (merge) {
+ fdMap.put(fd2.name, fd2);
+ return false;
+ } else {
+ duplicates = true;
+ fd2.name = fd1.name + "1";
+ fd2.duplicateIndex = 1;
+ fdMap.put(fd2.name, fd2);
+ fd1.name = fd1.name + "2";
+ fd1.duplicateIndex = 2;
+ }
+ } else if ((fd2 = fdMap.get(fd1.name + "1")) != null) {
+ int id = 2;
+ while (fdMap.containsKey(fd1.name + id)) id++;
+ fd1.name = fd1.name + id;
+ fd1.duplicateIndex = id;
+ }
+ fdMap.put(fd1.name, fd1);
+ return duplicates;
+ }
+
+ public static String expandProperties(final String str, final Map<String, String> map) {
+ if (str.indexOf("${") == -1) return str;
+ int state = 0;
+ final StringBuilder result = new StringBuilder();
+ final StringBuilder variable = new StringBuilder();
+ for (int i=0; i<str.length(); i++) {
+ final char ch = str.charAt(i);
+ switch (state) {
+ case 0:
+ if (ch == '$') state = 1;
+ else result.append(ch);
+ break;
+ case 1:
+ if (ch == '{') {
+ state = 2;
+ variable.setLength(0);
+ }
+ else {
+ state = 0;
+ result.append('$').append(ch);
+ }
+ break;
+ case 2:
+ if (ch == '}') {
+ final String value = map.get(variable.toString());
+ result.append(value == null? variable : value);
+ state = 0;
+ }
+ else {
+ variable.append(ch);
+ }
+ break;
+ }
+ }
+ return result.toString();
+ }
+}
+
diff --git a/plugins/devkit/src/dom/generator/XSDModelLoader.java b/plugins/devkit/src/dom/generator/XSDModelLoader.java
new file mode 100644
index 000000000000..b3e25e0dbaf6
--- /dev/null
+++ b/plugins/devkit/src/dom/generator/XSDModelLoader.java
@@ -0,0 +1,681 @@
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XSD/DTD Model generator tool
+ *
+ * By Gregory Shrago
+ * 2002 - 2006
+ */
+package org.jetbrains.idea.devkit.dom.generator;
+
+import org.apache.xerces.xs.*;
+import org.apache.xerces.impl.xs.XSComplexTypeDecl;
+import org.apache.xerces.impl.xs.XSParticleDecl;
+import org.apache.xerces.impl.xs.XSAttributeGroupDecl;
+import org.apache.xerces.impl.xs.XSElementDecl;
+import org.apache.xerces.impl.xs.util.XSObjectListImpl;
+import org.apache.xerces.impl.dv.XSSimpleType;
+import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.DOMErrorHandler;
+import org.w3c.dom.DOMError;
+import org.w3c.dom.TypeInfo;
+
+import javax.xml.namespace.QName;
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author Gregory.Shrago
+ * @author Konstantin Bulenkov
+ */
+public class XSDModelLoader implements ModelLoader {
+ private static final boolean TEXT_ELEMENTS_ARE_COMPLEX = false;
+
+
+ private ModelDesc model;
+
+ public void loadModel(ModelDesc model, Collection<File> files, XMLEntityResolver resolver) throws Exception {
+ this.model = model;
+ processSchemas(files, resolver);
+ }
+
+ public static boolean checkComplexType(XSTypeDefinition td) {
+ if (td.getTypeCategory() != XSTypeDefinition.COMPLEX_TYPE) return false;
+ XSComplexTypeDefinition ctd = (XSComplexTypeDefinition) td;
+ if (ctd.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_ELEMENT) {
+ return true;
+ }
+ if ((td instanceof XSComplexTypeDecl) && ((XSComplexTypeDecl) td).getAbstract()) return true;
+ if (TEXT_ELEMENTS_ARE_COMPLEX) return true;
+ if (ctd.getAttributeUses() != null) {
+ for (int i = 0; i < ctd.getAttributeUses().getLength(); i++) {
+ XSSimpleTypeDefinition xsstd = ((XSAttributeUse) ctd.getAttributeUses().item(i)).getAttrDeclaration().getTypeDefinition();
+ if ("ID".equals(xsstd.getName())) continue;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean checkEnumType(XSTypeDefinition td) {
+ final XSSimpleTypeDefinition st;
+ if (td.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
+ XSComplexTypeDefinition ctd = (XSComplexTypeDefinition) td;
+ if (ctd.getContentType() != XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) return false;
+ if (ctd.getAttributeUses() != null) {
+ for (int i = 0; i < ctd.getAttributeUses().getLength(); i++) {
+ XSSimpleTypeDefinition xsstd = ((XSAttributeUse) ctd.getAttributeUses().item(i)).getAttrDeclaration().getTypeDefinition();
+ if ("ID".equals(xsstd.getName())) continue;
+ return false;
+ }
+ }
+ st = ctd.getSimpleType();
+ } else if (td.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
+ st = (XSSimpleTypeDefinition) td;
+ } else {
+ return false;
+ }
+ return st.getLexicalEnumeration() != null && st.getLexicalEnumeration().getLength() != 0;
+ }
+
+ private static boolean checkBooleanType(XSTypeDefinition td) {
+ if (td.getTypeCategory() != XSTypeDefinition.SIMPLE_TYPE) return false;
+ final XSSimpleTypeDefinition st = ((XSSimpleTypeDefinition) td);
+ final XSObjectList facets = st.getFacets();
+ for (int i = 0; i < facets.getLength(); i++) {
+ final XSFacet facet = (XSFacet) facets.item(i);
+ if (facet.getFacetKind() == XSSimpleTypeDefinition.FACET_LENGTH) {
+ if ("0".equals(facet.getLexicalFacetValue())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ private XSModel loadSchema(File schemaFile, XMLEntityResolver resolver) throws Exception {
+ // get DOM Implementation using DOM Registry
+ System.setProperty(
+ DOMImplementationRegistry.PROPERTY,
+ "org.apache.xerces.dom.DOMXSImplementationSourceImpl");
+ DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
+ XSImplementation impl = (XSImplementation) registry.getDOMImplementation("XS-Loader");
+ XSLoader schemaLoader = impl.createXSLoader(null);
+ DOMConfiguration config = schemaLoader.getConfig();
+
+ // create Error Handler
+ DOMErrorHandler errorHandler = new DOMErrorHandler() {
+ public boolean handleError(DOMError domError) {
+ Util.log("DOMError: " + domError.getMessage());
+ Object relatedException = domError.getRelatedException();
+ if (relatedException != null) {
+ Util.log("DOMError: " + relatedException);
+ if (relatedException instanceof Throwable) {
+ ((Throwable) relatedException).printStackTrace(System.out);
+ }
+ }
+ return false;
+ }
+ };
+ // set error handler
+ config.setParameter("error-handler", errorHandler);
+ // set validation feature
+ config.setParameter("validate", Boolean.TRUE);
+ // parse document
+ config.setParameter("error-handler", errorHandler);
+ config.setParameter("http://apache.org/xml/properties/internal/entity-resolver", resolver);
+
+ XSModel model = schemaLoader.loadURI(schemaFile.getAbsolutePath());
+ if (model == null) return null;
+ XSNamedMap components = model.getComponents(XSConstants.ELEMENT_DECLARATION);
+ for (int i = 0; i < components.getLength(); i++) {
+ XSObject obj = components.item(i);
+ QName qname = new QName(obj.getNamespace(), obj.getName());
+ String file = this.model.qname2FileMap.get(qname);
+ this.model.qname2FileMap.put(qname, (file == null ? "" : file + ";") + schemaFile.getName());
+ }
+ components = model.getComponents(XSConstants.TYPE_DEFINITION);
+ for (int i = 0; i < components.getLength(); i++) {
+ XSObject obj = components.item(i);
+ QName qname = new QName(obj.getNamespace(), obj.getName());
+ String file = this.model.qname2FileMap.get(qname);
+ this.model.qname2FileMap.put(qname, (file == null ? "" : file) + ":" + schemaFile.getName() + ":");
+ }
+ return model;
+ }
+
+ public void processSchemas(Collection<File> schemas, XMLEntityResolver resolver) throws Exception {
+ Map<String, NamespaceDesc> nsdMap = model.nsdMap;
+ Map<String, TypeDesc> jtMap = model.jtMap;
+ final NamespaceDesc nsdDef = nsdMap.get("");
+ final ArrayList<XSModel> models = new ArrayList<XSModel>();
+ final HashMap<String, XSTypeDefinition> types = new HashMap<String, XSTypeDefinition>();
+ for (File schemaFile : schemas) {
+ String fileName = schemaFile.getPath();
+ if (schemaFile.isDirectory() || !fileName.endsWith(".xsd")) {
+ Util.log("skipping " + fileName);
+ continue;
+ }
+ Util.log("loading " + fileName + "..");
+
+ final XSModel model = loadSchema(schemaFile, resolver);
+ if (model == null) continue;
+
+ final StringList namespaceList = model.getNamespaces();
+ for (int i = 0; i < namespaceList.getLength(); i++) {
+ String ns = namespaceList.item(i);
+ if (!nsdMap.containsKey(ns)) {
+ Util.log("Adding default namespace desc for: " + ns);
+ NamespaceDesc nsd = new NamespaceDesc(ns, nsdDef);
+ nsdMap.put(ns, nsd);
+ }
+ }
+ models.add(model);
+ final XSNamedMap typeDefMap = model.getComponents(XSConstants.TYPE_DEFINITION);
+ for (int i = 0; i < typeDefMap.getLength(); i++) {
+ XSTypeDefinition o = (XSTypeDefinition) typeDefMap.item(i);
+ NamespaceDesc nsd = nsdMap.get(o.getNamespace());
+ if (nsd != null && nsd.skip) continue;
+ final String key = o.getName() + "," + o.getNamespace();
+ types.put(key, o);
+ }
+ final XSNamedMap elementDeclMap = model.getComponents(XSConstants.ELEMENT_DECLARATION);
+ for (int i = 0; i < elementDeclMap.getLength(); i++) {
+ XSElementDeclaration o = (XSElementDeclaration) elementDeclMap.item(i);
+ if (o.getTypeDefinition().getAnonymous() && (o.getTypeDefinition() instanceof XSComplexTypeDefinition)) {
+ //types.put(o.getName() + "," + o.getNamespace(), o);
+ XSComplexTypeDefinition ctd = makeTypeFromAnonymous(o);
+ NamespaceDesc nsd = nsdMap.get(o.getNamespace());
+ if (nsd != null && nsd.skip) continue;
+ final String key = ctd.getName() + "," + ctd.getNamespace();
+ types.put(key, ctd);
+ }
+ }
+ }
+ Util.log(types.size() + " elements loaded, processing..");
+ ArrayList<XSTypeDefinition> toProcess = new ArrayList<XSTypeDefinition>(types.values());
+ ArrayList<XSComplexTypeDefinition> toAdd = new ArrayList<XSComplexTypeDefinition>();
+ for (ListIterator<XSTypeDefinition> it = toProcess.listIterator(); it.hasNext();) {
+ XSTypeDefinition td = it.next();
+ Util.log("processing " + td.getName() + "," + td.getNamespace() + "..");
+ if (checkComplexType(td)) {
+ processType((XSComplexTypeDefinition) td, models, jtMap, nsdMap, toAdd);
+ } else if (checkEnumType(td)) {
+ processEnumType(td, jtMap, nsdMap);
+ }
+ if (toAdd.size() != 0) {
+ for (XSComplexTypeDefinition o : toAdd) {
+ final String key = o.getName() + "," + o.getNamespace();
+ if (!types.containsKey(key)) {
+ Util.log(" adding " + o.getName() + "," + o.getNamespace());
+ types.put(key, o);
+ it.add(o);
+ it.previous();
+ } else {
+ Util.logwarn(key + " already exists");
+ }
+ }
+ toAdd.clear();
+ }
+ }
+ }
+
+ private XSComplexTypeDefinition makeTypeFromAnonymous(XSObject o) {
+ final XSComplexTypeDecl ctd = new XSComplexTypeDecl();
+ if (o instanceof XSElementDeclaration && ((XSElementDeclaration) o).getTypeDefinition() instanceof XSComplexTypeDecl) {
+ final XSComplexTypeDecl ctd1 = (XSComplexTypeDecl) ((XSElementDeclaration) o).getTypeDefinition();
+ final XSObjectListImpl annotations = ctd1.getAnnotations() instanceof XSObjectListImpl ? (XSObjectListImpl) ctd1.getAnnotations() : new XSObjectListImpl();
+ ctd.setValues(o.getName(), ctd1.getNamespace(), ctd1.getBaseType(), ctd1.getDerivationMethod(),
+ ctd1.getFinal(), ctd1.getProhibitedSubstitutions(), ctd1.getContentType(),
+ ctd1.getAbstract(), ctd1.getAttrGrp(), (XSSimpleType) ctd1.getSimpleType(),
+ (XSParticleDecl) ctd1.getParticle(), annotations);
+ ctd.setName(o.getName() + Util.ANONYMOUS_ELEM_TYPE_SUFFIX);
+ } else if (o instanceof XSAttributeDeclaration) {
+ final XSSimpleTypeDecl ctd1 = (XSSimpleTypeDecl) ((XSAttributeDeclaration) o).getTypeDefinition();
+ final XSObjectListImpl annotations = ctd1.getAnnotations() instanceof XSObjectListImpl ? (XSObjectListImpl) ctd1.getAnnotations() : new XSObjectListImpl();
+ ctd.setValues(o.getName(), ctd1.getNamespace(), ctd1.getBaseType(), XSConstants.DERIVATION_RESTRICTION,
+ ctd1.getFinal(), (short) 0, XSComplexTypeDefinition.CONTENTTYPE_SIMPLE,
+ false, new XSAttributeGroupDecl(), ctd1,
+ null, annotations);
+ ctd.setName(o.getName() + Util.ANONYMOUS_ATTR_TYPE_SUFFIX);
+ }
+
+ model.qname2FileMap.put(new QName(ctd.getNamespace(), ctd.getName()), model.qname2FileMap.get(new QName(o.getNamespace(), o.getName())));
+ return ctd;
+ }
+
+ public void processEnumType(XSTypeDefinition def, Map<String, TypeDesc> jtMap, Map<String, NamespaceDesc> nsdMap) throws Exception {
+ boolean complexType = def instanceof XSComplexTypeDefinition;
+ if (!nsdMap.containsKey(def.getNamespace())) {
+ Util.log("Namespace desc not found for: " + def);
+ }
+ final String typeName = toJavaTypeName(def, nsdMap);
+ final TypeDesc td = new TypeDesc(def.getName(), def.getNamespace(), typeName, TypeDesc.TypeEnum.ENUM);
+ final XSComplexTypeDefinition ct = complexType ? (XSComplexTypeDefinition) def : null;
+ final XSSimpleTypeDefinition st = (XSSimpleTypeDefinition) (complexType ? ((XSComplexTypeDefinition) def).getSimpleType() : def);
+ for (int i = 0; i < st.getLexicalEnumeration().getLength(); i++) {
+ final String s = st.getLexicalEnumeration().item(i);
+ td.fdMap.put(s, new FieldDesc(Util.computeEnumConstantName(s, td.name), s));
+ }
+
+ final XSObjectList anns = complexType ? ct.getAnnotations() : st.getAnnotations();
+
+ td.documentation = parseAnnotationString("Enumeration " + def.getNamespace() + ":" + def.getName() + " documentation", anns != null && anns.getLength() > 0 ? ((XSAnnotation) anns.item(0)).getAnnotationString() : null);
+ jtMap.put(model.toJavaQualifiedTypeName(def, nsdMap, true), td);
+ }
+
+ public void processType(XSComplexTypeDefinition def, List<XSModel> models, Map<String, TypeDesc> jtMap, Map<String, NamespaceDesc> nsdMap, ArrayList<XSComplexTypeDefinition> toAdd) throws Exception {
+ if (!nsdMap.containsKey(def.getNamespace())) {
+ Util.log("Namespace desc not found for: " + def);
+ }
+ String typeName = toJavaTypeName(def, nsdMap);
+ TypeDesc td = jtMap.get(model.toJavaQualifiedTypeName(def, nsdMap, false));
+ if (td != null) {
+ if (td.fdMap.size() == 0) {
+ // Util.log("Reusing forward decl: "+typeName);
+ } else {
+ Util.logerr("merging: type names collision: " + typeName);
+ }
+ } else {
+ td = new TypeDesc(def.getName(), def.getNamespace(), typeName, TypeDesc.TypeEnum.CLASS);
+ }
+ XSObjectList anns = def.getAnnotations();
+ td.documentation = parseAnnotationString("Type " + def.getNamespace() + ":" + def.getName() + " documentation",
+ anns != null && anns.getLength() > 0 ? ((XSAnnotation) anns.item(0)).getAnnotationString() : null);
+ TypeDesc tdBase = null;
+ if (checkComplexType(def.getBaseType())) {
+ XSComplexTypeDefinition base = (XSComplexTypeDefinition) def.getBaseType();
+ String typeNameBase = toJavaTypeName(base, nsdMap);
+ if ((tdBase = jtMap.get(model.toJavaQualifiedTypeName(base, nsdMap, false))) == null) {
+ // logwarn("forward decl: "+et);
+ tdBase = new TypeDesc(base.getName(), base.getNamespace(), typeNameBase, TypeDesc.TypeEnum.CLASS);
+ jtMap.put(model.toJavaQualifiedTypeName(base, nsdMap, false), tdBase);
+ }
+ }
+ if (def.getSimpleType() != null || def.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_MIXED) {
+ FieldDesc fd = new FieldDesc(FieldDesc.SIMPLE, "value", "String", null, "null", true);
+ fd.realIndex = td.fdMap.size();
+ td.fdMap.put(fd.name, fd);
+ }
+ XSObjectList attrs = def.getAttributeUses();
+ for (int i = 0; i < attrs.getLength(); i++) {
+ XSAttributeUse au = (XSAttributeUse) attrs.item(i);
+ XSAttributeDeclaration ad = au.getAttrDeclaration();
+ XSSimpleTypeDefinition atd = ad.getTypeDefinition();
+ XSAnnotation ann = ad.getAnnotation();
+ String documentation = parseAnnotationString("Attribute " + ad.getNamespace() + ":" + ad.getName() + " documentation", ann != null ? ann.getAnnotationString() : null);
+ // skip "ID" and "FIXED"
+ if ("ID".equals(atd.getName())) continue;
+ // "language", "dewey-versionType", "boolean"
+ if (ad.getConstraintType() == XSConstants.VC_FIXED) continue;
+ FieldDesc fd1 = new FieldDesc(FieldDesc.ATTR, Util.toJavaFieldName(ad.getName()), "String", null, "null", au.getRequired());
+ fd1.tagName = ad.getName();
+ fd1.documentation = documentation;
+ fd1.realIndex = td.fdMap.size();
+ td.duplicates = Util.addToNameMap(td.fdMap, fd1, false) || td.duplicates;
+ if (checkEnumType(ad.getTypeDefinition())) {
+ XSTypeDefinition etRoot = ad.getTypeDefinition();
+ if (etRoot.getAnonymous()) {
+ etRoot = makeTypeFromAnonymous(ad);
+ if (toAdd != null) toAdd.add((XSComplexTypeDefinition) etRoot);
+ }
+ fd1.type = toJavaTypeName(etRoot, nsdMap);
+ fd1.contentQualifiedName = model.toJavaQualifiedTypeName(etRoot, nsdMap, true);
+ // forward decl
+ if (jtMap.get(fd1.contentQualifiedName) == null) {
+ // logwarn("forward decl: "+et);
+ TypeDesc ftd = new TypeDesc(etRoot.getName(), etRoot.getNamespace(), fd1.type, TypeDesc.TypeEnum.ENUM);
+ jtMap.put(fd1.contentQualifiedName, ftd);
+// // anonymous (simple type) enum
+// if (ad.getTypeDefinition().getAnonymous()) {
+// processEnumType(ad.getTypeDefinition(), jtMap, nsdMap);
+// }
+ }
+ } else {
+ fd1.simpleTypesString = getSimpleTypesString(ad.getTypeDefinition());
+ }
+ }
+ LinkedList<PEntry> plist = new LinkedList<PEntry>();
+ if (def.getParticle() != null) {
+ plist.add(new PEntry(def.getParticle(), false));
+ }
+ processParticles(def, plist, nsdMap, jtMap, td, models, toAdd, tdBase);
+ jtMap.put(model.toJavaQualifiedTypeName(def, nsdMap, false), td);
+ if (td.fdMap.size() == 1 && def.getSimpleType() != null) {
+ // calc type hierarchy for simple content
+ FieldDesc fd = td.fdMap.get("value");
+ fd.simpleTypesString = getSimpleTypesString(def);
+ }
+ }
+
+ private static String getSimpleTypesString(XSTypeDefinition et) {
+ StringBuffer typesHierarchy = new StringBuffer();
+ while (et != null && !"anySimpleType".equals(et.getName()) && !"anyType".equals(et.getName()) && et.getNamespace() != null) {
+ typesHierarchy.append(et.getNamespace().substring(et.getNamespace().lastIndexOf("/") + 1)).append(":").append(et.getName()).append(";");
+ if (et instanceof XSSimpleType) {
+ XSSimpleType simpleType = (XSSimpleType) et;
+ if (simpleType.getVariety() == XSSimpleTypeDefinition.VARIETY_LIST
+ || simpleType.getVariety() == XSSimpleTypeDefinition.VARIETY_UNION) {
+ XSObjectList list = simpleType.getMemberTypes();
+ if (list.getLength() > 0) {
+ typesHierarchy.append("{");
+ for (int i = 0; i < list.getLength(); i++) {
+ typesHierarchy.append(getSimpleTypesString((XSTypeDefinition) list.item(i)));
+ }
+ typesHierarchy.append("}");
+ }
+ }
+ }
+ et = et.getBaseType();
+ }
+ return typesHierarchy.toString();
+ }
+
+ private TypeDesc processGroup(XSModelGroup modelGroup, List<XSModel> models, Map<String, TypeDesc> jtMap, Map<String, NamespaceDesc> nsdMap) {
+ XSModelGroupDefinition def = null;
+ for (XSModel xsModel : models) {
+ XSNamedMap map = xsModel.getComponents(XSConstants.MODEL_GROUP_DEFINITION);
+ for (int i = 0; i < map.getLength(); i++) {
+ XSModelGroupDefinition mg = (XSModelGroupDefinition) map.item(i);
+ final XSModelGroup xsModelGroup = mg.getModelGroup();
+ if (xsModelGroup == modelGroup || xsModelGroup.toString().equals(modelGroup.toString())) {
+ def = mg;
+ break;
+ }
+ }
+ }
+ if (def == null) return null;
+ if (!nsdMap.containsKey(def.getNamespace())) {
+ Util.log("Namespace desc not found for: " + def);
+ }
+ String typeName = toJavaTypeName(def, nsdMap);
+ final String typeQName = model.toJavaQualifiedTypeName(def, nsdMap, false);
+ TypeDesc td = jtMap.get(typeQName);
+ if (td != null) {
+ if (td.type == TypeDesc.TypeEnum.GROUP_INTERFACE) {
+ return td;
+ } else {
+ Util.logerr("type-group conflict: " + typeName);
+ return null;
+ }
+ } else {
+ td = new TypeDesc(def.getName(), def.getNamespace(), typeName, TypeDesc.TypeEnum.GROUP_INTERFACE);
+ }
+
+ XSAnnotation ann = def.getAnnotation();
+ td.documentation = parseAnnotationString("Type " + def.getNamespace() + ":" + def.getName() + " documentation",
+ ann == null ? null : ann.getAnnotationString());
+ td.type = TypeDesc.TypeEnum.GROUP_INTERFACE;
+ LinkedList<PEntry> plist = new LinkedList<PEntry>();
+ for (int i = 0; i < def.getModelGroup().getParticles().getLength(); i++) {
+ XSParticle p = (XSParticle) def.getModelGroup().getParticles().item(i);
+ plist.add(new PEntry(p, false));
+ }
+ processParticles(def, plist, nsdMap, jtMap, td, models, null, null);
+ jtMap.put(typeQName, td);
+ return td;
+ }
+
+ private void processParticles(XSObject def, LinkedList<PEntry> plist, Map<String, NamespaceDesc> nsdMap, Map<String, TypeDesc> jtMap, TypeDesc td, List<XSModel> models, ArrayList<XSComplexTypeDefinition> toAdd, TypeDesc baseClass) {
+ final boolean globalMerge = jtMap.containsKey(model.toJavaQualifiedTypeName(def, nsdMap, td.type == TypeDesc.TypeEnum.ENUM));
+ final HashMap<XSParticle, String> globalChoice = new HashMap<XSParticle, String>();
+ final ArrayList<XSObjectList> choiceList = new ArrayList<XSObjectList>();
+ final ArrayList<TypeDesc> supers = new ArrayList<TypeDesc>();
+ if (baseClass != null) {
+ supers.add(baseClass);
+ }
+ while (!plist.isEmpty()) {
+ final PEntry pentry = plist.removeFirst();
+ final XSParticle p = pentry.p;
+ if (p.getTerm() instanceof XSElementDecl) {
+ final XSElementDecl el = (XSElementDecl) p.getTerm();
+ if (el.getConstraintType() == XSConstants.VC_FIXED) continue;
+ XSTypeDefinition etRoot = el.getTypeDefinition();
+ XSTypeDefinition et = etRoot;
+ XSAnnotation ann = el.getAnnotation();
+ String documentation = parseAnnotationString("Element " + el.getNamespace() + ":" + el.getName() + " documentation", ann != null ? ann.getAnnotationString() : null);
+ final FieldDesc fd1 = new FieldDesc(FieldDesc.STR, Util.toJavaFieldName(el.getName()), et.getName(), null, "null", !pentry.many && p.getMinOccurs() > 0);
+ fd1.documentation = documentation;
+ fd1.tagName = el.getName();
+ while (et.getBaseType() != null && !"anySimpleType".equals(et.getBaseType().getName()) && !"anyType".equals(et.getBaseType().getName())) {
+ et = et.getBaseType();
+ }
+ if (checkEnumType(etRoot)) {
+ if (etRoot.getAnonymous()) {
+ etRoot = makeTypeFromAnonymous(el);
+ if (toAdd != null) toAdd.add((XSComplexTypeDefinition) etRoot);
+ }
+ fd1.type = toJavaTypeName(etRoot, nsdMap);
+ fd1.clType = FieldDesc.OBJ;
+ fd1.contentQualifiedName = model.toJavaQualifiedTypeName(etRoot, nsdMap, true);
+ // forward decl
+ if (!jtMap.containsKey(fd1.contentQualifiedName)) {
+ // logwarn("forward decl: "+et);
+ TypeDesc ftd = new TypeDesc(etRoot.getName(), etRoot.getNamespace(), fd1.type, TypeDesc.TypeEnum.ENUM);
+ jtMap.put(fd1.contentQualifiedName, ftd);
+ }
+ } else if (checkComplexType(etRoot)) {
+ if (etRoot.getAnonymous()) {
+ etRoot = makeTypeFromAnonymous(el);
+ if (toAdd != null) toAdd.add((XSComplexTypeDefinition) etRoot);
+ }
+ fd1.type = toJavaTypeName(etRoot, nsdMap);
+ fd1.clType = FieldDesc.OBJ;
+ fd1.contentQualifiedName = model.toJavaQualifiedTypeName(etRoot, nsdMap, false);
+ // forward decl
+ if (jtMap.get(fd1.contentQualifiedName) == null) {
+ //logwarn("forward decl: "+etRoot);
+ jtMap.put(fd1.contentQualifiedName, new TypeDesc(etRoot.getName(), etRoot.getNamespace(), fd1.type, TypeDesc.TypeEnum.CLASS));
+ }
+ } else if (checkBooleanType(etRoot)) {
+ fd1.type = "boolean";
+ fd1.clType = FieldDesc.BOOL;
+ } else {
+ if (etRoot instanceof XSComplexTypeDefinition) {
+ final XSComplexTypeDefinition ct = (XSComplexTypeDefinition) etRoot;
+ // XXX xerces2.7.1 wierd annotation inheritance bug fix
+ //ann = (XSAnnotation) (ct.getAnnotations()!=null && ct.getAnnotations().getLength()>0?ct.getAnnotations().item(0):null);
+ ann = (XSAnnotation) (ct.getAnnotations() != null && ct.getAnnotations().getLength() > 0 ? ct.getAnnotations().item(ct.getAnnotations().getLength() - 1) : null);
+ documentation = parseAnnotationString("Type " + ct.getNamespace() + ":" + ct.getName() + " documentation", ann != null ? ann.getAnnotationString() : null);
+ if (documentation != null) {
+ fd1.documentation = fd1.documentation != null ? fd1.documentation + "\n" + documentation : documentation;
+ }
+ }
+ fd1.simpleTypesString = getSimpleTypesString(etRoot);
+
+ // "fully-qualified-classType", "jndi-nameType", "transaction-typeType"
+ // "java-identifierType", "pathType"
+ fd1.type = et.getName();
+ if (fd1.type == null) {
+ fd1.type = "String";
+ fd1.def = "null";
+ fd1.clType = FieldDesc.STR;
+// fd1.type = "boolean";
+// fd1.def = "false";
+// fd1.clType = FieldDesc.BOOL;
+ } else if (fd1.type.equals("string") || fd1.type.equals("anyURI")) {
+ fd1.type = "String";
+ } else if (fd1.type.equals("boolean")) {
+ fd1.type = "String";
+ } else if (fd1.type.equals("emptyType")) {
+ fd1.type = "boolean";
+ fd1.def = "false";
+ fd1.clType = FieldDesc.BOOL;
+ } else if (fd1.type.equals("decimal")) {
+ fd1.type = "String";
+ fd1.def = "\"0.0\"";
+ } else if (fd1.type.equals("QName")) {
+ fd1.type = "String";
+ } else if (fd1.type.equals("extensibleType")) {
+ fd1.type = "Object";
+ } else {
+ if (et.getBaseType() != null &&
+ ("anySimpleType".equals(et.getBaseType().getName())
+ || "anyType".equals(et.getBaseType().getName()))) {
+ fd1.type = "String";
+ fd1.def = "null";
+ fd1.clType = FieldDesc.STR;
+ } else {
+ fd1.type = "boolean";
+ fd1.def = "false";
+ fd1.clType = FieldDesc.BOOL;
+ }
+ Util.logwarn("using '" + fd1.type + "' for unknown base type: " + et.getName() + " for " + el);
+ }
+ }
+ if ((pentry.many || p.getMaxOccursUnbounded() || p.getMaxOccurs() > 1) && fd1.clType != FieldDesc.BOOL) {
+ fd1.elementType = fd1.type;
+ fd1.elementName = fd1.name;
+ fd1.type = "List<" + fd1.elementType + ">";
+ fd1.name = Util.pluralize(fd1.name);
+ fd1.def = "new ArrayList(0)";
+ fd1.clType = -fd1.clType;
+ fd1.comment = "array of " + fd1.elementType;
+ }
+ fd1.realIndex = td.fdMap.size();
+ boolean merge = globalMerge || globalChoice.containsKey(p) && globalChoice.values().contains(fd1.name);
+ td.duplicates = Util.addToNameMap(td.fdMap, fd1, merge) || td.duplicates;
+ globalChoice.put(p, fd1.name);
+ } else if (p.getTerm() instanceof XSModelGroup) {
+ boolean addToGlobalChoice = false;
+ boolean many = p.getMaxOccursUnbounded() || p.getMaxOccurs() > 1;
+ XSObjectList l = ((XSModelGroup) p.getTerm()).getParticles();
+ if (!many) {
+ if (((XSModelGroup) p.getTerm()).getCompositor() == XSModelGroup.COMPOSITOR_CHOICE) {
+ addToGlobalChoice = true;
+ choiceList.add(l);
+ } else {
+ // generate group interface???
+ XSModelGroup groupDef = (XSModelGroup) p.getTerm();
+ TypeDesc gtd = processGroup(groupDef, models, jtMap, nsdMap);
+ if (gtd != null) supers.add(gtd);
+ }
+ }
+ if (globalChoice.containsKey(p)) {
+ addToGlobalChoice = true;
+ }
+ for (int i = 0; i < l.getLength(); i++) {
+ final PEntry o = new PEntry((XSParticle) l.item(i), many);
+ plist.add(o);
+ if (addToGlobalChoice && !globalChoice.containsKey(o.p)) {
+ globalChoice.put(o.p, null);
+ }
+ }
+ }
+ }
+ int i = 0;
+ for (Iterator<FieldDesc> it = td.fdMap.values().iterator(); it.hasNext(); i++) {
+ FieldDesc fd = it.next();
+ fd.idx = i;
+ }
+ for (XSObjectList l : choiceList) {
+ final ArrayList<XSParticle> clist = new ArrayList<XSParticle>();
+ final LinkedList<XSParticle> elist = new LinkedList<XSParticle>();
+ for (i = 0; i < l.getLength(); i++) {
+ elist.add((XSParticle) l.item(i));
+ }
+ while (!elist.isEmpty()) {
+ final XSParticle p = elist.removeFirst();
+ if (p.getTerm() instanceof XSModelGroup) {
+ XSObjectList l2 = ((XSModelGroup) p.getTerm()).getParticles();
+ for (int i2 = 0; i2 < l2.getLength(); i2++) {
+ elist.addFirst((XSParticle) l2.item(i2));
+ }
+ } else if (p.getTerm() instanceof XSElementDecl) {
+ clist.add(p);
+ }
+ }
+ boolean choiceOpt = true;
+ FieldDesc[] choice = new FieldDesc[clist.size()];
+ for (i = 0; i < choice.length; i++) {
+ XSParticle p = clist.get(i);
+ XSElementDecl el = (XSElementDecl) p.getTerm();
+ String s = Util.toJavaFieldName(el.getName());
+ if (p.getMaxOccursUnbounded() || p.getMaxOccurs() > 1) {
+ s = Util.pluralize(s);
+ }
+ FieldDesc fd = td.fdMap.get(s);
+ if (fd == null) {
+ fd = td.fdMap.get(Util.pluralize(s));
+ if (fd == null) {
+ Util.logerr("uknown choice element: " + s);
+ }
+ }
+
+ if (fd != null) {
+ choice[i] = fd;
+ choice[i].choice = choice;
+ if (fd.required) choiceOpt = false;
+ }
+ }
+ for (i = 0; i < choice.length; i++) {
+ if (choice[i] != null) {
+ choice[i].choiceOpt = choiceOpt;
+ }
+ }
+ }
+ td.supers = supers.toArray(new TypeDesc[supers.size()]);
+ }
+ public static String parseAnnotationString(String title, String str) {
+ if (str == null) return null;
+ int idx = str.indexOf(":documentation");
+ if (idx == -1) idx = str.indexOf("<documentation");
+ if (idx == -1) return null;
+ idx = str.indexOf(">", idx + 1);
+ if (idx == -1) return null;
+ int idx2 = str.indexOf(":documentation", idx + 1);
+ if (idx2 == -1) idx2 = str.indexOf("</documentation", idx + 1);
+ idx2 = str.lastIndexOf("<", idx2 + 1);
+ str = str.substring(idx + 1, idx2).trim();
+
+ idx = str.indexOf("<![CDATA[");
+ if (idx > -1) {
+ idx = str.indexOf("[", idx + 3);
+ idx2 = str.indexOf("]]>", idx + 1);
+ str = str.substring(idx + 1, idx2);
+ }
+ return "<pre>\n<h3>" + title + "</h3>\n" + str + "\n</pre>";
+ }
+
+ public String toJavaTypeName(XSObject xs, Map<String, NamespaceDesc> nsdMap) {
+ String name = xs.getName();
+ if (name == null) {
+ if (xs instanceof TypeInfo) {
+ name = ((TypeInfo) xs).getTypeName();
+ if (name != null && name.startsWith("#")) {
+ name = name.substring(1);
+ }
+ }
+ }
+ return model.toJavaTypeName(name, xs.getNamespace());
+ }
+
+ public static class PEntry {
+ public PEntry(XSParticle p, boolean many) {
+ this.p = p;
+ this.many = many;
+ }
+
+ XSParticle p;
+ boolean many;
+ }
+
+}
diff --git a/plugins/devkit/src/dom/impl/InspectionsPropertiesReferenceProviderContributor.java b/plugins/devkit/src/dom/impl/InspectionsPropertiesReferenceProviderContributor.java
index 662e78840841..de5ab53b5dab 100644
--- a/plugins/devkit/src/dom/impl/InspectionsPropertiesReferenceProviderContributor.java
+++ b/plugins/devkit/src/dom/impl/InspectionsPropertiesReferenceProviderContributor.java
@@ -30,8 +30,8 @@ public class InspectionsPropertiesReferenceProviderContributor extends PsiRefere
@Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
ElementPattern pattern = XmlPatterns.xmlAttributeValue()
- .withParent(XmlPatterns.xmlAttribute().withLocalName(string().oneOf("key", "groupKey"))
- .withParent(XmlPatterns.xmlTag().withName(string().oneOf("localInspection", "globalInspection"))
+ .withParent(XmlPatterns.xmlAttribute().withLocalName("key", "groupKey")
+ .withParent(XmlPatterns.xmlTag().withName("localInspection", "globalInspection")
.withSuperParent(2, XmlPatterns.xmlTag().withName("idea-plugin"))));
registrar.registerReferenceProvider(pattern, new InspectionsKeyPropertiesReferenceProvider(false),
PsiReferenceRegistrar.DEFAULT_PRIORITY);
diff --git a/plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java b/plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java
index cf629df6796f..2c1aec6f72c7 100644
--- a/plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java
+++ b/plugins/devkit/src/inspections/quickfix/RegisterInspectionFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.InspectionEP;
import com.intellij.ide.TypePresentationService;
-import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
@@ -32,7 +31,6 @@ import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
-import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
@@ -125,6 +123,12 @@ class RegisterInspectionFix implements IntentionAction {
final BaseListPopupStep<DomFileElement<IdeaPlugin>> popupStep =
new BaseListPopupStep<DomFileElement<IdeaPlugin>>("Choose Plugin Descriptor", elements) {
+
+ @Override
+ public boolean isSpeedSearchEnabled() {
+ return true;
+ }
+
@Override
public Icon getIconFor(DomFileElement<IdeaPlugin> aValue) {
return TypePresentationService.getService().getIcon(aValue);
@@ -134,11 +138,8 @@ class RegisterInspectionFix implements IntentionAction {
@Override
public String getTextFor(DomFileElement<IdeaPlugin> value) {
final String name = value.getFile().getName();
- if (!Comparing.equal(PluginManager.PLUGIN_XML, name)) {
- return name;
- }
final Module module = value.getModule();
- return module != null ? name + " (" + module.getName() + ")" : name;
+ return module != null ? name + " [" + module.getName() + "]" : name;
}
@Override
diff --git a/plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java b/plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java
index 22dce5bfe9f9..6b1f53e8bc99 100644
--- a/plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java
+++ b/plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java
@@ -68,6 +68,8 @@ public abstract class AbstractEclipseClasspathReader<T> {
String srcUrl, ExpandMacroToPathMap macroMap);
protected abstract String expandEclipsePath2Url(T rootModel, String path);
+ protected abstract Set<String> getDefinedCons();
+
protected abstract int rearrange(T rootModel);
protected void readClasspathEntry(T rootModel,
@@ -197,18 +199,15 @@ public abstract class AbstractEclipseClasspathReader<T> {
else if (path.startsWith(EclipseXml.JUNIT_CONTAINER)) {
final String junitName = IdeaXml.JUNIT + getPresentableName(path);
addJUnitDefaultLib(rootModel, junitName, macroMap);
- }
- else if (path.equals(EclipseXml.GROOVY_DSL_CONTAINER)) {
- eclipseModuleManager.addGroovySupport(EclipseXml.GROOVY_DSL_CONTAINER);
- eclipseModuleManager.registerSrcPlace(EclipseXml.GROOVY_DSL_CONTAINER, idx);
- }
- else if (path.equals(EclipseXml.GROOVY_SUPPORT)) {
- eclipseModuleManager.addGroovySupport(EclipseXml.GROOVY_SUPPORT);
- eclipseModuleManager.registerSrcPlace(EclipseXml.GROOVY_SUPPORT, idx);
- }
- else {
- eclipseModuleManager.registerUnknownCons(path);
- addNamedLibrary(rootModel, new ArrayList<String>(), exported, path, true);
+ } else {
+ final Set<String> registeredCons = getDefinedCons();
+ if (registeredCons.contains(path)) {
+ eclipseModuleManager.registerCon(path);
+ eclipseModuleManager.registerSrcPlace(path, idx);
+ } else {
+ eclipseModuleManager.registerUnknownCons(path);
+ addNamedLibrary(rootModel, new ArrayList<String>(), exported, path, true);
+ }
}
}
else {
diff --git a/plugins/eclipse/common-eclipse-util/src/EclipseModuleManager.java b/plugins/eclipse/common-eclipse-util/src/EclipseModuleManager.java
index 1aa34e21763d..1ef8e7492309 100644
--- a/plugins/eclipse/common-eclipse-util/src/EclipseModuleManager.java
+++ b/plugins/eclipse/common-eclipse-util/src/EclipseModuleManager.java
@@ -30,9 +30,9 @@ public interface EclipseModuleManager {
@Nullable
String getInvalidJdk();
- void addGroovySupport(String name);
+ void registerCon(String name);
- String[] getGroovySupport();
+ String[] getUsedCons();
void registerEclipseVariablePath(String path, String var);
@@ -87,10 +87,10 @@ public interface EclipseModuleManager {
}
@Override
- public void addGroovySupport(String name) {}
+ public void registerCon(String name) {}
@Override
- public String[] getGroovySupport() {
+ public String[] getUsedCons() {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
diff --git a/plugins/eclipse/common-eclipse-util/src/EclipseProjectFinder.java b/plugins/eclipse/common-eclipse-util/src/EclipseProjectFinder.java
index 41041ae54198..a22a4066c38b 100644
--- a/plugins/eclipse/common-eclipse-util/src/EclipseProjectFinder.java
+++ b/plugins/eclipse/common-eclipse-util/src/EclipseProjectFinder.java
@@ -33,7 +33,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.List;
-import java.util.Set;
public class EclipseProjectFinder implements EclipseXml {
public static void findModuleRoots(final List<String> paths, final String rootPath, @Nullable Processor<String> progressUpdater) {
@@ -117,25 +116,6 @@ public class EclipseProjectFinder implements EclipseXml {
return null;
}
- public static void collectUnknownNatures(String path, Set<String> naturesNames) {
- final File projectfile = new File(path, DOT_PROJECT_EXT);
- try {
- final Element natures = JDOMUtil.loadDocument(projectfile).getRootElement().getChild("natures");
- if (natures != null) {
- final List naturesList = natures.getChildren("nature");
- for (Object nature : naturesList) {
- final String natureName = ((Element)nature).getText();
- if (!StringUtil.isEmptyOrSpaces(natureName)) {
- naturesNames.add(natureName);
- }
- }
- }
- }
- catch (Exception ignore) {
- }
- naturesNames.remove("org.eclipse.jdt.core.javanature");
- }
-
public static class LinkedResource {
private String myURI;
private String myLocation;
diff --git a/plugins/eclipse/common-eclipse-util/src/IdeaXml.java b/plugins/eclipse/common-eclipse-util/src/IdeaXml.java
index e10c3cbdf4e5..b32fe838f018 100644
--- a/plugins/eclipse/common-eclipse-util/src/IdeaXml.java
+++ b/plugins/eclipse/common-eclipse-util/src/IdeaXml.java
@@ -28,6 +28,8 @@ public interface IdeaXml {
@NonNls String SOURCE_FOLDER_TAG = "sourceFolder";
@NonNls String CONTENT_ENTRY_TAG = "contentEntry";
@NonNls String TEST_FOLDER_TAG = "testFolder";
+ @NonNls String PACKAGE_PREFIX_TAG = "packagePrefix";
+ @NonNls String PACKAGE_PREFIX_VALUE_ATTR = "value";
@NonNls String EXCLUDE_FOLDER_TAG = "excludeFolder";
@NonNls String FOR_TESTS_ATTR = "forTests";
@NonNls String TRUE_VALUE = "true";
diff --git a/plugins/eclipse/common-eclipse-util/src/conversion/AbstractIdeaSpecificSettings.java b/plugins/eclipse/common-eclipse-util/src/conversion/AbstractIdeaSpecificSettings.java
index eb586af7cb6d..3218f3a4d2ac 100644
--- a/plugins/eclipse/common-eclipse-util/src/conversion/AbstractIdeaSpecificSettings.java
+++ b/plugins/eclipse/common-eclipse-util/src/conversion/AbstractIdeaSpecificSettings.java
@@ -34,7 +34,6 @@ public abstract class AbstractIdeaSpecificSettings<T, C, SdkType> {
readLanguageLevel(root, model);
setupCompilerOutputs(root, model);
-
final List entriesElements = root.getChildren(IdeaXml.CONTENT_ENTRY_TAG);
if (!entriesElements.isEmpty()) {
for (Object o : entriesElements) {
@@ -53,6 +52,28 @@ public abstract class AbstractIdeaSpecificSettings<T, C, SdkType> {
readLibraryLevels(root, levels);
}
+ public void initLevels(final Element root, T model, Map<String, String> levels) throws InvalidDataException {
+ expandElement(root, model);
+ readLanguageLevel(root, model);
+ readLibraryLevels(root, levels);
+ }
+
+ public void updateEntries(Element root, T model, @Nullable SdkType projectSdkType) {
+ setupJdk(root, model, projectSdkType);
+ setupCompilerOutputs(root, model);
+ final List entriesElements = root.getChildren(IdeaXml.CONTENT_ENTRY_TAG);
+ if (!entriesElements.isEmpty()) {
+ for (Object o : entriesElements) {
+ readContentEntry((Element)o, createContentEntry(model, ((Element)o).getAttributeValue(IdeaXml.URL_ATTR)), model);
+ }
+ } else {
+ final C[] entries = getEntries(model);//todo
+ if (entries.length > 0) {
+ readContentEntry(root, entries[0], model);
+ }
+ }
+ }
+
protected abstract void readLibraryLevels(Element root, Map<String, String> levels);
protected abstract C[] getEntries(T model);
diff --git a/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathReader.java b/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathReader.java
index 5adca0bb5ed7..72a7065ba800 100644
--- a/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathReader.java
+++ b/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathReader.java
@@ -200,6 +200,11 @@ class JpsEclipseClasspathReader extends AbstractEclipseClasspathReader<JpsModule
return prepareValidUrlInsideJar(url);
}
+ @Override
+ protected Set<String> getDefinedCons() {
+ return Collections.emptySet();
+ }
+
@Override
protected int rearrange(JpsModule rootModel) {
diff --git a/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathSerializer.java b/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathSerializer.java
index 0da330c5437a..c7124f8ca8ea 100644
--- a/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathSerializer.java
+++ b/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsEclipseClasspathSerializer.java
@@ -48,15 +48,24 @@ public class JpsEclipseClasspathSerializer extends JpsModuleClasspathSerializer
final String eml = module.getName() + EclipseXml.IDEA_SETTINGS_POSTFIX;
final File emlFile = new File(baseModulePath, eml);
final Map<String, String> levels = new HashMap<String, String>();
+ final JpsIdeaSpecificSettings settings;
+ final Element root;
if (emlFile.isFile()) {
final Document emlDocument = JDOMUtil.loadDocument(emlFile);
- final Element root = emlDocument.getRootElement();
- new JpsIdeaSpecificSettings(expander).readIDEASpecific(root, module, projectSdkType, levels);
+ root = emlDocument.getRootElement();
+ settings = new JpsIdeaSpecificSettings(expander);
+ settings.initLevels(root, module, levels);
+ } else {
+ settings = null;
+ root = null;
}
final Document document = JDOMUtil.loadDocument(classpathFile);
final JpsEclipseClasspathReader reader = new JpsEclipseClasspathReader(classpathDir, paths, new HashSet<String>(), levels);
reader.readClasspath(module, null, document.getRootElement(), expander);//todo
+ if (settings != null) {
+ settings.updateEntries(root, module, projectSdkType);
+ }
}
catch (Exception e) {
LOG.info(e);
diff --git a/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsIdeaSpecificSettings.java b/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsIdeaSpecificSettings.java
index 9d722746650e..593ce86b4f0b 100644
--- a/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsIdeaSpecificSettings.java
+++ b/plugins/eclipse/jps-plugin/src/org/jetbrains/jps/eclipse/model/JpsIdeaSpecificSettings.java
@@ -18,11 +18,13 @@ package org.jetbrains.jps.eclipse.model;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ArrayUtil;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.eclipse.IdeaXml;
import org.jetbrains.idea.eclipse.conversion.AbstractIdeaSpecificSettings;
+import org.jetbrains.jps.model.JpsSimpleElement;
import org.jetbrains.jps.model.java.*;
import org.jetbrains.jps.model.library.sdk.JpsSdkType;
import org.jetbrains.jps.model.module.JpsDependenciesList;
@@ -31,6 +33,7 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
import org.jetbrains.jps.model.serialization.JpsMacroExpander;
import org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer;
+import java.io.File;
import java.util.List;
import java.util.Map;
@@ -150,6 +153,25 @@ class JpsIdeaSpecificSettings extends AbstractIdeaSpecificSettings<JpsModule, St
}
model.addSourceRoot(url, JavaSourceRootType.TEST_SOURCE);
}
+
+ for (Object o : root.getChildren(IdeaXml.EXCLUDE_FOLDER_TAG)) {
+ final String excludeUrl = ((Element)o).getAttributeValue(IdeaXml.URL_ATTR);
+ if (FileUtil.isAncestor(new File(contentUrl), new File(excludeUrl), false)) {
+ model.getExcludeRootsList().addUrl(excludeUrl);
+ }
+ }
+
+ for (Object o : root.getChildren(IdeaXml.PACKAGE_PREFIX_TAG)) {
+ Element ppElement = (Element)o;
+ final String prefix = ppElement.getAttributeValue(IdeaXml.PACKAGE_PREFIX_VALUE_ATTR);
+ final String url = ppElement.getAttributeValue(IdeaXml.URL_ATTR);
+ for (JpsModuleSourceRoot sourceRoot : model.getSourceRoots()) {
+ if (Comparing.strEqual(sourceRoot.getUrl(), url)) {
+ ((JpsSimpleElement)sourceRoot.getProperties()).setData(new JavaSourceRootProperties(prefix));
+ break;
+ }
+ }
+ }
}
private static JpsJavaExtensionService getService() {
diff --git a/plugins/eclipse/resources/EclipseBundle.properties b/plugins/eclipse/resources/EclipseBundle.properties
index bbf5b559ef25..658e139041d4 100644
--- a/plugins/eclipse/resources/EclipseBundle.properties
+++ b/plugins/eclipse/resources/EclipseBundle.properties
@@ -45,6 +45,6 @@ eclipse.message.rename.failed=Following modules could not be renamed because of
eclipse.title.unresolved.projects=Unresolved module references
eclipse.message.unresolved.projects=Some modules contain unresolved Eclipse-style project-relative library references:\n\n{0}
eclipse.file.type.descr=Eclipse project files
-eclipse.create.library.title=Locate Eclipse installation
+eclipse.create.library.title=Locate Eclipse Installation
eclipse.create.library.description=<html>Some of the projects you are importing depend on Eclipse platform.<br>\
IntelliJ IDEA will create a global library named {0} containing Eclipse libraries.</html> \ No newline at end of file
diff --git a/plugins/eclipse/resources/META-INF/plugin.xml b/plugins/eclipse/resources/META-INF/plugin.xml
index 18b92dd21ad5..a17e668f79d5 100644
--- a/plugins/eclipse/resources/META-INF/plugin.xml
+++ b/plugins/eclipse/resources/META-INF/plugin.xml
@@ -24,4 +24,7 @@
<add-to-group group-id="ExportImportGroup" anchor="last"/>
</action>
</actions>
+ <extensionPoints>
+ <extensionPoint name="natureImporter" interface="org.jetbrains.idea.eclipse.importWizard.EclipseNatureImporter"/>
+ </extensionPoints>
</idea-plugin> \ No newline at end of file
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java
index 8ac2a9d1c500..0450e375ab64 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java
@@ -63,7 +63,7 @@ public class EclipseModuleManagerImpl implements EclipseModuleManager, Persisten
private Map<String, Integer> mySrcPlace = new LinkedHashMap<String, Integer>();
private String myInvalidJdk;
- private Set<String> myGroovyDslSupport = new LinkedHashSet<String>();
+ private Set<String> myKnownCons = new LinkedHashSet<String>();
public EclipseModuleManagerImpl(Module module) {
myModule = module;
@@ -80,13 +80,13 @@ public class EclipseModuleManagerImpl implements EclipseModuleManager, Persisten
}
@Override
- public void addGroovySupport(String name) {
- myGroovyDslSupport.add(name);
+ public void registerCon(String name) {
+ myKnownCons.add(name);
}
@Override
- public String[] getGroovySupport() {
- return ArrayUtil.toStringArray(myGroovyDslSupport);
+ public String[] getUsedCons() {
+ return ArrayUtil.toStringArray(myKnownCons);
}
public static EclipseModuleManagerImpl getInstance(Module module) {
@@ -260,7 +260,7 @@ public class EclipseModuleManagerImpl implements EclipseModuleManager, Persisten
myEclipseVariablePaths.clear();
myUnknownCons.clear();
mySrcPlace.clear();
- myGroovyDslSupport.clear();
+ myKnownCons.clear();
}
@Override
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java
index b02f00013e76..951d161f9354 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java
@@ -41,6 +41,7 @@ import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.eclipse.*;
import org.jetbrains.idea.eclipse.config.EclipseModuleManagerImpl;
+import org.jetbrains.idea.eclipse.importWizard.EclipseNatureImporter;
import org.jetbrains.idea.eclipse.util.ErrorLog;
import java.io.IOException;
@@ -128,6 +129,11 @@ public class EclipseClasspathReader extends AbstractEclipseClasspathReader<Modif
}
@Override
+ protected Set<String> getDefinedCons() {
+ return EclipseNatureImporter.getAllDefinedCons();
+ }
+
+ @Override
protected void addModuleLibrary(ModifiableRootModel rootModel,
Element element,
boolean exported,
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java
index 4234301c7661..598d74cfb3f0 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java
@@ -80,7 +80,7 @@ public class EclipseClasspathWriter {
outputPath = EPathUtil.collapse2EclipsePath(compilerOutputUrl, myModel);
}
}
- for (String support : eclipseModuleManager.getGroovySupport()) {
+ for (String support : eclipseModuleManager.getUsedCons()) {
final Integer place = eclipseModuleManager.getSrcPlace(support);
addOrderEntry(EclipseXml.CON_KIND, support, classpathElement, place != null ? place.intValue() : -1);
}
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java
index 904e7ee4f97f..fa34a48a548d 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java
@@ -27,7 +27,6 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.*;
@@ -38,6 +37,7 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
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.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -215,21 +215,41 @@ public class IdeaSpecificSettings extends AbstractIdeaSpecificSettings<Modifiabl
@Override
public void readContentEntry(Element root, ContentEntry entry, ModifiableRootModel model) {
+ final SourceFolder[] folders = entry.getSourceFolders();
+ final String[] sourceFoldersUrls = new String[folders.length];
+ for (int i = 0; i < folders.length; i++) {
+ final SourceFolder folder = folders[i];
+ sourceFoldersUrls[i] = folder.getUrl();
+ entry.removeSourceFolder(folder);
+ }
+
+ final boolean[] testFolders = new boolean[sourceFoldersUrls.length];
for (Object o : root.getChildren(IdeaXml.TEST_FOLDER_TAG)) {
final String url = ((Element)o).getAttributeValue(IdeaXml.URL_ATTR);
- SourceFolder folderToBeTest = null;
+ for (int i = 0; i < sourceFoldersUrls.length; i++) {
+ if (Comparing.strEqual(sourceFoldersUrls[i], url)) {
+ testFolders[i] = true;
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < sourceFoldersUrls.length; i++) {
+ entry.addSourceFolder(sourceFoldersUrls[i], testFolders[i]);
+ }
+
+ for (Object o : root.getChildren(IdeaXml.PACKAGE_PREFIX_TAG)) {
+ Element ppElement = (Element)o;
+ final String prefix = ppElement.getAttributeValue(IdeaXml.PACKAGE_PREFIX_VALUE_ATTR);
+ final String url = ppElement.getAttributeValue(IdeaXml.URL_ATTR);
for (SourceFolder folder : entry.getSourceFolders()) {
if (Comparing.strEqual(folder.getUrl(), url)) {
- folderToBeTest = folder;
+ folder.setPackagePrefix(prefix);
break;
}
}
- if (folderToBeTest != null) {
- entry.removeSourceFolder(folderToBeTest);
- }
- entry.addSourceFolder(url, true);
}
-
+
final String url = entry.getUrl();
for (Object o : root.getChildren(IdeaXml.EXCLUDE_FOLDER_TAG)) {
final String excludeUrl = ((Element)o).getAttributeValue(IdeaXml.URL_ATTR);
@@ -278,6 +298,14 @@ public class IdeaSpecificSettings extends AbstractIdeaSpecificSettings<Modifiabl
element.setAttribute(IdeaXml.URL_ATTR, sourceFolder.getUrl());
isModified = true;
}
+ final String packagePrefix = sourceFolder.getPackagePrefix();
+ if (!StringUtil.isEmptyOrSpaces(packagePrefix)) {
+ Element element = new Element(IdeaXml.PACKAGE_PREFIX_TAG);
+ contentEntryElement.addContent(element);
+ element.setAttribute(IdeaXml.URL_ATTR, sourceFolder.getUrl());
+ element.setAttribute(IdeaXml.PACKAGE_PREFIX_VALUE_ATTR, packagePrefix);
+ isModified = true;
+ }
}
final VirtualFile entryFile = entry.getFile();
@@ -315,8 +343,7 @@ public class IdeaSpecificSettings extends AbstractIdeaSpecificSettings<Modifiabl
}
if (entry instanceof JdkOrderEntry) {
final Sdk jdk = ((JdkOrderEntry)entry).getJdk();
- if (EclipseModuleManagerImpl.getInstance(entry.getOwnerModule()).getInvalidJdk() != null ||
- (jdk != null && !(jdk.getSdkType() instanceof JavaSdk))) {
+ if (EclipseModuleManagerImpl.getInstance(entry.getOwnerModule()).getInvalidJdk() != null || jdk != null) {
if (entry instanceof InheritedJdkOrderEntry) {
root.setAttribute(INHERIT_JDK, "true");
} else {
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java
index c25a9429e8f3..fdbea3cafb7b 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java
@@ -41,6 +41,7 @@ import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
+import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
@@ -54,6 +55,7 @@ import com.intellij.packaging.artifacts.ModifiableArtifactModel;
import com.intellij.projectImport.ProjectImportBuilder;
import com.intellij.util.Function;
import com.intellij.util.Processor;
+import com.intellij.util.containers.HashMap;
import gnu.trove.THashSet;
import icons.EclipseIcons;
import org.jdom.Element;
@@ -171,17 +173,20 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
public boolean validate(final Project currentProject, final Project dstProject) {
final Ref<Exception> refEx = new Ref<Exception>();
final HashSet<String> variables = new HashSet<String>();
- final Set<String> naturesNames = new HashSet<String>();
+ final Map<String, String> naturesNames = new HashMap<String, String>();
+ final List<String> projectsToConvert = getParameters().projectsToConvert;
+ final boolean oneProjectToConvert = projectsToConvert.size() == 1;
+ final String separator = oneProjectToConvert ? "<br>" : ", ";
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
public void run() {
try {
- for (String path : getParameters().projectsToConvert) {
+ for (String path : projectsToConvert) {
final File classpathfile = new File(path, EclipseXml.DOT_CLASSPATH_EXT);
if (classpathfile.exists()) {
final Element classpathElement = JDOMUtil.loadDocument(classpathfile).getRootElement();
EclipseClasspathReader.collectVariables(variables, classpathElement, path);
}
- EclipseProjectFinder.collectUnknownNatures(path, naturesNames);
+ collectUnknownNatures(path, naturesNames, separator);
}
}
catch (IOException e) {
@@ -206,7 +211,19 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
public void run() {
if (!naturesNames.isEmpty()) {
final String title = "Unknown Natures Detected";
- Notifications.Bus.notify(new Notification(title, title, "Imported projects contain unknown natures:<br>" + StringUtil.join(naturesNames, "<br>")+ "<br>" +
+ final String naturesByProject;
+ if (oneProjectToConvert) {
+ naturesByProject = naturesNames.values().iterator().next();
+ }
+ else {
+ naturesByProject = StringUtil.join(naturesNames.keySet(), new Function<String, String>() {
+ @Override
+ public String fun(String projectPath) {
+ return projectPath + "(" + naturesNames.get(projectPath) + ")";
+ }
+ }, "<br>");
+ }
+ Notifications.Bus.notify(new Notification(title, title, "Imported projects contain unknown natures:<br>" + naturesByProject + "<br>" +
"Some settings may be lost after import.", NotificationType.WARNING));
}
}
@@ -224,6 +241,7 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
final Collection<String> unknownJdks = new TreeSet<String>();
final Set<String> refsToModules = new HashSet<String>();
final List<Module> result = new ArrayList<Module>();
+ final Map<Module, Set<String>> module2NatureNames = new HashMap<Module, Set<String>>();
try {
final ModifiableModuleModel moduleModel = model != null ? model : ModuleManager.getInstance(project).getModifiableModel();
@@ -296,6 +314,11 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
final Module module = moduleModel.newModule(modulesDirectory + "/" + EclipseProjectFinder.findProjectName(path) + IdeaXml.IML_EXT,
StdModuleTypes.JAVA.getId());
result.add(module);
+ final Set<String> natures = collectNatures(path);
+
+ if (natures.size() > 0) {
+ module2NatureNames.put(module, natures);
+ }
final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel();
rootModels[idx++] = rootModel;
@@ -330,7 +353,7 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
catch (Exception e) {
LOG.error(e);
}
-
+ scheduleNaturesImporting(project, module2NatureNames);
createEclipseLibrary(project, unknownLibraries, IdeaXml.ECLIPSE_LIBRARY);
StringBuffer message = new StringBuffer();
@@ -400,6 +423,40 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
return result;
}
+ private static void scheduleNaturesImporting(@NotNull final Project project,
+ @NotNull final Map<Module, Set<String>> module2NatureNames) {
+ if (module2NatureNames.size() == 0) {
+ return;
+ }
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() {
+ @Override
+ public void run() {
+ for (EclipseNatureImporter importer : EclipseNatureImporter.EP_NAME.getExtensions()) {
+ final String importerNatureName = importer.getNatureName();
+ final List<Module> modulesToImport = new ArrayList<Module>();
+
+ for (Map.Entry<Module, Set<String>> entry : module2NatureNames.entrySet()) {
+ final Module module = entry.getKey();
+ final Set<String> natureNames = entry.getValue();
+
+ if (natureNames.contains(importerNatureName)) {
+ modulesToImport.add(module);
+ }
+ }
+
+ if (modulesToImport.size() > 0) {
+ importer.doImport(project, modulesToImport);
+ }
+ }
+ }
+ });
+ }
+ });
+ }
+
private static void createEclipseLibrary(final Project project, final Collection<String> libraries, final String libraryName) {
if (libraries.contains(libraryName)) {
final FileChooserDescriptor fileChooserDescriptor = new FileChooserDescriptor(false, true, false, false, false, false) {
@@ -452,4 +509,38 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
}
return parameters;
}
+
+ public static void collectUnknownNatures(String path, Map<String, String> naturesNames, String separator) {
+ final Set<String> natures = collectNatures(path);
+ natures.remove("org.eclipse.jdt.core.javanature");
+
+ for (EclipseNatureImporter importer : EclipseNatureImporter.EP_NAME.getExtensions()) {
+ natures.remove(importer.getNatureName());
+ }
+
+ if (!natures.isEmpty()) {
+ naturesNames.put(path, StringUtil.join(natures, separator));
+ }
+ }
+
+ @NotNull
+ public static Set<String> collectNatures(@NotNull String path) {
+ final Set<String> naturesNames = new HashSet<String>();
+ final File projectfile = new File(path, EclipseXml.DOT_PROJECT_EXT);
+ try {
+ final Element natures = JDOMUtil.loadDocument(projectfile).getRootElement().getChild("natures");
+ if (natures != null) {
+ final List naturesList = natures.getChildren("nature");
+ for (Object nature : naturesList) {
+ final String natureName = ((Element)nature).getText();
+ if (!StringUtil.isEmptyOrSpaces(natureName)) {
+ naturesNames.add(natureName);
+ }
+ }
+ }
+ }
+ catch (Exception ignore) {
+ }
+ return naturesNames;
+ }
}
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseNatureImporter.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseNatureImporter.java
new file mode 100644
index 000000000000..d496d24145b4
--- /dev/null
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseNatureImporter.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.jetbrains.idea.eclipse.importWizard;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.eclipse.EclipseXml;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public abstract class EclipseNatureImporter {
+ public static final ExtensionPointName<EclipseNatureImporter> EP_NAME =
+ ExtensionPointName.create("org.jetbrains.idea.eclipse.natureImporter");
+
+ @NotNull
+ public abstract String getNatureName();
+ public abstract Set<String> getProvidedCons();
+
+ public abstract void doImport(@NotNull Project project, @NotNull List<Module> modules);
+
+ public static Set<String> getAllDefinedCons() {
+ final Set<String> allCons = new HashSet<String>();
+ allCons.add(EclipseXml.GROOVY_SUPPORT);
+ allCons.add(EclipseXml.GROOVY_DSL_CONTAINER);
+
+ for (EclipseNatureImporter provider : Extensions.getExtensions(EP_NAME)) {
+ allCons.addAll(provider.getProvidedCons());
+ }
+ return allCons;
+ }
+}
diff --git a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspection.java b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspection.java
index 95a165676c0f..3d6b64182590 100644
--- a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspection.java
+++ b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspection.java
@@ -33,12 +33,10 @@ import javax.swing.text.Document;
import java.awt.*;
/**
- * Intention to check if the current class overrides the toString() method.
+ * Inspection to check if the current class overrides the toString() method.
* <p/>
- * This inspection will use filter information from the settings to exclude certain fields (eg. constants etc.).
- * <p/>
- * This inspection will only perform inspection if the class have fields to be dumped but
- * does not have a toString method.
+ * This inspection will use filter information from the GenerateToString plugin settings to exclude certain fields (eg. constants etc.).
+ * Warns if the class has fields to be dumped and does not have a toString method.
*/
public class ClassHasNoToStringMethodInspection extends AbstractToStringInspection {
@@ -55,6 +53,8 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
public boolean excludeTestCode = false;
+ public boolean excludeInnerClasses = false;
+
@NotNull
public String getDisplayName() {
return "Class does not override 'toString()' method";
@@ -74,35 +74,27 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
if (log.isDebugEnabled()) log.debug("checkClass: clazz=" + clazz);
// must be a class
- PsiIdentifier nameIdentifier = clazz.getNameIdentifier();
- if (nameIdentifier == null || clazz.getName() == null)
- return;
+ final PsiIdentifier nameIdentifier = clazz.getNameIdentifier();
+ if (nameIdentifier == null || clazz.getName() == null) {
+ return;
+ }
- // must not be an exception
if (excludeException && InheritanceUtil.isInheritor(clazz, CommonClassNames.JAVA_LANG_THROWABLE)) {
- log.debug("This class is an exception");
return;
}
-
- // must not be deprecated
if (excludeDeprecated && clazz.isDeprecated()) {
- log.debug("Class is deprecated");
return;
}
-
- // must not be enum
if (excludeEnum && clazz.isEnum()) {
- log.debug("Class is an enum");
return;
}
-
if (excludeAbstract && clazz.hasModifierProperty(PsiModifier.ABSTRACT)) {
- log.debug("Class is abstract");
return;
}
-
if (excludeTestCode && TestFrameworks.getInstance().isTestClass(clazz)) {
- log.debug("Class is test class");
+ return;
+ }
+ if (excludeInnerClasses && clazz.getContainingClass() != null) {
return;
}
@@ -110,7 +102,6 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
if (StringUtil.isNotEmpty(excludeClassNames)) {
String name = clazz.getName();
if (name != null && name.matches(excludeClassNames)) {
- log.debug("This class is excluded");
return;
}
}
@@ -118,7 +109,6 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
// must have fields
PsiField[] fields = clazz.getFields();
if (fields.length == 0) {
- log.debug("Class does not have any fields");
return;
}
@@ -155,8 +145,6 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
return;
}
}
- if (log.isDebugEnabled()) log.debug("Class does not override toString() method: " + clazz.getQualifiedName());
-
holder.registerProblem(nameIdentifier, "Class '" + clazz.getName() + "' does not override 'toString()' method",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, GenerateToStringQuickFix.getInstance());
}
@@ -227,9 +215,13 @@ public class ClassHasNoToStringMethodInspection extends AbstractToStringInspecti
final CheckBox excludeInTestCodeCheckBox = new CheckBox("Ignore test classes", this, "excludeTestCode");
constraints.gridy = 5;
- constraints.weighty = 1.0;
panel.add(excludeInTestCodeCheckBox, constraints);
+ final CheckBox excludeInnerClasses = new CheckBox("Ignore inner classes", this, "excludeInnerClasses");
+ constraints.gridy = 6;
+ constraints.weighty = 1.0;
+ panel.add(excludeInnerClasses, constraints);
+
return panel;
}
}
diff --git a/plugins/generate-tostring/testSrc/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspectionTest.java b/plugins/generate-tostring/testSrc/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspectionTest.java
new file mode 100644
index 000000000000..32f131c16645
--- /dev/null
+++ b/plugins/generate-tostring/testSrc/org/jetbrains/generate/tostring/inspection/ClassHasNoToStringMethodInspectionTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.jetbrains.generate.tostring.inspection;
+
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ClassHasNoToStringMethodInspectionTest extends LightCodeInsightFixtureTestCase {
+
+ public void testBasic() {
+ doTest("class <warning descr=\"Class 'X' does not override 'toString()' method\">X</warning> {" +
+ " private int i = 0;" +
+ "}");
+ }
+
+ public void testDoNotWarnOnInnerClass() {
+ doTest("class X {" +
+ " class Inner {" +
+ " private int i = 0;" +
+ " }" +
+ "}");
+ }
+
+ private void doTest(@NonNls String text) {
+ myFixture.configureByText("X.java", text);
+ final ClassHasNoToStringMethodInspection inspection = new ClassHasNoToStringMethodInspection();
+ inspection.excludeInnerClasses = true;
+ myFixture.enableInspections(inspection);
+ myFixture.testHighlighting(true, false, false);
+ }
+}
diff --git a/plugins/git4idea/git4idea.iml b/plugins/git4idea/git4idea.iml
index b6b41c387096..56997779b16d 100644
--- a/plugins/git4idea/git4idea.iml
+++ b/plugins/git4idea/git4idea.iml
@@ -67,6 +67,7 @@
<orderEntry type="library" scope="TEST" name="cucumber-java" level="project" />
<orderEntry type="library" name="JSch" level="project" />
<orderEntry type="module" module-name="spellchecker" />
+ <orderEntry type="module" module-name="cucumber-test-runner" scope="RUNTIME" />
</component>
</module>
diff --git a/plugins/git4idea/resources/icons/ball0.png b/plugins/git4idea/resources/icons/ball0.png
index 772f9027d528..89798324f73e 100644
--- a/plugins/git4idea/resources/icons/ball0.png
+++ b/plugins/git4idea/resources/icons/ball0.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball0@2x.png b/plugins/git4idea/resources/icons/ball0@2x.png
new file mode 100644
index 000000000000..4e1b24e75e1a
--- /dev/null
+++ b/plugins/git4idea/resources/icons/ball0@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball1.png b/plugins/git4idea/resources/icons/ball1.png
index c1c0caaadc9f..527eb6ba3dd8 100644
--- a/plugins/git4idea/resources/icons/ball1.png
+++ b/plugins/git4idea/resources/icons/ball1.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball1@2x.png b/plugins/git4idea/resources/icons/ball1@2x.png
new file mode 100644
index 000000000000..273b8e09eff0
--- /dev/null
+++ b/plugins/git4idea/resources/icons/ball1@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball2.png b/plugins/git4idea/resources/icons/ball2.png
index 854c25f8bed1..d85d11a3ef34 100644
--- a/plugins/git4idea/resources/icons/ball2.png
+++ b/plugins/git4idea/resources/icons/ball2.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball2@2x.png b/plugins/git4idea/resources/icons/ball2@2x.png
new file mode 100644
index 000000000000..02665bed9bf0
--- /dev/null
+++ b/plugins/git4idea/resources/icons/ball2@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball3.png b/plugins/git4idea/resources/icons/ball3.png
index 97fed8f2c830..881358c85570 100644
--- a/plugins/git4idea/resources/icons/ball3.png
+++ b/plugins/git4idea/resources/icons/ball3.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball3@2x.png b/plugins/git4idea/resources/icons/ball3@2x.png
new file mode 100644
index 000000000000..20f50be2b5ec
--- /dev/null
+++ b/plugins/git4idea/resources/icons/ball3@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball4.png b/plugins/git4idea/resources/icons/ball4.png
index 19985f8409a3..701325bacc64 100644
--- a/plugins/git4idea/resources/icons/ball4.png
+++ b/plugins/git4idea/resources/icons/ball4.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball4@2x.png b/plugins/git4idea/resources/icons/ball4@2x.png
new file mode 100644
index 000000000000..696c76b694e9
--- /dev/null
+++ b/plugins/git4idea/resources/icons/ball4@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball5.png b/plugins/git4idea/resources/icons/ball5.png
index 0a2e8cdc43a2..70e86dd96323 100644
--- a/plugins/git4idea/resources/icons/ball5.png
+++ b/plugins/git4idea/resources/icons/ball5.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball5@2x.png b/plugins/git4idea/resources/icons/ball5@2x.png
new file mode 100644
index 000000000000..aac42c9539be
--- /dev/null
+++ b/plugins/git4idea/resources/icons/ball5@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball6.png b/plugins/git4idea/resources/icons/ball6.png
index 67941152e27a..1620c319a2c3 100644
--- a/plugins/git4idea/resources/icons/ball6.png
+++ b/plugins/git4idea/resources/icons/ball6.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball6@2x.png b/plugins/git4idea/resources/icons/ball6@2x.png
new file mode 100644
index 000000000000..264e19c8ed8f
--- /dev/null
+++ b/plugins/git4idea/resources/icons/ball6@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball7.png b/plugins/git4idea/resources/icons/ball7.png
index a6bd0559ea7d..146f810b907a 100644
--- a/plugins/git4idea/resources/icons/ball7.png
+++ b/plugins/git4idea/resources/icons/ball7.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/ball7@2x.png b/plugins/git4idea/resources/icons/ball7@2x.png
new file mode 100644
index 000000000000..cc46886da7ed
--- /dev/null
+++ b/plugins/git4idea/resources/icons/ball7@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/branch.png b/plugins/git4idea/resources/icons/branch.png
index 2e68e7e8414c..5f43b16a18ec 100644
--- a/plugins/git4idea/resources/icons/branch.png
+++ b/plugins/git4idea/resources/icons/branch.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/branch@2x.png b/plugins/git4idea/resources/icons/branch@2x.png
new file mode 100644
index 000000000000..c54fd6022d29
--- /dev/null
+++ b/plugins/git4idea/resources/icons/branch@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/branch@2x_dark.png b/plugins/git4idea/resources/icons/branch@2x_dark.png
new file mode 100644
index 000000000000..239be788d8cb
--- /dev/null
+++ b/plugins/git4idea/resources/icons/branch@2x_dark.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/branch_dark.png b/plugins/git4idea/resources/icons/branch_dark.png
index 5a2a44c6354f..ac2a7d15cdea 100644
--- a/plugins/git4idea/resources/icons/branch_dark.png
+++ b/plugins/git4idea/resources/icons/branch_dark.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/cherryPick.png b/plugins/git4idea/resources/icons/cherryPick.png
index 358d4919c147..7d1976c27e4d 100644
--- a/plugins/git4idea/resources/icons/cherryPick.png
+++ b/plugins/git4idea/resources/icons/cherryPick.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/cherryPick@2x.png b/plugins/git4idea/resources/icons/cherryPick@2x.png
new file mode 100644
index 000000000000..4519fa99bed8
--- /dev/null
+++ b/plugins/git4idea/resources/icons/cherryPick@2x.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/cherryPick@2x_dark.png b/plugins/git4idea/resources/icons/cherryPick@2x_dark.png
new file mode 100644
index 000000000000..56f574c19c33
--- /dev/null
+++ b/plugins/git4idea/resources/icons/cherryPick@2x_dark.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/cherryPick_dark.png b/plugins/git4idea/resources/icons/cherryPick_dark.png
index 7578c23c4a96..733ddd6d27c4 100644
--- a/plugins/git4idea/resources/icons/cherryPick_dark.png
+++ b/plugins/git4idea/resources/icons/cherryPick_dark.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/greyball.png b/plugins/git4idea/resources/icons/greyball.png
index 2374a54605d0..0131c2d72490 100644
--- a/plugins/git4idea/resources/icons/greyball.png
+++ b/plugins/git4idea/resources/icons/greyball.png
Binary files differ
diff --git a/plugins/git4idea/resources/icons/greyball@2x.png b/plugins/git4idea/resources/icons/greyball@2x.png
new file mode 100644
index 000000000000..9ae912318431
--- /dev/null
+++ b/plugins/git4idea/resources/icons/greyball@2x.png
Binary files differ
diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/GitExternalApp.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/GitExternalApp.java
new file mode 100644
index 000000000000..6e59bd172063
--- /dev/null
+++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/GitExternalApp.java
@@ -0,0 +1,24 @@
+/*
+ * 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 org.jetbrains.git4idea;
+
+/**
+ * Marker interface for external Java applications which are started by the Git process, when it needs to communicate with user.
+ *
+ * @author Kirill Likhodedov
+ */
+public interface GitExternalApp {
+}
diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassApp.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassApp.java
new file mode 100644
index 000000000000..8c8e425570a2
--- /dev/null
+++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassApp.java
@@ -0,0 +1,116 @@
+/*
+ * 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 org.jetbrains.git4idea.http;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.git4idea.GitExternalApp;
+
+/**
+ * <p>This is a program that would be called by Git when an HTTP connection is needed, that requires authorization,
+ * and if {@code GIT_ASKPASS} variable is set to the script that invokes this program.</p>
+ * <p>The program is called separately for each authorization aspect.
+ * I. e. if no username is specified, then it is started and queried for the username, and then started once again for the password.</p>
+ * <p>Since Git 1.7.9 the query format is the following:
+ * <ul>
+ * <li><code>Username for 'https://bitbucket.org':</code></li>
+ * <li><code>Password for 'https://bitbucket.org':</code></li>
+ * <li><code>Password for 'https://username@bitbucket.org':</code></li>
+ * </ul>
+ * </p>
+ * <p>Before Git 1.7.9 the query didn't contain the URL:
+ * <ul>
+ * <li><code>Username: </code></li>
+ * <li><code>Password: </code></li>
+ * </ul>
+ * </p>
+ * <p>Git expects the reply from the program's standard output.</p>
+ *
+ * @author Kirill Likhodedov
+ */
+public class GitAskPassApp implements GitExternalApp {
+
+ // STDOUT is used to provide credentials to Git process; STDERR is used to print error message to the main IDEA command line.
+ @SuppressWarnings("UseOfSystemOutOrSystemErr")
+ public static void main(String[] args) {
+ try {
+ if (args.length < 1) {
+ throw new IllegalArgumentException("No arguments specified!");
+ }
+
+ Pair<Boolean, String> arguments = parseArguments(args[0]);
+ boolean usernameNeeded = arguments.getFirst();
+ String url = arguments.getSecond();
+
+ int handler = Integer.parseInt(getNotNull(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV));
+ int xmlRpcPort = Integer.parseInt(getNotNull(GitAskPassXmlRpcHandler.GIT_ASK_PASS_PORT_ENV));
+ GitAskPassXmlRpcClient xmlRpcClient = new GitAskPassXmlRpcClient(xmlRpcPort);
+
+ if (usernameNeeded) {
+ String username = xmlRpcClient.askUsername(handler, url);
+ System.out.println(username);
+ }
+ else {
+ String pass = xmlRpcClient.askPassword(handler, url);
+ System.out.println(pass);
+ }
+ }
+ catch (Throwable t) {
+ System.err.println(t.getMessage());
+ t.printStackTrace(System.err);
+ }
+ }
+
+ @NotNull
+ private static String getNotNull(@NotNull String env) {
+ String handlerValue = System.getenv(env);
+ if (handlerValue == null) {
+ throw new IllegalStateException(env + " environment variable is not defined!");
+ }
+ return handlerValue;
+ }
+
+ @NotNull
+ private static Pair<Boolean, String> parseArguments(@NotNull String arg) {
+ boolean username = StringUtilRt.startsWithIgnoreCase(arg, "username");
+ String url;
+ String[] split = arg.split(" ");
+ if (split.length > 2) {
+ url = parseUrl(split[2]);
+ }
+ else {
+ url = ""; // XML RPC doesn't like nulls
+ }
+ return Pair.create(username, url);
+ }
+
+ private static String parseUrl(@NotNull String urlArg) {
+ // un-quote and remove the trailing colon
+ String url = urlArg;
+ if (url.startsWith("'")) {
+ url = url.substring(1);
+ }
+ if (url.endsWith(":")) {
+ url = url.substring(0, url.length() - 1);
+ }
+ if (url.endsWith("'")) {
+ url = url.substring(0, url.length() - 1);
+ }
+ return url;
+ }
+
+}
diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassXmlRpcClient.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassXmlRpcClient.java
new file mode 100644
index 000000000000..5d3f8681f099
--- /dev/null
+++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassXmlRpcClient.java
@@ -0,0 +1,80 @@
+/*
+ * 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 org.jetbrains.git4idea.http;
+
+import org.apache.xmlrpc.XmlRpcClientLite;
+import org.apache.xmlrpc.XmlRpcException;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Vector;
+
+/**
+ * Calls {@link GitAskPassXmlRpcHandler} methods via XML RPC.
+ *
+ * @author Kirill Likhodedov
+ */
+class GitAskPassXmlRpcClient {
+
+ @NotNull private final XmlRpcClientLite myClient;
+
+ GitAskPassXmlRpcClient(int port) throws MalformedURLException {
+ myClient = new XmlRpcClientLite("127.0.0.1", port);
+ }
+
+ // Obsolete collection usage because of the XmlRpcClientLite API
+ @SuppressWarnings({"UseOfObsoleteCollectionType", "unchecked"})
+ String askUsername(int handler, @NotNull String url) {
+ Vector parameters = new Vector();
+ parameters.add(handler);
+ parameters.add(url);
+
+ try {
+ return (String)myClient.execute(methodName("askUsername"), parameters);
+ }
+ catch (XmlRpcException e) {
+ throw new RuntimeException("Invocation failed " + e.getMessage(), e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Invocation failed " + e.getMessage(), e);
+ }
+ }
+
+ // Obsolete collection usage because of the XmlRpcClientLite API
+ @SuppressWarnings({"UseOfObsoleteCollectionType", "unchecked"})
+ String askPassword(int handler, @NotNull String url) {
+ Vector parameters = new Vector();
+ parameters.add(handler);
+ parameters.add(url);
+
+ try {
+ return (String)myClient.execute(methodName("askPassword"), parameters);
+ }
+ catch (XmlRpcException e) {
+ throw new RuntimeException("Invocation failed " + e.getMessage(), e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Invocation failed " + e.getMessage(), e);
+ }
+ }
+
+ @NotNull
+ private static String methodName(@NotNull String method) {
+ return GitAskPassXmlRpcHandler.HANDLER_NAME + "." + method;
+ }
+
+}
diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassXmlRpcHandler.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassXmlRpcHandler.java
new file mode 100644
index 000000000000..36cc365c1d80
--- /dev/null
+++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/http/GitAskPassXmlRpcHandler.java
@@ -0,0 +1,55 @@
+/*
+ * 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 org.jetbrains.git4idea.http;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * This handler is called via XML RPC from {@link GitAskPassApp} when Git requests user credentials.
+ *
+ * @author Kirill Likhodedov
+ */
+public interface GitAskPassXmlRpcHandler {
+
+ String GIT_ASK_PASS_ENV = "GIT_ASKPASS";
+ String GIT_ASK_PASS_HANDLER_ENV = "GIT_ASKPASS_HANDLER";
+ String GIT_ASK_PASS_PORT_ENV = "GIT_ASKPASS_PORT";
+ String HANDLER_NAME = GitAskPassXmlRpcHandler.class.getName();
+
+ /**
+ * Get the username from the user to access the given URL.
+ * @param handler XML RPC handler number.
+ * @param url URL which Git tries to access.
+ * @return The Username which should be used for the URL.
+ */
+ // UnusedDeclaration suppressed: the method is used via XML RPC
+ @SuppressWarnings("UnusedDeclaration")
+ @NotNull
+ String askUsername(int handler, @NotNull String url);
+
+ /**
+ * Get the password from the user to access the given URL.
+ * It is assumed that the username either is specified in the URL (http://username@host.com), or has been asked earlier.
+ * @param handler XML RPC handler number.
+ * @param url URL which Git tries to access.
+ * @return The password which should be used for the URL.
+ */
+ // UnusedDeclaration suppressed: the method is used via XML RPC
+ @SuppressWarnings("UnusedDeclaration")
+ @NotNull
+ String askPassword(int handler, @NotNull String url);
+
+}
diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java
index c5ed99e20966..a388b27fdd5d 100644
--- a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java
+++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java
@@ -124,7 +124,7 @@ public interface GitSSHHandler {
* @param method the authentication method, the empty string means that authentication failed
* @param error the error shown in the case when authentication process failed
*/
- String setLastSuccessful(final int handlerNo, final String userName, final String method, final String error);
+ void setLastSuccessful(final int handlerNo, final String userName, final String method, final String error);
/**
* Get last successful authentication method
diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java
index a000949f1ce6..935b5eaa2f03 100644
--- a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java
+++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java
@@ -182,9 +182,9 @@ public class GitSSHXmlRpcClient implements GitSSHHandler {
*/
@Override
@SuppressWarnings("unchecked")
- public String setLastSuccessful(int handlerNo, String userName, String method, String error) {
+ public void setLastSuccessful(int handlerNo, String userName, String method, String error) {
if (myClient == null) {
- return "";
+ return;
}
Vector parameters = new Vector();
parameters.add(handlerNo);
@@ -192,7 +192,7 @@ public class GitSSHXmlRpcClient implements GitSSHHandler {
parameters.add(method);
parameters.add(error);
try {
- return (String)myClient.execute(methodName("setLastSuccessful"), parameters);
+ myClient.execute(methodName("setLastSuccessful"), parameters);
}
catch (XmlRpcException e) {
throw new RuntimeException("Invocation failed " + e.getMessage(), e);
diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java
index 46c3fdf131bd..29a6b58ead19 100644
--- a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java
+++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java
@@ -21,6 +21,7 @@ import com.trilead.ssh2.*;
import com.trilead.ssh2.crypto.PEMDecoder;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.git4idea.GitExternalApp;
import java.io.*;
import java.util.*;
@@ -34,7 +35,7 @@ import java.util.concurrent.Semaphore;
* The code here is based on SwingShell example.
*/
@SuppressWarnings({"CallToPrintStackTrace", "UseOfSystemOutOrSystemErr"})
-public class SSHMain {
+public class SSHMain implements GitExternalApp {
/**
* the semaphore
*/
diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml
index 2d3afc086997..e093416f9e51 100644
--- a/plugins/git4idea/src/META-INF/plugin.xml
+++ b/plugins/git4idea/src/META-INF/plugin.xml
@@ -19,8 +19,8 @@
</action>
<group id="GitFileActions">
- <action id="Git.Add" class="git4idea.actions.GitAdd" text="Add" icon="AllIcons.General.Add" use-shortcut-of="ChangesView.AddUnversioned" />
<reference ref="CheckinFiles"/>
+ <reference ref="ChangesView.AddUnversioned"/>
<separator/>
<reference ref="Annotate"/>
<reference ref="Show.Current.Revision"/>
@@ -83,7 +83,6 @@
<component>
<interface-class>git4idea.repo.GitRepositoryManager</interface-class>
<implementation-class>git4idea.repo.GitRepositoryManagerImpl</implementation-class>
- <headless-implementation-class>git4idea.repo.GitFakeRepositoryManager</headless-implementation-class>
</component>
</project-components>
@@ -149,8 +148,10 @@
serviceInterface="git4idea.history.wholeTree.GitCommitsSequentially"/>
<applicationService serviceInterface="git4idea.config.GitVcsApplicationSettings"
serviceImplementation="git4idea.config.GitVcsApplicationSettings"/>
- <applicationService serviceInterface="git4idea.commands.GitSSHIdeaService"
- serviceImplementation="git4idea.commands.GitSSHIdeaService"/>
+ <applicationService serviceInterface="org.jetbrains.git4idea.ssh.GitXmlRpcSshService"
+ serviceImplementation="org.jetbrains.git4idea.ssh.GitXmlRpcSshService"/>
+ <applicationService serviceInterface="git4idea.commands.GitHttpAuthService"
+ serviceImplementation="git4idea.commands.GitHttpAuthServiceImpl" />
<applicationService serviceInterface="git4idea.rebase.GitRebaseEditorService"
serviceImplementation="git4idea.rebase.GitRebaseEditorService"/>
<applicationService serviceInterface="git4idea.config.SSHConnectionSettings"
diff --git a/plugins/git4idea/src/git4idea/GitDeprecatedRemote.java b/plugins/git4idea/src/git4idea/GitDeprecatedRemote.java
index d0bbfa8b9e86..22faa3841fbf 100644
--- a/plugins/git4idea/src/git4idea/GitDeprecatedRemote.java
+++ b/plugins/git4idea/src/git4idea/GitDeprecatedRemote.java
@@ -19,7 +19,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
@@ -160,7 +159,6 @@ public final class GitDeprecatedRemote {
*/
public static List<GitDeprecatedRemote> list(Project project, VirtualFile root) throws VcsException {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.REMOTE);
- handler.setNoSSH(true);
handler.setSilent(true);
handler.addParameters("-v");
String output = handler.run();
diff --git a/plugins/git4idea/src/git4idea/GitRevisionNumber.java b/plugins/git4idea/src/git4idea/GitRevisionNumber.java
index fda5e3fa8e13..cd6387a4e629 100644
--- a/plugins/git4idea/src/git4idea/GitRevisionNumber.java
+++ b/plugins/git4idea/src/git4idea/GitRevisionNumber.java
@@ -209,7 +209,6 @@ public class GitRevisionNumber implements ShortVcsRevisionNumber {
*/
public static GitRevisionNumber resolve(Project project, VirtualFile vcsRoot, @NonNls String rev) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, vcsRoot, GitCommand.REV_LIST);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("--timestamp", "--max-count=1", rev);
h.endOptions();
diff --git a/plugins/git4idea/src/git4idea/GitTag.java b/plugins/git4idea/src/git4idea/GitTag.java
index be875f1af791..12ae1d171949 100644
--- a/plugins/git4idea/src/git4idea/GitTag.java
+++ b/plugins/git4idea/src/git4idea/GitTag.java
@@ -65,7 +65,6 @@ public class GitTag extends GitReference {
public static void listAsStrings(final Project project, final VirtualFile root, final Collection<String> tags,
@Nullable final String containingCommit) throws VcsException {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.TAG);
- handler.setNoSSH(true);
handler.setSilent(true);
handler.addParameters("-l");
if (containingCommit != null) {
diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java
index d2bd20b8d4f8..734bae8430a6 100644
--- a/plugins/git4idea/src/git4idea/GitUtil.java
+++ b/plugins/git4idea/src/git4idea/GitUtil.java
@@ -143,7 +143,7 @@ public class GitUtil {
}
pathToDir = FileUtil.toSystemIndependentName(canonicalPath);
}
- return VcsUtil.getVirtualFile(pathToDir);
+ return VcsUtil.getVirtualFileWithRefresh(new File(pathToDir));
}
/**
@@ -522,7 +522,6 @@ public class GitUtil {
final Consumer<GitCommittedChangeList> consumer, boolean skipDiffsForMerge) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
h.setSilent(true);
- h.setNoSSH(true);
h.addParameters("--pretty=format:%x04%x01" + GitChangeUtils.COMMITTED_CHANGELIST_FORMAT, "--name-status");
parametersSpecifier.consume(h);
@@ -937,7 +936,6 @@ public class GitUtil {
if (staged) {
diff.addParameters("--cached");
}
- diff.setNoSSH(true);
diff.setStdoutSuppressed(true);
diff.setStderrSuppressed(true);
diff.setSilent(true);
diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java
index 29707a38cbe1..d848a15c197a 100644
--- a/plugins/git4idea/src/git4idea/GitVcs.java
+++ b/plugins/git4idea/src/git4idea/GitVcs.java
@@ -17,8 +17,8 @@ package git4idea;
import com.intellij.dvcs.DvcsUtil;
import com.intellij.execution.ui.ConsoleViewContentType;
-import com.intellij.notification.NotificationDisplayType;
-import com.intellij.notification.NotificationGroup;
+import com.intellij.ide.BrowserUtil;
+import com.intellij.notification.*;
import com.intellij.notification.impl.NotificationsConfigurationImpl;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.application.ApplicationManager;
@@ -27,6 +27,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.impl.patch.formove.FilePathComparator;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
@@ -84,6 +85,7 @@ import git4idea.vfs.GitVFSListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import javax.swing.event.HyperlinkEvent;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Collections;
@@ -457,11 +459,24 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
try {
myVersion = GitVersion.identifyVersion(executable);
if (! myVersion.isSupported()) {
- String message = GitBundle.message("vcs.unsupported.version", myVersion, GitVersion.MIN);
- if (! myProject.isDefault()) {
- showMessage(message, ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
- }
- VcsBalloonProblemNotifier.showOverVersionControlView(myProject, message, MessageType.ERROR);
+ log.info("Unsupported Git version: " + myVersion);
+ final String SETTINGS_LINK = "settings";
+ final String UPDATE_LINK = "update";
+ String message = String.format("The <a href='" + SETTINGS_LINK + "'>configured</a> version of Git is not supported: %s.<br/> " +
+ "The minimal supported version is %s. Please <a href='" + UPDATE_LINK + "'>update</a>.",
+ myVersion, GitVersion.MIN);
+ IMPORTANT_ERROR_NOTIFICATION.createNotification("Unsupported Git version", message, NotificationType.ERROR,
+ new NotificationListener.Adapter() {
+ @Override
+ protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
+ if (SETTINGS_LINK.equals(e.getDescription())) {
+ ShowSettingsUtil.getInstance().showSettingsDialog(myProject, getConfigurable().getDisplayName());
+ }
+ else if (UPDATE_LINK.equals(e.getDescription())) {
+ BrowserUtil.browse("http://git-scm.com");
+ }
+ }
+ }).notify(myProject);
}
} catch (Exception e) {
if (getExecutableValidator().checkExecutableAndNotifyIfNeeded()) { // check executable before notifying error
diff --git a/plugins/git4idea/src/git4idea/actions/GitAdd.java b/plugins/git4idea/src/git4idea/actions/GitAdd.java
deleted file mode 100644
index 516c131383aa..000000000000
--- a/plugins/git4idea/src/git4idea/actions/GitAdd.java
+++ /dev/null
@@ -1,93 +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.actions;
-
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.openapi.vcs.FileStatusManager;
-import com.intellij.openapi.vcs.ProjectLevelVcsManager;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
-import git4idea.GitUtil;
-import git4idea.GitVcs;
-import git4idea.util.GitFileUtils;
-import git4idea.i18n.GitBundle;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Git "add" action
- */
-public class GitAdd extends BasicAction {
-
- @Override
- public boolean perform(@NotNull final Project project,
- final GitVcs vcs,
- @NotNull final List<VcsException> exceptions,
- @NotNull final VirtualFile[] affectedFiles) {
- saveAll();
- if (!ProjectLevelVcsManager.getInstance(project).checkAllFilesAreUnder(GitVcs.getInstance(project), affectedFiles)) return false;
- return toBackground(project, vcs, affectedFiles, exceptions, new Consumer<ProgressIndicator>() {
- public void consume(ProgressIndicator indicator) {
- try {
- addFiles(project, affectedFiles, indicator);
- }
- catch (VcsException e) {
- exceptions.add(e);
- }
- }
- });
-
- }
-
- /**
- * Add the specified files to the project.
- *
- * @param project The project to add files to
- * @param files The files to add @throws VcsException If an error occurs
- * @param pi progress indicator
- */
- public static void addFiles(@NotNull final Project project, @NotNull final VirtualFile[] files, ProgressIndicator pi)
- throws VcsException {
- final Map<VirtualFile, List<VirtualFile>> roots = GitUtil.sortFilesByGitRoot(Arrays.asList(files));
- for (Map.Entry<VirtualFile, List<VirtualFile>> entry : roots.entrySet()) {
- pi.setText(entry.getKey().getPresentableUrl());
- GitFileUtils.addFiles(project, entry.getKey(), entry.getValue());
- }
- }
-
- @Override
- @NotNull
- protected String getActionName() {
- return GitBundle.getString("add.action.name");
- }
-
- @Override
- protected boolean isEnabled(@NotNull Project project, @NotNull GitVcs vcs, @NotNull VirtualFile... vFiles) {
- for (VirtualFile file : vFiles) {
- FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(file);
- if (file.isDirectory() || (fileStatus != FileStatus.NOT_CHANGED && fileStatus != FileStatus.DELETED && fileStatus != FileStatus.ADDED)) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/plugins/git4idea/src/git4idea/actions/GitPull.java b/plugins/git4idea/src/git4idea/actions/GitPull.java
index a1d071f85a4c..9aaa6c1e874a 100644
--- a/plugins/git4idea/src/git4idea/actions/GitPull.java
+++ b/plugins/git4idea/src/git4idea/actions/GitPull.java
@@ -31,20 +31,16 @@ import git4idea.commands.GitStandardProgressAnalyzer;
import git4idea.commands.GitTask;
import git4idea.commands.GitTaskResultHandlerAdapter;
import git4idea.i18n.GitBundle;
-import git4idea.jgit.GitHttpAdapter;
import git4idea.merge.GitMergeUtil;
import git4idea.merge.GitPullDialog;
import git4idea.repo.GitRemote;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
-import git4idea.update.GitFetcher;
import git4idea.util.GitUIUtil;
import org.jetbrains.annotations.NotNull;
-import java.util.Collections;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
/**
* Git "pull" action
@@ -69,7 +65,6 @@ public class GitPull extends GitRepositoryAction {
}
final Label beforeLabel = LocalHistory.getInstance().putSystemLabel(project, "Before update");
- final AtomicReference<GitLineHandler> handlerReference = new AtomicReference<GitLineHandler>();
new Task.Backgroundable(project, GitBundle.message("pulling.title", dialog.getRemote()), true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
@@ -86,18 +81,8 @@ public class GitPull extends GitRepositoryAction {
return;
}
- if (GitHttpAdapter.shouldUseJGit(url)) {
- boolean fetchSuccessful = new GitFetcher(project, indicator, true).fetchRootsAndNotify(Collections.singleton(repository),
- "Pull failed", false);
- if (!fetchSuccessful) {
- return;
- }
- handlerReference.set(dialog.pullOrMergeHandler(false));
- } else {
- handlerReference.set(dialog.pullOrMergeHandler(true));
- }
-
-
+ final GitLineHandler handler = dialog.makeHandler(url);
+
final VirtualFile root = dialog.gitRoot();
affectedRoots.add(root);
String revision = repository.getCurrentRevision();
@@ -106,7 +91,7 @@ public class GitPull extends GitRepositoryAction {
}
final GitRevisionNumber currentRev = new GitRevisionNumber(revision);
- GitTask pullTask = new GitTask(project, handlerReference.get(), GitBundle.message("pulling.title", dialog.getRemote()));
+ GitTask pullTask = new GitTask(project, handler, GitBundle.message("pulling.title", dialog.getRemote()));
pullTask.setProgressIndicator(indicator);
pullTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());
pullTask.execute(true, false, new GitTaskResultHandlerAdapter() {
@@ -120,7 +105,7 @@ public class GitPull extends GitRepositoryAction {
@Override
protected void onFailure() {
- GitUIUtil.notifyGitErrors(project, "Error pulling " + dialog.getRemote(), "", handlerReference.get().errors());
+ GitUIUtil.notifyGitErrors(project, "Error pulling " + dialog.getRemote(), "", handler.errors());
repositoryManager.updateRepository(root);
}
});
diff --git a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java
index 82a261cdc3af..46875b9d8c23 100644
--- a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java
+++ b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java
@@ -126,6 +126,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
command.run();
}
if (exception[0] != null) {
+ LOG.warn(exception[0]);
throw new VcsException("Failed to annotate: " + exception[0], exception[0]);
}
return annotation[0];
@@ -146,7 +147,6 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
final List<VcsFileRevision> revisions,
final VirtualFile file) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(myProject, GitUtil.getGitRoot(repositoryFilePath), GitCommand.BLAME);
- h.setNoSSH(true);
h.setStdoutSuppressed(true);
h.setCharset(file.getCharset());
h.addParameters("-p", "-l", "-t", "-w");
@@ -173,7 +173,8 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
commitHash = null;
}
s.spaceToken(); // skip revision line number
- int lineNum = Integer.parseInt(s.spaceToken());
+ String s1 = s.spaceToken();
+ int lineNum = Integer.parseInt(s1);
s.nextLine();
// parse commit information
CommitInfo commit = commits.get(commitHash);
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
index d980c88d2aa7..153d763133d3 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
@@ -45,7 +45,7 @@ import static com.intellij.openapi.util.text.StringUtil.pluralize;
*/
abstract class GitBranchOperation {
- private static final Logger LOG = Logger.getInstance(GitBranchOperation.class);
+ protected static final Logger LOG = Logger.getInstance(GitBranchOperation.class);
@NotNull protected final Project myProject;
@NotNull protected final GitPlatformFacade myFacade;
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java b/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java
index 3ac218b7fb7a..a9dcb401852a 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java
@@ -125,7 +125,6 @@ public class GitBranchUtil {
private static GitLocalBranch getCurrentBranchFromGit(@NotNull Project project, @NotNull VirtualFile root) {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.REV_PARSE);
handler.addParameters("--abbrev-ref", "HEAD");
- handler.setNoSSH(true);
handler.setSilent(true);
try {
String name = handler.run();
diff --git a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java
index 0fe26df6af57..1f22c6abed37 100644
--- a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java
@@ -152,24 +152,31 @@ class GitDeleteRemoteBranchOperation extends GitBranchOperation {
private GitCommandResult pushDeletion(@NotNull GitRepository repository, @NotNull String remoteName, @NotNull String branchName) {
GitRemote remote = getRemoteByName(repository, remoteName);
if (remote == null) {
- return pushDeletionNatively(repository, remoteName, branchName);
+ String error = "Couldn't find remote by name: " + remoteName;
+ LOG.error(error);
+ return GitCommandResult.error(error);
}
String remoteUrl = remote.getFirstUrl();
- if (remoteUrl != null && GitHttpAdapter.shouldUseJGit(remoteUrl)) {
+ if (remoteUrl == null) {
+ LOG.warn("No urls are defined for remote: " + remote);
+ return GitCommandResult.error("There is no urls defined for remote " + remote.getName());
+ }
+ if (GitHttpAdapter.shouldUseJGit(remoteUrl)) {
String fullBranchName = branchName.startsWith(GitBranch.REFS_HEADS_PREFIX) ? branchName : GitBranch.REFS_HEADS_PREFIX + branchName;
String spec = ":" + fullBranchName;
GitSimplePushResult simplePushResult = GitHttpAdapter.push(repository, remote.getName(), remoteUrl, spec);
return convertSimplePushResultToCommandResult(simplePushResult);
}
else {
- return pushDeletionNatively(repository, remoteName, branchName);
+ return pushDeletionNatively(repository, remoteName, remoteUrl, branchName);
}
}
@NotNull
- private GitCommandResult pushDeletionNatively(@NotNull GitRepository repository, @NotNull String remoteName, @NotNull String branchName) {
- return myGit.push(repository, remoteName, ":" + branchName);
+ private GitCommandResult pushDeletionNatively(@NotNull GitRepository repository, @NotNull String remoteName, @NotNull String url,
+ @NotNull String branchName) {
+ return myGit.push(repository, remoteName, url,":" + branchName);
}
@NotNull
diff --git a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java
index 760b77f096c3..e23f8ed91c30 100644
--- a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java
+++ b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java
@@ -189,14 +189,12 @@ public class GitChangeUtils {
GitSimpleHandler handler = new GitSimpleHandler(project, vcsRoot, GitCommand.REV_LIST);
handler.addParameters("--timestamp", "--max-count=1", reference);
handler.endOptions();
- handler.setNoSSH(true);
handler.setSilent(true);
String output = handler.run();
StringTokenizer stk = new StringTokenizer(output, "\n\r \t", false);
if (!stk.hasMoreTokens()) {
GitSimpleHandler dh = new GitSimpleHandler(project, vcsRoot, GitCommand.LOG);
dh.addParameters("-1", "HEAD");
- dh.setNoSSH(true);
dh.setSilent(true);
String out = dh.run();
LOG.info("Diagnostic output from 'git log -1 HEAD': [" + out + "]");
@@ -241,9 +239,9 @@ public class GitChangeUtils {
boolean skipDiffsForMerge,
boolean local, boolean revertable) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.SHOW);
- h.setNoSSH(true);
h.setSilent(true);
- h.addParameters("--name-status", "--no-abbrev", "-M", "--pretty=format:" + COMMITTED_CHANGELIST_FORMAT, "--encoding=UTF-8",
+ h.addParameters("--name-status", "--first-parent", "--no-abbrev", "-M", "--pretty=format:" + COMMITTED_CHANGELIST_FORMAT,
+ "--encoding=UTF-8",
revisionName, "--");
String output = h.run();
StringScanner s = new StringScanner(output);
@@ -253,7 +251,6 @@ public class GitChangeUtils {
@Nullable
public static String getCommitAbbreviation(final Project project, final VirtualFile root, final SHAHash hash) {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("--max-count=1", "--pretty=%h", "--encoding=UTF-8", "\"" + hash.getValue() + "\"", "--");
try {
@@ -270,7 +267,6 @@ public class GitChangeUtils {
public static SHAHash commitExists(final Project project, final VirtualFile root, final String anyReference,
List<VirtualFile> paths, final String... parameters) {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters(parameters);
h.addParameters("--max-count=1", "--pretty=%H", "--encoding=UTF-8", anyReference, "--");
@@ -290,7 +286,6 @@ public class GitChangeUtils {
public static boolean isAnyLevelChild(final Project project, final VirtualFile root, final SHAHash parent,
final String anyReferenceChild) {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.MERGE_BASE);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("\"" + parent.getValue() + "\"","\"" + anyReferenceChild + "\"", "--");
try {
@@ -306,7 +301,6 @@ public class GitChangeUtils {
@Nullable
public static List<AbstractHash> commitExistsByComment(final Project project, final VirtualFile root, final String anyReference) {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
- h.setNoSSH(true);
h.setSilent(true);
String escaped = StringUtil.escapeQuotes(anyReference);
escaped = StringUtil.escapeSlashes(escaped);
@@ -389,7 +383,6 @@ public class GitChangeUtils {
for (String parent : parents) {
final GitRevisionNumber parentRevision = resolveReference(project, root, parent);
GitSimpleHandler diffHandler = new GitSimpleHandler(project, root, GitCommand.DIFF);
- diffHandler.setNoSSH(true);
diffHandler.setSilent(true);
diffHandler.addParameters("--name-status", "-M", parentRevision.getRev(), thisRevision.getRev());
String diff = diffHandler.run();
@@ -463,7 +456,6 @@ public class GitChangeUtils {
@NotNull String diffRange, @Nullable Collection<FilePath> dirtyPaths) {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.DIFF);
handler.addParameters("--name-status", "--diff-filter=ADCMRUXT", "-M", diffRange);
- handler.setNoSSH(true);
handler.setSilent(true);
handler.setStdoutSuppressed(true);
handler.endOptions();
diff --git a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
index 932ec1432a05..cc286d7fd66a 100644
--- a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
+++ b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
@@ -133,9 +133,9 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider<
throws VcsException {
GitRepositoryLocation l = (GitRepositoryLocation)location;
final Long beforeRev = settings.getChangeBeforeFilter();
- final Long afterRev = settings.getChangeBeforeFilter();
+ final Long afterRev = settings.getChangeAfterFilter();
final Date beforeDate = settings.getDateBeforeFilter();
- final Date afterDate = settings.getDateBeforeFilter();
+ final Date afterDate = settings.getDateAfterFilter();
final String author = settings.getUserFilter();
VirtualFile root = LocalFileSystem.getInstance().findFileByIoFile(l.getRoot());
if (root == null) {
diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
index 3be534abef2e..d6b1ada21827 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
+++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
@@ -248,7 +248,6 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
HashSet<FilePath> realRemoved = new HashSet<FilePath>();
// perform diff
GitSimpleHandler diff = new GitSimpleHandler(project, root, GitCommand.DIFF);
- diff.setNoSSH(true);
diff.setSilent(true);
diff.setStdoutSuppressed(true);
diff.addParameters("--diff-filter=ADMRUX", "--name-status", "HEAD");
@@ -323,7 +322,6 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
// perform merge commit
try {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.COMMIT);
- handler.setNoSSH(true);
handler.addParameters("-F", messageFile.getAbsolutePath());
if (author != null) {
handler.addParameters("--author=" + author);
@@ -469,7 +467,6 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
boolean amend = nextCommitAmend;
for (List<String> paths : VcsFileUtil.chunkPaths(root, files)) {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.COMMIT);
- handler.setNoSSH(true);
if (amend) {
handler.addParameters("--amend");
}
diff --git a/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java b/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java
index 8b28dc10350f..57305c4d7d4f 100644
--- a/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java
+++ b/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java
@@ -15,7 +15,6 @@
*/
package git4idea.checkout;
-import com.intellij.notification.NotificationType;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
@@ -24,6 +23,7 @@ import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitVcs;
+import git4idea.Notificator;
import git4idea.actions.BasicAction;
import git4idea.commands.Git;
import git4idea.commands.GitCommandResult;
@@ -33,7 +33,6 @@ import git4idea.i18n.GitBundle;
import git4idea.jgit.GitHttpAdapter;
import git4idea.update.GitFetchResult;
import git4idea.update.GitFetcher;
-import git4idea.util.GitUIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -108,8 +107,8 @@ public class GitCheckoutProvider implements CheckoutProvider {
}.queue();
}
- private static boolean doClone(@NotNull Project project, @NotNull ProgressIndicator indicator, @NotNull Git git,
- @NotNull String directoryName, @NotNull String parentDirectory, @NotNull String sourceRepositoryURL) {
+ public static boolean doClone(@NotNull Project project, @NotNull ProgressIndicator indicator, @NotNull Git git,
+ @NotNull String directoryName, @NotNull String parentDirectory, @NotNull String sourceRepositoryURL) {
if (GitHttpAdapter.shouldUseJGit(sourceRepositoryURL)) {
GitFetchResult result = GitHttpAdapter.cloneRepository(project, new File(parentDirectory, directoryName), sourceRepositoryURL);
GitFetcher.displayFetchResult(project, result, "Clone failed", result.getErrors());
@@ -128,7 +127,7 @@ public class GitCheckoutProvider implements CheckoutProvider {
if (result.success()) {
return true;
}
- GitUIUtil.notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, project, "Clone failed", result.getErrorOutputAsHtmlString(), NotificationType.ERROR, null);
+ Notificator.getInstance(project).notifyError("Clone failed", result.getErrorOutputAsHtmlString());
return false;
}
diff --git a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java
index f745aec53e86..33bc8d0909d3 100644
--- a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java
+++ b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java
@@ -26,10 +26,7 @@ import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.EditorComboBox;
import com.intellij.util.ArrayUtil;
import git4idea.GitUtil;
-import git4idea.commands.GitCommand;
-import git4idea.commands.GitLineHandlerPasswordRequestAware;
-import git4idea.commands.GitTask;
-import git4idea.commands.GitTaskResult;
+import git4idea.commands.*;
import git4idea.i18n.GitBundle;
import git4idea.remote.GitRememberedInputs;
import org.jetbrains.annotations.NonNls;
@@ -167,6 +164,7 @@ public class GitCloneDialog extends DialogWrapper {
*/
private boolean test(String url) {
final GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(myProject, new File("."), GitCommand.LS_REMOTE);
+ handler.setUrl(url);
handler.addParameters(url, "master");
GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", url));
GitTaskResult result = task.executeModal();
diff --git a/plugins/git4idea/src/git4idea/commands/Git.java b/plugins/git4idea/src/git4idea/commands/Git.java
index 480be2106c2a..1b30a1e4518a 100644
--- a/plugins/git4idea/src/git4idea/commands/Git.java
+++ b/plugins/git4idea/src/git4idea/commands/Git.java
@@ -92,11 +92,11 @@ public interface Git {
GitCommandResult tip(@NotNull GitRepository repository, @NotNull String branchName);
@NotNull
- GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @NotNull String spec,
+ GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @NotNull String url, @NotNull String spec,
@NotNull GitLineHandlerListener... listeners);
@NotNull
- GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec,
+ GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec spec, @NotNull String url,
@NotNull GitLineHandlerListener... listeners);
@NotNull
diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java
index d0942ce6a092..226d663beb1f 100644
--- a/plugins/git4idea/src/git4idea/commands/GitCommand.java
+++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java
@@ -70,42 +70,38 @@ public class GitCommand {
*/
public static final String GIT_EDITOR_ENV = "GIT_EDITOR";
- /**
- * The myLocking policy for the command
- */
enum LockingPolicy {
- /**
- * Read lock should be acquired for the command
- */
READ,
- /**
- * Write lock should be acquired for the command
- */
WRITE,
- /**
- * Write lock should be acquired for the command, and it could be acquired in several intervals
- */
WRITE_SUSPENDABLE,
}
@NotNull @NonNls private final String myName; // command name passed to git
@NotNull private final LockingPolicy myLocking; // Locking policy for the command
+ private GitCommand(@NotNull String name, @NotNull LockingPolicy lockingPolicy) {
+ myLocking = lockingPolicy;
+ myName = name;
+ }
+
/**
- * Creates a git command with LockingPolicy different from the default one.
- * Use this constructor with care: specifying read-policy on a write operation may result in a conflict during simultaneous
- * modification of index.
- * @param command Original command.
- * @param lockingPolicy Locking policy overriding default locking policy of the original command.
+ * Copy constructor with other locking policy.
*/
private GitCommand(@NotNull GitCommand command, @NotNull LockingPolicy lockingPolicy) {
myName = command.name();
myLocking = lockingPolicy;
}
- private GitCommand(@NonNls @NotNull String name, @NotNull LockingPolicy locking) {
- myLocking = locking;
- myName = name;
+ /**
+ * <p>Creates the clone of this git command, but with LockingPolicy different from the default one.</p>
+ * <p>This can be used for commands, which are considered to be "write" commands in general, but can be "read" commands when a certain
+ * set of arguments is given ({@code git stash list}, for instance).</p>
+ * <p>Use this constructor with care: specifying read-policy on a write operation may result in a conflict during simultaneous
+ * modification of index.</p>
+ */
+ @NotNull
+ public GitCommand readLockingCommand() {
+ return new GitCommand(this, LockingPolicy.READ);
}
@NotNull
@@ -133,11 +129,6 @@ public class GitCommand {
return myLocking;
}
- @NotNull
- public GitCommand readLockingCommand() {
- return new GitCommand(this, LockingPolicy.READ);
- }
-
@Override
public String toString() {
return myName;
diff --git a/plugins/git4idea/src/git4idea/commands/GitCommandResult.java b/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
index c0437aa2ad1f..dad9f2d8aaa1 100644
--- a/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
+++ b/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -80,4 +81,8 @@ public class GitCommandResult {
return myException;
}
+ @NotNull
+ public static GitCommandResult error(@NotNull String error) {
+ return new GitCommandResult(false, 1, Collections.singletonList(error), Collections.<String>emptyList(), null);
+ }
}
diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java
index e50e95952094..952574ca4bcb 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java
@@ -19,8 +19,10 @@ import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.ProcessEventListener;
@@ -38,8 +40,9 @@ import git4idea.config.GitVersionSpecialty;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.git4idea.http.GitAskPassXmlRpcHandler;
import org.jetbrains.git4idea.ssh.GitSSHHandler;
-import org.jetbrains.git4idea.ssh.GitSSHService;
+import org.jetbrains.git4idea.ssh.GitXmlRpcSshService;
import java.io.File;
import java.io.OutputStream;
@@ -82,9 +85,6 @@ public abstract class GitHandler {
@NonNls
private Charset myCharset = Charset.forName("UTF-8"); // Character set to use for IO
- @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"})
- private boolean myNoSSHFlag = false;
-
private final EventDispatcher<ProcessEventListener> myListeners = EventDispatcher.create(ProcessEventListener.class);
@SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"})
protected boolean mySilent; // if true, the command execution is not logged in version control view
@@ -100,6 +100,7 @@ public abstract class GitHandler {
private long myStartTime; // git execution start timestamp
private static final long LONG_TIME = 10 * 1000;
@Nullable private ModalityState myState;
+ @Nullable private String myUrl;
/**
@@ -219,23 +220,13 @@ public abstract class GitHandler {
return file;
}
- /**
- * Set SSH flag. This flag should be set to true for commands that never interact with remote repositories.
- *
- * @param value if value is true, the custom ssh is not used for the command.
- */
- @SuppressWarnings({"WeakerAccess", "SameParameterValue"})
- public void setNoSSH(boolean value) {
- checkNotStarted();
- myNoSSHFlag = value;
+ @SuppressWarnings("NullableProblems")
+ public void setUrl(@NotNull String url) {
+ myUrl = url;
}
- /**
- * @return true if SSH is not invoked by this command.
- */
- @SuppressWarnings({"WeakerAccess"})
- public boolean isNoSSH() {
- return myNoSSHFlag;
+ protected boolean isRemote() {
+ return myUrl != null;
}
/**
@@ -413,6 +404,7 @@ public abstract class GitHandler {
/**
* Start process
*/
+ @SuppressWarnings("UseOfSystemOutOrSystemErr")
public synchronized void start() {
checkNotStarted();
@@ -429,9 +421,15 @@ public abstract class GitHandler {
LOG.debug(printableCommandLine());
}
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ System.out.println("cd " + myWorkingDirectory);
+ System.out.println(printableCommandLine());
+ }
+
// setup environment
- if (!myNoSSHFlag && myProjectSettings.isIdeaSsh()) {
- GitSSHService ssh = GitSSHIdeaService.getInstance();
+ GitRemoteProtocol remoteProtocol = GitRemoteProtocol.fromUrl(myUrl);
+ if (remoteProtocol == GitRemoteProtocol.SSH && myProjectSettings.isIdeaSsh()) {
+ GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class);
myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath());
myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject, myState));
myEnvironmentCleanedUp = false;
@@ -440,6 +438,19 @@ public abstract class GitHandler {
myEnv.put(GitSSHHandler.SSH_PORT_ENV, Integer.toString(port));
LOG.debug(String.format("handler=%s, port=%s", myHandlerNo, port));
}
+ else if (remoteProtocol == GitRemoteProtocol.HTTP) {
+ GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class);
+ myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_ENV, service.getScriptPath().getPath());
+ assert myUrl != null : "myUrl can't be null here";
+ GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myState, myCommand, myUrl);
+ myHandlerNo = service.registerHandler(httpAuthenticator);
+ myEnvironmentCleanedUp = false;
+ myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV, Integer.toString(myHandlerNo));
+ int port = service.getXmlRcpPort();
+ myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_PORT_ENV, Integer.toString(port));
+ LOG.debug(String.format("handler=%s, port=%s", myHandlerNo, port));
+ addAuthListener(httpAuthenticator);
+ }
myCommandLine.setEnvParams(myEnv);
// start process
myProcess = startProcess();
@@ -451,6 +462,33 @@ public abstract class GitHandler {
}
}
+ private void addAuthListener(@NotNull final GitHttpAuthenticator authenticator) {
+ // TODO this code should be located in GitLineHandler, and the other remote code should be move there as well
+ if (this instanceof GitLineHandler) {
+ ((GitLineHandler)this).addLineListener(new GitLineHandlerAdapter() {
+
+ private boolean myAuthFailed;
+
+ @Override
+ public void onLineAvailable(String line, Key outputType) {
+ if (line.toLowerCase().contains("authentication failed")) {
+ myAuthFailed = true;
+ }
+ }
+
+ @Override
+ public void processTerminated(int exitCode) {
+ if (myAuthFailed) {
+ authenticator.forgetPassword();
+ }
+ else {
+ authenticator.saveAuthData();
+ }
+ }
+ });
+ }
+ }
+
protected abstract Process startProcess() throws ExecutionException;
/**
@@ -502,11 +540,20 @@ public abstract class GitHandler {
* Cleanup environment
*/
protected synchronized void cleanupEnv() {
- if (!myNoSSHFlag && !myEnvironmentCleanedUp) {
- GitSSHService ssh = GitSSHIdeaService.getInstance();
+ if (myEnvironmentCleanedUp) {
+ return;
+ }
+ GitRemoteProtocol remoteProtocol = GitRemoteProtocol.fromUrl(myUrl);
+ if (remoteProtocol == GitRemoteProtocol.SSH) {
+ GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class);
myEnvironmentCleanedUp = true;
ssh.unregisterHandler(myHandlerNo);
}
+ else if (remoteProtocol == GitRemoteProtocol.HTTP) {
+ GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class);
+ myEnvironmentCleanedUp = true;
+ service.unregisterHandler(myHandlerNo);
+ }
}
/**
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java
new file mode 100644
index 000000000000..69be489be44b
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.commands;
+
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.git4idea.http.GitAskPassApp;
+import org.jetbrains.git4idea.http.GitAskPassXmlRpcHandler;
+import org.jetbrains.git4idea.ssh.GitXmlRpcHandlerService;
+import org.jetbrains.git4idea.util.ScriptGenerator;
+
+/**
+ * Provides the authentication mechanism for Git HTTP connections.
+ */
+public abstract class GitHttpAuthService extends GitXmlRpcHandlerService<GitHttpAuthenticator> {
+
+ protected GitHttpAuthService() {
+ super("git-askpass-", GitAskPassXmlRpcHandler.HANDLER_NAME, GitAskPassApp.class);
+ }
+
+ @Override
+ protected void customizeScriptGenerator(@NotNull ScriptGenerator generator) {
+ }
+
+ @NotNull
+ @Override
+ protected Object createRpcRequestHandlerDelegate() {
+ return new InternalRequestHandlerDelegate();
+ }
+
+ /**
+ * Creates new {@link GitHttpAuthenticator} that will be requested to handle username and password requests from Git.
+ */
+ @NotNull
+ public abstract GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state,
+ @NotNull GitCommand command, @NotNull String url);
+
+ /**
+ * Internal handler implementation class, it is made public to be accessible via XML RPC.
+ */
+ public class InternalRequestHandlerDelegate implements GitAskPassXmlRpcHandler {
+ @NotNull
+ @Override
+ public String askUsername(int handler, @NotNull String url) {
+ return getHandler(handler).askUsername(url);
+ }
+
+ @NotNull
+ @Override
+ public String askPassword(int handler, @NotNull String url) {
+ return getHandler(handler).askPassword(url);
+ }
+ }
+
+}
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java
new file mode 100644
index 000000000000..06374bf78864
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.commands;
+
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Kirill Likhodedov
+ */
+class GitHttpAuthServiceImpl extends GitHttpAuthService {
+
+ @Override
+ @NotNull
+ public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state, @NotNull GitCommand command,
+ @NotNull String url) {
+ return new GitHttpGuiAuthenticator(project, state, command, url);
+ }
+
+}
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthenticator.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthenticator.java
new file mode 100644
index 000000000000..3e14b5837da1
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthenticator.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.commands;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Performs HTTP authentication, i. e. handles "ask username" and "ask password" requests from Git:
+ *
+ * @author Kirill Likhodedov
+ */
+public interface GitHttpAuthenticator {
+
+ /**
+ * Asks the password to access the specified URL.
+ * @param url URL which needs authentication.
+ * @return Password to access the URL.
+ */
+ @NotNull
+ String askPassword(@NotNull String url);
+
+ /**
+ * Asks the username to access the specified URL. Password request will follow.
+ * @param url URL which needs authentication, without username in it.
+ * @return Username to access the URL.
+ */
+ @NotNull
+ String askUsername(@NotNull String url);
+
+ /**
+ * Saves the entered username and password to the database for the future access.
+ * This is called when authentication succeeds.
+ */
+ void saveAuthData();
+
+ /**
+ * Makes sure the entered password is removed from the database.
+ * This is called when authentication fails.
+ */
+ void forgetPassword();
+}
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java
new file mode 100644
index 000000000000..2d63e0783356
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.commands;
+
+import com.intellij.ide.passwordSafe.PasswordSafe;
+import com.intellij.ide.passwordSafe.PasswordSafeException;
+import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl;
+import com.intellij.ide.passwordSafe.ui.PasswordSafePromptDialog;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.AuthData;
+import com.intellij.util.io.URLUtil;
+import com.intellij.vcsUtil.AuthDialog;
+import git4idea.jgit.GitHttpAuthDataProvider;
+import git4idea.remote.GitRememberedInputs;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * <p>Handles "ask username" and "ask password" requests from Git:
+ * shows authentication dialog in the GUI, waits for user input and returns the credentials supplied by the user.</p>
+ * <p>If user cancels the dialog, empty string is returned.</p>
+ * <p>If no username is specified in the URL, Git queries for the username and for the password consecutively.
+ * In this case to avoid showing dialogs twice, the component asks for both credentials at once,
+ * and remembers the password to provide it to the Git process during the next request without requiring user interaction.</p>
+ * <p>New instance of the GitAskPassGuiHandler should be created for each session, i. e. for each remote operation call.</p>
+ *
+ * @author Kirill Likhodedov
+ */
+class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
+
+ private static final Logger LOG = Logger.getInstance(GitHttpGuiAuthenticator.class);
+ private static final Class<GitHttpAuthenticator> PASS_REQUESTER = GitHttpAuthenticator.class;
+
+ @NotNull private final Project myProject;
+ @Nullable private final ModalityState myModalityState;
+ @NotNull private final String myTitle;
+ @NotNull private final String myUrlFromCommand;
+
+ @Nullable private String myPassword;
+ @Nullable private String myPasswordKey;
+ @Nullable private String myUrl;
+ @Nullable private String myLogin;
+ private boolean myRememberOnDisk;
+
+ GitHttpGuiAuthenticator(@NotNull Project project, @Nullable ModalityState modalityState, @NotNull GitCommand command,
+ @NotNull String url) {
+ myProject = project;
+ myModalityState = modalityState;
+ myTitle = "Git " + StringUtil.capitalize(command.name());
+ myUrlFromCommand = url;
+ }
+
+ @Override
+ @NotNull
+ public String askPassword(@NotNull String url) {
+ if (myPassword != null) { // already asked in askUsername
+ return myPassword;
+ }
+ url = adjustUrl(url);
+ String prompt = "Enter the password for " + url;
+ myPasswordKey = url;
+ String password = PasswordSafePromptDialog.askPassword(myProject, myModalityState, myTitle, prompt, PASS_REQUESTER, url, false, null);
+ if (password == null) {
+ return "";
+ }
+ // Password is stored in the safe in PasswordSafePromptDialog.askPassword,
+ // but it is not the right behavior (incorrect password is stored too because of that) and should be fixed separately.
+ // We store it here manually, to let it work after that behavior is fixed.
+ myPassword = password;
+ return password;
+ }
+
+ @Override
+ @NotNull
+ public String askUsername(@NotNull String url) {
+ url = adjustUrl(url);
+ AuthData authData = getSavedAuthData(myProject, url);
+ String login = null;
+ String password = null;
+ if (authData != null) {
+ login = authData.getLogin();
+ password = authData.getPassword();
+ }
+ if (login != null && password != null) {
+ myPassword = password;
+ return login;
+ }
+
+ final AuthDialog dialog = new AuthDialog(myProject, myTitle, "Enter credentials for " + url, login, null, true);
+ ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ dialog.show();
+ }
+ }, myModalityState == null ? ModalityState.defaultModalityState() : myModalityState);
+
+ if (!dialog.isOK()) {
+ return "";
+ }
+
+ // remember values to store in the database afterwards, if authentication succeeds
+ myPassword = dialog.getPassword();
+ myLogin = dialog.getUsername();
+ myUrl = url;
+ myRememberOnDisk = dialog.isRememberPassword();
+ myPasswordKey = makeKey(myUrl, myLogin);
+
+ return myLogin;
+ }
+
+ @Override
+ public void saveAuthData() {
+ // save login and url
+ if (myUrl != null && myLogin != null) {
+ GitRememberedInputs.getInstance().addUrl(myUrl, myLogin);
+ }
+
+ // save password
+ if (myPasswordKey != null && myPassword != null) {
+ PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
+ try {
+ passwordSafe.getMemoryProvider().storePassword(myProject, PASS_REQUESTER, myPasswordKey, myPassword);
+ if (myRememberOnDisk) {
+ passwordSafe.getMasterKeyProvider().storePassword(myProject, PASS_REQUESTER, myPasswordKey, myPassword);
+ }
+ }
+ catch (PasswordSafeException e) {
+ LOG.error("Couldn't remember password for " + myPasswordKey, e);
+ }
+ }
+ }
+
+ @Override
+ public void forgetPassword() {
+ if (myPasswordKey != null) {
+ try {
+ PasswordSafe.getInstance().removePassword(myProject, PASS_REQUESTER, myPasswordKey);
+ }
+ catch (PasswordSafeException e) {
+ LOG.info("Couldn't forget the password for " + myPasswordKey);
+ }
+ }
+ }
+
+ @NotNull
+ private String adjustUrl(@NotNull String url) {
+ if (StringUtil.isEmptyOrSpaces(url)) {
+ // if Git doesn't specify the URL in the username/password query, we use the url from the Git command
+ // We only take the host, to avoid entering the same password for different repositories on the same host.
+ return adjustHttpUrl(getHost(myUrlFromCommand));
+ }
+ return adjustHttpUrl(url);
+ }
+
+ @NotNull
+ private static String getHost(@NotNull String url) {
+ Pair<String, String> split = URLUtil.splitScheme(url);
+ String scheme = split.getFirst();
+ String urlItself = split.getSecond();
+ int pathStart = urlItself.indexOf("/");
+ return scheme + URLUtil.SCHEME_SEPARATOR + urlItself.substring(0, pathStart);
+ }
+
+ /**
+ * If the url scheme is HTTPS, store it as HTTP in the database, not to make user enter and remember same credentials twice.
+ */
+ @NotNull
+ private static String adjustHttpUrl(@NotNull String url) {
+ String prefix = "https";
+ if (url.startsWith(prefix)) {
+ return "http" + url.substring(prefix.length());
+ }
+ return url;
+ }
+
+ @Nullable
+ private static AuthData getSavedAuthData(@NotNull Project project, @NotNull String url) {
+ String userName = GitRememberedInputs.getInstance().getUserNameForUrl(url);
+ if (userName == null) {
+ return trySavedAuthDataFromProviders(url);
+ }
+ String key = makeKey(url, userName);
+ final PasswordSafe passwordSafe = PasswordSafe.getInstance();
+ try {
+ String password = passwordSafe.getPassword(project, PASS_REQUESTER, key);
+ if (password != null) {
+ return new AuthData(userName, password);
+ }
+ return null;
+ }
+ catch (PasswordSafeException e) {
+ LOG.info("Couldn't get the password for key [" + key + "]", e);
+ return null;
+ }
+ }
+
+ @Nullable
+ private static AuthData trySavedAuthDataFromProviders(@NotNull String url) {
+ GitHttpAuthDataProvider[] extensions = GitHttpAuthDataProvider.EP_NAME.getExtensions();
+ for (GitHttpAuthDataProvider provider : extensions) {
+ AuthData authData = provider.getAuthData(url);
+ if (authData != null) {
+ return authData;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Makes the password database key for the URL: inserts the login after the scheme: http://login@url.
+ */
+ @NotNull
+ private static String makeKey(@NotNull String url, @NotNull String login) {
+ Pair<String,String> pair = URLUtil.splitScheme(url);
+ String scheme = pair.getFirst();
+ if (StringUtil.isEmpty(scheme)) {
+ return scheme + URLUtil.SCHEME_SEPARATOR + login + "@" + pair.getSecond();
+ }
+ return login + "@" + url;
+ }
+
+}
diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java
index 270752e434d0..54006632f0ee 100644
--- a/plugins/git4idea/src/git4idea/commands/GitImpl.java
+++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java
@@ -101,7 +101,6 @@ public class GitImpl implements Git {
throws VcsException {
final Set<VirtualFile> untrackedFiles = new HashSet<VirtualFile>();
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LS_FILES);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("--exclude-standard", "--others", "-z");
h.endOptions();
@@ -133,11 +132,12 @@ public class GitImpl implements Git {
public GitCommandResult clone(@NotNull Project project, @NotNull File parentDirectory, @NotNull String url,
@NotNull String clonedDirectoryName, @NotNull GitLineHandlerListener... listeners) {
GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(project, parentDirectory, GitCommand.CLONE);
+ handler.setUrl(url);
handler.addParameters("--progress");
handler.addParameters(url);
handler.addParameters(clonedDirectoryName);
addListeners(handler, listeners);
- return run(handler, true);
+ return run(handler);
}
@NotNull
@@ -154,7 +154,6 @@ public class GitImpl implements Git {
final GitLineHandler diff = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.DIFF);
diff.addParameters(parameters);
diff.addParameters(range);
- diff.setNoSSH(true);
diff.setStdoutSuppressed(true);
diff.setStderrSuppressed(true);
diff.setSilent(true);
@@ -357,26 +356,27 @@ public class GitImpl implements Git {
@Override
@NotNull
- public GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @NotNull String spec,
- @NotNull GitLineHandlerListener... listeners) {
+ public GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @NotNull String url, @NotNull String spec,
+ @NotNull GitLineHandlerListener... listeners) {
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(repository.getProject(), repository.getRoot(),
GitCommand.PUSH);
+ h.setUrl(url);
h.setSilent(false);
addListeners(h, listeners);
h.addProgressParameter();
h.addParameters(remote);
h.addParameters(spec);
- return run(h, true);
+ return run(h);
}
@Override
@NotNull
- public GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec,
- @NotNull GitLineHandlerListener... listeners) {
+ public GitCommandResult push(@NotNull GitRepository repository, @NotNull GitPushSpec pushSpec, @NotNull String url,
+ @NotNull GitLineHandlerListener... listeners) {
GitRemote remote = pushSpec.getRemote();
GitBranch remoteBranch = pushSpec.getDest();
String destination = remoteBranch.getName().replaceFirst(remote.getName() + "/", "");
- return push(repository, remote.getName(), pushSpec.getSource().getName() + ":" + destination, listeners);
+ return push(repository, remote.getName(), url, pushSpec.getSource().getName() + ":" + destination, listeners);
}
@NotNull
@@ -417,16 +417,10 @@ public class GitImpl implements Git {
}
}
- private static GitCommandResult run(@NotNull GitLineHandler handler) {
- return run(handler, false);
- }
-
/**
* Runs the given {@link GitLineHandler} in the current thread and returns the {@link GitCommandResult}.
*/
- private static GitCommandResult run(@NotNull GitLineHandler handler, boolean remote) {
- handler.setNoSSH(!remote);
-
+ private static GitCommandResult run(@NotNull GitLineHandler handler) {
final List<String> errorOutput = new ArrayList<String>();
final List<String> output = new ArrayList<String>();
final AtomicInteger exitCode = new AtomicInteger();
diff --git a/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java b/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java
new file mode 100644
index 000000000000..be1da0262662
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.commands;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+* @author Kirill Likhodedov
+*/
+public enum GitRemoteProtocol {
+ GIT,
+ SSH,
+ HTTP;
+
+ @Nullable
+ public static GitRemoteProtocol fromUrl(@Nullable String url) {
+ if (url == null) {
+ return null;
+ }
+ url = url.toLowerCase();
+ if (url.startsWith("http")) {
+ return HTTP;
+ }
+ if (url.startsWith("git://")) { // "://" are there not to mix with scp-like syntax used for SSH: git@host.com/path/to.git
+ return GIT;
+ }
+ return SSH;
+ }
+
+}
diff --git a/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java b/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
index 26f996fb027c..c27fb0dab72c 100644
--- a/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
@@ -25,7 +25,6 @@ import git4idea.config.SSHConnectionSettings;
import git4idea.i18n.GitBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.git4idea.ssh.GitSSHService;
import javax.swing.*;
import javax.swing.text.JTextComponent;
@@ -38,7 +37,7 @@ import java.util.concurrent.atomic.AtomicReference;
/**
* Swing GUI handler for the SSH events
*/
-class GitSSHGUIHandler implements GitSSHService.Handler {
+public class GitSSHGUIHandler {
@Nullable private final Project myProject;
@Nullable private final ModalityState myState;
@@ -74,6 +73,7 @@ class GitSSHGUIHandler implements GitSSHService.Handler {
return rc.get();
}
+ @Nullable
public String askPassphrase(final String username, final String keyPath, boolean resetPassword, final String lastError) {
String error = processLastError(resetPassword, lastError);
return PasswordSafePromptDialog.askPassphrase(myProject, myState, GitBundle.getString("ssh.ask.passphrase.title"),
@@ -112,6 +112,18 @@ class GitSSHGUIHandler implements GitSSHService.Handler {
}
}
+ /**
+ * Reply to challenge in keyboard-interactive scenario
+ *
+ * @param username a user name
+ * @param name a name of challenge
+ * @param instruction a instructions
+ * @param numPrompts number of prompts
+ * @param prompt prompts
+ * @param echo true if the reply for corresponding prompt should be echoed
+ * @param lastError the last error
+ * @return replies to the challenges
+ */
@SuppressWarnings({"UseOfObsoleteCollectionType", "unchecked"})
public Vector<String> replyToChallenge(final String username,
final String name,
@@ -143,6 +155,14 @@ class GitSSHGUIHandler implements GitSSHService.Handler {
return rc.get();
}
+ /**
+ * Ask password
+ *
+ * @param username a user name
+ * @param resetPassword true if the previous password supplied to the service was incorrect
+ * @param lastError the previous error @return a password or null if dialog was cancelled.
+ */
+ @Nullable
public String askPassword(final String username, boolean resetPassword, final String lastError) {
String error = processLastError(resetPassword, lastError);
return PasswordSafePromptDialog.askPassword(myProject, myState, GitBundle.getString("ssh.password.title"),
@@ -150,14 +170,26 @@ class GitSSHGUIHandler implements GitSSHService.Handler {
GitSSHGUIHandler.class, "PASSWORD:" + username, resetPassword, error);
}
- @Override
+ /**
+ * Get last successful authentication method. The default implementation returns empty string
+ * meaning that last authentication is unknown or failed.
+ *
+ * @param userName the user name
+ * @return the successful authentication method
+ */
public String getLastSuccessful(String userName) {
SSHConnectionSettings s = SSHConnectionSettings.getInstance();
String rc = s.getLastSuccessful(userName);
return rc == null ? "" : rc;
}
- @Override
+ /**
+ * Set last successful authentication method
+ *
+ * @param userName the user name
+ * @param method the authentication method, the empty string if authentication process failed.
+ * @param error the error to show to user in case when authentication process failed.
+ */
public void setLastSuccessful(String userName, String method, final String error) {
SSHConnectionSettings s = SSHConnectionSettings.getInstance();
s.setLastSuccessful(userName, method);
diff --git a/plugins/git4idea/src/git4idea/commands/GitSSHIdeaService.java b/plugins/git4idea/src/git4idea/commands/GitSSHIdeaService.java
deleted file mode 100644
index 7011dbbf67a5..000000000000
--- a/plugins/git4idea/src/git4idea/commands/GitSSHIdeaService.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2000-2010 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package git4idea.commands;
-
-import com.intellij.ide.XmlRpcServer;
-import com.intellij.openapi.components.ServiceManager;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.git4idea.ssh.GitSSHHandler;
-import org.jetbrains.git4idea.ssh.GitSSHService;
-import org.jetbrains.ide.WebServerManager;
-
-/**
- * The git ssh service implementation that uses IDEA XML RCP service
- */
-public class GitSSHIdeaService extends GitSSHService {
- /**
- * @return an instance of the server
- */
- @NotNull
- public static GitSSHIdeaService getInstance() {
- final GitSSHIdeaService service = ServiceManager.getService(GitSSHIdeaService.class);
- if (service == null) {
- throw new IllegalStateException("The service " + GitSSHIdeaService.class.getName() + " cannot be located");
- }
- return service;
- }
-
- public int getXmlRcpPort() {
- return WebServerManager.getInstance().waitForStart().getPort();
- }
-
- @Override
- protected void addInternalHandler() {
- XmlRpcServer xmlRpcServer = XmlRpcServer.SERVICE.getInstance();
- if (!xmlRpcServer.hasHandler(GitSSHHandler.HANDLER_NAME)) {
- xmlRpcServer.addHandler(GitSSHHandler.HANDLER_NAME, new InternalRequestHandler());
- }
- }
-}
diff --git a/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java b/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java
index 75436608246b..b1500259f4e7 100644
--- a/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitSimpleHandler.java
@@ -192,8 +192,8 @@ public class GitSimpleHandler extends GitTextHandler {
* @throws VcsException exception if process failed to start.
*/
public String run() throws VcsException {
- if (!isNoSSH()) {
- throw new IllegalStateException("Commands that require SSH could not be run using this method");
+ if (isRemote()) {
+ throw new IllegalStateException("Commands that require remote access could not be run using this method");
}
final VcsException[] ex = new VcsException[1];
final String[] result = new String[1];
diff --git a/plugins/git4idea/src/git4idea/config/GitConfigUtil.java b/plugins/git4idea/src/git4idea/config/GitConfigUtil.java
index b5dd005d38b0..4212fe4a2247 100644
--- a/plugins/git4idea/src/git4idea/config/GitConfigUtil.java
+++ b/plugins/git4idea/src/git4idea/config/GitConfigUtil.java
@@ -54,7 +54,6 @@ public class GitConfigUtil {
*/
public static void getValues(Project project, VirtualFile root, String keyMask, Map<String, String> result) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.CONFIG);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("--null");
if (keyMask != null) {
@@ -89,7 +88,6 @@ public class GitConfigUtil {
public static List<Pair<String, String>> getAllValues(Project project, VirtualFile root, @NonNls String key) throws VcsException {
List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.CONFIG);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("--null", "--get-all", key);
String output = h.run();
@@ -116,7 +114,6 @@ public class GitConfigUtil {
@Nullable
public static String getValue(Project project, VirtualFile root, @NonNls String key) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.CONFIG);
- h.setNoSSH(true);
h.setSilent(true);
h.ignoreErrorCode(1);
h.addParameters("--null", "--get", key);
@@ -225,7 +222,6 @@ public class GitConfigUtil {
*/
public static void unsetValue(Project project, VirtualFile root, String key) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.CONFIG);
- h.setNoSSH(true);
h.setSilent(true);
h.ignoreErrorCode(1);
h.addParameters("--unset", key);
@@ -243,7 +239,6 @@ public class GitConfigUtil {
*/
public static void setValue(Project project, VirtualFile root, String key, String value, String... additionalParameters) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.CONFIG);
- h.setNoSSH(true);
h.setSilent(true);
h.ignoreErrorCode(1);
h.addParameters(additionalParameters);
diff --git a/plugins/git4idea/src/git4idea/config/GitVersion.java b/plugins/git4idea/src/git4idea/config/GitVersion.java
index c1abec8539e2..794ca8b500e3 100644
--- a/plugins/git4idea/src/git4idea/config/GitVersion.java
+++ b/plugins/git4idea/src/git4idea/config/GitVersion.java
@@ -60,7 +60,7 @@ public final class GitVersion implements Comparable<GitVersion> {
/**
* The minimal supported version
*/
- public static final GitVersion MIN = new GitVersion(1, 6, 0, 0);
+ public static final GitVersion MIN = new GitVersion(1, 7, 1, 1);
/**
* Special version with a special Type which indicates, that Git version information is unavailable.
diff --git a/plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java b/plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java
index 5545c77b0360..10c133887168 100644
--- a/plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java
+++ b/plugins/git4idea/src/git4idea/diff/GitTreeDiffProvider.java
@@ -55,7 +55,6 @@ public class GitTreeDiffProvider implements TreeDiffProvider {
for (List<String> pathList : VcsFileUtil.chunkPaths(vcsRoot, files)) {
GitSimpleHandler handler = new GitSimpleHandler(myProject, vcsRoot, GitCommand.DIFF);
handler.addParameters("--name-status", "--diff-filter=ADCRUX", "-M", "HEAD..." + searcher.getRemote().getFullName());
- handler.setNoSSH(true);
handler.setSilent(true);
handler.setStdoutSuppressed(true);
handler.endOptions();
diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
index 141dcf710096..d3dedee00d1a 100644
--- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
+++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
@@ -88,7 +88,6 @@ public class GitHistoryUtils {
public static long getHeadTs(final Project project, FilePath filePath) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, GitUtil.getGitRoot(filePath), GitCommand.LOG);
GitLogParser parser = new GitLogParser(project, SHORT_HASH, COMMIT_TIME);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("-n1", parser.getPretty());
h.addParameters("HEAD");
@@ -111,7 +110,6 @@ public class GitHistoryUtils {
filePath = getLastCommitName(project, filePath);
GitSimpleHandler h = new GitSimpleHandler(project, GitUtil.getGitRoot(filePath), GitCommand.LOG);
GitLogParser parser = shortHash ? new GitLogParser(project, SHORT_HASH, COMMIT_TIME) : new GitLogParser(project, HASH, COMMIT_TIME);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("-n1", parser.getPretty());
h.addParameters(!StringUtil.isEmpty(branch) ? branch : "--all");
@@ -134,7 +132,6 @@ public class GitHistoryUtils {
filePath = getLastCommitName(project, filePath);
GitSimpleHandler h = new GitSimpleHandler(project, GitUtil.getGitRoot(filePath), GitCommand.LOG);
GitLogParser parser = new GitLogParser(project, HASH, COMMIT_TIME, AUTHOR_NAME, COMMITTER_NAME, SUBJECT, BODY, RAW_BODY);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("-n1", parser.getPretty());
if (branch != null && !branch.isEmpty()) {
@@ -179,7 +176,6 @@ public class GitHistoryUtils {
filePath = getLastCommitName(project, filePath);
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, HASH, COMMIT_TIME, SHORT_PARENTS);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("-n1", parser.getPretty(), "--name-status", t.getFullName());
h.endOptions();
@@ -202,9 +198,9 @@ public class GitHistoryUtils {
if (! GitUtil.isGitRoot(new File(root.getPath()))) throw new VcsException("Path " + root.getPath() + " is not git repository root");
final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG);
- h.setNoSSH(true);
h.setSilent(true);
- h.addParameters("--branches", "--remotes", "--tags", "--pretty=format:%H%x20%ct%x0A", "--date-order", "--reverse", "--encoding=UTF-8", "--full-history",
+ h.addParameters("HEAD", "--branches", "--remotes", "--tags",
+ "--pretty=format:%H%x20%ct%x0A", "--date-order", "--reverse", "--encoding=UTF-8", "--full-history",
"--sparse");
h.endOptions();
@@ -447,7 +443,6 @@ public class GitHistoryUtils {
private static GitLineHandler getLogHandler(Project project, VirtualFile root, GitLogParser parser, FilePath path, String lastCommit, String... parameters) {
final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG);
- h.setNoSSH(true);
h.setStdoutSuppressed(true);
h.addParameters("--name-status", parser.getPretty(), "--encoding=UTF-8", lastCommit);
if (parameters != null && parameters.length > 0) {
@@ -469,7 +464,6 @@ public class GitHistoryUtils {
// NB: we can't specify the filepath, because then rename detection will work only with the '--follow' option, which we don't wanna use.
final GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.SHOW);
final GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, HASH, COMMIT_TIME, SHORT_PARENTS);
- h.setNoSSH(true);
h.setStdoutSuppressed(true);
h.addParameters("-M", "--name-status", parser.getPretty(), "--encoding=UTF-8", commit);
h.endOptions();
@@ -578,7 +572,6 @@ public class GitHistoryUtils {
path = getLastCommitName(project, path);
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
GitLogParser parser = new GitLogParser(project, HASH, COMMIT_TIME);
- h.setNoSSH(true);
h.setStdoutSuppressed(true);
h.addParameters(parameters);
h.addParameters(parser.getPretty(), "--encoding=UTF-8");
@@ -626,7 +619,6 @@ public class GitHistoryUtils {
final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG);
final GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, SHORT_HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL,
COMMITTER_NAME, COMMITTER_EMAIL, SHORT_PARENTS, REF_NAMES, SUBJECT, BODY, RAW_BODY);
- h.setNoSSH(true);
h.setStdoutSuppressed(true);
h.addParameters(parameters);
h.addParameters("--name-status", parser.getPretty(), "--encoding=UTF-8");
@@ -763,7 +755,6 @@ public class GitHistoryUtils {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH.readLockingCommand());
GitLogParser parser = new GitLogParser(project, SHORT_HASH, SHORT_PARENTS);
h.setSilent(true);
- h.setNoSSH(true);
h.addParameters("list");
h.addParameters("-n1");
h.addParameters(parser.getPretty());
@@ -778,7 +769,6 @@ public class GitHistoryUtils {
GitSimpleHandler h1 = new GitSimpleHandler(project, root, GitCommand.LOG);
GitLogParser parser1 = new GitLogParser(project, SHORT_HASH, SHORT_PARENTS, SUBJECT);
h1.setSilent(true);
- h1.setNoSSH(true);
h1.addParameters("-n1");
h1.addParameters(parser1.getPretty());
//h1.endOptions();
@@ -813,7 +803,6 @@ public class GitHistoryUtils {
GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, SHORT_HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME,
COMMITTER_EMAIL, SHORT_PARENTS, REF_NAMES, SHORT_REF_LOG_SELECTOR, SUBJECT, BODY, RAW_BODY);
h.setSilent(true);
- h.setNoSSH(true);
h.addParameters("list");
h.addParameters(parameters);
h.addParameters(parser.getPretty());
@@ -840,7 +829,6 @@ public class GitHistoryUtils {
GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS,
SHORT_HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME,
COMMITTER_EMAIL, SHORT_PARENTS, REF_NAMES, SUBJECT, BODY, RAW_BODY);
- h.setNoSSH(true);
h.setStdoutSuppressed(true);
h.addParameters("--name-status", "-M", parser.getPretty(), "--encoding=UTF-8");
h.addParameters(new ArrayList<String>(commitsIds));
@@ -860,7 +848,6 @@ public class GitHistoryUtils {
final VirtualFile root = GitUtil.getGitRoot(path);
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.SHOW);
GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, AUTHOR_TIME);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("--name-status", parser.getPretty(), "--encoding=UTF-8");
h.addParameters(commitsId);
@@ -878,7 +865,6 @@ public class GitHistoryUtils {
final VirtualFile root = GitUtil.getGitRoot(path);
final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG);
final GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.NAME, SHORT_HASH, COMMIT_TIME, SHORT_PARENTS, AUTHOR_NAME);
- h.setNoSSH(true);
h.setStdoutSuppressed(true);
h.addParameters(parameters);
h.addParameters(parser.getPretty(), "--encoding=UTF-8", "--full-history");
@@ -953,7 +939,6 @@ public class GitHistoryUtils {
@NotNull final String second)
throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.MERGE_BASE);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters(first, second);
String output = h.run().trim();
diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java
index fe9b068fb2c7..6d255bdea893 100644
--- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java
+++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java
@@ -76,6 +76,7 @@ public class LowLevelAccessImpl implements LowLevelAccess {
parameters.add(startingPoint);
}
} else {
+ parameters.add("HEAD");
parameters.add("--branches");
parameters.add("--remotes");
parameters.add("--tags");
@@ -160,6 +161,7 @@ public class LowLevelAccessImpl implements LowLevelAccess {
parameters.add(startingPoint);
}
} else {
+ parameters.add("HEAD");
parameters.add("--branches");
parameters.add("--remotes");
parameters.add("--tags");
@@ -205,7 +207,6 @@ public class LowLevelAccessImpl implements LowLevelAccess {
@Nullable String containingCommit) throws VcsException {
// preparing native command executor
final GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.BRANCH);
- handler.setNoSSH(true);
handler.setSilent(true);
handler.addParameters("--no-color");
boolean remoteOnly = false;
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
index 552e8d31a1bb..9658cb9e8c9f 100644
--- a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,12 +54,14 @@ import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBList;
import com.intellij.ui.table.JBTable;
import com.intellij.util.*;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.AdjustComponentWhenShown;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.UIUtil;
+import com.intellij.vcsUtil.MoreAction;
import git4idea.GitUtil;
import git4idea.GitVcs;
import git4idea.branch.GitBranchUtil;
@@ -1158,12 +1160,11 @@ public class GitLogUI implements Disposable {
}
private static class CommentSearchContext {
- private final List<HighlightingRendererBase> myListeners;
+ private final List<HighlightingRendererBase> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private final List<String> mySearchContext;
private CommentSearchContext() {
mySearchContext = new ArrayList<String>();
- myListeners = new ArrayList<HighlightingRendererBase>();
}
public void addHighlighter(final HighlightingRendererBase renderer) {
@@ -1772,7 +1773,7 @@ public class GitLogUI implements Disposable {
}
interface Colors {
- Color tag = new JBColor(new Color(0xf1ef9e), new Color(0x7D7B12));
+ Color tag = new JBColor(new Color(0xf1ef9e), new Color(113, 111, 64));
Color remote = new JBColor(new Color(0xbcbcfc), new Color(0xbcbcfc).darker().darker());
Color local = new JBColor(new Color(0x75eec7), new Color(0x0D6D4F));
Color highlighted = new JBColor(new Color(210,255,233), UIUtil.getTableBackground());
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/MoreAction.java b/plugins/git4idea/src/git4idea/history/wholeTree/MoreAction.java
deleted file mode 100644
index 0898634d17e0..000000000000
--- a/plugins/git4idea/src/git4idea/history/wholeTree/MoreAction.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2000-2010 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package git4idea.history.wholeTree;
-
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
-import com.intellij.util.ui.UIUtil;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-/**
- * @author irengrig
- */
-public abstract class MoreAction extends AnAction implements CustomComponentAction {
- public static final String LOAD_MORE = "Load more";
- protected final JLabel myLabel;
- private final JPanel myPanel;
- private boolean myEnabled;
- private boolean myVisible;
- private JButton myLoadMoreBtn;
-
- protected MoreAction() {
- myPanel = new JPanel();
- final BoxLayout layout = new BoxLayout(myPanel, BoxLayout.X_AXIS);
- myPanel.setLayout(layout);
- myLoadMoreBtn = new JButton(LOAD_MORE);
- myLoadMoreBtn.setMargin(new Insets(2, 2, 2, 2));
- myLoadMoreBtn.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- MoreAction.this.actionPerformed(null);
- }
- });
- myPanel.add(myLoadMoreBtn);
- myLabel = new JLabel("Loading...");
- myLabel.setForeground(UIUtil.getInactiveTextColor());
- myLabel.setBorder(BorderFactory.createEmptyBorder(1, 3, 1, 1));
- myPanel.add(myLabel);
- }
-
- @Override
- public JComponent createCustomComponent(Presentation presentation) {
- return myPanel;
- }
-
- public void setEnabled(boolean enabled) {
- myEnabled = enabled;
- myLoadMoreBtn.setVisible(myEnabled);
- myLabel.setVisible(! myEnabled);
- //myLabel.setText(myEnabled ? "Load more" : "Loading...");
- //myLabel.setForeground(myEnabled ? UIUtil.getTextFieldForeground() : UIUtil.getInactiveTextColor());
- }
-
- @Override
- public void update(AnActionEvent e) {
- e.getPresentation().setEnabled(myEnabled);
- e.getPresentation().setVisible(myVisible);
- }
-
- public void setVisible(boolean b) {
- myVisible = b;
- }
-}
diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
index 275c9ed2015e..e155b0b77b14 100644
--- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
+++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
@@ -484,7 +484,6 @@ util.remote.renderer.none=<html><i>None</i></html>
util.remote.renderer.normal=<html><b>{0}</b>(<i>{1}</i>)</html>
util.remote.renderer.self=<html><i>Current repository</i></html>
vcs.unable.to.run.git=Unable to run git: {0} ({1})
-vcs.unsupported.version=Unsupported version of Git configured: {0}. The minimal supported version is {1}
vfs.listener.add.single.prompt=Do you want to add the following file to Git?\n{0}\n\nIf you say No, you can still add it later manually.
vfs.listener.add.single.title=Add File to Git
vfs.listener.add.title=Add Files to Git
diff --git a/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java b/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java
index 96f5fb9014ec..dc468653b6f5 100644
--- a/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java
+++ b/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java
@@ -34,7 +34,6 @@ import git4idea.repo.GitRemote;
import git4idea.repo.GitRepository;
import git4idea.update.GitFetchResult;
import git4idea.update.GitFetcher;
-import git4idea.util.NetrcData;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
@@ -52,7 +51,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -60,7 +58,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.regex.Pattern;
/**
* Handles remote operations over HTTP via JGit library.
@@ -71,32 +68,12 @@ public final class GitHttpAdapter {
private static final Logger LOG = Logger.getInstance(GitHttpAdapter.class);
- private static final Pattern HTTP_URL_WITH_USERNAME_AND_PASSWORD = Pattern.compile("http(s?)://([^\\s^@:]+):([^\\s^@:]+)@.*");
private static final String IGNORECASE_SETTING = "ignorecase";
public static boolean shouldUseJGit(@NotNull String url) {
- if (!url.startsWith("http")) {
- return false;
- }
- // if username & password are specified in the url, give it to the native Git
- if (HTTP_URL_WITH_USERNAME_AND_PASSWORD.matcher(url).matches()) {
- return false;
- }
-
- try {
- NetrcData netrcData = NetrcData.parse();
- return !netrcData.hasAuthDataForUrl(url);
- }
- catch (FileNotFoundException e) {
- return true;
- }
- catch (IOException e) {
- LOG.warn("Couldn't read netrc file", e);
- return true;
- }
+ return "jgit".equals(System.getProperty("git.http"));
}
-
private enum GeneralResult {
SUCCESS,
CANCELLED,
diff --git a/plugins/git4idea/src/git4idea/merge/GitMergeDialog.java b/plugins/git4idea/src/git4idea/merge/GitMergeDialog.java
index 78d0ee99da6d..294227718670 100644
--- a/plugins/git4idea/src/git4idea/merge/GitMergeDialog.java
+++ b/plugins/git4idea/src/git4idea/merge/GitMergeDialog.java
@@ -156,7 +156,6 @@ public class GitMergeDialog extends DialogWrapper {
public void updateBranches() throws VcsException {
VirtualFile root = getSelectedRoot();
GitSimpleHandler handler = new GitSimpleHandler(myProject, root, GitCommand.BRANCH);
- handler.setNoSSH(true);
handler.setSilent(true);
handler.addParameters("--no-color", "-a", "--no-merged");
String output = handler.run();
@@ -178,7 +177,6 @@ public class GitMergeDialog extends DialogWrapper {
GitLineHandler h = new GitLineHandler(myProject, root, GitCommand.MERGE);
// ignore merge failure
h.ignoreErrorCode(1);
- h.setNoSSH(true);
if (myNoCommitCheckBox.isSelected()) {
h.addParameters("--no-commit");
}
diff --git a/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java b/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java
index 4094af361950..a2bc9e4794a6 100644
--- a/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java
+++ b/plugins/git4idea/src/git4idea/merge/GitMergeProvider.java
@@ -288,7 +288,6 @@ public class GitMergeProvider implements MergeProvider2 {
VirtualFile root = e.getKey();
List<VirtualFile> files = e.getValue();
GitSimpleHandler h = new GitSimpleHandler(myProject, root, GitCommand.LS_FILES);
- h.setNoSSH(true);
h.setStdoutSuppressed(true);
h.setSilent(true);
h.addParameters("--exclude-standard", "--unmerged", "-t", "-z");
diff --git a/plugins/git4idea/src/git4idea/merge/GitMerger.java b/plugins/git4idea/src/git4idea/merge/GitMerger.java
index 4605aeb405d0..4a94c720635a 100644
--- a/plugins/git4idea/src/git4idea/merge/GitMerger.java
+++ b/plugins/git4idea/src/git4idea/merge/GitMerger.java
@@ -65,7 +65,6 @@ public class GitMerger {
public void mergeCommit(VirtualFile root) throws VcsException {
GitSimpleHandler handler = new GitSimpleHandler(myProject, root, GitCommand.COMMIT);
- handler.setNoSSH(true);
File gitDir = new File(VfsUtilCore.virtualToIoFile(root), GitUtil.DOT_GIT);
File messageFile = new File(gitDir, GitRepositoryFiles.MERGE_MSG);
diff --git a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
index d44804cb59ab..2daf8a972726 100644
--- a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
+++ b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
@@ -153,13 +153,12 @@ public class GitPullDialog extends DialogWrapper {
/**
* @return a pull handler configured according to dialog options
*/
- public GitLineHandler pullOrMergeHandler(boolean pull) {
- GitLineHandler h = new GitLineHandler(myProject, gitRoot(), pull ? GitCommand.PULL : GitCommand.MERGE);
+ public GitLineHandler makeHandler(@NotNull String url) {
+ GitLineHandler h = new GitLineHandler(myProject, gitRoot(), GitCommand.PULL);
// ignore merge failure for the pull
h.ignoreErrorCode(1);
- if (pull) {
- h.addProgressParameter();
- }
+ h.setUrl(url);
+ h.addProgressParameter();
h.addParameters("--no-stat");
if (myNoCommitCheckBox.isSelected()) {
h.addParameters("--no-commit");
@@ -180,24 +179,15 @@ public class GitPullDialog extends DialogWrapper {
h.addParameters("--strategy", strategy);
}
h.addParameters("-v");
- if (pull) {
- h.addProgressParameter();
- }
+ h.addProgressParameter();
final List<String> markedBranches = myBranchChooser.getMarkedElements();
String remote = getRemote();
LOG.assertTrue(remote != null, "Selected remote can't be null here.");
- if (pull) {
- // git pull origin master (remote branch name in the format local to that remote)
- h.addParameters(remote);
- for (String branch : markedBranches) {
- h.addParameters(removeRemotePrefix(branch, remote));
- }
- } else {
- // git merge origin/master (remote branch name in format of this repository)
- for (String branch : markedBranches) {
- h.addParameters(branch);
- }
+ // git pull origin master (remote branch name in the format local to that remote)
+ h.addParameters(remote);
+ for (String branch : markedBranches) {
+ h.addParameters(removeRemotePrefix(branch, remote));
}
return h;
}
diff --git a/plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java b/plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java
index fbd99cf2ad6d..c72e738851fa 100644
--- a/plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java
+++ b/plugins/git4idea/src/git4idea/merge/MergeChangeCollector.java
@@ -84,7 +84,6 @@ public class MergeChangeCollector {
public @NotNull Set<String> getUnmergedPaths() throws VcsException {
String root = myRoot.getPath();
final GitSimpleHandler h = new GitSimpleHandler(myProject, myRoot, GitCommand.LS_FILES);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("--unmerged");
final String result = h.run();
@@ -158,7 +157,6 @@ public class MergeChangeCollector {
String root = myRoot.getPath();
GitSimpleHandler h = new GitSimpleHandler(myProject, myRoot, GitCommand.DIFF);
h.setSilent(true);
- h.setNoSSH(true);
// note that moves are not detected here
h.addParameters("--name-status", "--diff-filter=ADMRUX", revisions);
for (StringScanner s = new StringScanner(h.run()); s.hasMoreData();) {
diff --git a/plugins/git4idea/src/git4idea/push/GitPushLog.java b/plugins/git4idea/src/git4idea/push/GitPushLog.java
index 8c492ed2e770..9fc48df5fa12 100644
--- a/plugins/git4idea/src/git4idea/push/GitPushLog.java
+++ b/plugins/git4idea/src/git4idea/push/GitPushLog.java
@@ -371,7 +371,6 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider {
GitBranch dest = branchInfo.getDestBranch();
GitPushBranchInfo.Type type = branchInfo.getType();
- final String showingRecentCommits = ", showing " + GitPusher.RECENT_COMMITS_NUMBER + " recent commits";
String text = fromBranch.getName();
SimpleTextAttributes attrs = SimpleTextAttributes.REGULAR_ATTRIBUTES;
String additionalText = "";
@@ -385,11 +384,11 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider {
case NEW_BRANCH:
text += " -> +" + dest.getName();
attrs = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
- additionalText = " new branch will be created" + showingRecentCommits;
+ additionalText = " new branch will be created.";
break;
case NO_TRACKED_OR_TARGET:
attrs = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
- additionalText = " no tracked branch. Use checkbox below to push branch to manually specified" + showingRecentCommits;
+ additionalText = " no tracked branch. Use checkbox below to push branch to manually specified.";
break;
}
renderer.append(text, attrs);
diff --git a/plugins/git4idea/src/git4idea/push/GitPusher.java b/plugins/git4idea/src/git4idea/push/GitPusher.java
index 251b55f50933..e56d15c1b6c4 100644
--- a/plugins/git4idea/src/git4idea/push/GitPusher.java
+++ b/plugins/git4idea/src/git4idea/push/GitPusher.java
@@ -59,11 +59,6 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public final class GitPusher {
- /**
- * if diff-log is not available (new branch is created, for example), we show a few recent commits made on the branch
- */
- static final int RECENT_COMMITS_NUMBER = 5;
-
@Deprecated
static final GitRemoteBranch NO_TARGET_BRANCH = new GitStandardRemoteBranch(GitRemote.DOT, "", GitBranch.DUMMY_HASH);
@@ -187,7 +182,7 @@ public final class GitPusher {
List<GitCommit> commits;
GitPushBranchInfo.Type type;
if (dest == NO_TARGET_BRANCH) {
- commits = collectRecentCommitsOnBranch(repository, source);
+ commits = collectCommitsToPushForNewBranch(repository, source, dest.getRemote());
type = GitPushBranchInfo.Type.NO_TRACKED_OR_TARGET;
}
else if (GitUtil.repoContainsRemoteBranch(repository, dest)) {
@@ -195,7 +190,7 @@ public final class GitPusher {
type = GitPushBranchInfo.Type.STANDARD;
}
else {
- commits = collectRecentCommitsOnBranch(repository, source);
+ commits = collectCommitsToPushForNewBranch(repository, source, dest.getRemote());
type = GitPushBranchInfo.Type.NEW_BRANCH;
}
commitsByBranch.put(source, new GitPushBranchInfo(source, dest, commits, type));
@@ -204,8 +199,13 @@ public final class GitPusher {
return new GitCommitsByBranch(commitsByBranch);
}
- private List<GitCommit> collectRecentCommitsOnBranch(GitRepository repository, GitBranch source) throws VcsException {
- return GitHistoryUtils.history(myProject, repository.getRoot(), "--max-count=" + RECENT_COMMITS_NUMBER, source.getName());
+ @NotNull
+ private static List<GitCommit> collectCommitsToPushForNewBranch(@NotNull GitRepository repository, @NotNull GitBranch source,
+ @NotNull GitRemote remote) throws VcsException {
+ // `git log new_branch --not --remotes=origin`
+ // shows all commits that are in the given branch, but not in any remote branches in the given remote
+ return GitHistoryUtils.history(repository.getProject(), repository.getRoot(),
+ source.getName(), "--not", "--remotes=" + remote.getName());
}
@NotNull
@@ -318,21 +318,18 @@ public final class GitPusher {
}
GitRemote remote = pushSpec.getRemote();
- String httpUrl = null;
- for (String pushUrl : remote.getPushUrls()) {
- if (GitHttpAdapter.shouldUseJGit(pushUrl)) {
- httpUrl = pushUrl;
- break; // TODO support http and ssh urls in one origin
- }
+ Collection<String> pushUrls = remote.getPushUrls();
+ if (pushUrls.isEmpty()) {
+ LOG.error("No urls or pushUrls are defined for " + remote);
+ return GitSimplePushResult.error("There are no URLs defined for remote " + remote.getName());
}
-
+ String url = pushUrls.iterator().next();
GitSimplePushResult pushResult;
- boolean pushOverHttp = httpUrl != null;
- if (pushOverHttp) {
- pushResult = GitHttpAdapter.push(repository, remote.getName(), httpUrl, formPushSpec(pushSpec, remote));
+ if (GitHttpAdapter.shouldUseJGit(url)) {
+ pushResult = GitHttpAdapter.push(repository, remote.getName(), url, formPushSpec(pushSpec, remote));
}
else {
- pushResult = pushNatively(repository, pushSpec);
+ pushResult = pushNatively(repository, pushSpec, url);
}
if (pushResult.getType() == GitSimplePushResult.Type.SUCCESS) {
@@ -396,10 +393,10 @@ public final class GitPusher {
}
@NotNull
- private GitSimplePushResult pushNatively(GitRepository repository, GitPushSpec pushSpec) {
+ private GitSimplePushResult pushNatively(GitRepository repository, GitPushSpec pushSpec, @NotNull String url) {
GitPushRejectedDetector rejectedDetector = new GitPushRejectedDetector();
GitLineHandlerListener progressListener = GitStandardProgressAnalyzer.createListener(myProgressIndicator);
- GitCommandResult res = myGit.push(repository, pushSpec, rejectedDetector, progressListener);
+ GitCommandResult res = myGit.push(repository, pushSpec, url, rejectedDetector, progressListener);
if (rejectedDetector.rejected()) {
Collection<String> rejectedBranches = rejectedDetector.getRejectedBranches();
return GitSimplePushResult.reject(rejectedBranches);
diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java b/plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java
index 19828846ceab..97d58b70681c 100644
--- a/plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java
+++ b/plugins/git4idea/src/git4idea/rebase/GitRebaseDialog.java
@@ -163,7 +163,6 @@ public class GitRebaseDialog extends DialogWrapper {
public GitLineHandler handler() {
GitLineHandler h = new GitLineHandler(myProject, gitRoot(), GitCommand.REBASE);
- h.setNoSSH(true);
if (myInteractiveCheckBox.isSelected() && myInteractiveCheckBox.isEnabled()) {
h.addParameters("-i");
}
diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaser.java b/plugins/git4idea/src/git4idea/rebase/GitRebaser.java
index ba28df93c802..aeee09c6931a 100644
--- a/plugins/git4idea/src/git4idea/rebase/GitRebaser.java
+++ b/plugins/git4idea/src/git4idea/rebase/GitRebaser.java
@@ -225,7 +225,6 @@ public class GitRebaser {
private void stageEverything(@NotNull VirtualFile root) throws VcsException {
GitSimpleHandler handler = new GitSimpleHandler(myProject, root, GitCommand.ADD);
handler.setSilent(false);
- handler.setNoSSH(true);
handler.addParameters("--update");
handler.run();
}
diff --git a/plugins/git4idea/src/git4idea/repo/GitFakeRepositoryManager.java b/plugins/git4idea/src/git4idea/repo/GitFakeRepositoryManager.java
deleted file mode 100644
index 0fa77affd281..000000000000
--- a/plugins/git4idea/src/git4idea/repo/GitFakeRepositoryManager.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package git4idea.repo;
-
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Kirill Likhodedov
- */
-public class GitFakeRepositoryManager implements GitRepositoryManager {
-
- private final List<GitRepository> myRepositories = new ArrayList<GitRepository>();
-
- public void add(GitRepository repository) {
- myRepositories.add(repository);
- }
-
- @Override
- public GitRepository getRepositoryForRoot(@Nullable VirtualFile root) {
- for (GitRepository repository : myRepositories) {
- if (repository.getRoot().equals(root)) {
- return repository;
- }
- }
- return null;
- }
-
- @Nullable
- @Override
- public GitRepository getRepositoryForFile(@NotNull VirtualFile file) {
- return null;
- }
-
- @Override
- public GitRepository getRepositoryForFile(@NotNull FilePath file) {
- return null;
- }
-
- @NotNull
- @Override
- public List<GitRepository> getRepositories() {
- return new ArrayList<GitRepository>(myRepositories);
- }
-
- @Override
- public boolean moreThanOneRoot() {
- return myRepositories.size() > 1;
- }
-
- @Override
- public void updateRepository(VirtualFile root) {
- }
-
- @Override
- public void updateAllRepositories() {
- }
-}
diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java
index 1d8d3c6c2377..97c3cc2a4526 100644
--- a/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java
+++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java
@@ -16,6 +16,7 @@
package git4idea.repo;
import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -29,7 +30,10 @@ import git4idea.roots.GitRootScanner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
@@ -59,8 +63,9 @@ public class GitRepositoryManagerImpl extends AbstractProjectComponent implement
myVcs = myPlatformFacade.getVcs(myProject);
Disposer.register(myProject, this);
myProject.getMessageBus().connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, this);
- GitRootScanner rootScanner = new GitRootScanner(myProject);
- Disposer.register(this, rootScanner);
+ if (!ApplicationManager.getApplication().isUnitTestMode()) {
+ GitRootScanner.start(myProject);
+ }
}
@Override
diff --git a/plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java b/plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java
index 9c67e64fe7fe..00f1830e6255 100644
--- a/plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java
+++ b/plugins/git4idea/src/git4idea/rollback/GitRollbackEnvironment.java
@@ -179,7 +179,6 @@ public class GitRollbackEnvironment implements RollbackEnvironment {
public void revert(final VirtualFile root, final List<FilePath> files) throws VcsException {
for (List<String> paths : VcsFileUtil.chunkPaths(root, files)) {
GitSimpleHandler handler = new GitSimpleHandler(myProject, root, GitCommand.CHECKOUT);
- handler.setNoSSH(true);
handler.addParameters("HEAD");
handler.endOptions();
handler.addParameters(paths);
@@ -247,7 +246,6 @@ public class GitRollbackEnvironment implements RollbackEnvironment {
public static void resetHardLocal(final Project project, final VirtualFile root) {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.RESET);
- handler.setNoSSH(true);
handler.addParameters("--hard");
handler.endOptions();
GitHandlerUtil.runInCurrentThread(handler, null);
diff --git a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java
index 226f8932b603..fb1612771653 100644
--- a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java
+++ b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java
@@ -16,7 +16,7 @@
package git4idea.roots;
import com.intellij.ProjectTopics;
-import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootEvent;
@@ -38,7 +38,7 @@ import java.util.concurrent.TimeUnit;
/**
* @author Kirill Likhodedov
*/
-public class GitRootScanner implements BulkFileListener, ModuleRootListener, Disposable, VcsListener {
+public class GitRootScanner implements BulkFileListener, ModuleRootListener, VcsListener {
@NotNull private final GitRootProblemNotifier myRootProblemNotifier;
@@ -48,7 +48,11 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
@NotNull private final Alarm myAlarm;
private static final long WAIT_BEFORE_SCAN = TimeUnit.SECONDS.toMillis(1);
- public GitRootScanner(@NotNull Project project) {
+ public static void start(@NotNull Project project) {
+ new GitRootScanner(project);
+ }
+
+ private GitRootScanner(@NotNull Project project) {
myRootProblemNotifier = GitRootProblemNotifier.getInstance(project);
StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
@@ -68,10 +72,6 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
}
@Override
- public void dispose() {
- }
-
- @Override
public void before(@NotNull List<? extends VFileEvent> events) {
}
@@ -111,6 +111,10 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
}
private void scheduleScan() {
+ if (myAlarm.isDisposed()) {
+ return;
+ }
+
myAlarm.cancelAllRequests(); // one scan is enough, no need to queue, they all do the same
myAlarm.addRequest(new Runnable() {
@Override
diff --git a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java
index 90cfac4153c6..e1da8a349d8a 100644
--- a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java
+++ b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java
@@ -56,7 +56,6 @@ public class GitStashUtils {
final Consumer<StashInfo> consumer) {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH.readLockingCommand());
h.setSilent(true);
- h.setNoSSH(true);
h.addParameters("list");
String out;
try {
diff --git a/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java b/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java
index b231ec1c14f2..a2188b74bcda 100644
--- a/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java
+++ b/plugins/git4idea/src/git4idea/status/GitNewChangesCollector.java
@@ -121,7 +121,6 @@ class GitNewChangesCollector extends GitChangesCollector {
GitSimpleHandler handler = new GitSimpleHandler(myProject, myVcsRoot, GitCommand.STATUS);
final String[] params = {"--porcelain", "-z", "--untracked-files=no"}; // untracked files are stored separately
handler.addParameters(params);
- handler.setNoSSH(true);
handler.setSilent(true);
handler.setStdoutSuppressed(true);
handler.endOptions();
@@ -130,7 +129,6 @@ class GitNewChangesCollector extends GitChangesCollector {
// if there are too much files, just get all changes for the project
handler = new GitSimpleHandler(myProject, myVcsRoot, GitCommand.STATUS);
handler.addParameters(params);
- handler.setNoSSH(true);
handler.setSilent(true);
handler.setStdoutSuppressed(true);
handler.endOptions();
diff --git a/plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java b/plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java
index 9e9354e60399..17ef984c6557 100644
--- a/plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java
+++ b/plugins/git4idea/src/git4idea/status/GitOldChangesCollector.java
@@ -134,7 +134,6 @@ class GitOldChangesCollector extends GitChangesCollector {
GitSimpleHandler handler = new GitSimpleHandler(myProject, myVcsRoot, GitCommand.UPDATE_INDEX);
handler.addParameters("--refresh", "--ignore-missing");
handler.setSilent(true);
- handler.setNoSSH(true);
handler.setStdoutSuppressed(true);
handler.ignoreErrorCode(1);
handler.run();
@@ -161,7 +160,6 @@ class GitOldChangesCollector extends GitChangesCollector {
}
GitSimpleHandler handler = new GitSimpleHandler(myProject, myVcsRoot, GitCommand.LS_FILES);
handler.addParameters("--cached");
- handler.setNoSSH(true);
handler.setSilent(true);
handler.setStdoutSuppressed(true);
// During init diff does not works because HEAD
@@ -193,7 +191,6 @@ class GitOldChangesCollector extends GitChangesCollector {
GitSimpleHandler handler = new GitSimpleHandler(myProject, myVcsRoot, GitCommand.LS_FILES);
handler.addParameters("-v", "--unmerged");
handler.setSilent(true);
- handler.setNoSSH(true);
handler.setStdoutSuppressed(true);
// run handler and collect changes
parseFiles(handler.run());
@@ -201,7 +198,6 @@ class GitOldChangesCollector extends GitChangesCollector {
handler = new GitSimpleHandler(myProject, myVcsRoot, GitCommand.LS_FILES);
handler.addParameters("-v", "--others", "--exclude-standard");
handler.setSilent(true);
- handler.setNoSSH(true);
handler.setStdoutSuppressed(true);
handler.endOptions();
handler.addRelativePaths(dirtyPaths);
@@ -209,7 +205,6 @@ class GitOldChangesCollector extends GitChangesCollector {
handler = new GitSimpleHandler(myProject, myVcsRoot, GitCommand.LS_FILES);
handler.addParameters("-v", "--others", "--exclude-standard");
handler.setSilent(true);
- handler.setNoSSH(true);
handler.setStdoutSuppressed(true);
handler.endOptions();
}
diff --git a/plugins/git4idea/src/git4idea/ui/GitResetDialog.java b/plugins/git4idea/src/git4idea/ui/GitResetDialog.java
index a208052d36bd..6600ee256acd 100644
--- a/plugins/git4idea/src/git4idea/ui/GitResetDialog.java
+++ b/plugins/git4idea/src/git4idea/ui/GitResetDialog.java
@@ -118,7 +118,6 @@ public class GitResetDialog extends DialogWrapper {
*/
public GitLineHandler handler() {
GitLineHandler handler = new GitLineHandler(myProject, getGitRoot(), GitCommand.RESET);
- handler.setNoSSH(true);
String type = (String)myResetTypeComboBox.getSelectedItem();
if (SOFT.equals(type)) {
handler.addParameters("--soft");
diff --git a/plugins/git4idea/src/git4idea/ui/GitTagDialog.java b/plugins/git4idea/src/git4idea/ui/GitTagDialog.java
index e81d49541e02..aafb3b05db0f 100644
--- a/plugins/git4idea/src/git4idea/ui/GitTagDialog.java
+++ b/plugins/git4idea/src/git4idea/ui/GitTagDialog.java
@@ -180,7 +180,6 @@ public class GitTagDialog extends DialogWrapper {
}
try {
GitSimpleHandler h = new GitSimpleHandler(myProject, getGitRoot(), GitCommand.TAG);
- h.setNoSSH(true);
if (hasMessage) {
h.addParameters("-a");
}
@@ -250,7 +249,6 @@ public class GitTagDialog extends DialogWrapper {
private void fetchTags() {
myExistingTags.clear();
GitSimpleHandler h = new GitSimpleHandler(myProject, getGitRoot(), GitCommand.TAG);
- h.setNoSSH(true);
h.setSilent(true);
String output = GitHandlerUtil.doSynchronously(h, GitBundle.getString("tag.getting.existing.tags"), h.printableCommandLine());
for (StringScanner s = new StringScanner(output); s.hasMoreData();) {
diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
index 0e3b7175ccd6..a6790ddb3a5f 100644
--- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
+++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
@@ -163,7 +163,6 @@ public class GitUnstashDialog extends DialogWrapper {
GitBundle.message("git.unstash.clear.confirmation.message"),
GitBundle.message("git.unstash.clear.confirmation.title"), Messages.getWarningIcon())) {
GitLineHandler h = new GitLineHandler(myProject, getGitRoot(), GitCommand.STASH);
- h.setNoSSH(true);
h.addParameters("clear");
GitHandlerUtil.doSynchronously(h, GitBundle.getString("unstash.clearing.stashes"), h.printableCommandLine());
refreshStashList();
@@ -203,7 +202,6 @@ public class GitUnstashDialog extends DialogWrapper {
private GitSimpleHandler dropHandler(String stash) {
GitSimpleHandler h = new GitSimpleHandler(myProject, getGitRoot(), GitCommand.STASH);
- h.setNoSSH(true);
h.addParameters("drop");
addStashParameter(h, stash);
return h;
@@ -216,7 +214,6 @@ public class GitUnstashDialog extends DialogWrapper {
String selectedStash = getSelectedStash().getStash();
try {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.REV_LIST);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters("--timestamp", "--max-count=1");
addStashParameter(h, selectedStash);
@@ -343,7 +340,6 @@ public class GitUnstashDialog extends DialogWrapper {
*/
private GitLineHandler handler() {
GitLineHandler h = new GitLineHandler(myProject, getGitRoot(), GitCommand.STASH);
- h.setNoSSH(true);
String branch = myBranchTextField.getText();
if (branch.length() == 0) {
h.addParameters(myPopStashCheckBox.isSelected() ? "pop" : "apply");
diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java
index c904ab769a35..7925ca720362 100644
--- a/plugins/git4idea/src/git4idea/update/GitFetcher.java
+++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java
@@ -132,7 +132,7 @@ public class GitFetcher {
if (GitHttpAdapter.shouldUseJGit(url)) {
return GitHttpAdapter.fetch(repository, remote, url, null);
}
- return fetchNatively(repository.getRoot(), remote, null);
+ return fetchNatively(repository.getRoot(), remote, url, null);
}
// leaving this unused method, because the wanted behavior can change again
@@ -150,7 +150,7 @@ public class GitFetcher {
if (GitHttpAdapter.shouldUseJGit(url)) {
return GitHttpAdapter.fetch(repository, remote, url, remoteBranch);
}
- return fetchNatively(repository.getRoot(), remote, remoteBranch);
+ return fetchNatively(repository.getRoot(), remote, url, remoteBranch);
}
@NotNull
@@ -198,7 +198,7 @@ public class GitFetcher {
}
}
else {
- GitFetchResult res = fetchNatively(repository.getRoot(), remote, null);
+ GitFetchResult res = fetchNatively(repository.getRoot(), remote, url, null);
res.addPruneInfo(fetchResult.getPrunedRefs());
fetchResult = res;
if (!fetchResult.isSuccess()) {
@@ -209,8 +209,9 @@ public class GitFetcher {
return fetchResult;
}
- private GitFetchResult fetchNatively(@NotNull VirtualFile root, @NotNull GitRemote remote, @Nullable String branch) {
+ private GitFetchResult fetchNatively(@NotNull VirtualFile root, @NotNull GitRemote remote, @NotNull String url, @Nullable String branch) {
final GitLineHandlerPasswordRequestAware h = new GitLineHandlerPasswordRequestAware(myProject, root, GitCommand.FETCH);
+ h.setUrl(url);
h.addProgressParameter();
if (GitVersionSpecialty.SUPPORTS_FETCH_PRUNE.existsIn(myVcs.getVersion())) {
h.addParameters("--prune");
diff --git a/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java b/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
index 38bdd91983f7..6221527d79be 100644
--- a/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
+++ b/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
@@ -189,7 +189,6 @@ public class GitMergeUpdater extends GitUpdater {
private void cancel() {
try {
GitSimpleHandler h = new GitSimpleHandler(myProject, myRoot, GitCommand.RESET);
- h.setNoSSH(true);
h.addParameters("--merge");
h.run();
} catch (VcsException e) {
diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java b/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java
index c295a54cda50..c3384cea20b0 100644
--- a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java
+++ b/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java
@@ -135,7 +135,6 @@ public class GitUpdateLocallyModifiedDialog extends DialogWrapper {
String rootPath = root.getPath();
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.DIFF);
h.addParameters("--name-status");
- h.setNoSSH(true);
h.setSilent(true);
h.setStdoutSuppressed(true);
StringScanner s = new StringScanner(h.run());
diff --git a/plugins/git4idea/src/git4idea/update/GitUpdater.java b/plugins/git4idea/src/git4idea/update/GitUpdater.java
index 71b703a60811..6d3b44800541 100644
--- a/plugins/git4idea/src/git4idea/update/GitUpdater.java
+++ b/plugins/git4idea/src/git4idea/update/GitUpdater.java
@@ -172,7 +172,6 @@ public abstract class GitUpdater {
protected boolean hasRemoteChanges(@NotNull String currentBranch, @NotNull String remoteBranch) throws VcsException {
GitSimpleHandler handler = new GitSimpleHandler(myProject, myRoot, GitCommand.REV_LIST);
handler.setSilent(true);
- handler.setNoSSH(true);
handler.addParameters("-1");
handler.addParameters(currentBranch + ".." + remoteBranch);
String output = handler.run();
diff --git a/plugins/git4idea/src/git4idea/util/GitFileUtils.java b/plugins/git4idea/src/git4idea/util/GitFileUtils.java
index 63f040651847..14afd526c249 100644
--- a/plugins/git4idea/src/git4idea/util/GitFileUtils.java
+++ b/plugins/git4idea/src/git4idea/util/GitFileUtils.java
@@ -61,7 +61,6 @@ public class GitFileUtils {
handler.addParameters(additionalOptions);
handler.endOptions();
handler.addParameters(paths);
- handler.setNoSSH(true);
handler.run();
}
}
@@ -80,7 +79,6 @@ public class GitFileUtils {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.RM);
handler.endOptions();
handler.addParameters(paths);
- handler.setNoSSH(true);
handler.run();
}
}
@@ -159,7 +157,6 @@ public class GitFileUtils {
handler.addParameters("--ignore-errors");
handler.endOptions();
handler.addParameters(paths);
- handler.setNoSSH(true);
handler.run();
}
}
@@ -168,7 +165,6 @@ public class GitFileUtils {
private static List<String> excludeIgnoredFiles(@NotNull Project project, @NotNull VirtualFile root,
@NotNull List<String> paths) throws VcsException {
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.LS_FILES);
- handler.setNoSSH(true);
handler.setSilent(true);
handler.addParameters("--ignored", "--others", "--exclude-standard");
handler.endOptions();
@@ -197,7 +193,6 @@ public class GitFileUtils {
*/
public static byte[] getFileContent(Project project, VirtualFile root, String revisionOrBranch, String relativePath) throws VcsException {
GitBinaryHandler h = new GitBinaryHandler(project, root, GitCommand.SHOW);
- h.setNoSSH(true);
h.setSilent(true);
h.addParameters(revisionOrBranch + ":" + relativePath);
return h.run();
diff --git a/plugins/git4idea/src/git4idea/util/NetrcData.java b/plugins/git4idea/src/git4idea/util/NetrcData.java
deleted file mode 100644
index 66c2f9267786..000000000000
--- a/plugins/git4idea/src/git4idea/util/NetrcData.java
+++ /dev/null
@@ -1,196 +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 git4idea.util;
-
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.util.SystemProperties;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-/**
- * Parses {@code .netrc} file and stores the parsed authentication information in {@link AuthRecord} objects.
- * Parse only {@code machine}, {@code login} and {@code password} fields.
- *
- * @author Kirill Likhodedov
- */
-public class NetrcData {
-
- private static final String NETRC_FILE = SystemInfo.isWindows ? "_netrc" : ".netrc";
- private final Map<String, AuthRecord> myAuthDataMap;
-
- private NetrcData(@NotNull Map<String, AuthRecord> authData) {
- myAuthDataMap = authData;
- }
-
- /**
- * Parses the {@code .netrc} file (which is {@code _netrc} on Windows) and returns the NetrcData object which can be analyzed further.
- */
- @NotNull
- public static NetrcData parse() throws IOException {
- File netrc = getNetrcFile();
- return parse(netrc);
- }
-
- @NotNull
- private static File getNetrcFile() {
- String home = System.getenv("HOME");
- if (home == null || !new File(home, NETRC_FILE).exists()) {
- home = SystemProperties.getUserHome();
- }
- return new File(home, NETRC_FILE);
- }
-
- @NotNull
- static NetrcData parse(@NotNull File netrcFile) throws IOException {
- if (!netrcFile.exists()) {
- throw new FileNotFoundException(netrcFile.getPath());
- }
- String netrcContent = FileUtil.loadFile(netrcFile);
- return parse(netrcContent);
- }
-
- /**
- * @return true iff the host of the given url is contained in {@code .netrc}, and both login and password are set for this host.
- */
- public boolean hasAuthDataForUrl(@NotNull String url) {
- String host = getHostFromUrl(url);
- AuthRecord authRecord = myAuthDataMap.get(host);
- return authRecord != null && authRecord.getLogin() != null && authRecord.getPassword() != null;
- }
-
- @NotNull
- Collection<AuthRecord> getAuthData() {
- return myAuthDataMap.values();
- }
-
- @NotNull
- private static String getHostFromUrl(@NotNull String url) {
- final String schemaSeparator = "://";
- String urlWithoutSchema = url.substring(url.indexOf(schemaSeparator) + schemaSeparator.length());
- return urlWithoutSchema.substring(0, urlWithoutSchema.indexOf('/'));
- }
-
- @NotNull
- private static NetrcData parse(@NotNull String content) {
- Map<String, AuthRecord> result = new HashMap<String, AuthRecord>();
- StringTokenizer tokenizer = new StringTokenizer(content);
- AuthRecord currentRecord = null;
- while (tokenizer.hasMoreTokens()) {
- String token = tokenizer.nextToken();
- if (token.equalsIgnoreCase("machine")) {
- if (!tokenizer.hasMoreTokens()) {
- break;
- }
- String host = tokenizer.nextToken();
- host = host.toLowerCase(); // hosts are case insensitive
- if (result.containsKey(host)) {
- currentRecord = result.get(host);
- } else {
- currentRecord = new AuthRecord(host);
- result.put(host, currentRecord);
- }
- }
- else if (token.equalsIgnoreCase("login")) {
- if (!tokenizer.hasMoreTokens()) {
- break;
- }
- if (currentRecord != null && currentRecord.getLogin() == null) {
- currentRecord.setLogin(tokenizer.nextToken());
- }
- }
- else if (token.equalsIgnoreCase("password")) {
- if (!tokenizer.hasMoreTokens()) {
- break;
- }
- if (currentRecord != null && currentRecord.getPassword() == null) {
- currentRecord.setPassword(tokenizer.nextToken());
- }
- }
- }
- return new NetrcData(result);
- }
-
- static class AuthRecord {
- private final String myHost;
- private String myLogin;
- private String myPassword;
-
- AuthRecord(String host, String login, String password) {
- myHost = host;
- myLogin = login;
- myPassword = password;
- }
-
- private AuthRecord(String host) {
- myHost = host;
- }
-
- @Nullable
- String getLogin() {
- return myLogin;
- }
-
- @Nullable
- String getPassword() {
- return myPassword;
- }
-
- private void setLogin(String login) {
- myLogin = login;
- }
-
- private void setPassword(String password) {
- myPassword = password;
- }
-
- @Override
- public String toString() {
- return String.format("AuthRecord{host=%s, login=%s, password=%s}", myHost, myLogin, myPassword);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- AuthRecord record = (AuthRecord)o;
-
- if (myHost != null ? !myHost.equalsIgnoreCase(record.myHost) : record.myHost != null) return false; // NB: host is case insensitive
- if (myLogin != null ? !myLogin.equals(record.myLogin) : record.myLogin != null) return false;
- if (myPassword != null ? !myPassword.equals(record.myPassword) : record.myPassword != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = myHost != null ? myHost.hashCode() : 0;
- result = 31 * result + (myLogin != null ? myLogin.hashCode() : 0);
- result = 31 * result + (myPassword != null ? myPassword.hashCode() : 0);
- return result;
- }
- }
-
-}
diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java
deleted file mode 100644
index 31bb063f777d..000000000000
--- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.git4idea.ssh;
-
-import com.trilead.ssh2.KnownHosts;
-import gnu.trove.THashMap;
-import org.apache.commons.codec.DecoderException;
-import org.apache.xmlrpc.XmlRpcClientLite;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.git4idea.util.ScriptGenerator;
-import com.intellij.openapi.util.io.FileUtilRt;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Random;
-import java.util.Vector;
-
-/**
- * The provider of SSH scripts for the Git
- */
-public abstract class GitSSHService {
-
- /**
- * random number generator to use
- */
- private static final Random RANDOM = new Random();
- /**
- * Path to the generated script
- */
- private File myScriptPath;
- /**
- * Registered handlers
- */
- private final THashMap<Integer, Handler> handlers = new THashMap<Integer, Handler>();
-
- /**
- * @return the port number for XML RCP
- */
- public abstract int getXmlRcpPort();
-
- /**
- * Get file to the script service
- *
- * @return path to the script
- * @throws IOException if script cannot be generated
- */
- @NotNull
- public synchronized File getScriptPath() throws IOException {
- if (myScriptPath == null || !myScriptPath.exists()) {
- ScriptGenerator generator = new ScriptGenerator(GitSSHHandler.GIT_SSH_PREFIX, SSHMain.class, getTempDir());
- generator.addClasses(XmlRpcClientLite.class, DecoderException.class, KnownHosts.class, FileUtilRt.class);
- generator.addResource(SSHMainBundle.class, "/org/jetbrains/git4idea/ssh/SSHMainBundle.properties");
- myScriptPath = generator.generate();
- }
- return myScriptPath;
- }
-
- /**
- * @return the temporary directory to use or null if the default directory might be used
- */
- @SuppressWarnings({"MethodMayBeStatic"})
- @Nullable
- protected File getTempDir() {
- return null;
- }
-
- protected abstract void addInternalHandler();
-
- /**
- * Register handler. Note that handlers must be unregistered using {@link #unregisterHandler(int)}.
- *
- * @param handler a handler to register
- * @return an identifier to pass to the environment variable
- */
- public synchronized int registerHandler(@NotNull Handler handler) {
- addInternalHandler();
-
- while (true) {
- int candidate = RANDOM.nextInt();
- if (candidate == Integer.MIN_VALUE) {
- continue;
- }
- candidate = Math.abs(candidate);
- if (handlers.containsKey(candidate)) {
- continue;
- }
- handlers.put(candidate, handler);
- return candidate;
- }
- }
-
- /**
- * Get handler for the key
- *
- * @param key the key to use
- * @return the registered handler
- */
- @NotNull
- private synchronized Handler getHandler(int key) {
- Handler rc = handlers.get(key);
- if (rc == null) {
- throw new IllegalStateException("No handler for the key " + key);
- }
- return rc;
- }
-
- /**
- * Unregister handler by the key
- *
- * @param key the key to unregister
- */
- public synchronized void unregisterHandler(int key) {
- if (handlers.remove(key) == null) {
- throw new IllegalArgumentException("The handler " + key + " is not registered");
- }
- }
-
- /**
- * Handler interface to use by the client code
- */
- public interface Handler {
- /**
- * Verify key
- *
- * @param hostname a host name
- * @param port a port number
- * @param serverHostKeyAlgorithm an algorithm
- * @param serverHostKey a key
- * @param isNew a isNew key
- * @return true if the key is valid
- */
- boolean verifyServerHostKey(final String hostname,
- final int port,
- final String serverHostKeyAlgorithm,
- final String serverHostKey,
- final boolean isNew);
-
- /**
- * Ask passphrase
- *
- * @param username a user name
- * @param keyPath a key path
- * @param resetPassword
- * @param lastError the last error for the handler @return a passphrase or null if dialog was cancelled.
- */
- String askPassphrase(final String username, final String keyPath, boolean resetPassword, final String lastError);
-
- /**
- * Reply to challenge in keyboard-interactive scenario
- *
- * @param username a user name
- * @param name a name of challenge
- * @param instruction a instructions
- * @param numPrompts number of prompts
- * @param prompt prompts
- * @param echo true if the reply for corresponding prompt should be echoed
- * @param lastError the last error
- * @return replies to the challenges
- */
- @SuppressWarnings({"UseOfObsoleteCollectionType"})
- Vector<String> replyToChallenge(final String username,
- final String name,
- final String instruction,
- final int numPrompts,
- final Vector<String> prompt,
- final Vector<Boolean> echo,
- final String lastError);
-
- /**
- * Ask password
- *
- * @param username a user name
- * @param resetPassword true if the previous password supplied to the service was incorrect
- * @param lastError the previous error @return a password or null if dialog was cancelled.
- */
- String askPassword(final String username, boolean resetPassword, final String lastError);
-
- /**
- * Get last successful authentication method. The default implementation returns empty string
- * meaning that last authentication is unknown or failed.
- *
- * @param userName the user name
- * @return the successful authentication method
- */
- String getLastSuccessful(String userName);
-
- /**
- * Set last successful authentication method
- *
- * @param userName the user name
- * @param method the authentication method, the empty string if authentication process failed.
- * @param error the error to show to user in case when authentication process failed.
- */
- void setLastSuccessful(String userName, String method, String error);
- }
-
- /**
- * Internal handler implementation class, do not use it.
- */
- public class InternalRequestHandler implements GitSSHHandler {
- /**
- * {@inheritDoc}
- */
- public boolean verifyServerHostKey(final int handler,
- final String hostname,
- final int port,
- final String serverHostKeyAlgorithm,
- final String serverHostKey,
- final boolean isNew) {
- return getHandler(handler).verifyServerHostKey(hostname, port, serverHostKeyAlgorithm, serverHostKey, isNew);
- }
-
- /**
- * {@inheritDoc}
- */
- public String askPassphrase(final int handler,
- final String username,
- final String keyPath,
- final boolean resetPassword,
- final String lastError) {
- return adjustNull(getHandler(handler).askPassphrase(username, keyPath, resetPassword, lastError));
- }
-
- /**
- * {@inheritDoc}
- */
- @SuppressWarnings({"UseOfObsoleteCollectionType"})
- public Vector<String> replyToChallenge(final int handlerNo,
- final String username,
- final String name,
- final String instruction,
- final int numPrompts,
- final Vector<String> prompt,
- final Vector<Boolean> echo,
- final String lastError) {
- return adjustNull(getHandler(handlerNo).replyToChallenge(username, name, instruction, numPrompts, prompt, echo, lastError));
- }
-
- /**
- * {@inheritDoc}
- */
- public String askPassword(final int handlerNo, final String username, final boolean resetPassword, final String lastError) {
- return adjustNull(getHandler(handlerNo).askPassword(username, resetPassword, lastError));
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String setLastSuccessful(int handlerNo, String userName, String method, String error) {
- getHandler(handlerNo).setLastSuccessful(userName, method, error);
- return "";
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getLastSuccessful(int handlerNo, String userName) {
- return getHandler(handlerNo).getLastSuccessful(userName);
- }
-
- /**
- * Adjust null value ({@code "-"} if null, {@code "+"+s) if non-null)
- *
- * @param s a value to adjust
- * @return adjusted string
- */
- private String adjustNull(final String s) {
- return s == null ? "-" : "+" + s;
- }
-
- /**
- * Adjust null value (returns empty array)
- *
- * @param s if null return empty array
- * @return s if not null, empty array otherwise
- */
- @SuppressWarnings({"UseOfObsoleteCollectionType"})
- private <T> Vector<T> adjustNull(final Vector<T> s) {
- return s == null ? new Vector<T>() : s;
- }
- }
-}
diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcHandlerService.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcHandlerService.java
new file mode 100644
index 000000000000..c7aaef856cc9
--- /dev/null
+++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcHandlerService.java
@@ -0,0 +1,163 @@
+/*
+ * 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 org.jetbrains.git4idea.ssh;
+
+import com.intellij.ide.XmlRpcServer;
+import com.intellij.openapi.util.io.FileUtilRt;
+import gnu.trove.THashMap;
+import org.apache.commons.codec.DecoderException;
+import org.apache.xmlrpc.XmlRpcClientLite;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.git4idea.GitExternalApp;
+import org.jetbrains.git4idea.util.ScriptGenerator;
+import org.jetbrains.ide.WebServerManager;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * <p>The provider of external application scripts called by Git when a remote operation needs communication with the user.</p>
+ * <p>
+ * Usage:
+ * <ol>
+ * <li>Get the script from {@link #getScriptPath()}.</li>
+ * <li>Set up proper environment variable
+ * (e.g. {@code GIT_SSH} for SSH connections, or {@code GIT_ASKPASS} for HTTP) pointing to the script.</li>
+ * <li>{@link #registerHandler(Object) Register} the handler of Git requests.</li>
+ * <li>Call Git operation.</li>
+ * <li>If the operation requires user interaction, the registered handler is called via XML RPC protocol.
+ * It can show a dialog in the GUI and return the answer via XML RPC to the external application, that further provides
+ * this value to the Git process.</li>
+ * <li>{@link #unregisterHandler(int) Unregister} the handler after operation has completed.</li>
+ * </ol>
+ * </p>
+ */
+public abstract class GitXmlRpcHandlerService<T> {
+
+ @NotNull private final String myScriptTempFilePrefix;
+ @NotNull private final String myHandlerName;
+ @NotNull private final Class<? extends GitExternalApp> myScriptMainClass;
+
+ @Nullable private File myScriptPath;
+ @NotNull private final Object SCRIPT_FILE_LOCK = new Object();
+
+ @NotNull private final THashMap<Integer, T> handlers = new THashMap<Integer, T>();
+ private int myNextHandlerKey;
+ @NotNull private final Object HANDLERS_LOCK = new Object();
+
+ /**
+ * @param handlerName Returns the name of the handler to be used by XML RPC client to call remote methods of a proper object.
+ * @param aClass Main class of the external application invoked by Git,
+ * which is able to handle its requests and pass to the main IDEA instance.
+ */
+ protected GitXmlRpcHandlerService(@NotNull String prefix, @NotNull String handlerName, @NotNull Class<? extends GitExternalApp> aClass) {
+ myScriptTempFilePrefix = prefix;
+ myHandlerName = handlerName;
+ myScriptMainClass = aClass;
+ }
+
+ /**
+ * @return the port number for XML RCP
+ */
+ public int getXmlRcpPort() {
+ return WebServerManager.getInstance().waitForStart().getPort();
+ }
+
+ /**
+ * Get file to the script service
+ *
+ * @return path to the script
+ * @throws IOException if script cannot be generated
+ */
+ @NotNull
+ public File getScriptPath() throws IOException {
+ ScriptGenerator generator = new ScriptGenerator(myScriptTempFilePrefix, myScriptMainClass);
+ generator.addClasses(XmlRpcClientLite.class, DecoderException.class, FileUtilRt.class);
+ customizeScriptGenerator(generator);
+
+ synchronized (SCRIPT_FILE_LOCK) {
+ if (myScriptPath == null || !myScriptPath.exists()) {
+ myScriptPath = generator.generate();
+ }
+ return myScriptPath;
+ }
+ }
+
+ /**
+ * Adds more classes or resources to the script if needed.
+ */
+ protected abstract void customizeScriptGenerator(@NotNull ScriptGenerator generator);
+
+ /**
+ * Register handler. Note that handlers must be unregistered using {@link #unregisterHandler(int)}.
+ *
+ * @param handler a handler to register
+ * @return an identifier to pass to the environment variable
+ */
+ public int registerHandler(@NotNull T handler) {
+ synchronized (HANDLERS_LOCK) {
+ XmlRpcServer xmlRpcServer = XmlRpcServer.SERVICE.getInstance();
+ if (!xmlRpcServer.hasHandler(myHandlerName)) {
+ xmlRpcServer.addHandler(myHandlerName, createRpcRequestHandlerDelegate());
+ }
+
+ int key = myNextHandlerKey;
+ handlers.put(key, handler);
+ myNextHandlerKey++;
+ return key;
+ }
+ }
+
+ /**
+ * Creates an implementation of the xml rpc handler, which methods will be called from the external application.
+ * This method should just delegate the call to the specific handler of type {@link T}, which can be achieved by {@link #getHandler(int)}.
+ * @return New instance of the xml rpc handler delegate.
+ */
+ @NotNull
+ protected abstract Object createRpcRequestHandlerDelegate();
+
+ /**
+ * Get handler for the key
+ *
+ * @param key the key to use
+ * @return the registered handler
+ */
+ @NotNull
+ protected T getHandler(int key) {
+ synchronized (HANDLERS_LOCK) {
+ T rc = handlers.get(key);
+ if (rc == null) {
+ throw new IllegalStateException("No handler for the key " + key);
+ }
+ return rc;
+ }
+ }
+
+ /**
+ * Unregister handler by the key
+ *
+ * @param key the key to unregister
+ */
+ public void unregisterHandler(int key) {
+ synchronized (HANDLERS_LOCK) {
+ if (handlers.remove(key) == null) {
+ throw new IllegalArgumentException("The handler " + key + " is not registered");
+ }
+ }
+ }
+
+}
diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcSshService.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcSshService.java
new file mode 100644
index 000000000000..de8437c72bcf
--- /dev/null
+++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitXmlRpcSshService.java
@@ -0,0 +1,105 @@
+/*
+ * 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 org.jetbrains.git4idea.ssh;
+
+import com.trilead.ssh2.KnownHosts;
+import git4idea.commands.GitSSHGUIHandler;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.git4idea.util.ScriptGenerator;
+
+import java.util.Vector;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class GitXmlRpcSshService extends GitXmlRpcHandlerService<GitSSHGUIHandler> {
+
+ private GitXmlRpcSshService() {
+ super(GitSSHHandler.GIT_SSH_PREFIX, GitSSHHandler.HANDLER_NAME, SSHMain.class);
+ }
+
+ @Override
+ protected void customizeScriptGenerator(@NotNull ScriptGenerator generator) {
+ generator.addClasses(KnownHosts.class);
+ generator.addResource(SSHMainBundle.class, "/org/jetbrains/git4idea/ssh/SSHMainBundle.properties");
+ }
+
+ @NotNull
+ @Override
+ protected Object createRpcRequestHandlerDelegate() {
+ return new InternalRequestHandler();
+ }
+
+ /**
+ * Internal handler implementation class, do not use it.
+ */
+ public class InternalRequestHandler implements GitSSHHandler {
+
+ @Override
+ public boolean verifyServerHostKey(int handler, String hostname, int port, String serverHostKeyAlgorithm, String serverHostKey,
+ boolean isNew) {
+ return getHandler(handler).verifyServerHostKey(hostname, port, serverHostKeyAlgorithm, serverHostKey, isNew);
+ }
+
+ @Override
+ public String askPassphrase(int handler, String username, String keyPath, boolean resetPassword, String lastError) {
+ return adjustNull(getHandler(handler).askPassphrase(username, keyPath, resetPassword, lastError));
+ }
+
+ @Override
+ @SuppressWarnings({"UseOfObsoleteCollectionType"})
+ public Vector<String> replyToChallenge(int handlerNo, String username, String name, String instruction, int numPrompts,
+ Vector<String> prompt, Vector<Boolean> echo, String lastError) {
+ return adjustNull(getHandler(handlerNo).replyToChallenge(username, name, instruction, numPrompts, prompt, echo, lastError));
+ }
+
+ @Override
+ public String askPassword(int handlerNo, String username, boolean resetPassword, String lastError) {
+ return adjustNull(getHandler(handlerNo).askPassword(username, resetPassword, lastError));
+ }
+
+ @Override
+ public void setLastSuccessful(int handlerNo, String userName, String method, String error) {
+ getHandler(handlerNo).setLastSuccessful(userName, method, error);
+ }
+
+ @Override
+ public String getLastSuccessful(int handlerNo, String userName) {
+ return getHandler(handlerNo).getLastSuccessful(userName);
+ }
+
+ /**
+ * Adjust null value ({@code "-"} if null, {@code "+"+s) if non-null)
+ *
+ * @param s a value to adjust
+ * @return adjusted string
+ */
+ private String adjustNull(final String s) {
+ return s == null ? "-" : "+" + s;
+ }
+
+ /**
+ * Adjust null value (returns empty array)
+ *
+ * @param s if null return empty array
+ * @return s if not null, empty array otherwise
+ */
+ @SuppressWarnings({"UseOfObsoleteCollectionType"})
+ private <T> Vector<T> adjustNull(final Vector<T> s) {
+ return s == null ? new Vector<T>() : s;
+ }
+ }
+}
diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java b/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java
index 6c6b6011e59a..a3f1e8d47b4c 100644
--- a/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java
+++ b/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java
@@ -21,7 +21,6 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileWriter;
@@ -57,10 +56,6 @@ public class ScriptGenerator {
*/
private final Class myMainClass;
/**
- * The temporary directory to use or null, if system directory should be used
- */
- @Nullable private final File myTempDir;
- /**
* The class paths for the script
*/
private final ArrayList<String> myPaths = new ArrayList<String>();
@@ -74,26 +69,14 @@ public class ScriptGenerator {
*
* @param prefix the script prefix
* @param mainClass the script main class
- * @param tempDir the temporary directory to use. if null, system default is used.
*/
- public ScriptGenerator(final String prefix, final Class mainClass, File tempDir) {
+ public ScriptGenerator(final String prefix, final Class mainClass) {
myPrefix = prefix;
myMainClass = mainClass;
- myTempDir = tempDir;
addClasses(myMainClass);
}
/**
- * A constructor
- *
- * @param prefix the script prefix
- * @param mainClass the script main class
- */
- public ScriptGenerator(final String prefix, final Class mainClass) {
- this(prefix, mainClass, null);
- }
-
- /**
* Add jar or directory that contains the class to the classpath
*
* @param classes classes which sources will be added
@@ -149,8 +132,7 @@ public class ScriptGenerator {
*/
@SuppressWarnings({"HardCodedStringLiteral"})
public File generate() throws IOException {
- File scriptPath = myTempDir != null ? FileUtil.createTempFile(myTempDir, myPrefix, SCRIPT_EXT, true)
- : FileUtil.createTempFile(myPrefix, SCRIPT_EXT);
+ File scriptPath = FileUtil.createTempFile(myPrefix, SCRIPT_EXT);
scriptPath.deleteOnExit();
PrintWriter out = new PrintWriter(new FileWriter(scriptPath));
try {
diff --git a/plugins/git4idea/test-features/git4idea/git-add.feature b/plugins/git4idea/test-features/git4idea/git-add.feature
new file mode 100644
index 000000000000..0a33e907bb7e
--- /dev/null
+++ b/plugins/git4idea/test-features/git4idea/git-add.feature
@@ -0,0 +1,35 @@
+Feature: Git Add
+ As a happy Git integration user,
+ I want to be able to add files to the VCS.
+
+ Scenario: Add one simple file
+ Given unversioned file unv.txt
+ When I add unv.txt to VCS
+ Then unv.txt should become ADDED
+
+ Scenario: Add a directory
+ Given unversioned file dir/unv.txt
+ When I add dir to VCS
+ Then dir/unv.txt should become ADDED
+
+ @nestedroot
+ Scenario: Add file from different roots
+ Given unversioned file unv.txt
+ And unversioned file community/com.txt
+ When I add unv.txt, community/com.txt to VCS
+ Then unv.txt should become ADDED
+ And community/com.txt should become ADDED
+
+ @nestedroot
+ Scenario: Add a file from subroot by calling "add" on the upper root
+ Given unversioned file community/com.txt
+ When I add the project dir to VCS
+ Then community/com.txt should become ADDED
+
+ @nestedroot
+ Scenario: Add a file from nested root and the directory above the nested root
+ Given unversioned file community/com.txt
+ And unversioned file community/unv.txt
+ When I add the project dir, community/com.txt to VCS
+ Then community/com.txt should become ADDED
+ And community/unv.txt should become ADDED \ No newline at end of file
diff --git a/plugins/git4idea/test-features/git4idea/git-http.feature b/plugins/git4idea/test-features/git4idea/git-http.feature
new file mode 100644
index 000000000000..9b1c272e43c0
--- /dev/null
+++ b/plugins/git4idea/test-features/git4idea/git-http.feature
@@ -0,0 +1,28 @@
+@remote
+Feature: Support remote operation over HTTP.
+ As a happy Git integration user
+ I want to be able to work with Git remotes via HTTP protocol.
+
+ Scenario: Clone from HTTP url containing username
+ When I clone http://gituser@deb6-vm7-git/projectA.git
+ Then I should be asked for the password
+ When I provide password 'gitpassword'
+ Then repository should be cloned to projectA
+
+ Scenario: Clone from HTTP url without username
+ When I clone http://deb6-vm7-git/projectA.git
+ Then I should be asked for the username
+ When I provide username 'gituser'
+ Then I should be asked for the password
+ When I provide password 'gitpassword'
+ Then repository should be cloned to projectA
+
+ Scenario: Clone from HTTP url containing username, provide incorrect password
+ When I clone http://gituser@deb6-vm7-git/projectA.git
+ Then I should be asked for the password
+ When I provide password 'incorrect'
+ Then repository should not be cloned to projectA
+ And error notification is shown 'Clone failed'
+ """
+ fatal: Authentication failed
+ """
diff --git a/plugins/git4idea/test-stepdefs/git4idea/GeneralStepdefs.java b/plugins/git4idea/test-stepdefs/git4idea/GeneralStepdefs.java
index 3a4ee1f35a35..b4d00413d88a 100644
--- a/plugins/git4idea/test-stepdefs/git4idea/GeneralStepdefs.java
+++ b/plugins/git4idea/test-stepdefs/git4idea/GeneralStepdefs.java
@@ -14,34 +14,22 @@ package git4idea;/*
* limitations under the License.
*/
-import com.intellij.dvcs.test.MockProject;
-import com.intellij.dvcs.test.MockVcsHelper;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
-import cucumber.annotation.After;
-import cucumber.annotation.Before;
import cucumber.annotation.en.And;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
-import git4idea.test.GitTestImpl;
-import git4idea.test.GitTestPlatformFacade;
-import git4idea.test.TestNotificator;
-import java.io.File;
-import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import static com.intellij.dvcs.test.Executor.cd;
-import static com.intellij.dvcs.test.Executor.mkdir;
-import static git4idea.GitCucumberWorld.*;
+import static git4idea.GitCucumberWorld.myNotificator;
+import static git4idea.GitCucumberWorld.virtualCommits;
import static git4idea.test.GitExecutor.git;
import static git4idea.test.GitExecutor.touch;
import static git4idea.test.GitScenarios.checkout;
-import static git4idea.test.GitTestInitUtil.createRepository;
+import static junit.framework.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -50,30 +38,6 @@ import static org.junit.Assert.assertNull;
*/
public class GeneralStepdefs {
- @Before
- public void setUpProject() throws IOException {
- myTestRoot = FileUtil.createTempDirectory("", "").getPath();
- cd(myTestRoot);
- myProjectRoot = mkdir("project");
- myProject = new MockProject(myProjectRoot);
- myPlatformFacade = new GitTestPlatformFacade();
- myGit = new GitTestImpl();
- mySettings = myPlatformFacade.getSettings(myProject);
- myVcsHelper = (MockVcsHelper) myPlatformFacade.getVcsHelper(myProject);
- myChangeListManager = myPlatformFacade.getChangeListManager(myProject);
-
- cd(myProjectRoot);
- myRepository = createRepository(myProjectRoot, myPlatformFacade, myProject);
-
- virtualCommits = new GitTestVirtualCommitsHolder();
- }
-
- @After
- public void cleanup() {
- FileUtil.delete(new File(myTestRoot));
- Disposer.dispose(myProject);
- }
-
@Given("^file (.+) '(.+)'$")
public void file_untracked_txt(String fileName, String content) throws Throwable {
touch(fileName, content);
@@ -104,9 +68,11 @@ public class GeneralStepdefs {
NotificationType type = notificationType.equals("success") ? NotificationType.INFORMATION :
notificationType.equals("warning") ? NotificationType.WARNING :
notificationType.equals("error") ? NotificationType.ERROR : null;
- assertEquals("Notification type is incorrect", type, lastNotification().getType());
- assertEquals("Notification title is incorrect", title, lastNotification().getTitle());
- assertNotificationContent(content, lastNotification().getContent());
+ Notification actualNotification = lastNotification();
+ assertNotNull("Notification should be shown", actualNotification);
+ assertEquals("Notification type is incorrect", type, actualNotification.getType());
+ assertEquals("Notification title is incorrect", title, actualNotification.getTitle());
+ assertNotificationContent(content, actualNotification.getContent());
}
private static void assertNotificationContent(String expected, String actual) {
@@ -123,7 +89,7 @@ public class GeneralStepdefs {
}
private static Notification lastNotification() {
- return ((TestNotificator)myPlatformFacade.getNotificator(myProject)).getLastNotification();
+ return myNotificator.getLastNotification();
}
@And("^no notification is shown$")
diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitAddSteps.java b/plugins/git4idea/test-stepdefs/git4idea/GitAddSteps.java
new file mode 100644
index 000000000000..4ff3c4176ee5
--- /dev/null
+++ b/plugins/git4idea/test-stepdefs/git4idea/GitAddSteps.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.VfsTestUtil;
+import cucumber.annotation.en.Given;
+import cucumber.annotation.en.Then;
+import cucumber.annotation.en.When;
+import git4idea.repo.GitRepository;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static git4idea.GitCucumberWorld.*;
+import static git4idea.test.GitExecutor.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class GitAddSteps {
+
+ @Given("^unversioned file (.*)$")
+ public void unversioned_file(String filePath) throws Throwable {
+ cd(myRepository);
+ VfsTestUtil.createFile(myProjectDir, filePath);
+ }
+
+ @When("^I add (.*) to VCS$")
+ public void I_add_file_to_VCS(List<String> files) throws Throwable {
+ List<VirtualFile> vFiles = Lists.transform(files, new Function<String, VirtualFile>() {
+ @Override
+ public VirtualFile apply(@Nullable String file) {
+ assertNotNull(file);
+ if ("the project dir".equals(file)) {
+ return myRepository.getRoot();
+ }
+ return myRepository.getRoot().findFileByRelativePath(file);
+ }
+ });
+ final CountDownLatch latch = new CountDownLatch(1);
+ //executeOnPooledThread(new Runnable() {
+ // public void run() {
+ // myChangeListManager.ensureUpToDate(false);
+ // latch.countDown();
+ // }
+ //});
+ latch.await(5, TimeUnit.SECONDS);
+ myChangeListManager.addUnversionedFiles(myChangeListManager.addChangeList("dummy", null), vFiles);
+ }
+
+
+ @Then("^(.*) should become ADDED$")
+ public void file_should_become_ADDED(String filePath) throws Throwable {
+ VirtualFile vf = myProjectDir.findFileByRelativePath(filePath);
+ assertNotNull(vf);
+ GitRepository repo = myPlatformFacade.getRepositoryManager(myProject).getRepositoryForFile(vf);
+ String status = git(repo, "status --porcelain " + vf.getPath());
+ assertTrue("File status is not added: " + status, 'A' == status.charAt(0));
+ }
+}
diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java b/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java
index f97204ed9405..2e15959c36a3 100644
--- a/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java
+++ b/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java
@@ -31,6 +31,7 @@ import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import git4idea.cherrypick.GitCherryPicker;
+import git4idea.config.GitVersionSpecialty;
import git4idea.history.browser.GitCommit;
import git4idea.history.browser.SHAHash;
import git4idea.history.wholeTree.AbstractHash;
@@ -154,13 +155,22 @@ public class GitCherryPickStepdefs {
public void git_log_should_return(int commitNum, String messages) throws Throwable {
List<String> expectedMessages = Arrays.asList(messages.split("-----"));
+
final String RECORD_SEPARATOR = "@";
- String output = git("log -%s --pretty=%%B%s", String.valueOf(commitNum), RECORD_SEPARATOR);
- List<String> actualMessages = Arrays.asList(output.split("@"));
+ boolean fullBody = GitVersionSpecialty.STARTED_USING_RAW_BODY_IN_FORMAT.existsIn(myVcs.getVersion());
+ String data= fullBody ? "%B" : "%s%b";
+ String output = git("log -%s --pretty=%s%s", String.valueOf(commitNum), data, RECORD_SEPARATOR);
+ List<String> actualMessages = Arrays.asList(output.split(RECORD_SEPARATOR));
for (int i = 0; i < expectedMessages.size(); i++) {
String expectedMessage = expectedMessages.get(i).trim();
String actualMessage = actualMessages.get(i).trim();
+ if (!fullBody) {
+ // the subject (%s) somehow contains both "fix #1" and "cherry-picked from <hash>" in a single line
+ // which is probably Git misbehavior, so let's compare without taking line breaks and spaces into consideration
+ expectedMessage = expectedMessage.replace("\n", "").replace(" ", "");
+ actualMessage = actualMessage.replace("\n", "").replace(" ", "");
+ }
expectedMessage = virtualCommits.replaceVirtualHashes(expectedMessage);
assertEquals("Commit doesn't match", expectedMessage, trimHash(actualMessage));
}
diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java b/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java
index 8e3b78c87f3a..ed3d9c2174da 100644
--- a/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java
+++ b/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java
@@ -1,11 +1,58 @@
package git4idea;
-import com.intellij.dvcs.test.MockProject;
import com.intellij.dvcs.test.MockVcsHelper;
+import com.intellij.idea.IdeaTestApplication;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.ProjectComponent;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.AbstractVcs;
+import com.intellij.openapi.vcs.AbstractVcsHelper;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.changes.ChangeListManager;
+import com.intellij.openapi.vcs.changes.ChangeListManagerImpl;
+import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
+import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
+import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
+import com.intellij.util.PlatformUtils;
+import com.intellij.util.ThrowableRunnable;
+import com.intellij.util.ui.UIUtil;
+import cucumber.annotation.After;
+import cucumber.annotation.Before;
+import cucumber.annotation.Order;
import git4idea.commands.Git;
+import git4idea.commands.GitHttpAuthService;
import git4idea.config.GitVcsSettings;
+import git4idea.remote.GitHttpAuthTestService;
import git4idea.repo.GitRepository;
+import git4idea.test.GitExecutor;
+import git4idea.test.GitTestInitUtil;
+import git4idea.test.TestNotificator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.ide.WebServerManager;
+import org.jetbrains.ide.WebServerManagerImpl;
+import org.junit.Assert;
+import org.picocontainer.MutablePicoContainer;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Random;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static com.intellij.dvcs.test.Executor.cd;
+import static com.intellij.dvcs.test.Executor.mkdir;
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
/**
* <p>The container of test environment variables which should be visible from any step definition script.</p>
@@ -17,13 +64,171 @@ public class GitCucumberWorld {
public static String myTestRoot;
public static String myProjectRoot;
- public static MockProject myProject;
+ public static VirtualFile myProjectDir;
+ public static Project myProject;
+
public static GitPlatformFacade myPlatformFacade;
public static Git myGit;
public static GitRepository myRepository;
public static GitVcsSettings mySettings;
+ public static ChangeListManagerImpl myChangeListManager;
+ public static GitVcs myVcs;
+
public static MockVcsHelper myVcsHelper;
- public static ChangeListManager myChangeListManager;
+ public static TestNotificator myNotificator;
+
+ public static GitHttpAuthTestService myHttpAuthService; // only with @remote tag
public static GitTestVirtualCommitsHolder virtualCommits;
+
+ private static Collection<Future> myAsyncTasks;
+
+ private IdeaProjectTestFixture myProjectFixture;
+
+ @Before
+ @Order(0)
+ public void setUp() throws Throwable {
+ System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, "PlatformLangXml");
+ IdeaTestApplication.getInstance(null);
+
+ String tempFileName = getClass().getName() + "-" + new Random().nextInt();
+ myProjectFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(tempFileName).getFixture();
+
+ edt(new ThrowableRunnable<Exception>() {
+ @Override
+ public void run() throws Exception {
+ myProjectFixture.setUp();
+ }
+ });
+
+ myProject = myProjectFixture.getProject();
+
+ ((ProjectComponent)ChangeListManager.getInstance(myProject)).projectOpened();
+ ((ProjectComponent)VcsDirtyScopeManager.getInstance(myProject)).projectOpened();
+
+ myProjectRoot = myProject.getBasePath();
+ myProjectDir = myProject.getBaseDir();
+ myTestRoot = myProjectRoot;
+
+ myPlatformFacade = ServiceManager.getService(myProject, GitPlatformFacade.class);
+ myGit = ServiceManager.getService(myProject, Git.class);
+ mySettings = myPlatformFacade.getSettings(myProject);
+ mySettings.getAppSettings().setPathToGit(GitExecutor.GIT_EXECUTABLE);
+
+ // dynamic overriding is used instead of making it in plugin.xml,
+ // because MockVcsHelper is not ready to be a full featured implementation for all tests.
+ myVcsHelper = overrideService(myProject, AbstractVcsHelper.class, MockVcsHelper.class);
+ myChangeListManager = (ChangeListManagerImpl)myPlatformFacade.getChangeListManager(myProject);
+ myNotificator = (TestNotificator)ServiceManager.getService(myProject, Notificator.class);
+ myVcs = GitVcs.getInstance(myProject);
+
+ virtualCommits = new GitTestVirtualCommitsHolder();
+ myAsyncTasks = new ArrayList<Future>();
+
+ cd(myProjectRoot);
+ myRepository = createRepo(myProjectRoot);
+
+ ProjectLevelVcsManagerImpl vcsManager = (ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(myProject);
+ AbstractVcs vcs = vcsManager.findVcsByName("Git");
+ Assert.assertEquals(1, vcsManager.getRootsUnderVcs(vcs).length);
+
+ assumeSupportedGitVersion();
+ }
+
+ private static void assumeSupportedGitVersion() {
+ assumeTrue(myVcs.getVersion().isSupported());
+ }
+
+ @NotNull
+ private static GitRepository createRepo(String root) {
+ GitTestInitUtil.initRepo(root);
+ ProjectLevelVcsManagerImpl vcsManager = (ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(myProject);
+ vcsManager.setDirectoryMapping(root, GitVcs.NAME);
+ VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(new File(root));
+ GitRepository repository = myPlatformFacade.getRepositoryManager(myProject).getRepositoryForRoot(file);
+ assertNotNull("Couldn't find repository for root " + root, repository);
+ return repository;
+ }
+
+ @Before("@remote")
+ @Order(1)
+ public void setUpRemoteOperations() {
+ ((WebServerManagerImpl)WebServerManager.getInstance()).setEnabledInUnitTestMode(true);
+ // default port will be occupied by main idea instance => define the custom default to avoid searching of free port
+ System.setProperty(WebServerManagerImpl.PROPERTY_RPC_PORT, "64463");
+ myHttpAuthService = (GitHttpAuthTestService)ServiceManager.getService(GitHttpAuthService.class);
+ }
+
+ @Before("@nestedroot")
+ @Order(2)
+ public void setUpStandardMultipleRootsConfig() {
+ cd(myProjectRoot);
+ String community = mkdir("community");
+ createRepo(community);
+ }
+
+ @After("@remote")
+ @Order(1)
+ public void tearDownRemoteOperations() {
+ ((WebServerManagerImpl)WebServerManager.getInstance()).setEnabledInUnitTestMode(false);
+ }
+
+ @After
+ public void tearDown() throws Throwable {
+ waitForPendingTasks();
+ nullifyStaticFields();
+ edt(new ThrowableRunnable<Exception>() {
+ @Override
+ public void run() throws Exception {
+ myProjectFixture.tearDown();
+ }
+ });
+ }
+
+ public static void executeOnPooledThread(Runnable runnable) {
+ myAsyncTasks.add(ApplicationManager.getApplication().executeOnPooledThread(runnable));
+ }
+
+ private static void waitForPendingTasks() throws InterruptedException, ExecutionException, TimeoutException {
+ for (Future future : myAsyncTasks) {
+ future.get(30, TimeUnit.SECONDS);
+ }
+ }
+
+ private static void nullifyStaticFields() throws IllegalAccessException {
+ for (Field field : GitCucumberWorld.class.getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers())) {
+ field.set(null, null);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T overrideService(@NotNull Project project, Class<? super T> serviceInterface, Class<T> serviceImplementation) {
+ String key = serviceInterface.getName();
+ MutablePicoContainer picoContainer = (MutablePicoContainer) project.getPicoContainer();
+ picoContainer.unregisterComponent(key);
+ picoContainer.registerComponentImplementation(key, serviceImplementation);
+ return (T) ServiceManager.getService(project, serviceInterface);
+ }
+
+ private static void edt(@NotNull final ThrowableRunnable<Exception> runnable) throws Exception {
+ final AtomicReference<Exception> exception = new AtomicReference<Exception>();
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ runnable.run();
+ }
+ catch (Exception throwable) {
+ exception.set(throwable);
+ }
+ }
+ });
+ //noinspection ThrowableResultOfMethodCallIgnored
+ if (exception.get() != null) {
+ throw exception.get();
+ }
+ }
+
}
diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitRemoteSteps.java b/plugins/git4idea/test-stepdefs/git4idea/GitRemoteSteps.java
new file mode 100644
index 000000000000..1958dacfc866
--- /dev/null
+++ b/plugins/git4idea/test-stepdefs/git4idea/GitRemoteSteps.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea;
+
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import cucumber.annotation.en.Then;
+import cucumber.annotation.en.When;
+import git4idea.checkout.GitCheckoutProvider;
+import git4idea.commands.GitHttpAuthenticator;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static git4idea.GitCucumberWorld.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class GitRemoteSteps {
+
+ private TestAuthenticator myAuthenticator;
+ private CountDownLatch myCloneCompleted = new CountDownLatch(1);
+
+ @When("I clone (\\S+)")
+ public void I_clone_the_repository(final String url) {
+ myAuthenticator = new TestAuthenticator();
+
+ myHttpAuthService.register(myAuthenticator);
+
+ executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ String projectName = url.substring(url.lastIndexOf('/') + 1).replace(".git", "");
+ GitCheckoutProvider.doClone(myProject, new EmptyProgressIndicator(), myGit, projectName, myTestRoot, url);
+ myCloneCompleted.countDown();
+ }
+ });
+ }
+
+ @Then("I should be asked for the password")
+ public void I_should_be_asked_for_the_password() throws InterruptedException {
+ myAuthenticator.waitUntilPasswordIsAsked();
+ assertTrue("Password was not requested", myAuthenticator.wasPasswordAsked());
+ }
+
+ @Then("I should be asked for the username")
+ public void I_should_be_asked_for_the_username() throws InterruptedException {
+ myAuthenticator.waitUntilUsernameIsAsked();
+ assertTrue("Password was not requested", myAuthenticator.wasUsernameAsked());
+ }
+
+ @When("I provide password '(\\S+)'")
+ public void I_provide_password(String password) {
+ myAuthenticator.supplyPassword(password);
+ }
+
+ @When("I provide username '(\\S+)'")
+ public void I_provide_username(String username) {
+ myAuthenticator.supplyUsername(username);
+ }
+
+ @Then("repository should (not )?be cloned to (\\S+)")
+ public void the_repository_should_be_cloned(String negation, String dir) throws InterruptedException {
+ assertTrue("Clone didn't complete during the reasonable period of time", myCloneCompleted.await(5, TimeUnit.SECONDS));
+ if (negation == null) {
+ assertTrue("Repository directory was not found", new File(myTestRoot, dir).exists());
+ }
+ else {
+ assertFalse("Repository directory shouldn't exist", new File(myTestRoot, dir).exists());
+ }
+ }
+
+ private static class TestAuthenticator implements GitHttpAuthenticator {
+
+ private static final int TIMEOUT = 10;
+
+ private final CountDownLatch myPasswordAskedWaiter = new CountDownLatch(1);
+ private final CountDownLatch myUsernameAskedWaiter = new CountDownLatch(1);
+ private final CountDownLatch myPasswordSuppliedWaiter = new CountDownLatch(1);
+ private final CountDownLatch myUsernameSuppliedWaiter = new CountDownLatch(1);
+
+ private volatile boolean myPasswordAsked;
+ private volatile boolean myUsernameAsked;
+
+ private volatile String myPassword;
+ private volatile String myUsername;
+
+ @NotNull
+ @Override
+ public String askPassword(@NotNull String url) {
+ myPasswordAskedWaiter.countDown();
+ myPasswordAsked = true;
+ try {
+ assertTrue("Password was not supplied during the reasonable period of time",
+ myPasswordSuppliedWaiter.await(TIMEOUT, TimeUnit.SECONDS));
+ }
+ catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return myPassword;
+ }
+
+ @NotNull
+ @Override
+ public String askUsername(@NotNull String url) {
+ myUsernameAskedWaiter.countDown();
+ myUsernameAsked = true;
+ try {
+ assertTrue("Password was not supplied during the reasonable period of time",
+ myUsernameSuppliedWaiter.await(TIMEOUT, TimeUnit.SECONDS));
+ }
+ catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return myUsername;
+ }
+
+
+ void supplyPassword(@NotNull String password) {
+ myPasswordSuppliedWaiter.countDown();
+ myPassword = password;
+ }
+
+ void supplyUsername(@NotNull String username) {
+ myUsernameSuppliedWaiter.countDown();
+ myUsername = username;
+ }
+
+ void waitUntilPasswordIsAsked() throws InterruptedException {
+ assertTrue("Password was not asked during the reasonable period of time",
+ myPasswordAskedWaiter.await(TIMEOUT, TimeUnit.SECONDS));
+ }
+
+ void waitUntilUsernameIsAsked() throws InterruptedException {
+ assertTrue("Username was not asked during the reasonable period of time",
+ myUsernameAskedWaiter.await(TIMEOUT, TimeUnit.SECONDS));
+ }
+
+ @Override
+ public void saveAuthData() {
+ }
+
+ @Override
+ public void forgetPassword() {
+ }
+
+ boolean wasPasswordAsked() {
+ return myPasswordAsked;
+ }
+
+ boolean wasUsernameAsked() {
+ return myUsernameAsked;
+ }
+ }
+}
+
diff --git a/plugins/git4idea/testFramework/META-INF/plugin.xml b/plugins/git4idea/testFramework/META-INF/plugin.xml
new file mode 100644
index 000000000000..90ca43720e5c
--- /dev/null
+++ b/plugins/git4idea/testFramework/META-INF/plugin.xml
@@ -0,0 +1,20 @@
+<idea-plugin>
+ <name>Git Integration Tests</name>
+ <id>Git4Idea-Tests</id>
+ <description>Overriding services for tests.</description>
+
+ <depends>com.intellij.modules.vcs</depends>
+ <depends>Git4Idea</depends>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <applicationService serviceInterface="git4idea.commands.GitHttpAuthService"
+ serviceImplementation="git4idea.remote.GitHttpAuthTestService"
+ overrides="true" />
+
+ <projectService serviceInterface="git4idea.Notificator"
+ serviceImplementation="git4idea.test.TestNotificator"
+ overrides="true"/>
+
+ </extensions>
+
+</idea-plugin>
diff --git a/plugins/git4idea/testFramework/git4idea/remote/GitHttpAuthTestService.java b/plugins/git4idea/testFramework/git4idea/remote/GitHttpAuthTestService.java
new file mode 100644
index 000000000000..2224b88232fe
--- /dev/null
+++ b/plugins/git4idea/testFramework/git4idea/remote/GitHttpAuthTestService.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.remote;
+
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.project.Project;
+import git4idea.commands.GitCommand;
+import git4idea.commands.GitHttpAuthService;
+import git4idea.commands.GitHttpAuthenticator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class GitHttpAuthTestService extends GitHttpAuthService {
+
+ @NotNull private GitHttpAuthenticator myAuthenticator = new GitHttpAuthenticator() {
+ @NotNull
+ @Override
+ public String askPassword(@NotNull String url) {
+ throw new IllegalStateException("Authenticator was not registered");
+ }
+
+ @NotNull
+ @Override
+ public String askUsername(@NotNull String url) {
+ throw new IllegalStateException("Authenticator was not registered");
+ }
+
+ @Override
+ public void saveAuthData() {
+ throw new IllegalStateException("Authenticator was not registered");
+ }
+
+ @Override
+ public void forgetPassword() {
+ throw new IllegalStateException("Authenticator was not registered");
+ }
+ };
+
+ @NotNull
+ @Override
+ public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state, @NotNull GitCommand command,
+ @NotNull String url) {
+ return myAuthenticator;
+ }
+
+ public void register(@NotNull GitHttpAuthenticator authenticator) {
+ myAuthenticator = authenticator;
+ }
+
+}
diff --git a/plugins/git4idea/testFramework/git4idea/test/GitExecutor.java b/plugins/git4idea/testFramework/git4idea/test/GitExecutor.java
index fe8513d65a61..a1d9704b4ee2 100644
--- a/plugins/git4idea/testFramework/git4idea/test/GitExecutor.java
+++ b/plugins/git4idea/testFramework/git4idea/test/GitExecutor.java
@@ -16,10 +16,8 @@
package git4idea.test;
import com.intellij.dvcs.test.Executor;
-import com.intellij.openapi.util.text.StringUtil;
import git4idea.repo.GitRepository;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -34,7 +32,7 @@ public class GitExecutor extends Executor {
private static final int MAX_RETRIES = 3;
private static boolean myVersionPrinted;
- private static final String GIT_EXECUTABLE = findGitExecutable();
+ public static final String GIT_EXECUTABLE = findGitExecutable();
private static String findGitExecutable() {
return findExecutable("Git", "git", "git.exe", Arrays.asList(GIT_EXECUTABLE_ENV, TEAMCITY_GIT_EXECUTABLE_ENV));
@@ -59,46 +57,6 @@ public class GitExecutor extends Executor {
throw new RuntimeException("fatal error during execution of Git command: $command");
}
- private static List<String> splitCommandInParameters(String command) {
- List<String> split = new ArrayList<String>();
-
- boolean insideParam = false;
- StringBuilder currentParam = new StringBuilder();
- for (char c : command.toCharArray()) {
- boolean flush = false;
- if (insideParam) {
- if (c == '\'') {
- insideParam = false;
- flush = true;
- }
- else {
- currentParam.append(c);
- }
- }
- else if (c == '\'') {
- insideParam = true;
- }
- else if (c == ' ') {
- flush = true;
- }
- else {
- currentParam.append(c);
- }
-
- if (flush) {
- if (!StringUtil.isEmptyOrSpaces(currentParam.toString())) {
- split.add(currentParam.toString());
- }
- currentParam = new StringBuilder();
- }
- }
-
- // last flush
- if (!StringUtil.isEmptyOrSpaces(currentParam.toString())) {
- split.add(currentParam.toString());
- }
- return split;
- }
public static String git(GitRepository repository, String command) {
if (repository != null) {
diff --git a/plugins/git4idea/testFramework/git4idea/test/GitTest.java b/plugins/git4idea/testFramework/git4idea/test/GitTest.java
index daecffe318b9..3f58bff4c75c 100644
--- a/plugins/git4idea/testFramework/git4idea/test/GitTest.java
+++ b/plugins/git4idea/testFramework/git4idea/test/GitTest.java
@@ -25,6 +25,7 @@ import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.testFramework.fixtures.TempDirTestFixture;
import com.intellij.testFramework.vcs.AbstractVcsTestCase;
import com.intellij.ui.GuiUtils;
+import com.intellij.util.PlatformUtils;
import com.intellij.util.ui.UIUtil;
import git4idea.GitVcs;
import org.testng.annotations.AfterMethod;
@@ -64,6 +65,7 @@ public abstract class GitTest extends AbstractVcsTestCase {
@BeforeMethod
protected void setUp(final Method testMethod) throws Exception {
+ System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, "PlatformLangXml");
myProjectDirFixture = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture();
myProjectDirFixture.setUp();
myProjectDir = new File(myProjectDirFixture.getTempDirPath());
diff --git a/plugins/git4idea/testFramework/git4idea/test/GitTestImpl.java b/plugins/git4idea/testFramework/git4idea/test/GitTestImpl.java
index f5bf37b79f13..4c04a4779a03 100644
--- a/plugins/git4idea/testFramework/git4idea/test/GitTestImpl.java
+++ b/plugins/git4idea/testFramework/git4idea/test/GitTestImpl.java
@@ -190,9 +190,7 @@ public class GitTestImpl implements Git {
@NotNull
@Override
- public GitCommandResult push(@NotNull GitRepository repository,
- @NotNull String remote,
- @NotNull String spec,
+ public GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @NotNull String url, @NotNull String spec,
@NotNull GitLineHandlerListener... listeners) {
throw new UnsupportedOperationException();
}
@@ -200,8 +198,7 @@ public class GitTestImpl implements Git {
@NotNull
@Override
public GitCommandResult push(@NotNull GitRepository repository,
- @NotNull GitPushSpec pushSpec,
- @NotNull GitLineHandlerListener... listeners) {
+ @NotNull GitPushSpec spec, @NotNull String url, @NotNull GitLineHandlerListener... listeners) {
throw new UnsupportedOperationException();
}
diff --git a/plugins/git4idea/tests/git4idea/history/GitAnnotationsClosedTest.java b/plugins/git4idea/tests/git4idea/history/GitAnnotationsClosedTest.java
index 2b23174bf38d..827f6eee69cf 100644
--- a/plugins/git4idea/tests/git4idea/history/GitAnnotationsClosedTest.java
+++ b/plugins/git4idea/tests/git4idea/history/GitAnnotationsClosedTest.java
@@ -19,7 +19,6 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsConfiguration;
@@ -33,12 +32,9 @@ import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
import com.intellij.openapi.vcs.update.CommonUpdateProjectAction;
import com.intellij.openapi.vfs.VirtualFile;
-import git4idea.GitPlatformFacade;
import git4idea.GitUtil;
import git4idea.GitVcs;
-import git4idea.repo.GitFakeRepositoryManager;
import git4idea.repo.GitRepository;
-import git4idea.repo.GitRepositoryImpl;
import git4idea.test.GitTest;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -121,7 +117,6 @@ public class GitAnnotationsClosedTest extends GitTest {
myRepo.addCommit("external_commit");
- registerGitRepository();
imitateEvent(myWorkingCopyDir);
sleep(100); // zipper-updater
@@ -139,7 +134,6 @@ public class GitAnnotationsClosedTest extends GitTest {
Assert.assertFalse(mySecondClosed);
myRepo.checkout(head);
- registerGitRepository();
imitateEvent(myWorkingCopyDir);
sleep(100); // zipper-updater
Assert.assertFalse(myFirstClosed);
@@ -199,7 +193,6 @@ public class GitAnnotationsClosedTest extends GitTest {
final ProjectLevelVcsManagerEx ex = ProjectLevelVcsManagerEx.getInstanceEx(myProject);
ex.setDirectoryMappings(Collections.singletonList(
new VcsDirectoryMapping(FileUtil.toSystemIndependentName(myWorkingCopyDir.getPath()), GitVcs.NAME)));
- registerGitRepository();
ex.getOptions(VcsConfiguration.StandardOption.UPDATE).setValue(false);
final CommonUpdateProjectAction action = new CommonUpdateProjectAction();
action.getTemplatePresentation().setText("1");
@@ -220,12 +213,6 @@ public class GitAnnotationsClosedTest extends GitTest {
sleep(100); // zipper updater
}
- private void registerGitRepository() {
- ((GitFakeRepositoryManager) GitUtil.getRepositoryManager(myProject)).add(
- GitRepositoryImpl
- .getLightInstance(myWorkingCopyDir, myProject, ServiceManager.getService(myProject, GitPlatformFacade.class), myProject));
- }
-
private void annotateFirst(final VirtualFile first) throws VcsException {
final VcsAnnotationLocalChangesListener listener = ProjectLevelVcsManager.getInstance(myProject).getAnnotationLocalChangesListener();
final FileAnnotation annotation = myVcs.getAnnotationProvider().annotate(first);
diff --git a/plugins/git4idea/tests/git4idea/history/GitLogPerformanceTest.java b/plugins/git4idea/tests/git4idea/history/GitLogPerformanceTest.java
index 3ce926d28895..c36ee2d46e2d 100644
--- a/plugins/git4idea/tests/git4idea/history/GitLogPerformanceTest.java
+++ b/plugins/git4idea/tests/git4idea/history/GitLogPerformanceTest.java
@@ -15,21 +15,15 @@
*/
package git4idea.history;
-import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.ui.ColumnInfo;
-import git4idea.GitPlatformFacade;
-import git4idea.GitUtil;
import git4idea.history.browser.CachedRefs;
import git4idea.history.browser.ChangesFilter;
import git4idea.history.wholeTree.*;
-import git4idea.repo.GitFakeRepositoryManager;
-import git4idea.repo.GitRepository;
-import git4idea.repo.GitRepositoryImpl;
import git4idea.test.GitTest;
import org.jetbrains.annotations.Nullable;
import org.testng.Assert;
@@ -107,12 +101,6 @@ public class GitLogPerformanceTest extends GitTest {
}
private void impl(RootsHolder rootsHolder, GitLogFilters filters) {
- for (VirtualFile root : rootsHolder.getRoots()) {
- final GitRepository repository = GitRepositoryImpl
- .getLightInstance(root, myProject, ServiceManager.getService(myProject, GitPlatformFacade.class), myProject);
- ((GitFakeRepositoryManager) GitUtil.getRepositoryManager(myProject)).add(repository);
- }
-
final GitCommitsSequentialIndex commitsSequentially = new GitCommitsSequentialIndex();
final MediatorImpl mediator = new MediatorImpl(myProject, commitsSequentially);
final LoadController controller = new LoadController(myProject, mediator, null, commitsSequentially);
diff --git a/plugins/git4idea/tests/git4idea/util/NetrcDataTest.java b/plugins/git4idea/tests/git4idea/util/NetrcDataTest.java
deleted file mode 100644
index ee872d8d4a58..000000000000
--- a/plugins/git4idea/tests/git4idea/util/NetrcDataTest.java
+++ /dev/null
@@ -1,72 +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 git4idea.util;
-
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.text.StringUtil;
-import git4idea.test.GitTestUtil;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-/**
- * @author Kirill Likhodedov
- */
-public class NetrcDataTest {
-
- @DataProvider(name = "netrc")
- public Object[][] loadBranches() throws IOException {
- return GitTestUtil.loadConfigData(new File(GitTestUtil.getTestDataFolder(), "netrc"));
- }
-
- @Test(dataProvider = "netrc")
- public void testBranches(String testName, File netrcFile, File resultFile) throws IOException {
- NetrcData netrcData = NetrcData.parse(netrcFile);
- Collection<NetrcData.AuthRecord> expectedRecord = readAuthData(resultFile);
- GitTestUtil.assertEqualCollections(netrcData.getAuthData(), expectedRecord);
-
- if (!testName.startsWith("n0") && !testName.startsWith("n1")) { // auth data not defined for these tests
- assertTrue(netrcData.hasAuthDataForUrl("http://bitbucket.org"));
- assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org"));
- assertTrue(netrcData.hasAuthDataForUrl("bitbucket.org"));
- assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org/user/repo.git"));
- assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org/user/repo"));
- }
-
- assertFalse(netrcData.hasAuthDataForUrl("http://example.com"));
- assertFalse(netrcData.hasAuthDataForUrl("https://example.com"));
- assertFalse(netrcData.hasAuthDataForUrl("example.com"));
- }
-
- private static Collection<NetrcData.AuthRecord> readAuthData(File file) throws IOException {
- Collection<NetrcData.AuthRecord> authRecords = new ArrayList<NetrcData.AuthRecord>();
- for (String authLine : FileUtil.loadFile(file).split("\n")) {
- if (StringUtil.isEmptyOrSpaces(authLine)) {
- continue;
- }
- String[] data = authLine.split(" ");
- authRecords.add(new NetrcData.AuthRecord(data[0], data[1], data.length > 2 ? data[2] : null));
- }
- return authRecords;
- }
-}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java
index adc47bd8bf97..a033ddcd4017 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java
@@ -99,7 +99,7 @@ public class GithubApiUtil {
}
@NotNull
- private static String removeProtocolPrefix(final String url) {
+ public static String removeProtocolPrefix(final String url) {
if (url.startsWith("https://")) {
return url.substring(8);
}
@@ -159,7 +159,8 @@ public class GithubApiUtil {
}
}
- private static String removeTrailingSlash(String s) {
+ @NotNull
+ public static String removeTrailingSlash(@NotNull String s) {
if (s.endsWith("/")) {
return s.substring(0, s.length() - 1);
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
index 9d41001a8133..18679e1bd375 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
@@ -180,7 +180,6 @@ public class GithubRebaseAction extends DumbAwareAction {
LOG.info("Adding GitHub parent as a remote host");
ProgressManager.getInstance().getProgressIndicator().setText("Adding GitHub parent as a remote host");
final GitSimpleHandler addRemoteHandler = new GitSimpleHandler(project, root, GitCommand.REMOTE);
- addRemoteHandler.setNoSSH(true);
addRemoteHandler.setSilent(true);
remoteForForkParentRepo.set("upstream");
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
index ca427dc9c642..01ee9ccc2af1 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
@@ -50,8 +50,6 @@ import git4idea.actions.BasicAction;
import git4idea.actions.GitInit;
import git4idea.commands.*;
import git4idea.i18n.GitBundle;
-import git4idea.jgit.GitHttpAdapter;
-import git4idea.push.GitSimplePushResult;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
import git4idea.util.GitFileUtils;
@@ -188,7 +186,6 @@ public class GithubShareAction extends DumbAwareAction {
if (!gitDetected) {
LOG.info("No git detected, creating empty git repo");
final GitLineHandler h = new GitLineHandler(project, root, GitCommand.INIT);
- h.setNoSSH(true);
GitHandlerUtil.doSynchronously(h, GitBundle.getString("initializing.title"), h.printableCommandLine());
if (!h.errors().isEmpty()) {
GitUIUtil.showOperationErrors(project, h.errors(), "git init");
@@ -216,7 +213,6 @@ public class GithubShareAction extends DumbAwareAction {
//git remote add origin git@github.com:login/name.git
LOG.info("Adding GitHub as a remote host");
final GitSimpleHandler addRemoteHandler = new GitSimpleHandler(project, root, GitCommand.REMOTE);
- addRemoteHandler.setNoSSH(true);
addRemoteHandler.setSilent(true);
final String remoteUrl = GithubApiUtil.getGitHost() + "/" + login + "/" + name + ".git";
addRemoteHandler.addParameters("add", "origin", remoteUrl);
@@ -239,29 +235,15 @@ public class GithubShareAction extends DumbAwareAction {
new Task.Backgroundable(project, "Pushing to GitHub", false) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
- GitSimplePushResult pushResult = GitHttpAdapter.push(repository, "origin", remoteUrl, "refs/heads/master:refs/heads/master");
- switch (pushResult.getType()) {
- case NOT_PUSHED:
- showPushError(project, "Push failed: <br/>" + pushResult.getOutput());
- break;
- case REJECT:
- showPushError(project, "Push was rejected: <br/>" + pushResult.getOutput());
- break;
- case CANCEL:
- Notificator.getInstance(project).notify(new Notification(GithubUtil.GITHUB_NOTIFICATION_GROUP, "Push cancelled",
- "The project was created on GitHub but wasn't pushed yet.", NotificationType.WARNING));
- break;
- case NOT_AUTHORIZED:
- showPushError(project, "Push authorization failure: <br/>" + pushResult.getOutput());
- break;
- case ERROR:
- showPushError(project, "Push failed: <br/>" + pushResult.getOutput());
- break;
- case SUCCESS:
- Notificator.getInstance(project).notify(new Notification(GithubUtil.GITHUB_NOTIFICATION_GROUP, "Success",
- "Successfully created project ''" + name + "'' on github",
- NotificationType.INFORMATION));
- break;
+ Git git = ServiceManager.getService(Git.class);
+ GitCommandResult result = git.push(repository, "origin", remoteUrl, "refs/heads/master:refs/heads/master");
+ if (result.success()) {
+ Notificator.getInstance(project).notify(new Notification(GithubUtil.GITHUB_NOTIFICATION_GROUP, "Success",
+ "Successfully created project '" + name + "' on GitHub",
+ NotificationType.INFORMATION));
+ }
+ else {
+ showPushError(project, "Push failed: <br/>" + result.getErrorOutputAsHtmlString());
}
}
}.queue();
@@ -372,7 +354,6 @@ public class GithubShareAction extends DumbAwareAction {
}
GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.COMMIT);
handler.addParameters("-m", "First commit");
- handler.setNoSSH(true);
handler.endOptions();
handler.run();
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java
index d5c548ff2d54..69989a371043 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java
@@ -26,7 +26,6 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.text.StringUtil;
import git4idea.config.GitVcsApplicationSettings;
@@ -42,6 +41,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Various utility methods for the GutHub plugin.
@@ -86,8 +86,8 @@ public class GithubUtil {
private static <T> T doAccessToGithubWithModalProgress(@NotNull final Project project,
@NotNull final ThrowableComputable<T, IOException> computable) throws IOException {
- final Ref<T> result = new Ref<T>();
- final Ref<IOException> exception = new Ref<IOException>();
+ final AtomicReference<T> result = new AtomicReference<T>();
+ final AtomicReference<IOException> exception = new AtomicReference<IOException>();
ProgressManager.getInstance().run(new Task.Modal(project, "Access to GitHub", true) {
public void run(@NotNull ProgressIndicator indicator) {
try {
@@ -98,7 +98,8 @@ public class GithubUtil {
}
}
});
- if (exception.isNull()) {
+ //noinspection ThrowableResultOfMethodCallIgnored
+ if (exception.get() == null) {
return result.get();
}
throw exception.get();
@@ -385,7 +386,7 @@ public class GithubUtil {
}
public static boolean isGithubUrl(@NotNull String url) {
- return url.contains(GithubApiUtil.getGitHost());
+ return url.contains(GithubApiUtil.removeProtocolPrefix(GithubSettings.getInstance().getHost()));
}
static void setVisibleEnabled(AnActionEvent e, boolean visible, boolean enabled) {
diff --git a/plugins/gradle/resources/i18n/GradleBundle.properties b/plugins/gradle/resources/i18n/GradleBundle.properties
index d0624415b827..b1a4e9c52030 100644
--- a/plugins/gradle/resources/i18n/GradleBundle.properties
+++ b/plugins/gradle/resources/i18n/GradleBundle.properties
@@ -49,13 +49,12 @@ gradle.import.text.error.project.undefined.config.location=Project config locati
gradle.import.text.error.file.config.location=Project config location points to file instead of directory
gradle.import.text.error.undefined.project.compile.output.location=Project compile output location is undefined
gradle.import.text.error.file.project.compile.output.location=Project compile output location points to file instead of directory
-gradle.import.text.error.module.undefined.config.location=Module config location is undefined
gradle.import.text.error.file.module.compile.output.location=Module compile output location is undefined
gradle.import.text.error.file.module.test.output.location=Module test output location is undefined
-gradle.sync.title.tab=project structure changes
+gradle.sync.title.tab=Project
gradle.sync.progress.initial.text=Refreshing Gradle project
-gradle.sync.progress.update.text=Gradle: {0}
+gradle.sync.progress.update.text=Gradle project refresh: {0}
gradle.sync.change.type.gradle=Gradle local entities
gradle.sync.change.type.intellij=IntelliJ IDEA local entities
gradle.sync.change.type.conflict=Entities with conflicting setup
@@ -72,6 +71,12 @@ gradle.sync.change.project.language.level.text=project language level change
gradle.sync.change.dependency.scope.text=Scope:
gradle.sync.change.dependency.exported.text=Exported:
+gradle.task.title.tab=Tasks
+gradle.task.progress.initial.text=Refreshing tasks list
+gradle.task.recent.title=Recent tasks
+gradle.task.all.title=All tasks
+gradle.tasks.progress.update.text=Gradle tasks refresh: {0}
+
gradle.library.resolve.progress.text=Resolving Gradle libraries
gradle.generic.text.error.jar.not.found=Gradle jars location is unknown
@@ -92,8 +97,8 @@ gradle.action.open.script.text=Open linked Gradle project
gradle.action.open.script.description=Allows to open project file of the linked Gradle project at the editor
gradle.action.import.entity.text=Import
gradle.action.import.entity.description=Import target Gradle entity
-gradle.action.sync.outdated.library.text=Sync
-gradle.action.sync.outdated.library.description=Synchronize outdated ide library with gradle
+gradle.action.sync.text=Sync
+gradle.action.sync.description=Synchronize mismatched IDE and Gradle entity
gradle.action.remove.entity.text=Remove
gradle.action.remove.entity.description=Remove target IDE entity
gradle.action.show.conflict.text=Show conflict
@@ -116,4 +121,8 @@ gradle.run.no.sdk.title=Configure Gradle SDK
gradle.notification.group.display.warning=Gradle warnings
gradle.notification.gradle.home.undefined.description=Gradle location is undefined
gradle.notification.refresh.fail.description=Refresh failed:\n{0}
-gradle.notification.action.show.settings=<a href="configure">Gradle settings</a> \ No newline at end of file
+gradle.notification.action.show.settings=<a href="configure">Gradle settings</a>
+
+gradle.text.loading=Loading...
+gradle.general.progress.update.text=Gradle: {0}
+gradle.general.progress.downloading.wrapper=Downloading gradle wrapper v.{0} \ No newline at end of file
diff --git a/plugins/gradle/resources/icons/gradle.png b/plugins/gradle/resources/icons/gradle.png
index 1dc839a7a464..e1dfe64e13fb 100644
--- a/plugins/gradle/resources/icons/gradle.png
+++ b/plugins/gradle/resources/icons/gradle.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradle@2x.png b/plugins/gradle/resources/icons/gradle@2x.png
new file mode 100644
index 000000000000..63ba4c2b4156
--- /dev/null
+++ b/plugins/gradle/resources/icons/gradle@2x.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradleImport.png b/plugins/gradle/resources/icons/gradleImport.png
index 87bf700a15c9..3848a09c1e08 100644
--- a/plugins/gradle/resources/icons/gradleImport.png
+++ b/plugins/gradle/resources/icons/gradleImport.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradleImport@2x.png b/plugins/gradle/resources/icons/gradleImport@2x.png
new file mode 100644
index 000000000000..e8f75acb5502
--- /dev/null
+++ b/plugins/gradle/resources/icons/gradleImport@2x.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradleImport@2x_dark.png b/plugins/gradle/resources/icons/gradleImport@2x_dark.png
new file mode 100644
index 000000000000..ef33ab54b8a8
--- /dev/null
+++ b/plugins/gradle/resources/icons/gradleImport@2x_dark.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradleImport_dark.png b/plugins/gradle/resources/icons/gradleImport_dark.png
new file mode 100644
index 000000000000..58ba2d864bf2
--- /dev/null
+++ b/plugins/gradle/resources/icons/gradleImport_dark.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradleNavigate.png b/plugins/gradle/resources/icons/gradleNavigate.png
index 851e7904e599..957963bf4598 100644
--- a/plugins/gradle/resources/icons/gradleNavigate.png
+++ b/plugins/gradle/resources/icons/gradleNavigate.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradleNavigate@2x.png b/plugins/gradle/resources/icons/gradleNavigate@2x.png
new file mode 100644
index 000000000000..f2c18c281105
--- /dev/null
+++ b/plugins/gradle/resources/icons/gradleNavigate@2x.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradleNavigate@2x_dark.png b/plugins/gradle/resources/icons/gradleNavigate@2x_dark.png
new file mode 100644
index 000000000000..c51f645d531c
--- /dev/null
+++ b/plugins/gradle/resources/icons/gradleNavigate@2x_dark.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/gradleNavigate_dark.png b/plugins/gradle/resources/icons/gradleNavigate_dark.png
new file mode 100644
index 000000000000..6aa51c673ef3
--- /dev/null
+++ b/plugins/gradle/resources/icons/gradleNavigate_dark.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/task.png b/plugins/gradle/resources/icons/task.png
new file mode 100644
index 000000000000..5afe720a46c0
--- /dev/null
+++ b/plugins/gradle/resources/icons/task.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/toolWindowGradle.png b/plugins/gradle/resources/icons/toolWindowGradle.png
index c05acc8bf1c0..71c8fb18d392 100644
--- a/plugins/gradle/resources/icons/toolWindowGradle.png
+++ b/plugins/gradle/resources/icons/toolWindowGradle.png
Binary files differ
diff --git a/plugins/gradle/resources/icons/toolWindowGradle@2x.png b/plugins/gradle/resources/icons/toolWindowGradle@2x.png
new file mode 100644
index 000000000000..d348244361be
--- /dev/null
+++ b/plugins/gradle/resources/icons/toolWindowGradle@2x.png
Binary files differ
diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index a981413c392e..cee39a6488c8 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -86,7 +86,7 @@
<projectService serviceImplementation="org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesDetector"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.autoimport.GradleUserProjectChangesCalculator"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.notification.GradleConfigNotificationManager"/>
- <projectService serviceImplementation="org.jetbrains.plugins.gradle.task.GradleTaskManager"/>
+ <projectService serviceImplementation="org.jetbrains.plugins.gradle.internal.task.GradleTaskManager"/>
<toolWindow id="JetGradle" anchor="right" icon="GradleIcons.ToolWindowGradle"
factoryClass="org.jetbrains.plugins.gradle.ui.GradleToolWindowFactory"/>
@@ -116,7 +116,7 @@
<action id="Gradle.ImportEntity" class="org.jetbrains.plugins.gradle.action.GradleImportEntityAction" icon="GradleIcons.GradleImport"/>
<action id="Gradle.ShowConflict" class="org.jetbrains.plugins.gradle.action.GradleShowConflictDetailsAction" icon="AllIcons.Actions.Diff"/>
<action id="Gradle.RemoveEntity" class="org.jetbrains.plugins.gradle.action.GradleRemoveIdeEntityAction" icon="AllIcons.General.Remove"/>
- <action id="Gradle.SyncOutdatedLibrary" class="org.jetbrains.plugins.gradle.action.GradleSyncOutdatedLibraryAction" icon="GradleIcons.GradleSync"/>
+ <action id="Gradle.SyncOutdatedLibrary" class="org.jetbrains.plugins.gradle.action.GradleSyncAction" icon="GradleIcons.GradleSync"/>
<group id="Gradle.SyncTreeGroup">
<reference id="Gradle.ImportEntity"/>
<reference id="Gradle.RemoveEntity"/>
@@ -139,6 +139,9 @@
</group>
<action id="Gradle.RebuildChangesTree" class="org.jetbrains.plugins.gradle.action.GradleRebuildStructureChangesTreeAction"/>
+ <group id="Gradle.TasksGroup">
+ <reference ref="RunContextGroup"/>
+ </group>
</actions>
</idea-plugin>
diff --git a/plugins/gradle/src/icons/GradleIcons.java b/plugins/gradle/src/icons/GradleIcons.java
index b347f2dcc472..f094cfd205e0 100644
--- a/plugins/gradle/src/icons/GradleIcons.java
+++ b/plugins/gradle/src/icons/GradleIcons.java
@@ -13,9 +13,10 @@ public class GradleIcons {
return IconLoader.getIcon(path, GradleIcons.class);
}
- public static final Icon Gradle = load("/icons/gradle.png"); // 16x16
- public static final Icon GradleImport = load("/icons/gradleImport.png"); // 16x16
- public static final Icon GradleNavigate = load("/icons/gradleNavigate.png"); // 16x16
- public static final Icon GradleSync = load("/icons/gradleSync.png"); // 16x16
+ public static final Icon Gradle = load("/icons/gradle.png"); // 16x16
+ public static final Icon GradleImport = load("/icons/gradleImport.png"); // 16x16
+ public static final Icon GradleNavigate = load("/icons/gradleNavigate.png"); // 16x16
+ public static final Icon GradleSync = load("/icons/gradleSync.png"); // 16x16
public static final Icon ToolWindowGradle = load("/icons/toolWindowGradle.png"); // 13x13
+ public static final Icon Task = load("/icons/task.png"); // 16x16
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleLinkedProjectAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleLinkedProjectAction.java
index c72cbae2dde9..4f50268ca750 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleLinkedProjectAction.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleLinkedProjectAction.java
@@ -42,7 +42,7 @@ public abstract class AbstractGradleLinkedProjectAction extends AnAction {
e.getPresentation().setVisible(false);
return;
}
- doActionPerformed(project, pair.second);
+ doActionPerformed(e, project, pair.second);
}
@Nullable
@@ -61,5 +61,5 @@ public abstract class AbstractGradleLinkedProjectAction extends AnAction {
}
protected abstract void doUpdate(@NotNull AnActionEvent event, @NotNull Project project, @NotNull String linkedProjectPath);
- protected abstract void doActionPerformed(@NotNull Project project, @NotNull String linkedProjectPath);
+ protected abstract void doActionPerformed(@NotNull AnActionEvent event, @NotNull Project project, @NotNull String linkedProjectPath);
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleSyncTreeNodeAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleSyncTreeNodeAction.java
index 47049f081c43..9ffd1860e22c 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleSyncTreeNodeAction.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/AbstractGradleSyncTreeNodeAction.java
@@ -10,8 +10,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.ui.treeStructure.Tree;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.task.GradleTaskManager;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskManager;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
import org.jetbrains.plugins.gradle.util.GradleConstants;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleOpenScriptAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleOpenScriptAction.java
index 29c3a8340604..0a99c78dbcfc 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleOpenScriptAction.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleOpenScriptAction.java
@@ -34,7 +34,7 @@ public class GradleOpenScriptAction extends AbstractGradleLinkedProjectAction im
}
@Override
- protected void doActionPerformed(@NotNull Project project, @NotNull String linkedProjectPath) {
+ protected void doActionPerformed(@NotNull AnActionEvent event, @NotNull Project project, @NotNull String linkedProjectPath) {
final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(linkedProjectPath);
if (virtualFile == null) {
LOG.warn(String.format("Can't obtain virtual file for the target file path: '%s'", linkedProjectPath));
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java
index 9d599e3ff2e7..72df7d86cbb3 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java
@@ -9,10 +9,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleSettings;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskManager;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
import org.jetbrains.plugins.gradle.notification.GradleConfigNotificationManager;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureTreeModel;
-import org.jetbrains.plugins.gradle.task.GradleTaskManager;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleUtil;
@@ -54,7 +54,7 @@ public class GradleRefreshProjectAction extends AbstractGradleLinkedProjectActio
}
@Override
- protected void doActionPerformed(@NotNull final Project project, @NotNull final String linkedProjectPath) {
+ protected void doActionPerformed(@NotNull AnActionEvent event, @NotNull final Project project, @NotNull final String linkedProjectPath) {
// We save all documents because there is more than one target 'build.gradle' file in case of multi-module gradle project.
FileDocumentManager.getInstance().saveAllDocuments();
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRemoveIdeEntityAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRemoveIdeEntityAction.java
index 0297660ee55c..502bdd047eca 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRemoveIdeEntityAction.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRemoveIdeEntityAction.java
@@ -6,14 +6,10 @@ import com.intellij.ui.treeStructure.Tree;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
import org.jetbrains.plugins.gradle.manage.GradleLocalNodeManageHelper;
-import org.jetbrains.plugins.gradle.model.GradleEntityType;
-import org.jetbrains.plugins.gradle.model.id.GradleEntityId;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
-import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import java.util.Collection;
-import java.util.Iterator;
/**
* Allows to remove IDE entity (module, dependency, content root etc). Convenient to use when project structure tree is configured
@@ -31,17 +27,7 @@ public class GradleRemoveIdeEntityAction extends AbstractGradleSyncTreeNodeActio
@Override
protected void filterNodes(@NotNull Collection<GradleProjectStructureNode<?>> nodes) {
- for (Iterator<GradleProjectStructureNode<?>> iterator = nodes.iterator(); iterator.hasNext(); ) {
- GradleProjectStructureNode<?> node = iterator.next();
- GradleProjectStructureNodeDescriptor<? extends GradleEntityId> descriptor = node.getDescriptor();
- if (descriptor.getAttributes() == GradleTextAttributes.GRADLE_LOCAL_CHANGE
- || descriptor.getAttributes() == GradleTextAttributes.OUTDATED_ENTITY
- || descriptor.getElement().getType() == GradleEntityType.SYNTHETIC
- || node.getParent() == null /* is root, i.e. is a project*/)
- {
- iterator.remove();
- }
- }
+ filterNodesByAttributes(nodes, GradleTextAttributes.INTELLIJ_LOCAL_CHANGE);
}
@Override
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleSyncAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleSyncAction.java
new file mode 100644
index 000000000000..c1b93e892fc1
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleSyncAction.java
@@ -0,0 +1,77 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.action;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.autoimport.GradleUserProjectChange;
+import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
+import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
+import org.jetbrains.plugins.gradle.manage.GradleEntityManageHelper;
+import org.jetbrains.plugins.gradle.manage.GradleOutdatedLibraryManager;
+import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
+import org.jetbrains.plugins.gradle.util.GradleBundle;
+
+import java.util.*;
+
+/**
+ * @author Denis Zhdanov
+ * @since 1/23/13 11:13 AM
+ */
+public class GradleSyncAction extends AbstractGradleSyncTreeNodeAction {
+
+ public GradleSyncAction() {
+ getTemplatePresentation().setText(GradleBundle.message("gradle.action.sync.text"));
+ getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.sync.description"));
+ }
+
+ @Override
+ protected void filterNodes(@NotNull Collection<GradleProjectStructureNode<?>> nodes) {
+ for (Iterator<GradleProjectStructureNode<?>> iterator = nodes.iterator(); iterator.hasNext(); ) {
+ GradleProjectStructureNode<?> node = iterator.next();
+ TextAttributesKey attributes = node.getDescriptor().getAttributes();
+ if (!GradleTextAttributes.OUTDATED_ENTITY.equals(attributes) && node.getConflictChanges().isEmpty()) {
+ iterator.remove();
+ }
+ }
+ }
+
+ @Override
+ protected void doActionPerformed(@NotNull Collection<GradleProjectStructureNode<?>> nodes, @NotNull Project project, @NotNull Tree tree) {
+ GradleOutdatedLibraryManager manager = ServiceManager.getService(project, GradleOutdatedLibraryManager.class);
+ GradleEntityManageHelper helper = ServiceManager.getService(project, GradleEntityManageHelper.class);
+
+ List<GradleProjectStructureNode<?>> outdatedLibraryNodes = ContainerUtilRt.newArrayList();
+ Set<GradleProjectStructureChange> conflictChanges = ContainerUtilRt.newHashSet();
+ for (GradleProjectStructureNode<?> node : nodes) {
+ if (GradleTextAttributes.OUTDATED_ENTITY.equals(node.getDescriptor().getAttributes())) {
+ outdatedLibraryNodes.add(node);
+ }
+ conflictChanges.addAll(node.getConflictChanges());
+ }
+
+ if (!outdatedLibraryNodes.isEmpty()) {
+ manager.sync(nodes);
+ }
+ if (!conflictChanges.isEmpty()) {
+ helper.eliminateChange(conflictChanges, Collections.<GradleUserProjectChange>emptySet(), true);
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleSyncOutdatedLibraryAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleSyncOutdatedLibraryAction.java
deleted file mode 100644
index 82e3ecc654a5..000000000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleSyncOutdatedLibraryAction.java
+++ /dev/null
@@ -1,50 +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 org.jetbrains.plugins.gradle.action;
-
-import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.ui.treeStructure.Tree;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
-import org.jetbrains.plugins.gradle.manage.GradleOutdatedLibraryManager;
-import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
-import org.jetbrains.plugins.gradle.util.GradleBundle;
-
-import java.util.Collection;
-
-/**
- * @author Denis Zhdanov
- * @since 1/23/13 11:13 AM
- */
-public class GradleSyncOutdatedLibraryAction extends AbstractGradleSyncTreeNodeAction {
-
- public GradleSyncOutdatedLibraryAction() {
- getTemplatePresentation().setText(GradleBundle.message("gradle.action.sync.outdated.library.text"));
- getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.sync.outdated.library.description"));
- }
-
- @Override
- protected void filterNodes(@NotNull Collection<GradleProjectStructureNode<?>> nodes) {
- filterNodesByAttributes(nodes, GradleTextAttributes.OUTDATED_ENTITY);
- }
-
- @Override
- protected void doActionPerformed(@NotNull Collection<GradleProjectStructureNode<?>> nodes, @NotNull Project project, @NotNull Tree tree) {
- GradleOutdatedLibraryManager manager = ServiceManager.getService(project, GradleOutdatedLibraryManager.class);
- manager.sync(nodes);
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyExportedUserChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyExportedUserChange.java
new file mode 100644
index 000000000000..b4c887fdc0f8
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyExportedUserChange.java
@@ -0,0 +1,78 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.autoimport;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/4/13 12:17 PM
+ */
+public abstract class AbstractGradleDependencyExportedUserChange<T extends AbstractGradleDependencyExportedUserChange<T>>
+ extends AbstractGradleDependencyUserChange<T>
+{
+ private boolean myExported;
+
+ protected AbstractGradleDependencyExportedUserChange() {
+ // Required for IJ serialization
+ }
+
+ protected AbstractGradleDependencyExportedUserChange(@NotNull String moduleName, @NotNull String dependencyName, boolean exported) {
+ super(moduleName, dependencyName);
+ myExported = exported;
+ }
+
+ public boolean isExported() {
+ return myExported;
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public void setExported(boolean exported) {
+ myExported = exported;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ return 31 * result + (myExported ? 1 : 0);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!super.equals(o)) return false;
+
+ AbstractGradleDependencyExportedUserChange<?> change = (AbstractGradleDependencyExportedUserChange<?>)o;
+
+ return myExported == change.myExported;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Override
+ public int compareTo(@NotNull GradleUserProjectChange<?> o) {
+ int cmp = super.compareTo(o);
+ if (cmp != 0 || (!(o instanceof AbstractGradleDependencyExportedUserChange<?>))) {
+ return cmp;
+ }
+
+ AbstractGradleDependencyExportedUserChange<T> that = (AbstractGradleDependencyExportedUserChange<T>)o;
+ if (myExported) {
+ return that.myExported ? 0 : 1;
+ }
+ else {
+ return that.myExported ? -1 : 0;
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyScopeUserChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyScopeUserChange.java
new file mode 100644
index 000000000000..54fc3fd2efd4
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyScopeUserChange.java
@@ -0,0 +1,92 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.autoimport;
+
+import com.intellij.openapi.roots.DependencyScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/4/13 12:08 PM
+ */
+public abstract class AbstractGradleDependencyScopeUserChange<T extends AbstractGradleDependencyScopeUserChange<T>>
+ extends AbstractGradleDependencyUserChange<T>
+{
+ @Nullable
+ private DependencyScope myScope;
+
+ protected AbstractGradleDependencyScopeUserChange() {
+ // Required for IJ serialization
+ }
+
+ @SuppressWarnings("NullableProblems")
+ protected AbstractGradleDependencyScopeUserChange(@NotNull String moduleName,
+ @NotNull String dependencyName,
+ @NotNull DependencyScope scope)
+ {
+ super(moduleName, dependencyName);
+ myScope = scope;
+ }
+
+ @Nullable
+ public DependencyScope getScope() {
+ return myScope;
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public void setScope(@Nullable DependencyScope scope) {
+ myScope = scope;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (myScope != null ? myScope.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!super.equals(o)) return false;
+
+ AbstractGradleDependencyScopeUserChange<?> change = (AbstractGradleDependencyScopeUserChange<?>)o;
+
+ if (myScope != null ? !myScope.equals(change.myScope) : change.myScope != null) return false;
+
+ return true;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Override
+ public int compareTo(@NotNull GradleUserProjectChange<?> o) {
+ int cmp = super.compareTo(o);
+ if (cmp != 0 || (!(o instanceof AbstractGradleDependencyScopeUserChange<?>))) {
+ return cmp;
+ }
+
+ AbstractGradleDependencyScopeUserChange<T> that = (AbstractGradleDependencyScopeUserChange<T>)o;
+ if (myScope == null) {
+ return that.myScope == null ? 0 : 1;
+ }
+ else if (that.myScope == null) {
+ return -1;
+ }
+ else {
+ return myScope.compareTo(that.myScope);
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyUserChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyUserChange.java
index 2cf43a33ec02..f06be43d1fba 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyUserChange.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleDependencyUserChange.java
@@ -22,8 +22,8 @@ import org.jetbrains.annotations.Nullable;
* @author Denis Zhdanov
* @since 2/19/13 8:54 AM
*/
-public abstract class AbstractGradleDependencyUserChange<T extends AbstractGradleDependencyUserChange>
- extends AbstractGradleModuleAwareUserChange
+public abstract class AbstractGradleDependencyUserChange<T extends AbstractGradleDependencyUserChange<T>>
+ extends AbstractGradleModuleAwareUserChange<T>
{
@Nullable
@@ -66,11 +66,11 @@ public abstract class AbstractGradleDependencyUserChange<T extends AbstractGradl
return true;
}
- @SuppressWarnings({"CovariantCompareTo", "unchecked"})
+ @SuppressWarnings({"unchecked"})
@Override
- public int compareTo(AbstractGradleModuleAwareUserChange o) {
+ public int compareTo(@NotNull GradleUserProjectChange<?> o) {
int cmp = super.compareTo(o);
- if (cmp != 0) {
+ if (cmp != 0 || (!(o instanceof AbstractGradleDependencyUserChange))) {
return cmp;
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleModuleAwareUserChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleModuleAwareUserChange.java
index b61ef4a4dd1f..ada0fdd8de12 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleModuleAwareUserChange.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleModuleAwareUserChange.java
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable;
* @author Denis Zhdanov
* @since 2/19/13 8:48 AM
*/
-public abstract class AbstractGradleModuleAwareUserChange<T extends AbstractGradleModuleAwareUserChange>
+public abstract class AbstractGradleModuleAwareUserChange<T extends AbstractGradleModuleAwareUserChange<T>>
extends AbstractGradleUserProjectChange<T>
{
@@ -67,7 +67,11 @@ public abstract class AbstractGradleModuleAwareUserChange<T extends AbstractGrad
@SuppressWarnings("unchecked")
@Override
- public int compareTo(T o) {
+ public int compareTo(@NotNull GradleUserProjectChange<?> o) {
+ int cmp = super.compareTo(o);
+ if (cmp != 0 || !(o instanceof AbstractGradleModuleAwareUserChange<?>)) {
+ return cmp;
+ }
AbstractGradleModuleAwareUserChange<T> that = (AbstractGradleModuleAwareUserChange<T>)o;
if (myModuleName == null) {
return that.myModuleName == null ? 0 : 1;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleUserProjectChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleUserProjectChange.java
index bd40b71a176d..42d840c4df74 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleUserProjectChange.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/AbstractGradleUserProjectChange.java
@@ -16,20 +16,15 @@
package org.jetbrains.plugins.gradle.autoimport;
import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Denis Zhdanov
* @since 2/18/13 8:29 PM
*/
-public abstract class AbstractGradleUserProjectChange<T extends AbstractGradleUserProjectChange> implements GradleUserProjectChange<T> {
+public abstract class AbstractGradleUserProjectChange<T extends AbstractGradleUserProjectChange<T>> implements GradleUserProjectChange<T> {
- private long myTimestamp;
-
- protected AbstractGradleUserProjectChange() {
- myTimestamp = System.currentTimeMillis();
- }
-
@SuppressWarnings("unchecked")
@Nullable
@Override
@@ -43,12 +38,7 @@ public abstract class AbstractGradleUserProjectChange<T extends AbstractGradleUs
}
@Override
- public long getTimestamp() {
- return myTimestamp;
- }
-
- @Override
- public void setTimestamp(long timestamp) {
- myTimestamp = timestamp;
+ public int compareTo(@NotNull GradleUserProjectChange<?> o) {
+ return getClass().getName().compareTo(o.getClass().getName());
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleAutoImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleAutoImporter.java
index 5610330f3948..4b039050b74b 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleAutoImporter.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleAutoImporter.java
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.gradle.autoimport;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleLocalSettings;
import org.jetbrains.plugins.gradle.config.GradleSettings;
@@ -65,7 +66,8 @@ public class GradleAutoImporter implements GradleProjectStructureChangesPostProc
@NotNull Project project,
boolean onIdeProjectStructureChange)
{
- if (onIdeProjectStructureChange || !GradleSettings.getInstance(project).isUseAutoImport()) {
+ GradleSettings s = GradleSettings.getInstance(project);
+ if (onIdeProjectStructureChange || !s.isUseAutoImport() || StringUtil.isEmpty(s.getLinkedProjectPath())) {
return;
}
GradleLocalSettings settings = GradleLocalSettings.getInstance(project);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleLibraryDependencyExportedChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleLibraryDependencyExportedChange.java
new file mode 100644
index 000000000000..6703ce7d0b53
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleLibraryDependencyExportedChange.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.autoimport;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/4/13 12:22 PM
+ */
+public class GradleLibraryDependencyExportedChange
+ extends AbstractGradleDependencyExportedUserChange<GradleLibraryDependencyExportedChange>
+{
+
+ @SuppressWarnings("UnusedDeclaration")
+ public GradleLibraryDependencyExportedChange() {
+ // Required for IJ serialization
+ }
+
+ public GradleLibraryDependencyExportedChange(@NotNull String moduleName, @NotNull String dependencyName, boolean exported) {
+ super(moduleName, dependencyName, exported);
+ }
+
+ @Override
+ public void invite(@NotNull GradleUserProjectChangeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("library dependency '%s' is %sexported at module '%s'",
+ getDependencyName(), isExported() ? "" : "non-", getModuleName());
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleLibraryDependencyScopeUserChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleLibraryDependencyScopeUserChange.java
new file mode 100644
index 000000000000..8f787b3a6469
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleLibraryDependencyScopeUserChange.java
@@ -0,0 +1,48 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.autoimport;
+
+import com.intellij.openapi.roots.DependencyScope;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/4/13 12:12 PM
+ */
+public class GradleLibraryDependencyScopeUserChange extends AbstractGradleDependencyScopeUserChange<GradleLibraryDependencyScopeUserChange> {
+
+ @SuppressWarnings("UnusedDeclaration")
+ public GradleLibraryDependencyScopeUserChange() {
+ // Required for IJ serialization
+ }
+
+ public GradleLibraryDependencyScopeUserChange(@NotNull String moduleName,
+ @NotNull String dependencyName,
+ @NotNull DependencyScope scope)
+ {
+ super(moduleName, dependencyName, scope);
+ }
+
+ @Override
+ public void invite(@NotNull GradleUserProjectChangeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("scope set to '%s' for library dependency '%s' of module '%s'", getScope(), getDependencyName(), getModuleName());
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleModuleDependencyExportedChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleModuleDependencyExportedChange.java
new file mode 100644
index 000000000000..d2bb711ae463
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleModuleDependencyExportedChange.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.autoimport;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/4/13 12:24 PM
+ */
+public class GradleModuleDependencyExportedChange
+ extends AbstractGradleDependencyExportedUserChange<GradleModuleDependencyExportedChange>
+{
+
+ @SuppressWarnings("UnusedDeclaration")
+ public GradleModuleDependencyExportedChange() {
+ // Required for IJ serialization
+ }
+
+ public GradleModuleDependencyExportedChange(@NotNull String moduleName, @NotNull String dependencyName, boolean exported) {
+ super(moduleName, dependencyName, exported);
+ }
+
+ @Override
+ public void invite(@NotNull GradleUserProjectChangeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("module dependency '%s' is %sexported at module '%s'",
+ getDependencyName(), isExported() ? "" : "non-", getModuleName());
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleModuleDependencyScopeUserChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleModuleDependencyScopeUserChange.java
new file mode 100644
index 000000000000..e9e03c760a56
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleModuleDependencyScopeUserChange.java
@@ -0,0 +1,48 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.autoimport;
+
+import com.intellij.openapi.roots.DependencyScope;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/4/13 12:16 PM
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class GradleModuleDependencyScopeUserChange extends AbstractGradleDependencyScopeUserChange<GradleLibraryDependencyScopeUserChange> {
+
+ public GradleModuleDependencyScopeUserChange() {
+ // Required for IJ serialization
+ }
+
+ public GradleModuleDependencyScopeUserChange(@NotNull String moduleName,
+ @NotNull String dependencyName,
+ @NotNull DependencyScope scope)
+ {
+ super(moduleName, dependencyName, scope);
+ }
+
+ @Override
+ public void invite(@NotNull GradleUserProjectChangeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("scope set to '%s' for module dependency '%s' of module '%s'", getScope(), getDependencyName(), getModuleName());
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChange.java
index c289102310ff..77554ad450c7 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChange.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChange.java
@@ -28,17 +28,9 @@ import org.jetbrains.annotations.NotNull;
* @author Denis Zhdanov
* @since 2/18/13 8:03 PM
*/
-public interface GradleUserProjectChange<T extends GradleUserProjectChange> extends PersistentStateComponent<T>, Comparable<T> {
+public interface GradleUserProjectChange<T extends GradleUserProjectChange>
+ extends PersistentStateComponent<T>, Comparable<GradleUserProjectChange<?>>
+{
void invite(@NotNull GradleUserProjectChangeVisitor visitor);
-
- /**
- * @return timestamp of the last known point when current change was not outdated. This information is useful
- * if we want to return a change if it was inactive for a while (e.g. a user temporarily added a module and after
- * that project files are re-written on update from VCS. We don't want to keep the change forever then)
- */
- long getTimestamp();
-
- @SuppressWarnings("UnusedDeclaration") // Used by IJ serialization
- void setTimestamp(long timestamp);
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangeVisitor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangeVisitor.java
index fbd395b4074f..3a736c08264e 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangeVisitor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangeVisitor.java
@@ -29,4 +29,8 @@ public interface GradleUserProjectChangeVisitor {
void visit(@NotNull GradleRemoveModuleDependencyUserChange change);
void visit(@NotNull GradleAddLibraryDependencyUserChange change);
void visit(@NotNull GradleRemoveLibraryDependencyUserChange change);
+ void visit(@NotNull GradleLibraryDependencyScopeUserChange change);
+ void visit(@NotNull GradleModuleDependencyScopeUserChange change);
+ void visit(@NotNull GradleLibraryDependencyExportedChange change);
+ void visit(@NotNull GradleModuleDependencyExportedChange change);
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangesCalculator.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangesCalculator.java
index d784448964ea..10c8d2e8c1c0 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangesCalculator.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/autoimport/GradleUserProjectChangesCalculator.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
+import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
@@ -137,10 +138,7 @@ public class GradleUserProjectChangesCalculator {
public void filterOutdatedChanges() {
Set<GradleUserProjectChange> changes = ContainerUtilRt.newHashSet(mySettings.getUserProjectChanges());
for (GradleUserProjectChange change : mySettings.getUserProjectChanges()) {
- if (isUpToDate(change)) {
- change.setTimestamp(System.currentTimeMillis());
- }
- else {
+ if (!isUpToDate(change)) {
changes.remove(change);
}
}
@@ -148,27 +146,27 @@ public class GradleUserProjectChangesCalculator {
}
private static void buildModulePresenceChanges(@NotNull final Context context) {
- buildChanges(context.oldModules.keySet(), context.currentModules.keySet(), MODULE_ADDED, MODULE_REMOVED, context);
+ buildPresenceChanges(context.oldModules.keySet(), context.currentModules.keySet(), MODULE_ADDED, MODULE_REMOVED, context);
}
private static void buildDependencyPresenceChanges(@NotNull Context context) {
Set<String> commonModuleNames = ContainerUtilRt.newHashSet(context.currentModules.keySet());
commonModuleNames.retainAll(context.oldModules.keySet());
for (final String moduleName : commonModuleNames) {
- final Set<String> currentModuleDependencies = ContainerUtilRt.newHashSet();
- final Set<String> oldModuleDependencies = ContainerUtilRt.newHashSet();
- final Set<String> currentLibraryDependencies = ContainerUtilRt.newHashSet();
- final Set<String> oldLibraryDependencies = ContainerUtilRt.newHashSet();
+ final Map<String, GradleModuleDependency> currentModuleDependencies = ContainerUtilRt.newHashMap();
+ final Map<String, GradleModuleDependency> oldModuleDependencies = ContainerUtilRt.newHashMap();
+ final Map<String, GradleLibraryDependency> currentLibraryDependencies = ContainerUtilRt.newHashMap();
+ final Map<String, GradleLibraryDependency> oldLibraryDependencies = ContainerUtilRt.newHashMap();
GradleEntityVisitor oldStateVisitor = new GradleEntityVisitorAdapter() {
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
- oldModuleDependencies.add(dependency.getTarget().getName());
+ oldModuleDependencies.put(dependency.getTarget().getName(), dependency);
}
@Override
public void visit(@NotNull GradleLibraryDependency dependency) {
- oldLibraryDependencies.add(dependency.getTarget().getName());
+ oldLibraryDependencies.put(dependency.getTarget().getName(), dependency);
}
};
for (GradleDependency dependency : context.oldModules.get(moduleName).getDependencies()) {
@@ -178,12 +176,12 @@ public class GradleUserProjectChangesCalculator {
GradleEntityVisitor currentStateVisitor = new GradleEntityVisitorAdapter() {
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
- currentModuleDependencies.add(dependency.getTarget().getName());
+ currentModuleDependencies.put(dependency.getTarget().getName(), dependency);
}
@Override
public void visit(@NotNull GradleLibraryDependency dependency) {
- currentLibraryDependencies.add(dependency.getTarget().getName());
+ currentLibraryDependencies.put(dependency.getTarget().getName(), dependency);
}
};
for (GradleDependency dependency : context.currentModules.get(moduleName).getDependencies()) {
@@ -215,16 +213,68 @@ public class GradleUserProjectChangesCalculator {
}
};
- buildChanges(oldModuleDependencies, currentModuleDependencies, addedModuleDependency, removedModuleDependency, context);
- buildChanges(oldLibraryDependencies, currentLibraryDependencies, addedLibraryDependency, removedLibraryDependency, context);
+ buildPresenceChanges(oldModuleDependencies.keySet(), currentModuleDependencies.keySet(),
+ addedModuleDependency, removedModuleDependency, context);
+ buildPresenceChanges(oldLibraryDependencies.keySet(), currentLibraryDependencies.keySet(),
+ addedLibraryDependency, removedLibraryDependency, context);
+
+ NullableFunction<Pair<GradleModuleDependency, GradleModuleDependency>, GradleUserProjectChange<?>> exportedModuleDependencyBuilder
+ = new NullableFunction<Pair<GradleModuleDependency, GradleModuleDependency>, GradleUserProjectChange<?>>() {
+ @Nullable
+ @Override
+ public GradleUserProjectChange<?> fun(Pair<GradleModuleDependency, GradleModuleDependency> pair) {
+ if (pair.first.isExported() != pair.second.isExported()) {
+ return new GradleModuleDependencyExportedChange(moduleName, pair.second.getName(), pair.second.isExported());
+ }
+ return null;
+ }
+ };
+ NullableFunction<Pair<GradleModuleDependency, GradleModuleDependency>, GradleUserProjectChange<?>> scopeModuleDependencyBuilder
+ = new NullableFunction<Pair<GradleModuleDependency, GradleModuleDependency>, GradleUserProjectChange<?>>() {
+ @Nullable
+ @Override
+ public GradleUserProjectChange<?> fun(Pair<GradleModuleDependency, GradleModuleDependency> pair) {
+ if (pair.first.getScope() != pair.second.getScope()) {
+ return new GradleModuleDependencyScopeUserChange(moduleName, pair.second.getName(), pair.second.getScope());
+ }
+ return null;
+ }
+ };
+ NullableFunction<Pair<GradleLibraryDependency, GradleLibraryDependency>, GradleUserProjectChange<?>> exportedLibDependencyBuilder
+ = new NullableFunction<Pair<GradleLibraryDependency, GradleLibraryDependency>, GradleUserProjectChange<?>>() {
+ @Nullable
+ @Override
+ public GradleUserProjectChange<?> fun(Pair<GradleLibraryDependency, GradleLibraryDependency> pair) {
+ if (pair.first.isExported() != pair.second.isExported()) {
+ return new GradleLibraryDependencyExportedChange(moduleName, pair.second.getName(), pair.second.isExported());
+ }
+ return null;
+ }
+ };
+ NullableFunction<Pair<GradleLibraryDependency, GradleLibraryDependency>, GradleUserProjectChange<?>> scopeLibDependencyBuilder
+ = new NullableFunction<Pair<GradleLibraryDependency, GradleLibraryDependency>, GradleUserProjectChange<?>>() {
+ @Nullable
+ @Override
+ public GradleUserProjectChange<?> fun(Pair<GradleLibraryDependency, GradleLibraryDependency> pair) {
+ if (pair.first.getScope() != pair.second.getScope()) {
+ return new GradleLibraryDependencyScopeUserChange(moduleName, pair.second.getName(), pair.second.getScope());
+ }
+ return null;
+ }
+ };
+
+ buildSettingsChanges(oldModuleDependencies, currentModuleDependencies, exportedModuleDependencyBuilder, context);
+ buildSettingsChanges(oldModuleDependencies, currentModuleDependencies, scopeModuleDependencyBuilder, context);
+ buildSettingsChanges(oldLibraryDependencies, currentLibraryDependencies, exportedLibDependencyBuilder, context);
+ buildSettingsChanges(oldLibraryDependencies, currentLibraryDependencies, scopeLibDependencyBuilder, context);
}
}
- private static <T> void buildChanges(@NotNull Set<T> oldData,
- @NotNull Set<T> currentData,
- @NotNull Function<T,GradleUserProjectChange<?>> addChangeBuilder,
- @NotNull Function<T,GradleUserProjectChange<?>> removeChangeBuilder,
- @NotNull Context context)
+ private static <T> void buildPresenceChanges(@NotNull Set<T> oldData,
+ @NotNull Set<T> currentData,
+ @NotNull Function<T, GradleUserProjectChange<?>> addChangeBuilder,
+ @NotNull Function<T, GradleUserProjectChange<?>> removeChangeBuilder,
+ @NotNull Context context)
{
Set<T> removed = ContainerUtilRt.newHashSet(oldData);
removed.removeAll(currentData);
@@ -243,6 +293,21 @@ public class GradleUserProjectChangesCalculator {
}
}
+ private static <T> void buildSettingsChanges(@NotNull Map<String, T> oldData,
+ @NotNull Map<String, T> currentData,
+ @NotNull NullableFunction<Pair<T, T>, GradleUserProjectChange<?>> builder,
+ @NotNull Context context)
+ {
+ Set<String> keys = ContainerUtilRt.newHashSet(oldData.keySet());
+ keys.retainAll(currentData.keySet());
+ for (String key : keys) {
+ GradleUserProjectChange<?> change = builder.fun(Pair.create(oldData.get(key), currentData.get(key)));
+ if (change != null) {
+ context.currentChanges.add(change);
+ }
+ }
+ }
+
@Nullable
private GradleProject buildCurrentIdeProject() {
GradleSettings settings = GradleSettings.getInstance(myProject);
@@ -273,7 +338,10 @@ public class GradleUserProjectChangesCalculator {
public Void visitLibraryOrderEntry(LibraryOrderEntry libraryOrderEntry, Void value) {
Library library = libraryOrderEntry.getLibrary();
if (library != null) {
- module.addDependency(new GradleLibraryDependency(module, new GradleLibrary(GradleUtil.getLibraryName(library))));
+ GradleLibraryDependency dependency = new GradleLibraryDependency(module, new GradleLibrary(GradleUtil.getLibraryName(library)));
+ dependency.setScope(libraryOrderEntry.getScope());
+ dependency.setExported(libraryOrderEntry.isExported());
+ module.addDependency(dependency);
}
return value;
}
@@ -282,7 +350,10 @@ public class GradleUserProjectChangesCalculator {
public Void visitModuleOrderEntry(ModuleOrderEntry moduleOrderEntry, Void value) {
GradleModule dependencyModule = modules.get(moduleOrderEntry.getModuleName());
if (dependencyModule != null) {
- module.addDependency(new GradleModuleDependency(module, dependencyModule));
+ GradleModuleDependency dependency = new GradleModuleDependency(module, dependencyModule);
+ dependency.setScope(moduleOrderEntry.getScope());
+ dependency.setExported(moduleOrderEntry.isExported());
+ module.addDependency(dependency);
}
return value;
}
@@ -355,6 +426,46 @@ public class GradleUserProjectChangesCalculator {
assert dependencyName != null;
result.set(myProjectStructureHelper.findIdeLibraryDependency(moduleName, dependencyName) == null);
}
+
+ @Override
+ public void visit(@NotNull GradleLibraryDependencyScopeUserChange change) {
+ String moduleName = change.getModuleName();
+ assert moduleName != null;
+ String dependencyName = change.getDependencyName();
+ assert dependencyName != null;
+ ExportableOrderEntry dependency = myProjectStructureHelper.findIdeLibraryDependency(moduleName, dependencyName);
+ result.set(dependency != null && dependency.getScope() == change.getScope());
+ }
+
+ @Override
+ public void visit(@NotNull GradleModuleDependencyScopeUserChange change) {
+ String moduleName = change.getModuleName();
+ assert moduleName != null;
+ String dependencyName = change.getDependencyName();
+ assert dependencyName != null;
+ ExportableOrderEntry dependency = myProjectStructureHelper.findIdeModuleDependency(moduleName, dependencyName);
+ result.set(dependency != null && dependency.getScope() == change.getScope());
+ }
+
+ @Override
+ public void visit(@NotNull GradleLibraryDependencyExportedChange change) {
+ String moduleName = change.getModuleName();
+ assert moduleName != null;
+ String dependencyName = change.getDependencyName();
+ assert dependencyName != null;
+ ExportableOrderEntry dependency = myProjectStructureHelper.findIdeLibraryDependency(moduleName, dependencyName);
+ result.set(dependency != null && dependency.isExported() == change.isExported());
+ }
+
+ @Override
+ public void visit(@NotNull GradleModuleDependencyExportedChange change) {
+ String moduleName = change.getModuleName();
+ assert moduleName != null;
+ String dependencyName = change.getDependencyName();
+ assert dependencyName != null;
+ ExportableOrderEntry dependency = myProjectStructureHelper.findIdeModuleDependency(moduleName, dependencyName);
+ result.set(dependency != null && dependency.isExported() == change.isExported());
+ }
});
return result.get();
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLocalSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLocalSettings.java
index c817e257c9cf..7e4ecdea647c 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLocalSettings.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLocalSettings.java
@@ -9,12 +9,9 @@ import com.intellij.util.xmlb.annotations.AbstractCollection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.autoimport.*;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
+import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -26,8 +23,6 @@ import java.util.concurrent.atomic.AtomicReference;
@State(name = "GradleLocalSettings", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)} )
public class GradleLocalSettings implements PersistentStateComponent<GradleLocalSettings> {
- private static final long USER_CHANGE_TTL_MS = SystemProperties.getIntProperty("gradle.user.change.ttl", (int)TimeUnit.DAYS.toMillis(7));
-
private static final boolean PRESERVE_EXPAND_STATE = !SystemProperties.getBooleanProperty("gradle.forget.expand.nodes.state", false);
/** Holds changes confirmed by the end-user. */
@@ -40,6 +35,11 @@ public class GradleLocalSettings implements PersistentStateComponent<GradleLocal
private final AtomicReference<Set<GradleUserProjectChange>> myUserChanges
= new AtomicReference<Set<GradleUserProjectChange>>(new HashSet<GradleUserProjectChange>());
+ private final AtomicReference<List<GradleTaskDescriptor>> myRecentTasks =
+ new AtomicReference<List<GradleTaskDescriptor>>(ContainerUtilRt.<GradleTaskDescriptor>newArrayList());
+ private final AtomicReference<Collection<GradleTaskDescriptor>> myAvailableTasks =
+ new AtomicReference<Collection<GradleTaskDescriptor>>(ContainerUtilRt.<GradleTaskDescriptor>newArrayList());
+
@NotNull
public static GradleLocalSettings getInstance(@NotNull Project project) {
return ServiceManager.getService(project, GradleLocalSettings.class);
@@ -57,20 +57,6 @@ public class GradleLocalSettings implements PersistentStateComponent<GradleLocal
@Override
public void loadState(GradleLocalSettings state) {
XmlSerializerUtil.copyBean(state, this);
- Set<GradleUserProjectChange> activeChange = ContainerUtilRt.newHashSet();
- boolean update = false;
- long now = System.currentTimeMillis();
- for (GradleUserProjectChange change : getUserProjectChanges()) {
- if (now - change.getTimestamp() > USER_CHANGE_TTL_MS) {
- update = true;
- }
- else {
- activeChange.add(change);
- }
- }
- if (update) {
- setUserProjectChanges(activeChange);
- }
}
@SuppressWarnings("UnusedDeclaration")
@@ -107,7 +93,9 @@ public class GradleLocalSettings implements PersistentStateComponent<GradleLocal
elementTypes = {
GradleAddModuleUserChange.class, GradleRemoveModuleUserChange.class,
GradleAddModuleDependencyUserChange.class, GradleRemoveModuleDependencyUserChange.class,
- GradleAddLibraryDependencyUserChange.class, GradleRemoveLibraryDependencyUserChange.class
+ GradleAddLibraryDependencyUserChange.class, GradleRemoveLibraryDependencyUserChange.class,
+ GradleModuleDependencyExportedChange.class, GradleModuleDependencyScopeUserChange.class,
+ GradleLibraryDependencyExportedChange.class, GradleLibraryDependencyScopeUserChange.class
}
)
@NotNull
@@ -118,4 +106,22 @@ public class GradleLocalSettings implements PersistentStateComponent<GradleLocal
public void setUserProjectChanges(@Nullable Set<GradleUserProjectChange> changes) {
myUserChanges.set(changes);
}
+
+ @NotNull
+ public Collection<GradleTaskDescriptor> getAvailableTasks() {
+ return myAvailableTasks.get();
+ }
+
+ public void setAvailableTasks(@NotNull Collection<GradleTaskDescriptor> taskNames) {
+ myAvailableTasks.set(taskNames);
+ }
+
+ @NotNull
+ public List<GradleTaskDescriptor> getRecentTasks() {
+ return myRecentTasks.get();
+ }
+
+ public void setRecentTasks(@NotNull List<GradleTaskDescriptor> taskNames) {
+ myRecentTasks.set(taskNames);
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
index cffb66fcd9ab..beeac03c38ef 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
@@ -40,9 +40,14 @@ import com.intellij.psi.search.NonClasspathDirectoryScope;
import icons.GradleIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.execution.GradleTaskLocation;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
+import org.jetbrains.plugins.gradle.tasks.GradleTasksList;
+import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleInstallationManager;
+import org.jetbrains.plugins.gradle.util.GradleUtil;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.extensions.GroovyScriptType;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
@@ -61,6 +66,8 @@ import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -84,24 +91,38 @@ public class GradleScriptType extends GroovyScriptType {
}
@Override
- public boolean isConfigurationByLocation(@NotNull GroovyScriptRunConfiguration existing, @NotNull Location location) {
+ public boolean isConfigurationByLocation(@NotNull GroovyScriptRunConfiguration existing, @NotNull Location location) {
final String params = existing.getScriptParameters();
- final String s = getTaskTarget(location);
- return s != null && params != null && (params.startsWith(s + " ") || params.equals(s));
+ if (params == null) {
+ return false;
+ }
+
+ final List<String> tasks = getTasksTarget(location);
+ if (tasks == null) {
+ return false;
+ }
+
+ String s = StringUtil.join(tasks, " ");
+ return params.startsWith(s + " ") || params.equals(s);
}
@Override
public void tuneConfiguration(@NotNull GroovyFile file, @NotNull GroovyScriptRunConfiguration configuration, Location location) {
- String target = getTaskTarget(location);
- if (target != null) {
- configuration.setScriptParameters(target);
- configuration.setName(configuration.getName() + "." + target);
+ List<String> tasks = getTasksTarget(location);
+ if (tasks != null) {
+ String s = StringUtil.join(tasks, " ");
+ configuration.setScriptParameters(s);
+ configuration.setName("gradle:" + s);
}
RunManagerEx.disableTasks(file.getProject(), configuration, CompileStepBeforeRun.ID, CompileStepBeforeRunNoErrorCheck.ID);
}
@Nullable
- private static String getTaskTarget(Location location) {
+ private static List<String> getTasksTarget(Location location) {
+ if (location instanceof GradleTaskLocation) {
+ return ((GradleTaskLocation)location).getTasks();
+ }
+
PsiElement parent = location.getPsiElement();
while (parent.getParent() != null && !(parent.getParent() instanceof PsiFile)) {
parent = parent.getParent();
@@ -110,7 +131,7 @@ public class GradleScriptType extends GroovyScriptType {
if (isCreateTaskMethod(parent)) {
final GrExpression[] arguments = ((GrMethodCallExpression)parent).getExpressionArguments();
if (arguments.length > 0 && arguments[0] instanceof GrLiteral && ((GrLiteral)arguments[0]).getValue() instanceof String) {
- return (String)((GrLiteral)arguments[0]).getValue();
+ return Collections.singletonList((String)((GrLiteral)arguments[0]).getValue());
}
}
else if (parent instanceof GrApplicationStatement) {
@@ -118,17 +139,17 @@ public class GradleScriptType extends GroovyScriptType {
if (shiftExpression instanceof GrShiftExpressionImpl) {
PsiElement shiftiesChild = shiftExpression.getChildren()[0];
if (shiftiesChild instanceof GrReferenceExpression) {
- return shiftiesChild.getText();
+ return Collections.singletonList(shiftiesChild.getText());
}
else if (shiftiesChild instanceof GrMethodCallExpression) {
- return shiftiesChild.getChildren()[0].getText();
+ return Collections.singletonList(shiftiesChild.getChildren()[0].getText());
}
}
else if (shiftExpression instanceof GrMethodCallExpression) {
- return shiftExpression.getChildren()[0].getText();
+ return Collections.singletonList(shiftExpression.getChildren()[0].getText());
}
}
-
+
return null;
}
@@ -152,6 +173,19 @@ public class GradleScriptType extends GroovyScriptType {
@Override
public boolean ensureRunnerConfigured(@Nullable Module module, RunProfile profile, Executor executor, final Project project) throws ExecutionException {
+ if (project != null && profile instanceof GroovyScriptRunConfiguration) {
+ GroovyScriptRunConfiguration configuration = (GroovyScriptRunConfiguration)profile;
+ String parameters = configuration.getScriptParameters();
+ if (parameters != null) {
+ GradleTasksList list = GradleUtil.getToolWindowElement(GradleTasksList.class, project, GradleDataKeys.RECENT_TASKS_LIST);
+ if (list != null) {
+ GradleTaskDescriptor descriptor = new GradleTaskDescriptor(parameters, null);
+ descriptor.setExecutorId(executor.getId());
+ list.setFirst(descriptor);
+ GradleLocalSettings.getInstance(project).setRecentTasks(list.getModel().getTasks());
+ }
+ }
+ }
final GradleInstallationManager libraryManager = ServiceManager.getService(GradleInstallationManager.class);
if (libraryManager.getGradleHome(module, project) == null) {
int result = Messages.showOkCancelDialog(
@@ -177,6 +211,8 @@ public class GradleScriptType extends GroovyScriptType {
throws CantRunException
{
final Project project = configuration.getProject();
+ String scriptParameters = configuration.getScriptParameters();
+
final GradleInstallationManager libraryManager = ServiceManager.getService(GradleInstallationManager.class);
final VirtualFile gradleHome = libraryManager.getGradleHome(module, project);
assert gradleHome != null;
@@ -217,7 +253,7 @@ public class GradleScriptType extends GroovyScriptType {
params.getProgramParametersList().add("--build-file");
params.getProgramParametersList().add(FileUtil.toSystemDependentName(scriptPath));
params.getProgramParametersList().addParametersString(configuration.getProgramParameters());
- params.getProgramParametersList().addParametersString(configuration.getScriptParameters());
+ params.getProgramParametersList().addParametersString(scriptParameters);
}
};
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java
index 8adb91f3a252..bd2aa9d90214 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java
@@ -10,16 +10,13 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SideBorder;
-import com.intellij.util.Consumer;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.notification.GradleConfigNotificationManager;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesDetector;
import org.jetbrains.plugins.gradle.ui.RichTextControlBuilder;
import org.jetbrains.plugins.gradle.util.GradleBundle;
-import org.jetbrains.plugins.gradle.util.GradleUtil;
import javax.swing.*;
import java.awt.*;
@@ -62,25 +59,8 @@ public abstract class GradleToolWindowPanel extends SimpleToolWindowPanel {
setContent(myContent);
MessageBusConnection connection = project.getMessageBus().connect(project);
- connection.subscribe(GradleConfigNotifier.TOPIC, new GradleConfigNotifier() {
+ connection.subscribe(GradleConfigNotifier.TOPIC, new GradleConfigNotifierAdapter() {
- private boolean myRefresh;
- private boolean myInBulk;
-
- @Override
- public void onBulkChangeStart() {
- myInBulk = true;
- }
-
- @Override
- public void onBulkChangeEnd() {
- myInBulk = false;
- if (myRefresh) {
- myRefresh = false;
- refreshAll();
- }
- }
-
@Override public void onLinkedProjectPathChange(@Nullable String oldPath, @Nullable String newPath) {
if (StringUtil.isEmpty(newPath)) {
myLayout.show(myContent, NON_LINKED_CARD_NAME);
@@ -89,34 +69,6 @@ public abstract class GradleToolWindowPanel extends SimpleToolWindowPanel {
if (StringUtil.isEmpty(oldPath) && !StringUtil.isEmpty(newPath)) {
myLayout.show(myContent, CONTENT_CARD_NAME);
}
- refreshAll();
- }
-
- @Override public void onPreferLocalGradleDistributionToWrapperChange(boolean preferLocalToWrapper) { refreshAll(); }
- @Override public void onGradleHomeChange(@Nullable String oldPath, @Nullable String newPath) { refreshAll(); }
- @Override public void onServiceDirectoryPathChange(@Nullable String oldPath, @Nullable String newPath) { refreshAll(); }
- @Override public void onUseAutoImportChange(boolean oldValue, boolean newValue) { refreshAll(); }
-
- private void refreshAll() {
- if (myInBulk) {
- myRefresh = true;
- return;
- }
- GradleUtil.refreshProject(myProject, new Consumer<String>() {
- @Override
- public void consume(String s) {
- GradleConfigNotificationManager notificationManager
- = ServiceManager.getService(myProject, GradleConfigNotificationManager.class);
- notificationManager.processRefreshError(s);
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- update();
- }
- });
- }
- });
- update();
}
});
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java
index 24fee47667da..9a5c4eea8b93 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java
@@ -1,5 +1,6 @@
package org.jetbrains.plugins.gradle.diff;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LibraryOrderEntry;
@@ -33,6 +34,8 @@ import java.util.Map;
*/
public class GradleDiffUtil {
+ private static final Logger LOG = Logger.getInstance("#" + GradleDiffUtil.class.getName());
+
private GradleDiffUtil() {
}
@@ -42,7 +45,7 @@ public class GradleDiffUtil {
* <p/>
* Example: particular module has been added at the gradle side. We want to mark that module, its content root(s), dependencies etc
* as gradle-local changes.
- *
+ *
* @param entity target gradle-local entity
* @param context changes calculation context to use
*/
@@ -66,7 +69,7 @@ public class GradleDiffUtil {
@Override
public void visit(@NotNull GradleContentRoot contentRoot) {
- context.register(new GradleContentRootPresenceChange(contentRoot, null));
+ context.register(new GradleContentRootPresenceChange(contentRoot, null));
}
@Override
@@ -182,8 +185,11 @@ public class GradleDiffUtil {
{
Map<Object, I> ideEntitiesByKeys = new HashMap<Object, I>();
for (I entity : ideEntities) {
- final I previous = ideEntitiesByKeys.put(calculator.getIdeKey(entity), entity);
- assert previous == null;
+ Object key = calculator.getIdeKey(entity);
+ final I previous = ideEntitiesByKeys.put(key, entity);
+ if (previous != null) {
+ LOG.warn("Duplicate setup for library " + key);
+ }
}
for (G gradleEntity: gradleEntities) {
I ideEntity = ideEntitiesByKeys.remove(calculator.getGradleKey(gradleEntity, context));
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyExportedChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyExportedChange.java
index 6782ddaa86ee..728590803158 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyExportedChange.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyExportedChange.java
@@ -19,6 +19,12 @@ public class GradleDependencyExportedChange extends AbstractGradleConflictingPro
super(id, GradleBundle.message("gradle.sync.change.dependency.exported", id), gradleValue, intellijValue);
}
+ @NotNull
+ @Override
+ public AbstractGradleDependencyId getEntityId() {
+ return (AbstractGradleDependencyId)super.getEntityId();
+ }
+
@Override
public void invite(@NotNull GradleProjectStructureChangeVisitor visitor) {
visitor.visit(this);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyScopeChange.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyScopeChange.java
index cf166af2c014..0cf20951d9a4 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyScopeChange.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/dependency/GradleDependencyScopeChange.java
@@ -4,7 +4,7 @@ import com.intellij.openapi.roots.DependencyScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.diff.AbstractGradleConflictingPropertyChange;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangeVisitor;
-import org.jetbrains.plugins.gradle.model.id.GradleEntityId;
+import org.jetbrains.plugins.gradle.model.id.AbstractGradleDependencyId;
import org.jetbrains.plugins.gradle.util.GradleBundle;
/**
@@ -13,13 +13,19 @@ import org.jetbrains.plugins.gradle.util.GradleBundle;
*/
public class GradleDependencyScopeChange extends AbstractGradleConflictingPropertyChange<DependencyScope> {
- public GradleDependencyScopeChange(@NotNull GradleEntityId id,
+ public GradleDependencyScopeChange(@NotNull AbstractGradleDependencyId id,
@NotNull DependencyScope gradleValue,
@NotNull DependencyScope intellijValue)
{
super(id, GradleBundle.message("gradle.sync.change.dependency.scope", id), gradleValue, intellijValue);
}
+ @NotNull
+ @Override
+ public AbstractGradleDependencyId getEntityId() {
+ return (AbstractGradleDependencyId)super.getEntityId();
+ }
+
@Override
public void invite(@NotNull GradleProjectStructureChangeVisitor visitor) {
visitor.visit(this);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleTaskLocation.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleTaskLocation.java
new file mode 100644
index 000000000000..019561d61274
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleTaskLocation.java
@@ -0,0 +1,42 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.execution;
+
+import com.intellij.execution.PsiLocation;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/16/13 1:54 PM
+ */
+public class GradleTaskLocation extends PsiLocation<PsiFile> {
+
+ @NotNull private final List<String> myTasks;
+
+ public GradleTaskLocation(@NotNull Project p, @NotNull PsiFile file, @NotNull List<String> tasks) {
+ super(p, file);
+ myTasks = tasks;
+ }
+
+ @NotNull
+ public List<String> getTasks() {
+ return myTasks;
+ }
+} \ No newline at end of file
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/AbstractGradleTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/AbstractGradleTask.java
index c2e5af793d9c..897772b4bc24 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/AbstractGradleTask.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/AbstractGradleTask.java
@@ -1,9 +1,10 @@
-package org.jetbrains.plugins.gradle.task;
+package org.jetbrains.plugins.gradle.internal.task;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager;
@@ -25,17 +26,17 @@ import java.util.concurrent.atomic.AtomicReference;
* @since 1/24/12 7:03 AM
*/
public abstract class AbstractGradleTask implements GradleTask {
-
+
private static final Logger LOG = Logger.getInstance("#" + AbstractGradleTask.class.getName());
-
+
private final AtomicReference<GradleTaskState> myState = new AtomicReference<GradleTaskState>(GradleTaskState.NOT_STARTED);
private final AtomicReference<Throwable> myError = new AtomicReference<Throwable>();
- @Nullable transient private final Project myIntellijProject;
- @NotNull private final GradleTaskId myId;
+ @Nullable transient private final Project myIdeProject;
+ @NotNull private final GradleTaskId myId;
protected AbstractGradleTask(@Nullable Project project, @NotNull GradleTaskType type) {
- myIntellijProject = project;
+ myIdeProject = project;
myId = GradleTaskId.create(type);
}
@@ -59,8 +60,8 @@ public abstract class AbstractGradleTask implements GradleTask {
}
@Nullable
- public Project getIntellijProject() {
- return myIntellijProject;
+ public Project getIdeProject() {
+ return myIdeProject;
}
public void refreshState() {
@@ -69,27 +70,36 @@ public abstract class AbstractGradleTask implements GradleTask {
}
final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
try {
- final GradleApiFacade facade = manager.getFacade(myIntellijProject);
+ final GradleApiFacade facade = manager.getFacade(myIdeProject);
setState(facade.isTaskInProgress(getId()) ? GradleTaskState.IN_PROGRESS : GradleTaskState.FAILED);
}
catch (Throwable e) {
setState(GradleTaskState.FAILED);
myError.set(e);
- if (myIntellijProject == null || !myIntellijProject.isDisposed()) {
+ if (myIdeProject == null || !myIdeProject.isDisposed()) {
LOG.warn(e);
}
}
}
@Override
- public void execute(@NotNull final ProgressIndicator indicator) {
+ public void execute(@NotNull final ProgressIndicator indicator, @NotNull GradleTaskNotificationListener ... listeners) {
indicator.setIndeterminate(true);
- execute(new GradleTaskNotificationListenerAdapter() {
+ GradleTaskNotificationListenerAdapter adapter = new GradleTaskNotificationListenerAdapter() {
@Override
public void onStatusChange(@NotNull GradleTaskNotificationEvent event) {
- indicator.setText(GradleBundle.message("gradle.sync.progress.update.text", event.getDescription()));
+ indicator.setText(wrapProgressText(event.getDescription()));
}
- });
+ };
+ final GradleTaskNotificationListener[] ls;
+ if (listeners.length > 0) {
+ ls = ArrayUtil.append(listeners, adapter);
+ }
+ else {
+ ls = new GradleTaskNotificationListener[] { adapter };
+ }
+
+ execute(ls);
}
@Override
@@ -114,6 +124,11 @@ public abstract class AbstractGradleTask implements GradleTask {
}
protected abstract void doExecute() throws Exception;
+
+ @NotNull
+ protected String wrapProgressText(@NotNull String text) {
+ return GradleBundle.message("gradle.general.progress.update.text", text);
+ }
@Override
public int hashCode() {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleExecuteTaskTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleExecuteTaskTask.java
new file mode 100644
index 000000000000..e24efbe45601
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleExecuteTaskTask.java
@@ -0,0 +1,55 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.internal.task;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
+import org.jetbrains.plugins.gradle.remote.GradleBuildManager;
+
+import java.util.List;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/15/13 10:02 PM
+ */
+public class GradleExecuteTaskTask extends AbstractGradleTask {
+
+ @NotNull private final List<String> myTasksToExecute;
+ @NotNull private final String myGradleProjectPath;
+
+ public GradleExecuteTaskTask(@Nullable Project project, @NotNull String gradleProjectPath, @NotNull List<String> tasksToExecute) {
+ super(project, GradleTaskType.EXECUTE_TASK);
+ myGradleProjectPath = gradleProjectPath;
+ myTasksToExecute = tasksToExecute;
+ }
+
+ @Override
+ protected void doExecute() throws Exception {
+ final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
+ Project project = getIdeProject();
+ GradleBuildManager buildManager = manager.getFacade(project).getBuildManager();
+ setState(GradleTaskState.IN_PROGRESS);
+ try {
+ buildManager.executeTasks(getId(), myTasksToExecute, myGradleProjectPath);
+ }
+ finally {
+ setState(GradleTaskState.FINISHED);
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleRefreshTasksListTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleRefreshTasksListTask.java
new file mode 100644
index 000000000000..17b156e11e39
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleRefreshTasksListTask.java
@@ -0,0 +1,87 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.internal.task;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.config.GradleLocalSettings;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
+import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
+import org.jetbrains.plugins.gradle.remote.GradleBuildManager;
+import org.jetbrains.plugins.gradle.tasks.GradleTasksModel;
+import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
+import org.jetbrains.plugins.gradle.util.GradleBundle;
+import org.jetbrains.plugins.gradle.util.GradleUtil;
+
+import java.util.Collection;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/15/13 1:20 PM
+ */
+public class GradleRefreshTasksListTask extends AbstractGradleTask {
+
+ @NotNull private final String myProjectPath;
+
+ public GradleRefreshTasksListTask(@Nullable Project project, @NotNull String projectPath) {
+ super(project, GradleTaskType.REFRESH_TASKS_LIST);
+ myProjectPath = projectPath;
+ }
+
+ @Override
+ protected void doExecute() throws Exception {
+ final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
+ Project project = getIdeProject();
+ GradleBuildManager buildManager = manager.getFacade(project).getBuildManager();
+ setState(GradleTaskState.IN_PROGRESS);
+ try {
+ final Collection<GradleTaskDescriptor> descriptors = buildManager.listTasks(getId(), myProjectPath);
+ if (descriptors == null || descriptors.isEmpty()) {
+ return;
+ }
+
+ if (project == null) {
+ return;
+ }
+
+ GradleLocalSettings settings = GradleLocalSettings.getInstance(project);
+ settings.setAvailableTasks(descriptors);
+
+ final GradleTasksModel tasksModel = GradleUtil.getToolWindowElement(GradleTasksModel.class, project, GradleDataKeys.ALL_TASKS_MODEL);
+ if (tasksModel == null) {
+ return;
+ }
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ tasksModel.setTasks(descriptors);
+ }
+ });
+ }
+ finally {
+ setState(GradleTaskState.FINISHED);
+ }
+ }
+
+ @Override
+ @NotNull
+ protected String wrapProgressText(@NotNull String text) {
+ return GradleBundle.message("gradle.tasks.progress.update.text", text);
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleResolveProjectTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleResolveProjectTask.java
index 29c1720896dc..a3952731afd0 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleResolveProjectTask.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleResolveProjectTask.java
@@ -1,4 +1,4 @@
-package org.jetbrains.plugins.gradle.task;
+package org.jetbrains.plugins.gradle.internal.task;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
@@ -8,6 +8,7 @@ import org.jetbrains.plugins.gradle.model.gradle.GradleProject;
import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel;
+import org.jetbrains.plugins.gradle.util.GradleBundle;
import java.util.concurrent.atomic.AtomicReference;
@@ -21,8 +22,7 @@ public class GradleResolveProjectTask extends AbstractGradleTask {
private final AtomicReference<GradleProject> myGradleProject = new AtomicReference<GradleProject>();
-
- private final String myProjectPath;
+ @NotNull private final String myProjectPath;
private final boolean myResolveLibraries;
public GradleResolveProjectTask(@Nullable Project project, @NotNull String projectPath, boolean resolveLibraries) {
@@ -33,13 +33,13 @@ public class GradleResolveProjectTask extends AbstractGradleTask {
protected void doExecute() throws Exception {
final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class);
- GradleProjectResolver resolver = manager.getFacade(getIntellijProject()).getResolver();
+ Project ideProject = getIdeProject();
+ GradleProjectResolver resolver = manager.getFacade(ideProject).getResolver();
setState(GradleTaskState.IN_PROGRESS);
GradleProjectStructureChangesModel model = null;
- final Project intellijProject = getIntellijProject();
- if (intellijProject != null && !intellijProject.isDisposed()) {
- model = ServiceManager.getService(intellijProject, GradleProjectStructureChangesModel.class);
+ if (ideProject != null && !ideProject.isDisposed()) {
+ model = ServiceManager.getService(ideProject, GradleProjectStructureChangesModel.class);
}
final GradleProject project;
try {
@@ -70,4 +70,10 @@ public class GradleResolveProjectTask extends AbstractGradleTask {
public GradleProject getGradleProject() {
return myGradleProject.get();
}
+
+ @Override
+ @NotNull
+ protected String wrapProgressText(@NotNull String text) {
+ return GradleBundle.message("gradle.sync.progress.update.text", text);
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTask.java
index 690a3a0e0e9f..cf7b2b73e2c7 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTask.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTask.java
@@ -1,4 +1,4 @@
-package org.jetbrains.plugins.gradle.task;
+package org.jetbrains.plugins.gradle.internal.task;
import com.intellij.openapi.progress.ProgressIndicator;
import org.jetbrains.annotations.NotNull;
@@ -27,8 +27,9 @@ public interface GradleTask {
* Executes current task and updates given indicator's {@link ProgressIndicator#setText2(String) status} during that.
*
* @param indicator target progress indicator
+ * @param listeners callbacks to be notified on task execution update
*/
- void execute(@NotNull ProgressIndicator indicator);
+ void execute(@NotNull ProgressIndicator indicator, @NotNull GradleTaskNotificationListener ... listeners);
/**
* Executes current task at the calling thread, i.e. the call to this method blocks.
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskAware.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskAware.java
index 6ca2482310d4..ba9744ca07bb 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskAware.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskAware.java
@@ -1,4 +1,4 @@
-package org.jetbrains.plugins.gradle.task;
+package org.jetbrains.plugins.gradle.internal.task;
import org.jetbrains.annotations.NotNull;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskId.java
index 577242f3a00e..ac4acc0f9c66 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskId.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskId.java
@@ -1,4 +1,4 @@
-package org.jetbrains.plugins.gradle.task;
+package org.jetbrains.plugins.gradle.internal.task;
import org.jetbrains.annotations.NotNull;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskManager.java
index e55c0dd83d8c..8da1782fb42a 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskManager.java
@@ -1,4 +1,4 @@
-package org.jetbrains.plugins.gradle.task;
+package org.jetbrains.plugins.gradle.internal.task;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskState.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskState.java
index 3a51f6801d56..9c59c48b640d 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskState.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskState.java
@@ -1,4 +1,4 @@
-package org.jetbrains.plugins.gradle.task;
+package org.jetbrains.plugins.gradle.internal.task;
/**
* @author Denis Zhdanov
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskType.java
index fb223ad7cd1d..6eadd3852d50 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskType.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/internal/task/GradleTaskType.java
@@ -1,4 +1,4 @@
-package org.jetbrains.plugins.gradle.task;
+package org.jetbrains.plugins.gradle.internal.task;
/**
* Enumerates interested types of tasks that may be enqueued to Gradle API.
@@ -8,5 +8,5 @@ package org.jetbrains.plugins.gradle.task;
*/
public enum GradleTaskType {
- RESOLVE_PROJECT
+ RESOLVE_PROJECT, REFRESH_TASKS_LIST, EXECUTE_TASK
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java
index 22c403502f88..3c52c398d16f 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleDependencyManager.java
@@ -6,6 +6,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
+import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.PlatformFacade;
import org.jetbrains.plugins.gradle.model.gradle.*;
@@ -181,23 +182,55 @@ public class GradleDependencyManager {
}
}
+ @SuppressWarnings("MethodMayBeStatic")
public void setScope(@NotNull final DependencyScope scope, @NotNull final ExportableOrderEntry dependency, boolean synchronous) {
Project project = dependency.getOwnerModule().getProject();
GradleUtil.executeProjectChangeAction(project, dependency, synchronous, new Runnable() {
@Override
public void run() {
- dependency.setScope(scope);
+ doForDependency(dependency, new Consumer<ExportableOrderEntry>() {
+ @Override
+ public void consume(ExportableOrderEntry entry) {
+ entry.setScope(scope);
+ }
+ });
}
});
}
+ @SuppressWarnings("MethodMayBeStatic")
public void setExported(final boolean exported, @NotNull final ExportableOrderEntry dependency, boolean synchronous) {
Project project = dependency.getOwnerModule().getProject();
GradleUtil.executeProjectChangeAction(project, dependency, synchronous, new Runnable() {
@Override
public void run() {
- dependency.setExported(exported);
+ doForDependency(dependency, new Consumer<ExportableOrderEntry>() {
+ @Override
+ public void consume(ExportableOrderEntry entry) {
+ entry.setExported(exported);
+ }
+ });
}
});
}
+
+ private static void doForDependency(@NotNull ExportableOrderEntry entry, @NotNull Consumer<ExportableOrderEntry> consumer) {
+ // We need to get an up-to-date modifiable model to work with.
+ ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(entry.getOwnerModule());
+ final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
+ try {
+ // The thing is that intellij created order entry objects every time new modifiable model is created,
+ // that's why we can't use target dependency object as is but need to get a reference to the current
+ // entry object from the model instead.
+ for (OrderEntry e : moduleRootModel.getOrderEntries()) {
+ if (e instanceof ExportableOrderEntry && e.getPresentableName().equals(entry.getPresentableName())) {
+ consumer.consume((ExportableOrderEntry)e);
+ break;
+ }
+ }
+ }
+ finally {
+ moduleRootModel.commit();
+ }
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleEntityManageHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleEntityManageHelper.java
index c9a8838b2a39..f107280b0afa 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleEntityManageHelper.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleEntityManageHelper.java
@@ -207,10 +207,14 @@ public class GradleEntityManageHelper {
private static void processProjectRenameChange(@NotNull GradleProjectRenameChange change, @NotNull EliminateChangesContext context) {
context.projectManager.renameProject(change.getGradleValue(), context.projectStructureHelper.getProject(), context.synchronous);
}
+
+ // Don't auto-apply language level change because we can't correctly process language level change manually made
+ // by a user - there is crazy processing related to project reloading after language level change and there is just
+ // no normal way to inject there.
- private static void processLanguageLevelChange(@NotNull GradleLanguageLevelChange change, @NotNull EliminateChangesContext context) {
- context.projectManager.setLanguageLevel(change.getGradleValue(), context.projectStructureHelper.getProject(), context.synchronous);
- }
+// private static void processLanguageLevelChange(@NotNull GradleLanguageLevelChange change, @NotNull EliminateChangesContext context) {
+// context.projectManager.setLanguageLevel(change.getGradleValue(), context.projectStructureHelper.getProject(), context.synchronous);
+// }
private static void processModulePresenceChange(@NotNull GradleModulePresenceChange change, @NotNull EliminateChangesContext context) {
GradleModuleId id = change.getGradleEntity();
@@ -336,7 +340,21 @@ public class GradleEntityManageHelper {
private static void processDependencyScopeChange(@NotNull GradleDependencyScopeChange change, @NotNull EliminateChangesContext context) {
ExportableOrderEntry dependency = findDependency(change, context);
- if (dependency != null) {
+ if (dependency == null) {
+ return;
+ }
+ AbstractGradleDependencyId id = change.getEntityId();
+ GradleUserProjectChange<?> userChange;
+ if (dependency instanceof LibraryOrderEntry) {
+ userChange = new GradleLibraryDependencyScopeUserChange(id.getOwnerModuleName(), id.getDependencyName(), change.getIdeValue());
+ }
+ else {
+ userChange = new GradleModuleDependencyScopeUserChange(id.getOwnerModuleName(), id.getDependencyName(), change.getIdeValue());
+ }
+ if (context.changesToPreserve.contains(userChange)) {
+ context.nonProcessedChanges.add(change);
+ }
+ else {
context.dependencyManager.setScope(change.getGradleValue(), dependency, context.synchronous);
}
}
@@ -345,7 +363,21 @@ public class GradleEntityManageHelper {
@NotNull EliminateChangesContext context)
{
ExportableOrderEntry dependency = findDependency(change, context);
- if (dependency != null) {
+ if (dependency == null) {
+ return;
+ }
+ AbstractGradleDependencyId id = change.getEntityId();
+ GradleUserProjectChange<?> userChange;
+ if (dependency instanceof LibraryOrderEntry) {
+ userChange = new GradleLibraryDependencyExportedChange(id.getOwnerModuleName(), id.getDependencyName(), change.getIdeValue());
+ }
+ else {
+ userChange = new GradleModuleDependencyExportedChange(id.getOwnerModuleName(), id.getDependencyName(), change.getIdeValue());
+ }
+ if (context.changesToPreserve.contains(userChange)) {
+ context.nonProcessedChanges.add(change);
+ }
+ else {
context.dependencyManager.setExported(change.getGradleValue(), dependency, context.synchronous);
}
}
@@ -386,7 +418,7 @@ public class GradleEntityManageHelper {
@Override
public void visit(@NotNull GradleLanguageLevelChange change) {
- processLanguageLevelChange(change, EliminateChangesContext.this);
+// processLanguageLevelChange(change, EliminateChangesContext.this);
}
@Override
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java
index b082cac59366..22f338a3c113 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleLocalNodeManageHelper.java
@@ -210,9 +210,7 @@ public class GradleLocalNodeManageHelper {
Collection<Object> entities = ContainerUtilRt.newArrayList();
for (GradleProjectStructureNode<?> node : nodes) {
GradleProjectStructureNodeDescriptor<? extends GradleEntityId> descriptor = node.getDescriptor();
- if (descriptor.getAttributes() == GradleTextAttributes.GRADLE_LOCAL_CHANGE
- || descriptor.getElement().getType() == GradleEntityType.SYNTHETIC
- || node.getParent() == null /* is root */) {
+ if (descriptor.getAttributes() != GradleTextAttributes.INTELLIJ_LOCAL_CHANGE) {
continue;
}
Object entity = myIdMapper.mapIdToEntity(descriptor.getElement());
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java
index 947e02c2d1a4..efa7c392a063 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectImportBuilder.java
@@ -36,7 +36,7 @@ import org.jetbrains.plugins.gradle.model.gradle.GradleModule;
import org.jetbrains.plugins.gradle.model.gradle.GradleProject;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper;
-import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask;
+import org.jetbrains.plugins.gradle.internal.task.GradleResolveProjectTask;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleLog;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectManager.java
index 6f4fb8d40856..8f2321c13981 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/manage/GradleProjectManager.java
@@ -28,6 +28,7 @@ import org.jetbrains.plugins.gradle.util.GradleUtil;
*/
public class GradleProjectManager {
+ @SuppressWarnings("MethodMayBeStatic")
public void renameProject(@NotNull final String newName, @NotNull final Project project, boolean synchronous) {
if (!(project instanceof ProjectEx) || newName.equals(project.getName())) {
return;
@@ -40,6 +41,7 @@ public class GradleProjectManager {
});
}
+ @SuppressWarnings("MethodMayBeStatic")
public void setLanguageLevel(@NotNull final LanguageLevel languageLevel, @NotNull Project project, boolean synchronous) {
final LanguageLevelProjectExtension languageLevelExtension = LanguageLevelProjectExtension.getInstance(project);
if (languageLevel == languageLevelExtension.getLanguageLevel()) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/gradle/GradleTaskDescriptor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/gradle/GradleTaskDescriptor.java
new file mode 100644
index 000000000000..b87b058b613b
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/gradle/GradleTaskDescriptor.java
@@ -0,0 +1,109 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.model.gradle;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/15/13 1:01 PM
+ */
+public class GradleTaskDescriptor implements Serializable, Comparable<GradleTaskDescriptor> {
+
+ private static final long serialVersionUID = 1L;
+
+ // The fields are mutable in order to ease IJ default xml serialization.
+ private String myName;
+
+ @Nullable private String myDescription;
+ @Nullable private String myExecutorId;
+
+ @SuppressWarnings("UnusedDeclaration")
+ public GradleTaskDescriptor() {
+ // Necessary for IJ serialization
+ }
+
+ public GradleTaskDescriptor(@NotNull String name, @Nullable String description) {
+ setName(name);
+ setDescription(description);
+ }
+
+ @Nullable
+ public String getDescription() {
+ return myDescription;
+ }
+
+ public void setDescription(@Nullable String description) {
+ myDescription = description;
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public void setName(@NotNull String name) {
+ myName = name;
+ }
+
+ @Nullable
+ public String getExecutorId() {
+ return myExecutorId;
+ }
+
+ public void setExecutorId(@Nullable String executorId) {
+ myExecutorId = executorId;
+ }
+
+ @Override
+ public int compareTo(GradleTaskDescriptor that) {
+ int cmp = myName.compareTo(that.myName);
+ if (cmp == 0) {
+ return Comparing.compare(myExecutorId, that.myExecutorId);
+ }
+ return cmp;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myName.hashCode();
+ result = 31 * result + (myExecutorId != null ? myExecutorId.hashCode() : 0);
+ result = 31 * result + (myDescription != null ? myDescription.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ GradleTaskDescriptor that = (GradleTaskDescriptor)o;
+
+ if (!myName.equals(that.myName)) return false;
+ if (myExecutorId != null ? !myExecutorId.equals(that.myExecutorId) : that.myExecutorId != null) return false;
+ if (myDescription != null ? !myDescription.equals(that.myDescription) : that.myDescription != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return myName;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManager.java
index a048f1cead9f..a7fb3823dff6 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManager.java
@@ -1,7 +1,7 @@
package org.jetbrains.plugins.gradle.notification;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
/**
* @author Denis Zhdanov
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManagerImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManagerImpl.java
index 0eb9d5570ce4..bdc59ef0bd8d 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManagerImpl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleProgressNotificationManagerImpl.java
@@ -5,7 +5,7 @@ import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.ConcurrentHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.remote.RemoteGradleProgressNotificationManager;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
import java.util.Collections;
import java.util.Map;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationEvent.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationEvent.java
index 3769a310e4c3..885bf9015a63 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationEvent.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationEvent.java
@@ -1,7 +1,7 @@
package org.jetbrains.plugins.gradle.notification;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
import java.io.Serializable;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListener.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListener.java
index ba4a73fee1fa..eb3b827fcd0c 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListener.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListener.java
@@ -1,7 +1,7 @@
package org.jetbrains.plugins.gradle.notification;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
/**
* Defines contract for callback to listen gradle task notifications.
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListenerAdapter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListenerAdapter.java
index 6d44810bdf5a..5a788ecca4fb 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListenerAdapter.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/notification/GradleTaskNotificationListenerAdapter.java
@@ -1,7 +1,7 @@
package org.jetbrains.plugins.gradle.notification;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
/**
* @author Denis Zhdanov
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacade.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacade.java
index ffe28cdf671b..4861a095f142 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacade.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacade.java
@@ -1,9 +1,9 @@
package org.jetbrains.plugins.gradle.remote;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.task.GradleTaskAware;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskAware;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
import java.rmi.Remote;
import java.rmi.RemoteException;
@@ -31,6 +31,12 @@ public interface GradleApiFacade extends Remote, GradleTaskAware {
return GradleProjectResolver.NULL_OBJECT;
}
+ @NotNull
+ @Override
+ public GradleBuildManager getBuildManager() throws RemoteException {
+ return GradleBuildManager.NULL_OBJECT;
+ }
+
@Override
public void applySettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
}
@@ -50,10 +56,10 @@ public interface GradleApiFacade extends Remote, GradleTaskAware {
return Collections.emptyMap();
}
};
-
+
/**
* Exposes <code>'resolve gradle project'</code> service that works at another process.
- *
+ *
* @return <code>'resolve gradle project'</code> service
* @throws RemoteException in case of unexpected I/O exception during processing
* @throws IllegalStateException in case of inability to create the service
@@ -62,8 +68,17 @@ public interface GradleApiFacade extends Remote, GradleTaskAware {
GradleProjectResolver getResolver() throws RemoteException, IllegalStateException;
/**
+ * Exposes <code>'run gradle task'</code> service which works at another process.
+ *
+ * @return gradle build manager
+ * @throws RemoteException in case of inability to create the service
+ */
+ @NotNull
+ GradleBuildManager getBuildManager() throws RemoteException;
+
+ /**
* Asks remote gradle process to apply given settings.
- *
+ *
* @param settings settings to apply
* @throws RemoteException in case of unexpected I/O exception during processing
*/
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleBuildManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleBuildManager.java
new file mode 100644
index 000000000000..3a8b1164372c
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleBuildManager.java
@@ -0,0 +1,72 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.remote;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
+import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
+
+import java.rmi.RemoteException;
+import java.util.*;
+
+/**
+ * Abstraction layer for executing gradle tasks.
+ *
+ * @author Denis Zhdanov
+ * @since 3/14/13 5:04 PM
+ */
+public interface GradleBuildManager extends RemoteGradleService {
+
+ GradleBuildManager NULL_OBJECT = new GradleBuildManager() {
+ @Override
+ public Collection<GradleTaskDescriptor> listTasks(@NotNull GradleTaskId id, @NotNull String projectPath) {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void executeTasks(@NotNull GradleTaskId id, @NotNull List<String> taskNames, @NotNull String projectPath)
+ throws RemoteException
+ {
+ }
+
+ @Override
+ public void setSettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
+ }
+
+ @Override
+ public void setNotificationListener(@NotNull GradleTaskNotificationListener notificationListener) throws RemoteException {
+ }
+
+ @Override
+ public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
+ return false;
+ }
+
+ @NotNull
+ @Override
+ public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
+ return Collections.emptyMap();
+ }
+ };
+
+ Collection<GradleTaskDescriptor> listTasks(@NotNull GradleTaskId id, @NotNull String projectPath)
+ throws RemoteException, GradleApiException;
+
+ void executeTasks(@NotNull GradleTaskId id, @NotNull List<String> taskNames, @NotNull String projectPath)
+ throws RemoteException, GradleApiException;
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleProjectResolver.java
index e6dc6a74df27..b70a90cacc23 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleProjectResolver.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleProjectResolver.java
@@ -4,8 +4,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.gradle.GradleProject;
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
import java.rmi.RemoteException;
import java.util.Collections;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProgressNotificationManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProgressNotificationManager.java
index dc35e524c44d..5fd9e36030cf 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProgressNotificationManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProgressNotificationManager.java
@@ -1,7 +1,7 @@
package org.jetbrains.plugins.gradle.remote;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
import java.rmi.Remote;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleService.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleService.java
index 84af289eec64..27e10f6e9adc 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleService.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleService.java
@@ -2,7 +2,7 @@ package org.jetbrains.plugins.gradle.remote;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
-import org.jetbrains.plugins.gradle.task.GradleTaskAware;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskAware;
import java.rmi.Remote;
import java.rmi.RemoteException;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleApiFacadeImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleApiFacadeImpl.java
index e753764fbc9a..35ec2177b765 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleApiFacadeImpl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleApiFacadeImpl.java
@@ -4,12 +4,12 @@ import com.intellij.execution.rmi.RemoteServer;
import com.intellij.util.Alarm;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
import org.jetbrains.plugins.gradle.remote.RemoteGradleProgressNotificationManager;
import org.jetbrains.plugins.gradle.remote.*;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
@@ -69,6 +69,17 @@ public class GradleApiFacadeImpl extends RemoteServer implements GradleApiFacade
}
}
+ @NotNull
+ @Override
+ public GradleBuildManager getBuildManager() throws RemoteException {
+ try {
+ return getRemote(GradleBuildManager.class, GradleBuildManagerImpl.class);
+ }
+ catch (Exception e) {
+ throw new IllegalStateException(String.format("Can't create '%s' service", GradleBuildManager.class.getName()), e);
+ }
+ }
+
/**
* Generic method to retrieve exposed implementations of the target interface.
* <p/>
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleBuildManagerImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleBuildManagerImpl.java
new file mode 100644
index 000000000000..6dc6278ed616
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleBuildManagerImpl.java
@@ -0,0 +1,116 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.remote.impl;
+
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
+import org.gradle.tooling.BuildLauncher;
+import org.gradle.tooling.ModelBuilder;
+import org.gradle.tooling.ProjectConnection;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.GradleTask;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
+import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
+import org.jetbrains.plugins.gradle.remote.GradleApiException;
+import org.jetbrains.plugins.gradle.remote.GradleBuildManager;
+import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
+
+import java.rmi.RemoteException;
+import java.util.*;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/14/13 5:09 PM
+ */
+public class GradleBuildManagerImpl implements GradleBuildManager {
+
+ private final RemoteGradleServiceHelper myHelper = new RemoteGradleServiceHelper();
+
+ @Override
+ public Collection<GradleTaskDescriptor> listTasks(@NotNull final GradleTaskId id, @NotNull final String projectPath) {
+ Function<ProjectConnection, Collection<GradleTaskDescriptor>> f = new Function<ProjectConnection, Collection<GradleTaskDescriptor>>() {
+ @Nullable
+ @Override
+ public Collection<GradleTaskDescriptor> fun(ProjectConnection connection) {
+ ModelBuilder<? extends IdeaProject> modelBuilder = myHelper.getModelBuilder(id, connection, false);
+ IdeaProject project = modelBuilder.get();
+ DomainObjectSet<? extends IdeaModule> modules = project.getModules();
+ if (modules == null) {
+ return Collections.emptyList();
+ }
+ Set<GradleTaskDescriptor> result = new HashSet<GradleTaskDescriptor>();
+ for (IdeaModule module : modules) {
+ for (GradleTask task : module.getGradleProject().getTasks()) {
+ String name = task.getName();
+ if (name == null || name.trim().isEmpty()) {
+ continue;
+ }
+ String s = name.toLowerCase();
+ if (s.contains("idea") || s.contains("eclipse")) {
+ continue;
+ }
+ result.add(new GradleTaskDescriptor(name, task.getDescription()));
+ }
+ }
+ return result;
+ }
+ };
+ return myHelper.execute(id, GradleTaskType.REFRESH_TASKS_LIST, projectPath, f);
+ }
+
+ @Override
+ public void executeTasks(@NotNull final GradleTaskId id, @NotNull final List<String> taskNames, @NotNull String projectPath)
+ throws RemoteException, GradleApiException
+ {
+ Function<ProjectConnection, Void> f = new Function<ProjectConnection, Void>() {
+ @Override
+ public Void fun(ProjectConnection connection) {
+ BuildLauncher launcher = myHelper.getBuildLauncher(id, connection);
+ launcher.forTasks(ArrayUtil.toStringArray(taskNames));
+ launcher.run();
+ return null;
+ }
+ };
+ myHelper.execute(id, GradleTaskType.EXECUTE_TASK, projectPath, f);
+ }
+
+ @Override
+ public void setSettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
+ myHelper.setSettings(settings);
+ }
+
+ @Override
+ public void setNotificationListener(@NotNull GradleTaskNotificationListener notificationListener) throws RemoteException {
+ myHelper.setNotificationListener(notificationListener);
+ }
+
+ @Override
+ public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
+ return myHelper.isTaskInProgress(id);
+ }
+
+ @NotNull
+ @Override
+ public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
+ return myHelper.getTasksInProgress();
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java
index 30863ae996fe..72668e712e9f 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java
@@ -4,35 +4,30 @@ import com.intellij.execution.rmi.RemoteObject;
import com.intellij.openapi.roots.DependencyScope;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.Function;
import com.intellij.util.PathUtil;
-import com.intellij.util.containers.ConcurrentHashSet;
import com.intellij.util.containers.HashMap;
-import org.gradle.tooling.*;
-import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
+import org.gradle.tooling.ModelBuilder;
+import org.gradle.tooling.ProjectConnection;
import org.gradle.tooling.model.DomainObjectSet;
import org.gradle.tooling.model.idea.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
import org.jetbrains.plugins.gradle.model.gradle.*;
-import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
import org.jetbrains.plugins.gradle.remote.GradleApiException;
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
import org.jetbrains.plugins.gradle.remote.RemoteGradleService;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
-import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleUtil;
import java.io.File;
-import java.io.IOException;
import java.rmi.RemoteException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
/**
* @author Denis Zhdanov
@@ -40,46 +35,33 @@ import java.util.concurrent.atomic.AtomicReference;
*/
public class GradleProjectResolverImpl extends RemoteObject implements GradleProjectResolver, RemoteGradleService {
- private final AtomicReference<RemoteGradleProcessSettings> mySettings = new AtomicReference<RemoteGradleProcessSettings>();
- private final GradleLibraryNamesMixer myLibraryNamesMixer = new GradleLibraryNamesMixer();
- private final ConcurrentHashSet<GradleTaskId> myTasksInProgress = new ConcurrentHashSet<GradleTaskId>();
- private final AtomicReference<GradleTaskNotificationListener> myNotificationListener
- = new AtomicReference<GradleTaskNotificationListener>();
-
+ @NotNull private final RemoteGradleServiceHelper myHelper = new RemoteGradleServiceHelper();
+
+ private final GradleLibraryNamesMixer myLibraryNamesMixer = new GradleLibraryNamesMixer();
@NotNull
@Override
- public GradleProject resolveProjectInfo(@NotNull GradleTaskId id, @NotNull String projectPath, boolean downloadLibraries)
+ public GradleProject resolveProjectInfo(@NotNull final GradleTaskId id, @NotNull final String projectPath, final boolean downloadLibraries)
throws RemoteException, GradleApiException, IllegalArgumentException, IllegalStateException
{
- ProjectConnection connection = getConnection(projectPath);
- try {
- return doResolveProjectInfo(id, projectPath, connection, downloadLibraries);
- }
- catch (Throwable e) {
- throw new GradleApiException(e);
- }
- finally {
- try {
- connection.close();
- }
- catch (Throwable e) {
- // ignore
+ return myHelper.execute(id, GradleTaskType.RESOLVE_PROJECT, projectPath, new Function<ProjectConnection, GradleProject>() {
+ @Nullable
+ @Override
+ public GradleProject fun(ProjectConnection connection) {
+ return doResolveProjectInfo(id, projectPath, connection, downloadLibraries);
}
- }
+ });
}
@Override
- public boolean isTaskInProgress(@NotNull GradleTaskId id) {
- return myTasksInProgress.contains(id);
+ public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
+ return myHelper.isTaskInProgress(id);
}
@NotNull
@Override
public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
- Map<GradleTaskType, Set<GradleTaskId>> result = new HashMap<GradleTaskType, Set<GradleTaskId>>();
- result.put(GradleTaskType.RESOLVE_PROJECT, new HashSet<GradleTaskId>(myTasksInProgress));
- return result;
+ return myHelper.getTasksInProgress();
}
@NotNull
@@ -87,24 +69,9 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
@NotNull String projectPath,
@NotNull ProjectConnection connection,
boolean downloadLibraries)
- throws RemoteException, IllegalArgumentException, IllegalStateException
+ throws IllegalArgumentException, IllegalStateException
{
- final GradleTaskNotificationListener progressManager = myNotificationListener.get();
- progressManager.onStart(id);
- ModelBuilder<? extends IdeaProject> modelBuilder = connection.model(downloadLibraries ? IdeaProject.class : BasicIdeaProject.class);
- final RemoteGradleProcessSettings settings = mySettings.get();
- if (settings != null) {
- final String javaHome = settings.getJavaHome();
- if (javaHome != null && new File(javaHome).isDirectory()) {
- modelBuilder.setJavaHome(new File(javaHome));
- }
- }
- modelBuilder.addProgressListener(new ProgressListener() {
- @Override
- public void statusChanged(ProgressEvent event) {
- progressManager.onStatusChange(new GradleTaskNotificationEvent(id, event.getDescription()));
- }
- });
+ ModelBuilder<? extends IdeaProject> modelBuilder = myHelper.getModelBuilder(id, connection, downloadLibraries);
IdeaProject project = modelBuilder.get();
GradleProject result = populateProject(project, projectPath);
@@ -376,72 +343,13 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
return null;
}
- /**
- * Allows to retrieve gradle api connection to use for the given project.
- *
- * @param projectPath target project path
- * @return connection to use
- * @throws IllegalStateException if it's not possible to create the connection
- */
- @NotNull
- private ProjectConnection getConnection(@NotNull String projectPath) throws IllegalStateException {
- File projectFile = new File(projectPath);
- if (!projectFile.isFile()) {
- throw new IllegalArgumentException(GradleBundle.message("gradle.import.text.error.invalid.path", projectPath));
- }
- File projectDir = projectFile.getParentFile();
- GradleConnector connector = GradleConnector.newConnector();
- RemoteGradleProcessSettings settings = mySettings.get();
- if (settings != null) {
-
- // Setup wrapper/local installation usage.
- if (!settings.isUseWrapper()) {
- String gradleHome = settings.getGradleHome();
- if (gradleHome != null) {
- try {
- // There were problems with symbolic links processing at the gradle side.
- connector.useInstallation(new File(gradleHome).getCanonicalFile());
- }
- catch (IOException e) {
- connector.useInstallation(new File(settings.getGradleHome()));
- }
- }
- }
-
- // Setup service directory if necessary.
- String serviceDirectory = settings.getServiceDirectory();
- if (serviceDirectory != null) {
- connector.useGradleUserHomeDir(new File(serviceDirectory));
- }
-
- // Setup logging if necessary.
- if (settings.isVerboseApi() && connector instanceof DefaultGradleConnector) {
- ((DefaultGradleConnector)connector).setVerboseLogging(true);
- }
-
- // Setup daemon ttl if necessary.
- long ttl = settings.getTtlInMs();
- if (ttl > 0 && connector instanceof DefaultGradleConnector) {
- ((DefaultGradleConnector)connector).daemonMaxIdleTime((int)ttl, TimeUnit.MILLISECONDS);
- }
- }
- connector.forProjectDirectory(projectDir);
- ProjectConnection connection = connector.connect();
- if (connection == null) {
- throw new IllegalStateException(String.format(
- "Can't create connection to the target project via gradle tooling api. Project path: '%s'", projectPath
- ));
- }
- return connection;
- }
-
@Override
- public void setSettings(@NotNull RemoteGradleProcessSettings settings) {
- mySettings.set(settings);
+ public void setSettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
+ myHelper.setSettings(settings);
}
@Override
- public void setNotificationListener(@NotNull GradleTaskNotificationListener notificationListener) {
- myNotificationListener.set(notificationListener);
+ public void setNotificationListener(@NotNull GradleTaskNotificationListener notificationListener) throws RemoteException {
+ myHelper.setNotificationListener(notificationListener);
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/RemoteGradleServiceHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/RemoteGradleServiceHelper.java
new file mode 100644
index 000000000000..63d9a1aa704b
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/RemoteGradleServiceHelper.java
@@ -0,0 +1,205 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.remote.impl;
+
+import com.intellij.util.Function;
+import com.intellij.util.containers.ConcurrentHashMap;
+import com.intellij.util.containers.ConcurrentHashSet;
+import com.intellij.util.containers.HashMap;
+import org.gradle.tooling.*;
+import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
+import org.gradle.tooling.model.idea.BasicIdeaProject;
+import org.gradle.tooling.model.idea.IdeaProject;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
+import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
+import org.jetbrains.plugins.gradle.remote.GradleApiException;
+import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
+import org.jetbrains.plugins.gradle.remote.RemoteGradleService;
+import org.jetbrains.plugins.gradle.util.GradleBundle;
+
+import java.io.File;
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/14/13 5:11 PM
+ */
+public class RemoteGradleServiceHelper implements RemoteGradleService {
+
+ private final AtomicReference<RemoteGradleProcessSettings> mySettings = new AtomicReference<RemoteGradleProcessSettings>();
+ private final ConcurrentMap<GradleTaskType, Set<GradleTaskId>> myTasksInProgress =
+ new ConcurrentHashMap<GradleTaskType, Set<GradleTaskId>>();
+
+ private final AtomicReference<GradleTaskNotificationListener> myNotificationListener
+ = new AtomicReference<GradleTaskNotificationListener>();
+
+ @Override
+ public void setSettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
+ mySettings.set(settings);
+ }
+
+ @Override
+ public void setNotificationListener(@NotNull GradleTaskNotificationListener notificationListener) throws RemoteException {
+ myNotificationListener.set(notificationListener);
+ }
+
+ @Override
+ public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
+ for (Set<GradleTaskId> ids : myTasksInProgress.values()) {
+ if (ids.contains(id)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @NotNull
+ @Override
+ public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
+ return new HashMap<GradleTaskType, Set<GradleTaskId>>(myTasksInProgress);
+ }
+
+ @NotNull
+ public ModelBuilder<? extends IdeaProject> getModelBuilder(@NotNull final GradleTaskId id,
+ @NotNull ProjectConnection connection,
+ boolean downloadLibraries)
+ {
+ ModelBuilder<? extends IdeaProject> result = connection.model(downloadLibraries ? IdeaProject.class : BasicIdeaProject.class);
+ prepare(result, id);
+ return result;
+ }
+
+ @NotNull
+ public BuildLauncher getBuildLauncher(@NotNull final GradleTaskId id, @NotNull ProjectConnection connection) {
+ BuildLauncher result = connection.newBuild();
+ prepare(result, id);
+ return result;
+ }
+
+ private void prepare(LongRunningOperation operation, @NotNull final GradleTaskId id) {
+ final GradleTaskNotificationListener progressManager = myNotificationListener.get();
+ progressManager.onStart(id);
+ final RemoteGradleProcessSettings settings = mySettings.get();
+ if (settings != null) {
+ final String javaHome = settings.getJavaHome();
+ if (javaHome != null && new File(javaHome).isDirectory()) {
+ operation.setJavaHome(new File(javaHome));
+ }
+ }
+ operation.addProgressListener(new ProgressListener() {
+ @Override
+ public void statusChanged(ProgressEvent event) {
+ progressManager.onStatusChange(new GradleTaskNotificationEvent(id, event.getDescription()));
+ }
+ });
+ }
+
+ public <T> T execute(@NotNull GradleTaskId id,
+ @NotNull final GradleTaskType type,
+ @NotNull String projectPath,
+ @NotNull Function<ProjectConnection, T> f)
+ {
+ Set<GradleTaskId> ids = myTasksInProgress.get(type);
+ if (ids == null) {
+ myTasksInProgress.putIfAbsent(type, new ConcurrentHashSet<GradleTaskId>());
+ ids = myTasksInProgress.get(type);
+ }
+ ids.add(id);
+ ProjectConnection connection = getConnection(projectPath);
+ try {
+ return f.fun(connection);
+ }
+ catch (Throwable e) {
+ throw new GradleApiException(e);
+ }
+ finally {
+ try {
+ connection.close();
+ }
+ catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Allows to retrieve gradle api connection to use for the given project.
+ *
+ * @param projectPath target project path
+ * @return connection to use
+ * @throws IllegalStateException if it's not possible to create the connection
+ */
+ @NotNull
+ private ProjectConnection getConnection(@NotNull String projectPath) throws IllegalStateException {
+ File projectFile = new File(projectPath);
+ if (!projectFile.isFile()) {
+ throw new IllegalArgumentException(GradleBundle.message("gradle.import.text.error.invalid.path", projectPath));
+ }
+ File projectDir = projectFile.getParentFile();
+ GradleConnector connector = GradleConnector.newConnector();
+ RemoteGradleProcessSettings settings = mySettings.get();
+ if (settings != null) {
+
+ // Setup wrapper/local installation usage.
+ if (!settings.isUseWrapper()) {
+ String gradleHome = settings.getGradleHome();
+ if (gradleHome != null) {
+ try {
+ // There were problems with symbolic links processing at the gradle side.
+ connector.useInstallation(new File(gradleHome).getCanonicalFile());
+ }
+ catch (IOException e) {
+ connector.useInstallation(new File(settings.getGradleHome()));
+ }
+ }
+ }
+
+ // Setup service directory if necessary.
+ String serviceDirectory = settings.getServiceDirectory();
+ if (serviceDirectory != null) {
+ connector.useGradleUserHomeDir(new File(serviceDirectory));
+ }
+
+ // Setup logging if necessary.
+ if (settings.isVerboseApi() && connector instanceof DefaultGradleConnector) {
+ ((DefaultGradleConnector)connector).setVerboseLogging(true);
+ }
+
+ // Setup daemon ttl if necessary.
+ long ttl = settings.getTtlInMs();
+ if (ttl > 0 && connector instanceof DefaultGradleConnector) {
+ ((DefaultGradleConnector)connector).daemonMaxIdleTime((int)ttl, TimeUnit.MILLISECONDS);
+ }
+ }
+ connector.forProjectDirectory(projectDir);
+ ProjectConnection connection = connector.connect();
+ if (connection == null) {
+ throw new IllegalStateException(String.format(
+ "Can't create connection to the target project via gradle tooling api. Project path: '%s'", projectPath
+ ));
+ }
+ return connection;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/AbstractRemoteGradleServiceWrapper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/AbstractRemoteGradleServiceWrapper.java
new file mode 100644
index 000000000000..6d60b0d3b309
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/AbstractRemoteGradleServiceWrapper.java
@@ -0,0 +1,66 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.remote.wrapper;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
+import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
+import org.jetbrains.plugins.gradle.remote.RemoteGradleService;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
+
+import java.rmi.RemoteException;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/14/13 5:55 PM
+ */
+public abstract class AbstractRemoteGradleServiceWrapper<T extends RemoteGradleService> implements RemoteGradleService {
+
+ @NotNull private final T myDelegate;
+
+ public AbstractRemoteGradleServiceWrapper(@NotNull T delegate) {
+ myDelegate = delegate;
+ }
+
+ @Override
+ public void setSettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
+ myDelegate.setSettings(settings);
+ }
+
+ @Override
+ public void setNotificationListener(@NotNull GradleTaskNotificationListener notificationListener) throws RemoteException {
+ myDelegate.setNotificationListener(notificationListener);
+ }
+
+ @Override
+ public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
+ return myDelegate.isTaskInProgress(id);
+ }
+
+ @Override
+ @NotNull
+ public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
+ return myDelegate.getTasksInProgress();
+ }
+
+ @NotNull
+ public T getDelegate() {
+ return myDelegate;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleApiFacadeWrapper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleApiFacadeWrapper.java
index 9838e8320b21..6936c9519a42 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleApiFacadeWrapper.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleApiFacadeWrapper.java
@@ -2,12 +2,9 @@ package org.jetbrains.plugins.gradle.remote.wrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl;
-import org.jetbrains.plugins.gradle.remote.GradleApiFacade;
-import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
-import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
-import org.jetbrains.plugins.gradle.remote.RemoteGradleProgressNotificationManager;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.remote.*;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
import java.rmi.RemoteException;
import java.util.Map;
@@ -39,6 +36,12 @@ public class GradleApiFacadeWrapper implements GradleApiFacade {
return new GradleProjectResolverWrapper(myDelegate.getResolver(), myNotificationManager);
}
+ @NotNull
+ @Override
+ public GradleBuildManager getBuildManager() throws RemoteException {
+ return new GradleBuildManagerWrapper(myDelegate.getBuildManager(), myNotificationManager);
+ }
+
@Override
public void applySettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
myDelegate.applySettings(settings);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleBuildManagerWrapper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleBuildManagerWrapper.java
new file mode 100644
index 000000000000..fd05eb6e261e
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleBuildManagerWrapper.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.remote.wrapper;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
+import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl;
+import org.jetbrains.plugins.gradle.remote.GradleApiException;
+import org.jetbrains.plugins.gradle.remote.GradleBuildManager;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+
+import java.rmi.RemoteException;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/14/13 5:53 PM
+ */
+public class GradleBuildManagerWrapper extends AbstractRemoteGradleServiceWrapper<GradleBuildManager> implements GradleBuildManager {
+
+ @NotNull private final GradleProgressNotificationManagerImpl myNotificationManager;
+
+ public GradleBuildManagerWrapper(@NotNull GradleBuildManager delegate, @NotNull GradleProgressNotificationManagerImpl manager) {
+ super(delegate);
+ myNotificationManager = manager;
+ }
+
+ @Override
+ public Collection<GradleTaskDescriptor> listTasks(@NotNull GradleTaskId id, @NotNull String projectPath)
+ throws RemoteException, GradleApiException
+ {
+ myNotificationManager.onQueued(id);
+ try {
+ return getDelegate().listTasks(id, projectPath);
+ }
+ finally {
+ myNotificationManager.onEnd(id);
+ }
+ }
+
+ @Override
+ public void executeTasks(@NotNull GradleTaskId id, @NotNull List<String> taskNames, @NotNull String projectPath)
+ throws RemoteException, GradleApiException
+ {
+ myNotificationManager.onQueued(id);
+ try {
+ getDelegate().executeTasks(id, taskNames, projectPath);
+ }
+ finally {
+ myNotificationManager.onEnd(id);
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleProjectResolverWrapper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleProjectResolverWrapper.java
index 7142f850e216..b495481ba033 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleProjectResolverWrapper.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/wrapper/GradleProjectResolverWrapper.java
@@ -4,17 +4,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.gradle.GradleProject;
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl;
-import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
import org.jetbrains.plugins.gradle.remote.GradleApiException;
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
-import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
-import org.jetbrains.plugins.gradle.task.GradleTaskId;
-import org.jetbrains.plugins.gradle.task.GradleTaskManager;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskId;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskManager;
import java.rmi.RemoteException;
-import java.util.Map;
-import java.util.Set;
/**
* Intercepts calls to the target {@link GradleProjectResolver} and
@@ -25,15 +20,16 @@ import java.util.Set;
* @author Denis Zhdanov
* @since 2/8/12 7:21 PM
*/
-public class GradleProjectResolverWrapper implements GradleProjectResolver {
+public class GradleProjectResolverWrapper extends AbstractRemoteGradleServiceWrapper<GradleProjectResolver>
+ implements GradleProjectResolver
+{
- @NotNull private final GradleProjectResolver myResolver;
@NotNull private final GradleProgressNotificationManagerImpl myNotificationManager;
- public GradleProjectResolverWrapper(@NotNull GradleProjectResolver resolver,
+ public GradleProjectResolverWrapper(@NotNull GradleProjectResolver delegate,
@NotNull GradleProgressNotificationManagerImpl notificationManager)
{
- myResolver = resolver;
+ super(delegate);
myNotificationManager = notificationManager;
}
@@ -44,31 +40,10 @@ public class GradleProjectResolverWrapper implements GradleProjectResolver {
{
myNotificationManager.onQueued(id);
try {
- return myResolver.resolveProjectInfo(id, projectPath, downloadLibraries);
+ return getDelegate().resolveProjectInfo(id, projectPath, downloadLibraries);
}
finally {
myNotificationManager.onEnd(id);
}
}
-
- @Override
- public void setSettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
- myResolver.setSettings(settings);
- }
-
- @Override
- public void setNotificationListener(@NotNull GradleTaskNotificationListener notificationListener) throws RemoteException {
- myResolver.setNotificationListener(notificationListener);
- }
-
- @Override
- public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
- return myResolver.isTaskInProgress(id);
- }
-
- @Override
- @NotNull
- public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
- return myResolver.getTasksInProgress();
- }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java
index 52e905cefb74..faeb8bbe5f50 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java
@@ -7,17 +7,20 @@ import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootAdapter;
import com.intellij.openapi.roots.ModuleRootEvent;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Alarm;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.autoimport.GradleAutoImporter;
import org.jetbrains.plugins.gradle.autoimport.GradleUserProjectChangesCalculator;
+import org.jetbrains.plugins.gradle.config.GradleSettings;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
import org.jetbrains.plugins.gradle.manage.GradleProjectEntityChangeListener;
import org.jetbrains.plugins.gradle.model.gradle.GradleProject;
-import org.jetbrains.plugins.gradle.task.GradleTaskManager;
-import org.jetbrains.plugins.gradle.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskManager;
+import org.jetbrains.plugins.gradle.internal.task.GradleTaskType;
+import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
import org.jetbrains.plugins.gradle.util.GradleUtil;
import java.util.Collection;
@@ -99,7 +102,9 @@ public class GradleProjectStructureChangesDetector implements GradleProjectStruc
}
private void rebuildTreeModel() {
- final GradleProjectStructureTreeModel treeModel = GradleUtil.getProjectStructureTreeModel(myProject);
+ final GradleProjectStructureTreeModel treeModel = GradleUtil.getToolWindowElement(
+ GradleProjectStructureTreeModel.class, myProject, GradleDataKeys.SYNC_TREE_MODEL
+ );
if (treeModel != null) {
treeModel.rebuild(myAutoImporter.isInProgress());
}
@@ -113,10 +118,12 @@ public class GradleProjectStructureChangesDetector implements GradleProjectStruc
}
private void scheduleUpdate() {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
+ if (ApplicationManager.getApplication().isUnitTestMode()
+ || StringUtil.isEmpty(GradleSettings.getInstance(myProject).getLinkedProjectPath()))
+ {
return;
}
-
+
myUserProjectChangesCalculator.updateChanges();
// We experienced a situation when project root change event has been fired but no actual project structure change has
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java
index 056ae011c46c..5304d4e82f55 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java
@@ -2,18 +2,24 @@ package org.jetbrains.plugins.gradle.sync;
import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Alarm;
+import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtilRt;
+import com.intellij.util.messages.MessageBusConnection;
+import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeModelAdapter;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.config.GradleConfigNotifier;
import org.jetbrains.plugins.gradle.config.GradleLocalSettings;
import org.jetbrains.plugins.gradle.config.GradleToolWindowPanel;
+import org.jetbrains.plugins.gradle.notification.GradleConfigNotificationManager;
import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
import org.jetbrains.plugins.gradle.util.GradleConstants;
@@ -39,7 +45,7 @@ import java.util.List;
* @since 11/3/11 3:58 PM
*/
public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
-
+
private static final int COLLAPSE_STATE_PROCESSING_DELAY_MILLIS = 200;
private static final Comparator<TreePath> PATH_COMPARATOR = new Comparator<TreePath>() {
@@ -71,6 +77,59 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
myToolbarControls.add(new GradleProjectStructureFiltersPanel());
mySettings = GradleLocalSettings.getInstance(project);
initContent();
+
+ MessageBusConnection connection = project.getMessageBus().connect(project);
+ connection.subscribe(GradleConfigNotifier.TOPIC, new GradleConfigNotifier() {
+
+ private boolean myRefresh;
+ private boolean myInBulk;
+
+ @Override
+ public void onBulkChangeStart() {
+ myInBulk = true;
+ }
+
+ @Override
+ public void onBulkChangeEnd() {
+ myInBulk = false;
+ if (myRefresh) {
+ myRefresh = false;
+ refreshAll();
+ }
+ }
+
+ @Override public void onLinkedProjectPathChange(@Nullable String oldPath, @Nullable String newPath) { refreshAll(); }
+ @Override public void onPreferLocalGradleDistributionToWrapperChange(boolean preferLocalToWrapper) { refreshAll(); }
+ @Override public void onGradleHomeChange(@Nullable String oldPath, @Nullable String newPath) { refreshAll(); }
+ @Override public void onServiceDirectoryPathChange(@Nullable String oldPath, @Nullable String newPath) { refreshAll(); }
+ @Override public void onUseAutoImportChange(boolean oldValue, boolean newValue) {
+ if (newValue) {
+ update();
+ }
+ }
+
+ private void refreshAll() {
+ if (myInBulk) {
+ myRefresh = true;
+ return;
+ }
+ GradleUtil.refreshProject(getProject(), new Consumer<String>() {
+ @Override
+ public void consume(String s) {
+ GradleConfigNotificationManager notificationManager
+ = ServiceManager.getService(getProject(), GradleConfigNotificationManager.class);
+ notificationManager.processRefreshError(s);
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ update();
+ }
+ });
+ }
+ });
+ update();
+ }
+ });
}
@NotNull
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java
index f294e16eea16..2b3813415fa3 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java
@@ -250,6 +250,7 @@ public class GradleProjectStructureHelper {
return null;
}
+ @SuppressWarnings("MethodMayBeStatic")
@Nullable
public LibraryOrderEntry findIdeLibraryDependency(@NotNull final String libraryName,
@NotNull ModifiableRootModel model)
@@ -386,6 +387,7 @@ public class GradleProjectStructureHelper {
return null;
}
+ @SuppressWarnings("MethodMayBeStatic")
@Nullable
public ModuleOrderEntry findIdeModuleDependency(@NotNull GradleModuleDependency dependency, @NotNull ModifiableRootModel model) {
for (OrderEntry entry : model.getOrderEntries()) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java
index 7bba4434d174..85073ce319d7 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java
@@ -186,8 +186,11 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
GradleLibraryDependencyId id = GradleEntityIdMapper.mapEntityToId(libraryOrderEntry);
GradleProjectStructureNode<GradleLibraryDependencyId> dependencyNode = buildNode(id, id.getDependencyName());
- libraryDependencies.add(Pair.create(dependencyNode, libraryOrderEntry.getLibrary()));
- dependencies.add(dependencyNode);
+ Library library = libraryOrderEntry.getLibrary();
+ if (library != null) {
+ libraryDependencies.add(Pair.create(dependencyNode, library));
+ dependencies.add(dependencyNode);
+ }
return value;
}
};
@@ -229,7 +232,8 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
GradleProject project = myChangesModel.getGradleProject();
if (project != null) {
GradleChangesCalculationContext context = myChangesModel.getCurrentChangesContext(project, onIdeProjectStructureChange);
- processChanges(Collections.<GradleProjectStructureChange>emptyList(), context.getCurrentChanges());
+ processChanges(Collections.<GradleProjectStructureChange>emptyList(),
+ ContainerUtil.union(context.getKnownChanges(), context.getCurrentChanges()));
filterNodes(root);
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksList.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksList.java
new file mode 100644
index 000000000000..6d84d882b13e
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksList.java
@@ -0,0 +1,118 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.tasks;
+
+import com.intellij.execution.Executor;
+import com.intellij.execution.ExecutorRegistry;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.containers.ContainerUtilRt;
+import icons.GradleIcons;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/15/13 7:38 PM
+ */
+public class GradleTasksList extends JBList {
+
+ @NotNull private static final MyRenderer RENDERER = new MyRenderer();
+ @NotNull private static final JLabel EMPTY_RENDERER = new JLabel(" ");
+
+ public GradleTasksList(@NotNull GradleTasksModel model) {
+ super(model);
+ setCellRenderer(RENDERER);
+ }
+
+ @Override
+ public GradleTasksModel getModel() {
+ return (GradleTasksModel)super.getModel();
+ }
+
+ public void setFirst(@NotNull GradleTaskDescriptor descriptor) {
+ Set<GradleTaskDescriptor> selected = getSelectedDescriptors();
+ GradleTasksModel model = getModel();
+ model.setFirst(descriptor);
+ clearSelection();
+ for (int i = 0; i < model.size(); i++) {
+ //noinspection SuspiciousMethodCalls
+ if (selected.contains(model.getElementAt(i))) {
+ addSelectionInterval(i, i);
+ }
+ }
+ }
+
+ @NotNull
+ public Set<GradleTaskDescriptor> getSelectedDescriptors() {
+ int[] indices = getSelectedIndices();
+ if (indices == null || indices.length <= 0) {
+ return Collections.emptySet();
+ }
+ Set<GradleTaskDescriptor> result = ContainerUtilRt.newHashSet();
+ GradleTasksModel model = getModel();
+ for (int i : indices) {
+ Object e = model.getElementAt(i);
+ if (e instanceof GradleTaskDescriptor) {
+ result.add((GradleTaskDescriptor)e);
+ }
+ }
+ return result;
+ }
+
+ private static class MyRenderer extends DefaultListCellRenderer {
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ if (value instanceof GradleTasksModel.MyEmptyDescriptor) {
+ return EMPTY_RENDERER;
+ }
+ else if (value instanceof GradleTaskDescriptor) {
+ GradleTaskDescriptor descriptor = (GradleTaskDescriptor)value;
+ setText(descriptor.getName());
+ Icon icon = null;
+ String executorId = descriptor.getExecutorId();
+ if (!StringUtil.isEmpty(executorId)) {
+ Executor executor = ExecutorRegistry.getInstance().getExecutorById(executorId);
+ if (executor != null) {
+ icon = executor.getIcon();
+ }
+ }
+
+ if (icon == null) {
+ icon = GradleIcons.Task;
+ }
+ setIcon(icon);
+ }
+ return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+ }
+
+ @Override
+ public void setIcon(Icon icon) {
+ if (icon != null) {
+ // Don't allow to reset icon.
+ super.setIcon(icon);
+ }
+ }
+ }
+
+
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksModel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksModel.java
new file mode 100644
index 000000000000..425d72d20a6a
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksModel.java
@@ -0,0 +1,85 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.tasks;
+
+import com.intellij.util.containers.ContainerUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
+
+import javax.swing.*;
+import java.util.*;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/15/13 12:50 PM
+ */
+public class GradleTasksModel extends DefaultListModel {
+
+ public static final Comparator<GradleTaskDescriptor> BY_NAME_COMPARATOR = new Comparator<GradleTaskDescriptor>() {
+ @Override
+ public int compare(GradleTaskDescriptor d1, GradleTaskDescriptor d2) {
+ return d1.getName().compareTo(d2.getName());
+ }
+ };
+
+ public void setTasks(@NotNull Collection<GradleTaskDescriptor> taskDescriptors) {
+ clear();
+ ArrayList<GradleTaskDescriptor> descriptorsToUse = ContainerUtilRt.newArrayList(taskDescriptors);
+ Collections.sort(descriptorsToUse, BY_NAME_COMPARATOR);
+ for (GradleTaskDescriptor descriptor : descriptorsToUse) {
+ addElement(descriptor);
+ }
+ }
+
+ public void setFirst(@NotNull GradleTaskDescriptor descriptor) {
+ insertElementAt(descriptor, 0);
+ for (int i = 1; i < size(); i++) {
+ if (descriptor.equals(getElementAt(i))) {
+ remove(i);
+ return;
+ }
+ }
+
+ if (size() > 1) {
+ remove(size() - 1);
+ }
+ }
+
+ @NotNull
+ public List<GradleTaskDescriptor> getTasks() {
+ List<GradleTaskDescriptor> result = ContainerUtilRt.newArrayList();
+ for (int i = 0; i < size(); i++) {
+ Object e = getElementAt(i);
+ if (e instanceof GradleTaskDescriptor) {
+ result.add((GradleTaskDescriptor)e);
+ }
+ }
+ return result;
+ }
+
+ public void ensureSize(int elementsNumber) {
+ int toAdd = elementsNumber - size();
+ if (toAdd <= 0) {
+ return;
+ }
+ while (--toAdd >= 0) {
+ addElement(new MyEmptyDescriptor());
+ }
+ }
+
+ static class MyEmptyDescriptor {
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksPanel.java
new file mode 100644
index 000000000000..7b9532e17b68
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/tasks/GradleTasksPanel.java
@@ -0,0 +1,265 @@
+/*
+ * 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 org.jetbrains.plugins.gradle.tasks;
+
+import com.intellij.execution.Executor;
+import com.intellij.execution.ExecutorRegistry;
+import com.intellij.execution.Location;
+import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.ide.DataManager;
+import com.intellij.ide.ui.customization.CustomizationUtil;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.components.JBList;
+import com.intellij.ui.components.JBScrollPane;
+import com.intellij.util.containers.ContainerUtilRt;
+import com.intellij.util.ui.GridBag;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.config.GradleLocalSettings;
+import org.jetbrains.plugins.gradle.config.GradleSettings;
+import org.jetbrains.plugins.gradle.config.GradleToolWindowPanel;
+import org.jetbrains.plugins.gradle.execution.GradleTaskLocation;
+import org.jetbrains.plugins.gradle.model.gradle.GradleTaskDescriptor;
+import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
+import org.jetbrains.plugins.gradle.util.GradleBundle;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Denis Zhdanov
+ * @since 3/14/13 4:36 PM
+ */
+public class GradleTasksPanel extends GradleToolWindowPanel {
+
+ @NotNull private final GradleTasksModel myRecentTasksModel = new GradleTasksModel();
+ @NotNull private final GradleTasksList myRecentTasksList;
+
+ @NotNull private final GradleTasksModel myAllTasksModel = new GradleTasksModel();
+ @NotNull private final GradleTasksList myAllTasksList;
+
+ @NotNull private final GradleLocalSettings myLocalSettings;
+
+ @Nullable private GradleTasksList myActiveList;
+
+ public GradleTasksPanel(@NotNull Project project) {
+ super(project, GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE);
+ myRecentTasksList = buildList(myRecentTasksModel);
+ myAllTasksList = buildList(myAllTasksModel);
+ myLocalSettings = GradleLocalSettings.getInstance(project);
+ initContent();
+ }
+
+ @NotNull
+ private GradleTasksList buildList(@NotNull GradleTasksModel model) {
+ return new GradleTasksList(model) {
+ @Override
+ protected void processMouseEvent(MouseEvent e) {
+ if (e.getID() == MouseEvent.MOUSE_PRESSED) {
+ myActiveList = this;
+ }
+ super.processMouseEvent(e);
+ }
+ };
+ }
+
+ @NotNull
+ @Override
+ protected JComponent buildContent() {
+ JPanel result = new JPanel(new GridBagLayout());
+ result.setBorder(IdeBorderFactory.createEmptyBorder(8));
+ result.setOpaque(false);
+
+ myRecentTasksModel.clear();
+ myRecentTasksModel.setTasks(myLocalSettings.getRecentTasks());
+ int recentTasksNumber = Registry.intValue(GradleConstants.REGISTRY_RECENT_TASKS_NUMBER_KEY, 5);
+ myRecentTasksModel.ensureSize(recentTasksNumber);
+ myRecentTasksList.setVisibleRowCount(recentTasksNumber);
+ addListPanel(myRecentTasksList, result, GradleBundle.message("gradle.task.recent.title"), false);
+
+ myAllTasksModel.clear();
+ Collection<GradleTaskDescriptor> tasks = myLocalSettings.getAvailableTasks();
+ if (!tasks.isEmpty()) {
+ myAllTasksModel.setTasks(tasks);
+ }
+ addListPanel(myAllTasksList, result, GradleBundle.message("gradle.task.all.title"), true);
+
+ return result;
+ }
+
+ private static void addListPanel(@NotNull GradleTasksList list, @NotNull JPanel parent, @NotNull String title, boolean fillY) {
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.setOpaque(false);
+ panel.setBorder(IdeBorderFactory.createTitledBorder(title));
+
+ setupMouseListener(list);
+ CustomizationUtil.installPopupHandler(list, GradleConstants.ACTION_GROUP_TASKS, GradleConstants.TASKS_CONTEXT_MENU_PLACE);
+ list.setEmptyText(GradleBundle.message("gradle.text.loading"));
+ JBScrollPane scrollPane = new JBScrollPane(list);
+ scrollPane.setBorder(null);
+ panel.add(scrollPane, BorderLayout.CENTER);
+ parent.add(panel, new GridBag().fillCell().weightx(1).weighty(fillY ? 1 : 0).coverLine());
+ }
+
+ private static void setupMouseListener(@NotNull final JBList list) {
+ list.addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ // Change list selection on right click. That allows to right-click target task node and run/debug it.
+ if (!e.isPopupTrigger()) {
+ return;
+ }
+ int i = list.locationToIndex(e.getPoint());
+ if (i < 0) {
+ return;
+ }
+ if (list.isSelectedIndex(i)) {
+ return;
+ }
+ list.setSelectedIndex(i);
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() < 2) {
+ return;
+ }
+
+ int row = list.locationToIndex(e.getPoint());
+ ListModel model = list.getModel();
+ if (row < 0 || row >= model.getSize()) {
+ return;
+ }
+
+ Object element = model.getElementAt(row);
+ if (!(element instanceof GradleTaskDescriptor)) {
+ return;
+ }
+
+ String executorId = ((GradleTaskDescriptor)element).getExecutorId();
+ if (StringUtil.isEmpty(executorId)) {
+ executorId = DefaultRunExecutor.EXECUTOR_ID;
+ }
+
+ Executor executor = ExecutorRegistry.getInstance().getExecutorById(executorId);
+ if (executor == null) {
+ return;
+ }
+
+ final String actionId = executor.getContextActionId();
+ if (StringUtil.isEmpty(actionId)) {
+ return;
+ }
+
+ ActionManager actionManager = ActionManager.getInstance();
+ AnAction action = actionManager.getAction(actionId);
+ if (action == null) {
+ return;
+ }
+
+ final Presentation presentation = new Presentation();
+ DataContext dataContext = DataManager.getInstance().getDataContext(e.getComponent());
+ final AnActionEvent event = new AnActionEvent(e, dataContext, GradleConstants.TASKS_LIST_PLACE, presentation, actionManager, 0);
+ action.update(event);
+ if (presentation.isEnabled()) {
+ action.actionPerformed(event);
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void updateContent() {
+ }
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (GradleDataKeys.ALL_TASKS_MODEL.is(dataId)) {
+ return myAllTasksModel;
+ }
+ else if (GradleDataKeys.RECENT_TASKS_LIST.is(dataId)) {
+ return myRecentTasksList;
+ }
+ else if (Location.DATA_KEY.is(dataId)) {
+ Location location = buildLocation();
+ return location == null ? super.getData(dataId) : location;
+ }
+ else {
+ return super.getData(dataId);
+ }
+ }
+
+ @Nullable
+ private Location buildLocation() {
+ if (myActiveList == null) {
+ return null;
+ }
+ List<String> tasks = getSelectedTasks(myActiveList);
+ if (tasks == null) {
+ return null;
+ }
+
+ String gradleProjectPath = GradleSettings.getInstance(getProject()).getLinkedProjectPath();
+ if (StringUtil.isEmpty(gradleProjectPath)) {
+ return null;
+ }
+
+ assert gradleProjectPath != null;
+ VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(gradleProjectPath);
+ if (vFile == null) {
+ return null;
+ }
+
+ PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
+ if (psiFile == null) {
+ return null;
+ }
+
+ return new GradleTaskLocation(getProject(), psiFile, tasks);
+ }
+
+ @Nullable
+ private static List<String> getSelectedTasks(@NotNull JBList list) {
+ int[] selectedIndices = list.getSelectedIndices();
+ if (selectedIndices == null) {
+ return null;
+ }
+ final List<String> tasks = ContainerUtilRt.newArrayList();
+ for (int index : selectedIndices) {
+ Object data = list.getModel().getElementAt(index);
+ if (data instanceof GradleTaskDescriptor) {
+ tasks.add(((GradleTaskDescriptor)data).getName());
+ }
+ }
+ return tasks.isEmpty() ? null : tasks;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleDataKeys.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleDataKeys.java
index f739382b1171..27aa19b64df0 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleDataKeys.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleDataKeys.java
@@ -3,6 +3,8 @@ package org.jetbrains.plugins.gradle.ui;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.ui.treeStructure.Tree;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureTreeModel;
+import org.jetbrains.plugins.gradle.tasks.GradleTasksList;
+import org.jetbrains.plugins.gradle.tasks.GradleTasksModel;
import java.util.Collection;
@@ -17,7 +19,7 @@ public class GradleDataKeys {
/** Key for obtaining 'sync project structure' tree model. */
public static final DataKey<GradleProjectStructureTreeModel> SYNC_TREE_MODEL = DataKey.create("gradle.sync.tree.model");
-
+
/** Key for obtaining currently selected nodes at the gradle 'sync project structure' tree. */
public static final DataKey<Collection<GradleProjectStructureNode<?>>> SYNC_TREE_SELECTED_NODE
= DataKey.create("gradle.sync.tree.node.selected");
@@ -26,6 +28,10 @@ public class GradleDataKeys {
public static final DataKey<GradleProjectStructureNode<?>> SYNC_TREE_NODE_UNDER_MOUSE
= DataKey.create("gradle.sync.tree.node.under.mouse");
+ public static final DataKey<GradleTasksList> RECENT_TASKS_LIST = DataKey.create("gradle.recent.tasks.list");
+
+ public static final DataKey<GradleTasksModel> ALL_TASKS_MODEL = DataKey.create("gradle.all.tasks.model");
+
private GradleDataKeys() {
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java
index 99bed994756c..a3e2826f701f 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java
@@ -1,6 +1,7 @@
package org.jetbrains.plugins.gradle.ui;
import com.intellij.ProjectTopics;
+import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
@@ -8,27 +9,54 @@ import com.intellij.openapi.roots.ModuleRootAdapter;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
+import com.intellij.ui.content.ContentManager;
+import com.intellij.ui.content.ContentManagerAdapter;
+import com.intellij.ui.content.ContentManagerEvent;
import com.intellij.ui.content.impl.ContentImpl;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.config.PlatformFacade;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesPanel;
+import org.jetbrains.plugins.gradle.tasks.GradleTasksPanel;
import org.jetbrains.plugins.gradle.util.GradleBundle;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext;
public class GradleToolWindowFactory implements ToolWindowFactory, DumbAware {
-
+
@Override
public void createToolWindowContent(final Project project, final ToolWindow toolWindow) {
final GradleProjectStructureContext context = ServiceManager.getService(project, GradleProjectStructureContext.class);
-
- final GradleProjectStructureChangesPanel panel = new GradleProjectStructureChangesPanel(project, context);
- final String syncTitle = GradleBundle.message("gradle.sync.title.tab");
- toolWindow.getContentManager().addContent(new ContentImpl(panel, syncTitle, true));
+
+ // Project structure.
+ final GradleProjectStructureChangesPanel projectStructurePanel = new GradleProjectStructureChangesPanel(project, context);
+ final String projectStructureTitle = GradleBundle.message("gradle.sync.title.tab");
+ ContentImpl projectStructureContent = new ContentImpl(projectStructurePanel, projectStructureTitle, true);
+ ContentManager contentManager = toolWindow.getContentManager();
+ contentManager.addContent(projectStructureContent);
+
+ // Task.
+ String tasksTitle = GradleBundle.message("gradle.task.title.tab");
+ ContentImpl tasksContent = new ContentImpl(
+ new GradleTasksPanel(project), tasksTitle, true);
+ contentManager.addContent(tasksContent);
project.getMessageBus().connect(project).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
@Override
public void rootsChanged(ModuleRootEvent event) {
// The general idea is to change dependencies order at the UI if they are changed at the module settings.
- panel.getTreeModel().onModuleRootsChange();
+ projectStructurePanel.getTreeModel().onModuleRootsChange();
+ }
+ });
+
+ // Restore previously selected tab.
+ String toSelect = PropertiesComponent.getInstance(project).getValue(GradleConstants.ACTIVE_TOOL_WINDOW_TAB_KEY, projectStructureTitle);
+ if (tasksTitle.equals(toSelect)) {
+ contentManager.setSelectedContent(tasksContent);
+ }
+
+ contentManager.addContentManagerListener(new ContentManagerAdapter() {
+ @Override
+ public void selectionChanged(ContentManagerEvent event) {
+ if (!project.isDisposed()) {
+ PropertiesComponent.getInstance(project).setValue(GradleConstants.ACTIVE_TOOL_WINDOW_TAB_KEY, event.getContent().getDisplayName());
+ }
}
});
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
index 567603c23b58..3e4f8e68d20f 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
@@ -13,22 +13,30 @@ import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor;
public class GradleConstants {
@NonNls public static final String NEWLY_IMPORTED_PROJECT = "gradle.newly.imported";
-
+
@NonNls public static final String EXTENSION = "gradle";
@NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle";
-
+
@NonNls public static final String TOOL_WINDOW_ID = "JetGradle";
- @NonNls public static final String TOOL_WINDOW_TOOLBAR_PLACE = "GRADLE_SYNC_CHANGES_TOOLBAR";
- @NonNls public static final String SYNC_TREE_CONTEXT_MENU_PLACE = "GRADLE_SYNC_TREE_CONTEXT_MENU_PLACE";
- @NonNls public static final String SYNC_TREE_FILTER_PLACE = "GRADLE_SYNC_TREE_FILTER_PLACE";
-
+ @NonNls public static final String TOOL_WINDOW_TOOLBAR_PLACE = "GRADLE_SYNC_CHANGES_TOOLBAR";
+ @NonNls public static final String SYNC_TREE_CONTEXT_MENU_PLACE = "GRADLE_SYNC_TREE_CONTEXT_MENU_PLACE";
+ @NonNls public static final String SYNC_TREE_FILTER_PLACE = "GRADLE_SYNC_TREE_FILTER_PLACE";
+ @NonNls public static final String TASKS_LIST_PLACE = "TASKS_LIST_PLACE";
+ @NonNls public static final String TASKS_CONTEXT_MENU_PLACE = "GRADLE_TASKS_CONTEXT_MENU_PLACE";
+
@NonNls public static final String ACTION_GROUP_SYNC_TREE = "Gradle.SyncTreeGroup";
+ @NonNls public static final String ACTION_GROUP_TASKS = "Gradle.TasksGroup";
@NonNls public static final String HELP_TOPIC_IMPORT_SELECT_PROJECT_STEP = "reference.dialogs.new.project.import.gradle.page1";
@NonNls public static final String HELP_TOPIC_ADJUST_SETTINGS_STEP = "reference.dialogs.new.project.import.gradle.page2";
@NonNls public static final String HELP_TOPIC_TOOL_WINDOW = "reference.toolwindows.gradle";
-
+
+ @NonNls public static final String ACTIVE_TOOL_WINDOW_TAB_KEY = "gradle.tool.window.active";
+
+ @NonNls public static final String REGISTRY_RECENT_TASKS_NUMBER_KEY = "gradle.recent.tasks.number";
+ @NonNls public static final String REGISTRY_DEBUG_ON_TASK_CLICK_KEY = "gradle.debug.task.on.double.click";
+
public static final GradleProjectStructureNodeDescriptor<GradleSyntheticId> DEPENDENCIES_NODE_DESCRIPTOR
= GradleUtil.buildSyntheticDescriptor(GradleBundle.message("gradle.project.structure.tree.node.dependencies"));
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleInstallationManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleInstallationManager.java
index f71ab809ed80..eb33d0fde816 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleInstallationManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleInstallationManager.java
@@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.util;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderEnumerator;
+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;
@@ -28,7 +29,7 @@ import java.util.regex.Pattern;
*/
@SuppressWarnings("MethodMayBeStatic")
public class GradleInstallationManager {
-
+
public static final Pattern GRADLE_JAR_FILE_PATTERN;
public static final Pattern ANY_GRADLE_JAR_FILE_PATTERN;
@@ -46,7 +47,7 @@ public class GradleInstallationManager {
* Allows to get file handles for the gradle binaries to use.
*
* @param project target project
- * @return file handles for the gradle binaries; <code>null</code> if gradle is not discovered
+ * @return file handles for the gradle binaries; <code>null</code> if gradle is not discovered
*/
@Nullable
public Collection<File> getAllLibraries(@Nullable Project project) {
@@ -74,13 +75,17 @@ public class GradleInstallationManager {
/**
* Tries to return file handle that points to the gradle installation home.
- *
+ *
* @param project target project (if any)
- * @return file handle that points to the gradle installation home (if any)
+ * @return file handle that points to the gradle installation home (if any)
*/
@Nullable
public File getGradleHome(@Nullable Project project) {
- File result = getManuallyDefinedGradleHome(project);
+ File result = getWrapperHome(project);
+ if (result != null) {
+ return result;
+ }
+ result = getManuallyDefinedGradleHome(project);
if (result != null) {
return result;
}
@@ -89,8 +94,8 @@ public class GradleInstallationManager {
/**
* Tries to deduce gradle location from current environment.
- *
- * @return gradle home deduced from the current environment (if any); <code>null</code> otherwise
+ *
+ * @return gradle home deduced from the current environment (if any); <code>null</code> otherwise
*/
@Nullable
public File getAutodetectedGradleHome() {
@@ -100,9 +105,9 @@ public class GradleInstallationManager {
/**
* Tries to return gradle home that is defined as a dependency to the given module.
- *
+ *
* @param module target module
- * @return file handle that points to the gradle installation home defined as a dependency of the given module (if any)
+ * @return file handle that points to the gradle installation home defined as a dependency of the given module (if any)
*/
@Nullable
public VirtualFile getGradleHome(@Nullable Module module) {
@@ -138,6 +143,55 @@ public class GradleInstallationManager {
final File home = getGradleHome(project);
return home == null ? null : LocalFileSystem.getInstance().refreshAndFindFileByIoFile(home);
}
+
+ @Nullable
+ public File getWrapperHome(@Nullable Project project) {
+ if (project == null) {
+ return null;
+ }
+ GradleSettings settings = GradleSettings.getInstance(project);
+ String gradleProjectPath = settings.getLinkedProjectPath();
+ if (StringUtil.isEmpty(gradleProjectPath)) {
+ return null;
+ }
+
+ if (settings.isPreferLocalInstallationToWrapper()) {
+ return null;
+ }
+
+ String version = GradleUtil.getWrapperVersion(gradleProjectPath);
+ if (version == null) {
+ return null;
+ }
+ File gradleSystemDir = new File(System.getProperty("user.home"), ".gradle");
+ if (!gradleSystemDir.isDirectory()) {
+ return null;
+ }
+
+ File gradleWrapperDistributionsHome = new File(gradleSystemDir, "wrapper/dists");
+ if (!gradleWrapperDistributionsHome.isDirectory()) {
+ return null;
+ }
+
+ File targetDistributionHome = new File(gradleWrapperDistributionsHome, String.format("gradle-%s-bin", version));
+ if (!targetDistributionHome.isDirectory()) {
+ return null;
+ }
+
+ File[] files = targetDistributionHome.listFiles();
+ if (files == null || files.length != 1) {
+ // Gradle keeps wrapper at a directory which name is a hash value like '35oej0jnbfh6of4dd05531edaj'
+ return null;
+ }
+
+ File result = new File(files[0], String.format("gradle-%s", version));
+ if (result.isDirectory()) {
+ return result;
+ }
+ else {
+ return null;
+ }
+ }
/**
* Allows to ask for user-defined path to gradle.
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java
index 4a4c3227e360..6ca421fe8622 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java
@@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.util;
import com.intellij.execution.rmi.RemoteUtil;
import com.intellij.ide.actions.OpenProjectFileChooserDescriptor;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
@@ -40,6 +41,8 @@ import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.config.GradleSettings;
+import org.jetbrains.plugins.gradle.internal.task.GradleRefreshTasksListTask;
+import org.jetbrains.plugins.gradle.internal.task.GradleResolveProjectTask;
import org.jetbrains.plugins.gradle.manage.GradleProjectEntityChangeListener;
import org.jetbrains.plugins.gradle.model.gradle.GradleEntity;
import org.jetbrains.plugins.gradle.model.gradle.GradleEntityVisitor;
@@ -50,7 +53,7 @@ import org.jetbrains.plugins.gradle.model.intellij.IdeEntityVisitor;
import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot;
import org.jetbrains.plugins.gradle.remote.GradleApiException;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureTreeModel;
-import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask;
+import org.jetbrains.plugins.gradle.tasks.GradleTasksModel;
import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor;
@@ -59,12 +62,10 @@ import org.jetbrains.plugins.gradle.ui.MatrixControlBuilder;
import javax.swing.*;
import javax.swing.tree.TreePath;
import java.awt.*;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import java.io.*;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -77,9 +78,11 @@ import java.util.regex.Pattern;
*/
public class GradleUtil {
- public static final String PATH_SEPARATOR = "/";
- public static final String SYSTEM_DIRECTORY_PATH_KEY = "GRADLE_USER_HOME";
- private static final Pattern ARTIFACT_PATTERN = Pattern.compile("(?:.*/)?(.+?)(?:-([\\d+](?:\\.[\\d]+)*))?(?:\\.[^\\.]+?)?");
+ public static final String PATH_SEPARATOR = "/";
+ public static final String SYSTEM_DIRECTORY_PATH_KEY = "GRADLE_USER_HOME";
+ private static final String WRAPPER_VERSION_PROPERTY_KEY = "distributionUrl";
+ private static final Pattern WRAPPER_VERSION_PATTERN = Pattern.compile(".*gradle-(.+)-bin.zip");
+ private static final Pattern ARTIFACT_PATTERN = Pattern.compile("(?:.*/)?(.+?)(?:-([\\d+](?:\\.[\\d]+)*))?(?:\\.[^\\.]+?)?");
private static final NotNullLazyValue<GradleInstallationManager> INSTALLATION_MANAGER =
new NotNullLazyValue<GradleInstallationManager>() {
@@ -122,22 +125,34 @@ public class GradleUtil {
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
public static boolean isGradleWrapperDefined(@Nullable String gradleProjectPath) {
+ return !StringUtil.isEmpty(getWrapperVersion(gradleProjectPath));
+ }
+
+ /**
+ * Tries to parse what gradle version should be used with gradle wrapper for the gradle project located at the given path.
+ *
+ * @param gradleProjectPath target gradle project path
+ * @return gradle version should be used with gradle wrapper for the gradle project located at the given path
+ * if any; <code>null</code> otherwise
+ */
+ @Nullable
+ public static String getWrapperVersion(@Nullable String gradleProjectPath) {
if (gradleProjectPath == null) {
- return false;
+ return null;
}
File file = new File(gradleProjectPath);
if (!file.isFile()) {
- return false;
+ return null;
}
File gradleDir = new File(file.getParentFile(), "gradle");
if (!gradleDir.isDirectory()) {
- return false;
+ return null;
}
File wrapperDir = new File(gradleDir, "wrapper");
if (!wrapperDir.isDirectory()) {
- return false;
+ return null;
}
File[] candidates = wrapperDir.listFiles(new FileFilter() {
@@ -148,19 +163,48 @@ public class GradleUtil {
});
if (candidates == null) {
GradleLog.LOG.warn("No *.properties file is found at the gradle wrapper directory " + wrapperDir.getAbsolutePath());
- return false;
+ return null;
}
else if (candidates.length != 1) {
GradleLog.LOG.warn(String.format(
"%d *.properties files instead of one have been found at the wrapper directory (%s): %s",
candidates.length, wrapperDir.getAbsolutePath(), Arrays.toString(candidates)
));
- return false;
+ return null;
}
- // Consider that single *.properties file existence inside 'wrapper' directory is enough to be sure that gradle wrapper
- // is configured for the target project.
- return true;
+ Properties props = new Properties();
+ BufferedReader reader = null;
+ try {
+ //noinspection IOResourceOpenedButNotSafelyClosed
+ reader = new BufferedReader(new FileReader(candidates[0]));
+ props.load(reader);
+ String value = props.getProperty(WRAPPER_VERSION_PROPERTY_KEY);
+ if (StringUtil.isEmpty(value)) {
+ return null;
+ }
+ Matcher matcher = WRAPPER_VERSION_PATTERN.matcher(value);
+ if (matcher.matches()) {
+ return matcher.group(1);
+ }
+ }
+ catch (IOException e) {
+ GradleLog.LOG.warn(
+ String.format("I/O exception on reading gradle wrapper properties file at '%s'", candidates[0].getAbsolutePath()),
+ e
+ );
+ }
+ finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ }
+ catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+ return null;
}
/**
@@ -229,6 +273,7 @@ public class GradleUtil {
@Override
public void set(@Nullable String error) {
if (!StringUtil.isEmpty(error)) {
+ assert error != null;
GradleLog.LOG.warn(error);
}
}
@@ -289,7 +334,7 @@ public class GradleUtil {
final boolean modal)
{
final Ref<GradleProject> gradleProject = new Ref<GradleProject>();
- final TaskUnderProgress task = new TaskUnderProgress() {
+ final TaskUnderProgress refreshProjectStructureTask = new TaskUnderProgress() {
@SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "IOResourceOpenedButNotSafelyClosed"})
@Override
public void execute(@NotNull ProgressIndicator indicator) {
@@ -310,6 +355,15 @@ public class GradleUtil {
errorDetailsHolder.set(extractDetails(error));
}
};
+
+ final TaskUnderProgress refreshTasksTask = new TaskUnderProgress() {
+ @Override
+ public void execute(@NotNull ProgressIndicator indicator) {
+ final GradleRefreshTasksListTask task = new GradleRefreshTasksListTask(project, gradleProjectPath);
+ task.execute(indicator);
+ }
+ };
+
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
@@ -317,7 +371,9 @@ public class GradleUtil {
ProgressManager.getInstance().run(new Task.Modal(project, GradleBundle.message("gradle.import.progress.text"), false) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
- task.execute(indicator);
+ refreshProjectStructureTask.execute(indicator);
+ setTitle(GradleBundle.message("gradle.task.progress.initial.text"));
+ refreshTasksTask.execute(indicator);
}
});
}
@@ -325,7 +381,9 @@ public class GradleUtil {
ProgressManager.getInstance().run(new Task.Backgroundable(project, GradleBundle.message("gradle.sync.progress.initial.text")) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
- task.execute(indicator);
+ refreshProjectStructureTask.execute(indicator);
+ setTitle(GradleBundle.message("gradle.task.progress.initial.text"));
+ refreshTasksTask.execute(indicator);
}
});
}
@@ -463,34 +521,43 @@ public class GradleUtil {
/**
* Tries to find the current {@link GradleProjectStructureTreeModel} instance.
- *
+ *
* @param context target context (if defined)
* @return current {@link GradleProjectStructureTreeModel} instance (if any has been found); <code>null</code> otherwise
*/
@Nullable
public static GradleProjectStructureTreeModel getProjectStructureTreeModel(@Nullable DataContext context) {
+ return getToolWindowElement(GradleProjectStructureTreeModel.class, context, GradleDataKeys.SYNC_TREE_MODEL);
+ }
+
+ @Nullable
+ public static <T> T getToolWindowElement(@NotNull Class<T> clazz, @Nullable DataContext context, @NotNull DataKey<T> key) {
if (context != null) {
- final GradleProjectStructureTreeModel model = GradleDataKeys.SYNC_TREE_MODEL.getData(context);
- if (model != null) {
- return model;
+ final T result = key.getData(context);
+ if (result != null) {
+ return result;
}
}
if (context == null) {
return null;
}
-
+
final Project project = PlatformDataKeys.PROJECT.getData(context);
if (project == null) {
return null;
}
- return getProjectStructureTreeModel(project);
+ return getToolWindowElement(clazz, project, key);
}
+ @SuppressWarnings("unchecked")
@Nullable
- public static GradleProjectStructureTreeModel getProjectStructureTreeModel(@NotNull Project project) {
+ public static <T> T getToolWindowElement(@NotNull Class<T> clazz, @NotNull Project project, @NotNull DataKey<T> key) {
final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
+ if (toolWindowManager == null) {
+ return null;
+ }
final ToolWindow toolWindow = toolWindowManager.getToolWindow(GradleConstants.TOOL_WINDOW_ID);
if (toolWindow == null) {
return null;
@@ -504,15 +571,15 @@ public class GradleUtil {
for (Content content : contentManager.getContents()) {
final JComponent component = content.getComponent();
if (component instanceof DataProvider) {
- final Object data = ((DataProvider)component).getData(GradleDataKeys.SYNC_TREE_MODEL.getName());
- if (data instanceof GradleProjectStructureTreeModel) {
- return (GradleProjectStructureTreeModel)data;
+ final Object data = ((DataProvider)component).getData(key.getName());
+ if (data != null && clazz.isInstance(data)) {
+ return (T)data;
}
}
}
return null;
}
-
+
/**
* @return {@link MatrixControlBuilder} with predefined set of columns ('gradle' and 'intellij')
*/
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/TextIcon.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/TextIcon.java
index 6138504fceae..023b4bd426c2 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/TextIcon.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/TextIcon.java
@@ -1,5 +1,6 @@
package org.jetbrains.plugins.gradle.util;
+import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -30,6 +31,7 @@ public class TextIcon implements Icon {
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
+ GraphicsUtil.setupAntialiasing(g, true, false);
if (myTextHeight <= 0) {
myTextHeight = g.getFont().createGlyphVector(((Graphics2D)g).getFontRenderContext(), myText).getPixelBounds(null, 0, 0).height;
}
diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
index 8df50c2fdabd..8d0840af44be 100644
--- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
+++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
@@ -134,7 +134,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
rememberStubSources(context, compiled);
}
- for (CompilerMessage message : handler.getCompilerMessages()) {
+ for (CompilerMessage message : handler.getCompilerMessages(chunk.representativeTarget().getModule().getName())) {
context.processMessage(message);
}
@@ -210,7 +210,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
}
private static boolean checkChunkRebuildNeeded(CompileContext context, GroovycOSProcessHandler handler) {
- if (context.isProjectRebuild() || !handler.shouldRetry()) {
+ if (JavaBuilderUtil.isForcedRecompilationAllJavaModules(context) || !handler.shouldRetry()) {
return false;
}
diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java
index 38d3ae233e72..47b7fe58c4d9 100644
--- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java
+++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java
@@ -210,11 +210,16 @@ public class GroovycOSProcessHandler extends BaseOSProcessHandler {
return false;
}
- public List<CompilerMessage> getCompilerMessages() {
+ public List<CompilerMessage> getCompilerMessages(String moduleName) {
ArrayList<CompilerMessage> messages = new ArrayList<CompilerMessage>(compilerMessages);
final StringBuffer unparsedBuffer = getStdErr();
if (unparsedBuffer.length() != 0) {
- messages.add(new CompilerMessage("Groovyc", BuildMessage.Kind.INFO, unparsedBuffer.toString()));
+ String msg = unparsedBuffer.toString();
+ if (msg.contains(GroovyRtConstants.NO_GROOVY)) {
+ msg = "Cannot compile Groovy files: no Groovy library is defined for module '" + moduleName + "'";
+ }
+
+ messages.add(new CompilerMessage("Groovyc", BuildMessage.Kind.INFO, msg));
}
final int exitValue = getProcess().exitValue();
diff --git a/plugins/groovy/resources/icons/griffon/griffon-icon-24x24.png b/plugins/groovy/resources/icons/griffon/griffon-icon-24x24.png
index 7dd8c19e8c4a..e085bbe76dbd 100644
--- a/plugins/groovy/resources/icons/griffon/griffon-icon-24x24.png
+++ b/plugins/groovy/resources/icons/griffon/griffon-icon-24x24.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/griffon/griffon-icon-24x24@2x.png b/plugins/groovy/resources/icons/griffon/griffon-icon-24x24@2x.png
new file mode 100644
index 000000000000..0ae1aa6e7690
--- /dev/null
+++ b/plugins/groovy/resources/icons/griffon/griffon-icon-24x24@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/griffon/griffon.png b/plugins/groovy/resources/icons/griffon/griffon.png
index d1ba0c50cb55..41ea0c1b3a3a 100644
--- a/plugins/groovy/resources/icons/griffon/griffon.png
+++ b/plugins/groovy/resources/icons/griffon/griffon.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/griffon/griffon@2x.png b/plugins/groovy/resources/icons/griffon/griffon@2x.png
new file mode 100644
index 000000000000..b2245f6abd33
--- /dev/null
+++ b/plugins/groovy/resources/icons/griffon/griffon@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/griffon/griffonToolWindow.png b/plugins/groovy/resources/icons/griffon/griffonToolWindow.png
index 88f66b40e2fb..fd96eaefb65f 100644
--- a/plugins/groovy/resources/icons/griffon/griffonToolWindow.png
+++ b/plugins/groovy/resources/icons/griffon/griffonToolWindow.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/griffon/griffonToolWindow@2x.png b/plugins/groovy/resources/icons/griffon/griffonToolWindow@2x.png
new file mode 100644
index 000000000000..c6a4241166ad
--- /dev/null
+++ b/plugins/groovy/resources/icons/griffon/griffonToolWindow@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/GroovyDoc.png b/plugins/groovy/resources/icons/groovy/GroovyDoc.png
index 24eb3da163ec..cdc342196609 100644
--- a/plugins/groovy/resources/icons/groovy/GroovyDoc.png
+++ b/plugins/groovy/resources/icons/groovy/GroovyDoc.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/GroovyDoc@2x.png b/plugins/groovy/resources/icons/groovy/GroovyDoc@2x.png
new file mode 100644
index 000000000000..82fc63008409
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/GroovyDoc@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/abstractClass.png b/plugins/groovy/resources/icons/groovy/abstractClass.png
index ca354ba67075..229d4d3cc951 100644
--- a/plugins/groovy/resources/icons/groovy/abstractClass.png
+++ b/plugins/groovy/resources/icons/groovy/abstractClass.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/abstractClass@2x.png b/plugins/groovy/resources/icons/groovy/abstractClass@2x.png
new file mode 100644
index 000000000000..d3405ffc200d
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/abstractClass@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/annotationType.png b/plugins/groovy/resources/icons/groovy/annotationType.png
index 76e291b60642..17d335b606f6 100644
--- a/plugins/groovy/resources/icons/groovy/annotationType.png
+++ b/plugins/groovy/resources/icons/groovy/annotationType.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/annotationType@2x.png b/plugins/groovy/resources/icons/groovy/annotationType@2x.png
new file mode 100644
index 000000000000..5bf3fb562293
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/annotationType@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/ant_task.png b/plugins/groovy/resources/icons/groovy/ant_task.png
index db63cb1b6b56..c18ea939a5b1 100644
--- a/plugins/groovy/resources/icons/groovy/ant_task.png
+++ b/plugins/groovy/resources/icons/groovy/ant_task.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/ant_task@2x.png b/plugins/groovy/resources/icons/groovy/ant_task@2x.png
new file mode 100644
index 000000000000..4510f5989767
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/ant_task@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/ant_task@2x_dark.png b/plugins/groovy/resources/icons/groovy/ant_task@2x_dark.png
new file mode 100644
index 000000000000..abaa01c9d378
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/ant_task@2x_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/ant_task_dark.png b/plugins/groovy/resources/icons/groovy/ant_task_dark.png
new file mode 100644
index 000000000000..d3d39dae8c6c
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/ant_task_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/class.png b/plugins/groovy/resources/icons/groovy/class.png
index 8f5a8aa084d6..2daede4c3339 100644
--- a/plugins/groovy/resources/icons/groovy/class.png
+++ b/plugins/groovy/resources/icons/groovy/class.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/class@2x.png b/plugins/groovy/resources/icons/groovy/class@2x.png
new file mode 100644
index 000000000000..bbf4a3dda926
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/class@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/def.png b/plugins/groovy/resources/icons/groovy/def.png
index e0b6feef146f..861ebd9b5a17 100644
--- a/plugins/groovy/resources/icons/groovy/def.png
+++ b/plugins/groovy/resources/icons/groovy/def.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/def@2x.png b/plugins/groovy/resources/icons/groovy/def@2x.png
new file mode 100644
index 000000000000..459b22fbe3a5
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/def@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/def@2x_dark.png b/plugins/groovy/resources/icons/groovy/def@2x_dark.png
new file mode 100644
index 000000000000..719a20035f9b
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/def@2x_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/def_dark.png b/plugins/groovy/resources/icons/groovy/def_dark.png
new file mode 100644
index 000000000000..21151b7248bb
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/def_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/dynamicProperty.png b/plugins/groovy/resources/icons/groovy/dynamicProperty.png
index c8bc7e99c70b..27d38eb2a6ac 100644
--- a/plugins/groovy/resources/icons/groovy/dynamicProperty.png
+++ b/plugins/groovy/resources/icons/groovy/dynamicProperty.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/dynamicProperty@2x.png b/plugins/groovy/resources/icons/groovy/dynamicProperty@2x.png
new file mode 100644
index 000000000000..7557d944e2d7
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/dynamicProperty@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/dynamicProperty_13.png b/plugins/groovy/resources/icons/groovy/dynamicProperty_13.png
index 20064e198aaa..23ccf4e05e7b 100644
--- a/plugins/groovy/resources/icons/groovy/dynamicProperty_13.png
+++ b/plugins/groovy/resources/icons/groovy/dynamicProperty_13.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/dynamicProperty_13@2x.png b/plugins/groovy/resources/icons/groovy/dynamicProperty_13@2x.png
new file mode 100644
index 000000000000..578361cb80f6
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/dynamicProperty_13@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/enum.png b/plugins/groovy/resources/icons/groovy/enum.png
index dd1bc173d687..fb0f98204ecd 100644
--- a/plugins/groovy/resources/icons/groovy/enum.png
+++ b/plugins/groovy/resources/icons/groovy/enum.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/enum@2x.png b/plugins/groovy/resources/icons/groovy/enum@2x.png
new file mode 100644
index 000000000000..e0f596dd88db
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/enum@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/field.png b/plugins/groovy/resources/icons/groovy/field.png
index 3875341d826c..c76203a16466 100644
--- a/plugins/groovy/resources/icons/groovy/field.png
+++ b/plugins/groovy/resources/icons/groovy/field.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/field@2x.png b/plugins/groovy/resources/icons/groovy/field@2x.png
new file mode 100644
index 000000000000..4c5a549dc59b
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/field@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_16x16.png b/plugins/groovy/resources/icons/groovy/gant_16x16.png
index 4ba5c41da028..b52626f30e75 100644
--- a/plugins/groovy/resources/icons/groovy/gant_16x16.png
+++ b/plugins/groovy/resources/icons/groovy/gant_16x16.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_16x16@2x.png b/plugins/groovy/resources/icons/groovy/gant_16x16@2x.png
new file mode 100644
index 000000000000..4f18b06610fd
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/gant_16x16@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_16x16@2x_dark.png b/plugins/groovy/resources/icons/groovy/gant_16x16@2x_dark.png
new file mode 100644
index 000000000000..86cf1434dd6e
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/gant_16x16@2x_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_16x16_dark.png b/plugins/groovy/resources/icons/groovy/gant_16x16_dark.png
new file mode 100644
index 000000000000..ef7d1c06b3f2
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/gant_16x16_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_sdk.png b/plugins/groovy/resources/icons/groovy/gant_sdk.png
index 0ecfacd15e7e..2076c7e0f3bf 100644
--- a/plugins/groovy/resources/icons/groovy/gant_sdk.png
+++ b/plugins/groovy/resources/icons/groovy/gant_sdk.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_sdk@2x.png b/plugins/groovy/resources/icons/groovy/gant_sdk@2x.png
new file mode 100644
index 000000000000..0e55871bb8ea
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/gant_sdk@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_sdk@2x_dark.png b/plugins/groovy/resources/icons/groovy/gant_sdk@2x_dark.png
new file mode 100644
index 000000000000..0d0466f646ee
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/gant_sdk@2x_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_sdk_dark.png b/plugins/groovy/resources/icons/groovy/gant_sdk_dark.png
new file mode 100644
index 000000000000..686e4b55ad34
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/gant_sdk_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_target.png b/plugins/groovy/resources/icons/groovy/gant_target.png
index 788477f154ab..dc66cc98c592 100644
--- a/plugins/groovy/resources/icons/groovy/gant_target.png
+++ b/plugins/groovy/resources/icons/groovy/gant_target.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/gant_target@2x.png b/plugins/groovy/resources/icons/groovy/gant_target@2x.png
new file mode 100644
index 000000000000..2b42537ac800
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/gant_target@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovy-transparent.ico b/plugins/groovy/resources/icons/groovy/groovy-transparent.ico
index f1d74129f5ea..f7acba3be816 100644
--- a/plugins/groovy/resources/icons/groovy/groovy-transparent.ico
+++ b/plugins/groovy/resources/icons/groovy/groovy-transparent.ico
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovy.ico b/plugins/groovy/resources/icons/groovy/groovy.ico
index b4d91a4c0999..f7acba3be816 100644
--- a/plugins/groovy/resources/icons/groovy/groovy.ico
+++ b/plugins/groovy/resources/icons/groovy/groovy.ico
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovy_13x13.png b/plugins/groovy/resources/icons/groovy/groovy_13x13.png
index 7a9c09cb872f..376e5bc0b975 100644
--- a/plugins/groovy/resources/icons/groovy/groovy_13x13.png
+++ b/plugins/groovy/resources/icons/groovy/groovy_13x13.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovy_13x13@2x.png b/plugins/groovy/resources/icons/groovy/groovy_13x13@2x.png
new file mode 100644
index 000000000000..33731cbe316b
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/groovy_13x13@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovy_16x16.png b/plugins/groovy/resources/icons/groovy/groovy_16x16.png
index 984a94d1aef7..b7db528f22bf 100644
--- a/plugins/groovy/resources/icons/groovy/groovy_16x16.png
+++ b/plugins/groovy/resources/icons/groovy/groovy_16x16.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovy_16x16@2x.png b/plugins/groovy/resources/icons/groovy/groovy_16x16@2x.png
new file mode 100644
index 000000000000..2d38fdd8c91f
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/groovy_16x16@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovy_32x32.png b/plugins/groovy/resources/icons/groovy/groovy_32x32.png
index 456b9307783a..8818a18fc164 100644
--- a/plugins/groovy/resources/icons/groovy/groovy_32x32.png
+++ b/plugins/groovy/resources/icons/groovy/groovy_32x32.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovy_32x32@2x.png b/plugins/groovy/resources/icons/groovy/groovy_32x32@2x.png
new file mode 100644
index 000000000000..22ad5f9bfeff
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/groovy_32x32@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/interface.png b/plugins/groovy/resources/icons/groovy/interface.png
index 291df31028bb..cd4db435066e 100644
--- a/plugins/groovy/resources/icons/groovy/interface.png
+++ b/plugins/groovy/resources/icons/groovy/interface.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/interface@2x.png b/plugins/groovy/resources/icons/groovy/interface@2x.png
new file mode 100644
index 000000000000..b5e3d1c28283
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/interface@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/method.png b/plugins/groovy/resources/icons/groovy/method.png
index 5e169f8d737d..553460156a46 100644
--- a/plugins/groovy/resources/icons/groovy/method.png
+++ b/plugins/groovy/resources/icons/groovy/method.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/method@2x.png b/plugins/groovy/resources/icons/groovy/method@2x.png
new file mode 100644
index 000000000000..bfb2458c5da0
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/method@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/property.png b/plugins/groovy/resources/icons/groovy/property.png
index c8bc7e99c70b..b957db002507 100644
--- a/plugins/groovy/resources/icons/groovy/property.png
+++ b/plugins/groovy/resources/icons/groovy/property.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/property@2x.png b/plugins/groovy/resources/icons/groovy/property@2x.png
new file mode 100644
index 000000000000..7557d944e2d7
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/property@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/variable.png b/plugins/groovy/resources/icons/groovy/variable.png
index 8388fe99f219..e57146b90cde 100644
--- a/plugins/groovy/resources/icons/groovy/variable.png
+++ b/plugins/groovy/resources/icons/groovy/variable.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/variable@2x.png b/plugins/groovy/resources/icons/groovy/variable@2x.png
new file mode 100644
index 000000000000..ae1fc1516de6
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/variable@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/action_method.png b/plugins/groovy/resources/icons/mvc/action_method.png
index a79953dacdcd..8c07fb979dfb 100644
--- a/plugins/groovy/resources/icons/mvc/action_method.png
+++ b/plugins/groovy/resources/icons/mvc/action_method.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/action_method@2x.png b/plugins/groovy/resources/icons/mvc/action_method@2x.png
new file mode 100644
index 000000000000..86e770a0ea28
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/action_method@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/config_folder_closed.png b/plugins/groovy/resources/icons/mvc/config_folder_closed.png
index 6a5aa5350ae6..54ada8da24b5 100644
--- a/plugins/groovy/resources/icons/mvc/config_folder_closed.png
+++ b/plugins/groovy/resources/icons/mvc/config_folder_closed.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/config_folder_closed@2x.png b/plugins/groovy/resources/icons/mvc/config_folder_closed@2x.png
new file mode 100644
index 000000000000..4e4e770d8011
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/config_folder_closed@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/config_folder_closed@2x_dark.png b/plugins/groovy/resources/icons/mvc/config_folder_closed@2x_dark.png
new file mode 100644
index 000000000000..7821a1672512
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/config_folder_closed@2x_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/config_folder_closed_dark.png b/plugins/groovy/resources/icons/mvc/config_folder_closed_dark.png
new file mode 100644
index 000000000000..dc64168a6972
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/config_folder_closed_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/controller.png b/plugins/groovy/resources/icons/mvc/controller.png
index 31441f5711bd..d10517aca333 100644
--- a/plugins/groovy/resources/icons/mvc/controller.png
+++ b/plugins/groovy/resources/icons/mvc/controller.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/controller@2x.png b/plugins/groovy/resources/icons/mvc/controller@2x.png
new file mode 100644
index 000000000000..9b6e28843c53
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/controller@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/domain_class.png b/plugins/groovy/resources/icons/mvc/domain_class.png
index 168ad347ed68..2e5984ba15e1 100644
--- a/plugins/groovy/resources/icons/mvc/domain_class.png
+++ b/plugins/groovy/resources/icons/mvc/domain_class.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/domain_class@2x.png b/plugins/groovy/resources/icons/mvc/domain_class@2x.png
new file mode 100644
index 000000000000..c7b088fa7d18
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/domain_class@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin.png b/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin.png
index 82e9678a3423..0b26153d0b33 100644
--- a/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin.png
+++ b/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin@2x.png b/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin@2x.png
new file mode 100644
index 000000000000..80b4d95c8233
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin@2x_dark.png b/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin@2x_dark.png
new file mode 100644
index 000000000000..66b768d47833
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin@2x_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin_dark.png b/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin_dark.png
new file mode 100644
index 000000000000..88afc11d6db4
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/groovy_mvc_plugin_dark.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/modelsNode.png b/plugins/groovy/resources/icons/mvc/modelsNode.png
index efa91aa48abc..52e70bea205b 100644
--- a/plugins/groovy/resources/icons/mvc/modelsNode.png
+++ b/plugins/groovy/resources/icons/mvc/modelsNode.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/mvc/modelsNode@2x.png b/plugins/groovy/resources/icons/mvc/modelsNode@2x.png
new file mode 100644
index 000000000000..da235e89c95e
--- /dev/null
+++ b/plugins/groovy/resources/icons/mvc/modelsNode@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/inspectionDescriptions/TypeCustomizer.html b/plugins/groovy/resources/inspectionDescriptions/TypeCustomizer.html
new file mode 100644
index 000000000000..3513f9a99afc
--- /dev/null
+++ b/plugins/groovy/resources/inspectionDescriptions/TypeCustomizer.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<font face="verdana" size="-1">
+ This inspection reports files which can be custom type checkers and are not added to compiler resources yet.
+</font>
+<font face="verdana" size="-2">Powered by JetGroovy </font></body>
+</html> \ No newline at end of file
diff --git a/plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/after.groovy.template b/plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/after.groovy.template
index a30765f6a90a..aca22e95f99b 100644
--- a/plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/after.groovy.template
+++ b/plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/after.groovy.template
@@ -1,3 +1,2 @@
-def <spot>ArrayList<Integer></spot> getDigits() {
- return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-} \ No newline at end of file
+print <spot>'first line\n' +
+ 'second line'</spot> \ No newline at end of file
diff --git a/plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/before.groovy.template b/plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/before.groovy.template
index a4d2f148943b..4bfcc8b50edb 100644
--- a/plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/before.groovy.template
+++ b/plugins/groovy/resources/intentionDescriptions/GrBreakStringOnLineBreaksIntention/before.groovy.template
@@ -1,3 +1 @@
-def getDigits() {
- return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-} \ No newline at end of file
+print <spot>'first line\nsecond line'</spot> \ No newline at end of file
diff --git a/plugins/groovy/resources/standardDsls/metaDsl.gdsl b/plugins/groovy/resources/standardDsls/metaDsl.gdsl
index d61502853775..4bc4e55bdd35 100644
--- a/plugins/groovy/resources/standardDsls/metaDsl.gdsl
+++ b/plugins/groovy/resources/standardDsls/metaDsl.gdsl
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,7 +25,8 @@ contributor([gdslScriptContext]) {
method name: "contributor", params: [contexts: "java.util.Map", body: {}], type: void
method name: "contributor", params: [contexts: "java.lang.Object", body: {}], type: void
method name: "contribute", params: [pointcut: "Pointcut", body: {}], type: void
-
+ method name: "scriptSuperClass", params: [args: [pattern: 'java.lang.String', superClass: 'java.lang.String']]
+
method name: "currentType", params: [qName: String.name], type: "Pointcut", doc:'Matches when the current (qualifier or this) type is a subtype of the type described by the parameter'
method name: "category", params: [categoryClass: "java.lang.String", isStatic:"java.lang.Boolean"], type: void
@@ -62,6 +63,10 @@ Its elements should be calls to <code>parameter</code> method.'''),
parameter(name:'type', type:Object.name, doc:'Return type name of the method'),
parameter(name:'doc', type:String.name, doc:'Method documentation text'),
]], doc:'Describe a DSL method'
+ method name: "variable", type: "void", params: [args: [
+ parameter(name: "name", type: String.name, doc: 'Variable name'),
+ parameter(name: 'type', type: String.name, doc: 'Variable type')
+ ]], doc: 'Descrive a DSL local variable'
method name: "property", type: "void", params: [args: [
parameter(name:'name', type:String.name, doc:'Property name'),
parameter(name:'type', type:Object.name, doc:'Property type name'),
diff --git a/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java b/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java
index ff764c09d0a7..d146db0caa35 100644
--- a/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java
+++ b/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/GroovyRtConstants.java
@@ -35,4 +35,5 @@ public class GroovyRtConstants {
//public static final Controller ourController = initController();
public static final String PRESENTABLE_MESSAGE = "@#$%@# Presentable:";
public static final String CLEAR_PRESENTABLE = "$@#$%^ CLEAR_PRESENTABLE";
+ public static final String NO_GROOVY = "Cannot compile Groovy files: no Groovy library is defined";
}
diff --git a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java
new file mode 100644
index 000000000000..d340342538a7
--- /dev/null
+++ b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java
@@ -0,0 +1,507 @@
+/*
+ * 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 org.jetbrains.groovy.compiler.rt;
+
+import groovy.lang.GroovyClassLoader;
+import groovyjarjarasm.asm.Opcodes;
+import org.codehaus.groovy.ast.*;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.ListExpression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.classgen.GeneratorContext;
+import org.codehaus.groovy.control.*;
+import org.codehaus.groovy.control.messages.WarningMessage;
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.URI;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+
+/**
+ * @author peter
+ */
+public class DependentGroovycRunner {
+ static boolean runGroovyc(boolean forStubs, File argsFile) {
+ final CompilerConfiguration config = new CompilerConfiguration();
+ config.setClasspath("");
+ config.setOutput(new PrintWriter(System.err));
+ config.setWarningLevel(WarningMessage.PARANOIA);
+
+ final List<CompilerMessage> compilerMessages = new ArrayList<CompilerMessage>();
+ final List<CompilationUnitPatcher> patchers = new ArrayList<CompilationUnitPatcher>();
+ final List<File> srcFiles = new ArrayList<File>();
+ final Map<String, File> class2File = new HashMap<String, File>();
+
+ final String[] finalOutput = new String[1];
+ fillFromArgsFile(argsFile, config, patchers, compilerMessages, srcFiles, class2File, finalOutput);
+ if (srcFiles.isEmpty()) return true;
+
+ if (forStubs) {
+ Map<String, Object> options = new HashMap<String, Object>();
+ options.put("stubDir", config.getTargetDirectory());
+ options.put("keepStubs", Boolean.TRUE);
+ config.setJointCompilationOptions(options);
+ }
+
+ System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: loading sources...");
+ final AstAwareResourceLoader resourceLoader = new AstAwareResourceLoader(class2File);
+ final CompilationUnit unit = createCompilationUnit(forStubs, config, finalOutput[0], buildClassLoaderFor(config, resourceLoader));
+ unit.addPhaseOperation(new CompilationUnit.SourceUnitOperation() {
+ public void call(SourceUnit source) throws CompilationFailedException {
+ File file = new File(source.getName());
+ for (ClassNode aClass : source.getAST().getClasses()) {
+ resourceLoader.myClass2File.put(aClass.getName(), file);
+ }
+ }
+ }, Phases.CONVERSION);
+
+ addSources(forStubs, srcFiles, unit);
+ runPatchers(patchers, compilerMessages, unit, resourceLoader, srcFiles);
+
+ System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: compiling...");
+ final List<GroovyCompilerWrapper.OutputItem> compiledFiles = new GroovyCompilerWrapper(compilerMessages, forStubs).compile(unit);
+ System.out.println(GroovyRtConstants.CLEAR_PRESENTABLE);
+
+ System.out.println();
+ reportCompiledItems(compiledFiles);
+
+ System.out.println();
+ if (compiledFiles.isEmpty()) {
+ reportNotCompiledItems(srcFiles);
+ }
+
+ int errorCount = 0;
+ for (CompilerMessage message : compilerMessages) {
+ if (message.getCategory() == GroovyCompilerMessageCategories.ERROR) {
+ if (errorCount > 100) {
+ continue;
+ }
+ errorCount++;
+ }
+
+ printMessage(message);
+ }
+ return false;
+ }
+
+ private static String fillFromArgsFile(File argsFile, CompilerConfiguration compilerConfiguration, List<CompilationUnitPatcher> patchers, List<CompilerMessage> compilerMessages,
+ List<File> srcFiles, Map<String, File> class2File, String[] finalOutput) {
+ String moduleClasspath = null;
+
+ BufferedReader reader = null;
+ FileInputStream stream;
+
+ try {
+ stream = new FileInputStream(argsFile);
+ reader = new BufferedReader(new InputStreamReader(stream));
+
+ String line;
+
+ while ((line = reader.readLine()) != null) {
+ if (!GroovyRtConstants.SRC_FILE.equals(line)) {
+ break;
+ }
+
+ final File file = new File(reader.readLine());
+ srcFiles.add(file);
+ }
+
+ while (line != null) {
+ if (line.equals("class2src")) {
+ while (!GroovyRtConstants.END.equals(line = reader.readLine())) {
+ class2File.put(line, new File(reader.readLine()));
+ }
+ }
+ else if (line.startsWith(GroovyRtConstants.PATCHERS)) {
+ String s;
+ while (!GroovyRtConstants.END.equals(s = reader.readLine())) {
+ try {
+ final CompilationUnitPatcher patcher = (CompilationUnitPatcher)Class.forName(s).newInstance();
+ patchers.add(patcher);
+ }
+ catch (InstantiationException e) {
+ addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
+ }
+ catch (IllegalAccessException e) {
+ addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
+ }
+ catch (ClassNotFoundException e) {
+ addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
+ }
+ }
+ }
+ else if (line.startsWith(GroovyRtConstants.ENCODING)) {
+ compilerConfiguration.setSourceEncoding(reader.readLine());
+ }
+ else if (line.startsWith(GroovyRtConstants.OUTPUTPATH)) {
+ compilerConfiguration.setTargetDirectory(reader.readLine());
+ }
+ else if (line.startsWith(GroovyRtConstants.FINAL_OUTPUTPATH)) {
+ finalOutput[0] = reader.readLine();
+ }
+
+ line = reader.readLine();
+ }
+
+ }
+ catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ finally {
+ try {
+ reader.close();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ finally {
+ argsFile.delete();
+ }
+ }
+ return moduleClasspath;
+ }
+
+ private static void addSources(boolean forStubs, List<File> srcFiles, final CompilationUnit unit) {
+ for (final File file : srcFiles) {
+ if (forStubs && file.getName().endsWith(".java")) {
+ continue;
+ }
+
+ unit.addSource(new SourceUnit(file, unit.getConfiguration(), unit.getClassLoader(), unit.getErrorCollector()) {
+ public void parse() throws CompilationFailedException {
+ System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Parsing " + file.getName() + "...");
+ super.parse();
+ System.out.println(GroovyRtConstants.CLEAR_PRESENTABLE);
+ }
+ });
+ }
+ }
+
+ private static void runPatchers(List<CompilationUnitPatcher> patchers, List<CompilerMessage> compilerMessages, CompilationUnit unit, final AstAwareResourceLoader loader, List<File> srcFiles) {
+ if (!patchers.isEmpty()) {
+ for (CompilationUnitPatcher patcher : patchers) {
+ try {
+ patcher.patchCompilationUnit(unit, loader, srcFiles.toArray(new File[srcFiles.size()]));
+ }
+ catch (LinkageError e) {
+ addExceptionInfo(compilerMessages, e, "Couldn't run " + patcher.getClass().getName());
+ }
+ }
+ }
+ }
+
+ private static void reportNotCompiledItems(Collection<File> toRecompile) {
+ for (File file : toRecompile) {
+ System.out.print(GroovyRtConstants.TO_RECOMPILE_START);
+ System.out.print(file.getAbsolutePath());
+ System.out.print(GroovyRtConstants.TO_RECOMPILE_END);
+ System.out.println();
+ }
+ }
+
+ private static void reportCompiledItems(List<GroovyCompilerWrapper.OutputItem> compiledFiles) {
+ for (GroovyCompilerWrapper.OutputItem compiledFile : compiledFiles) {
+ /*
+ * output path
+ * source file
+ * output root directory
+ */
+ System.out.print(GroovyRtConstants.COMPILED_START);
+ System.out.print(compiledFile.getOutputPath());
+ System.out.print(GroovyRtConstants.SEPARATOR);
+ System.out.print(compiledFile.getSourceFile());
+ System.out.print(GroovyRtConstants.COMPILED_END);
+ System.out.println();
+ }
+ }
+
+ private static void printMessage(CompilerMessage message) {
+ System.out.print(GroovyRtConstants.MESSAGES_START);
+ System.out.print(message.getCategory());
+ System.out.print(GroovyRtConstants.SEPARATOR);
+ System.out.print(message.getMessage());
+ System.out.print(GroovyRtConstants.SEPARATOR);
+ System.out.print(message.getUrl());
+ System.out.print(GroovyRtConstants.SEPARATOR);
+ System.out.print(message.getLineNum());
+ System.out.print(GroovyRtConstants.SEPARATOR);
+ System.out.print(message.getColumnNum());
+ System.out.print(GroovyRtConstants.SEPARATOR);
+ System.out.print(GroovyRtConstants.MESSAGES_END);
+ System.out.println();
+ }
+
+ private static void addExceptionInfo(List<CompilerMessage> compilerMessages, Throwable e, String message) {
+ final StringWriter writer = new StringWriter();
+ e.printStackTrace(new PrintWriter(writer));
+ compilerMessages.add(new CompilerMessage(GroovyCompilerMessageCategories.WARNING, message + ":\n" + writer, "<exception>", -1, -1));
+ }
+
+ private static CompilationUnit createCompilationUnit(final boolean forStubs,
+ final CompilerConfiguration config,
+ final String finalOutput, final GroovyClassLoader classLoader) {
+
+ final GroovyClassLoader transformLoader = new GroovyClassLoader(classLoader) {
+ public Enumeration<URL> getResources(String name) throws IOException {
+ if (name.endsWith("org.codehaus.groovy.transform.ASTTransformation")) {
+ final Enumeration<URL> resources = super.getResources(name);
+ final ArrayList<URL> list = Collections.list(resources);
+ for (Iterator iterator = list.iterator(); iterator.hasNext();) {
+ final URL url = (URL)iterator.next();
+ try {
+ final String file = new File(new URI(url.toString())).getCanonicalPath();
+ if (file.startsWith(finalOutput) || file.startsWith("/" + finalOutput)) {
+ iterator.remove();
+ }
+ }
+ catch (Exception ignored) {
+ System.out.println("Invalid URI syntax: " + url.toString());
+ }
+ }
+ return Collections.enumeration(list);
+ }
+ return super.getResources(name);
+ }
+ };
+
+ try {
+ if (forStubs) {
+ return createStubGenerator(config, classLoader, transformLoader);
+ }
+ }
+ catch (NoClassDefFoundError ignore) { // older groovy distributions just don't have stub generation capability
+ }
+
+ CompilationUnit unit;
+ try {
+ unit = new CompilationUnit(config, null, classLoader, transformLoader) {
+
+ public void gotoPhase(int phase) throws CompilationFailedException {
+ super.gotoPhase(phase);
+ if (phase <= Phases.ALL) {
+ System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: " + getPhaseDescription());
+ }
+ }
+ };
+ }
+ catch (NoSuchMethodError e) {
+ //groovy 1.5.x
+ unit = new CompilationUnit(config, null, classLoader) {
+
+ public void gotoPhase(int phase) throws CompilationFailedException {
+ super.gotoPhase(phase);
+ if (phase <= Phases.ALL) {
+ System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: " + getPhaseDescription());
+ }
+ }
+ };
+ }
+ return unit;
+ }
+
+ private static CompilationUnit createStubGenerator(final CompilerConfiguration config, final GroovyClassLoader classLoader, final GroovyClassLoader transformLoader) {
+ JavaAwareCompilationUnit unit = new JavaAwareCompilationUnit(config, classLoader) {
+ private boolean annoRemovedAdded;
+
+ public GroovyClassLoader getTransformLoader() {
+ return transformLoader;
+ }
+
+ @Override
+ public void addPhaseOperation(PrimaryClassNodeOperation op, int phase) {
+ if (!annoRemovedAdded && phase == Phases.CONVERSION && op.getClass().getName().startsWith("org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit$")) {
+ annoRemovedAdded = true;
+ super.addPhaseOperation(new PrimaryClassNodeOperation() {
+ @Override
+ public void call(final SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
+ final ClassCodeVisitorSupport annoRemover = new ClassCodeVisitorSupport() {
+ @Override
+ protected SourceUnit getSourceUnit() {
+ return source;
+ }
+
+ public void visitClass(ClassNode node) {
+ if (node.isEnum()) {
+ node.setModifiers(node.getModifiers() & ~Opcodes.ACC_FINAL);
+ }
+ super.visitClass(node);
+ }
+
+ @Override
+ public void visitField(FieldNode fieldNode) {
+ Expression valueExpr = fieldNode.getInitialValueExpression();
+ if (valueExpr instanceof ConstantExpression && ClassHelper.STRING_TYPE.equals(valueExpr.getType())) {
+ fieldNode.setInitialValueExpression(new MethodCallExpression(valueExpr, "toString", new ListExpression()));
+ }
+ super.visitField(fieldNode);
+ }
+
+ @Override
+ public void visitAnnotations(AnnotatedNode node) {
+ List<AnnotationNode> annotations = node.getAnnotations();
+ if (!annotations.isEmpty()) {
+ annotations.clear();
+ }
+ super.visitAnnotations(node);
+ }
+ };
+ try {
+ annoRemover.visitClass(classNode);
+ }
+ catch (LinkageError ignored) {
+ }
+ }
+ }, phase);
+ }
+
+ super.addPhaseOperation(op, phase);
+ }
+
+ public void gotoPhase(int phase) throws CompilationFailedException {
+ if (phase == Phases.SEMANTIC_ANALYSIS) {
+ System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Generating Groovy stubs...");
+ // clear javaSources field so that no javac is invoked
+ try {
+ Field field = JavaAwareCompilationUnit.class.getDeclaredField("javaSources");
+ field.setAccessible(true);
+ LinkedList javaSources = (LinkedList)field.get(this);
+ javaSources.clear();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ else if (phase <= Phases.ALL) {
+ System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovy stub generator: " + getPhaseDescription());
+ }
+
+ super.gotoPhase(phase);
+ }
+
+ };
+ unit.addSources(new String[]{"SomeClass.java"});
+ return unit;
+ }
+
+ static GroovyClassLoader buildClassLoaderFor(final CompilerConfiguration compilerConfiguration, final AstAwareResourceLoader resourceLoader) {
+ GroovyClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<GroovyClassLoader>() {
+ public GroovyClassLoader run() {
+ return new GroovyClassLoader(getClass().getClassLoader(), compilerConfiguration) {
+ public Class loadClass(String name, boolean lookupScriptFiles, boolean preferClassOverScript)
+ throws ClassNotFoundException, CompilationFailedException {
+ Class aClass;
+ try {
+ aClass = super.loadClass(name, lookupScriptFiles, preferClassOverScript);
+ }
+ catch (NoClassDefFoundError e) {
+ throw new ClassNotFoundException(name);
+ }
+ catch (LinkageError e) {
+ throw new RuntimeException("Problem loading class " + name, e);
+ }
+
+ ensureWellFormed(aClass, new HashSet<Class>());
+
+ return aClass;
+ }
+
+ private void ensureWellFormed(Type aClass, Set<Class> visited) throws ClassNotFoundException {
+ if (aClass instanceof Class) {
+ ensureWellFormed((Class)aClass, visited);
+ }
+ else if (aClass instanceof ParameterizedType) {
+ ensureWellFormed(((ParameterizedType)aClass).getOwnerType(), visited);
+ for (Type type : ((ParameterizedType)aClass).getActualTypeArguments()) {
+ ensureWellFormed(type, visited);
+ }
+ }
+ else if (aClass instanceof WildcardType) {
+ for (Type type : ((WildcardType)aClass).getLowerBounds()) {
+ ensureWellFormed(type, visited);
+ }
+ for (Type type : ((WildcardType)aClass).getUpperBounds()) {
+ ensureWellFormed(type, visited);
+ }
+ }
+ else if (aClass instanceof GenericArrayType) {
+ ensureWellFormed(((GenericArrayType)aClass).getGenericComponentType(), visited);
+ }
+ }
+
+ private void ensureWellFormed(Class aClass, Set<Class> visited) throws ClassNotFoundException {
+ String name = aClass.getName();
+ if (resourceLoader.getSourceFile(name) != null && visited.add(aClass)) {
+ try {
+ for (Method method : aClass.getDeclaredMethods()) {
+ ensureWellFormed(method.getGenericReturnType(), visited);
+ for (Type type : method.getGenericExceptionTypes()) {
+ ensureWellFormed(type, visited);
+ }
+ for (Type type : method.getGenericParameterTypes()) {
+ ensureWellFormed(type, visited);
+ }
+ }
+ for (Constructor method : aClass.getDeclaredConstructors()) {
+ for (Type type : method.getGenericExceptionTypes()) {
+ ensureWellFormed(type, visited);
+ }
+ for (Type type : method.getGenericParameterTypes()) {
+ ensureWellFormed(type, visited);
+ }
+ }
+
+ for (Field field : aClass.getDeclaredFields()) {
+ ensureWellFormed(field.getGenericType(), visited);
+ }
+
+ Type superclass = aClass.getGenericSuperclass();
+ if (superclass != null) {
+ ensureWellFormed(aClass, visited);
+ }
+
+ for (Type intf : aClass.getGenericInterfaces()) {
+ ensureWellFormed(intf, visited);
+ }
+
+ aClass.getAnnotations();
+ Package aPackage = aClass.getPackage();
+ if (aPackage != null) {
+ aPackage.getAnnotations();
+ }
+ }
+ catch (LinkageError e) {
+ throw new ClassNotFoundException(name);
+ }
+ catch (TypeNotPresentException e) {
+ throw new ClassNotFoundException(name);
+ }
+ }
+ }
+ };
+ }
+ });
+ classLoader.setResourceLoader(resourceLoader);
+ return classLoader;
+ }
+}
diff --git a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java
index 1781b4ed02cf..3d7e8eb5dd80 100644
--- a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java
+++ b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/GroovycRunner.java
@@ -15,25 +15,7 @@
package org.jetbrains.groovy.compiler.rt;
-import groovy.lang.GroovyClassLoader;
-import groovyjarjarasm.asm.Opcodes;
-import org.codehaus.groovy.ast.*;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.ListExpression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.classgen.GeneratorContext;
-import org.codehaus.groovy.control.*;
-import org.codehaus.groovy.control.messages.WarningMessage;
-import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.URI;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.*;
+import java.io.File;
/**
* @author: Dmitry.Krasilschikov
@@ -92,65 +74,15 @@ public class GroovycRunner {
}
try {
- final CompilerConfiguration config = new CompilerConfiguration();
- config.setClasspath("");
- config.setOutput(new PrintWriter(System.err));
- config.setWarningLevel(WarningMessage.PARANOIA);
-
- final List<CompilerMessage> compilerMessages = new ArrayList<CompilerMessage>();
- final List<CompilationUnitPatcher> patchers = new ArrayList<CompilationUnitPatcher>();
- final List<File> srcFiles = new ArrayList<File>();
- final Map<String, File> class2File = new HashMap<String, File>();
-
- final String[] finalOutput = new String[1];
- fillFromArgsFile(argsFile, config, patchers, compilerMessages, srcFiles, class2File, finalOutput);
- if (srcFiles.isEmpty()) return;
-
- if (forStubs) {
- Map<String, Object> options = new HashMap<String, Object>();
- options.put("stubDir", config.getTargetDirectory());
- options.put("keepStubs", Boolean.TRUE);
- config.setJointCompilationOptions(options);
- }
-
- System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: loading sources...");
- final AstAwareResourceLoader resourceLoader = new AstAwareResourceLoader(class2File);
- final CompilationUnit unit = createCompilationUnit(forStubs, config, finalOutput[0], buildClassLoaderFor(config, resourceLoader));
- unit.addPhaseOperation(new CompilationUnit.SourceUnitOperation() {
- public void call(SourceUnit source) throws CompilationFailedException {
- File file = new File(source.getName());
- for (ClassNode aClass : source.getAST().getClasses()) {
- resourceLoader.myClass2File.put(aClass.getName(), file);
- }
- }
- }, Phases.CONVERSION);
-
- addSources(forStubs, srcFiles, unit);
- runPatchers(patchers, compilerMessages, unit, resourceLoader, srcFiles);
-
- System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: compiling...");
- final List<GroovyCompilerWrapper.OutputItem> compiledFiles = new GroovyCompilerWrapper(compilerMessages, forStubs).compile(unit);
- System.out.println(GroovyRtConstants.CLEAR_PRESENTABLE);
-
- System.out.println();
- reportCompiledItems(compiledFiles);
-
- System.out.println();
- if (compiledFiles.isEmpty()) {
- reportNotCompiledItems(srcFiles);
- }
-
- int errorCount = 0;
- for (CompilerMessage message : compilerMessages) {
- if (message.getCategory() == GroovyCompilerMessageCategories.ERROR) {
- if (errorCount > 100) {
- continue;
- }
- errorCount++;
- }
+ Class.forName("org.codehaus.groovy.control.CompilationUnit");
+ }
+ catch (Throwable e) {
+ System.err.println(GroovyRtConstants.NO_GROOVY);
+ System.exit(1);
+ }
- printMessage(message);
- }
+ try {
+ DependentGroovycRunner.runGroovyc(forStubs, argsFile);
}
catch (Throwable e) {
e.printStackTrace();
@@ -170,407 +102,4 @@ public class GroovycRunner {
}
*/
}
-
- private static String fillFromArgsFile(File argsFile, CompilerConfiguration compilerConfiguration, List<CompilationUnitPatcher> patchers, List<CompilerMessage> compilerMessages,
- List<File> srcFiles, Map<String, File> class2File, String[] finalOutput) {
- String moduleClasspath = null;
-
- BufferedReader reader = null;
- FileInputStream stream;
-
- try {
- stream = new FileInputStream(argsFile);
- reader = new BufferedReader(new InputStreamReader(stream));
-
- String line;
-
- while ((line = reader.readLine()) != null) {
- if (!GroovyRtConstants.SRC_FILE.equals(line)) {
- break;
- }
-
- final File file = new File(reader.readLine());
- srcFiles.add(file);
- }
-
- while (line != null) {
- if (line.equals("class2src")) {
- while (!GroovyRtConstants.END.equals(line = reader.readLine())) {
- class2File.put(line, new File(reader.readLine()));
- }
- }
- else if (line.startsWith(GroovyRtConstants.PATCHERS)) {
- String s;
- while (!GroovyRtConstants.END.equals(s = reader.readLine())) {
- try {
- final CompilationUnitPatcher patcher = (CompilationUnitPatcher)Class.forName(s).newInstance();
- patchers.add(patcher);
- }
- catch (InstantiationException e) {
- addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
- }
- catch (IllegalAccessException e) {
- addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
- }
- catch (ClassNotFoundException e) {
- addExceptionInfo(compilerMessages, e, "Couldn't instantiate " + s);
- }
- }
- }
- else if (line.startsWith(GroovyRtConstants.ENCODING)) {
- compilerConfiguration.setSourceEncoding(reader.readLine());
- }
- else if (line.startsWith(GroovyRtConstants.OUTPUTPATH)) {
- compilerConfiguration.setTargetDirectory(reader.readLine());
- }
- else if (line.startsWith(GroovyRtConstants.FINAL_OUTPUTPATH)) {
- finalOutput[0] = reader.readLine();
- }
-
- line = reader.readLine();
- }
-
- }
- catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- finally {
- try {
- reader.close();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- finally {
- argsFile.delete();
- }
- }
- return moduleClasspath;
- }
-
- private static void addSources(boolean forStubs, List<File> srcFiles, final CompilationUnit unit) {
- for (final File file : srcFiles) {
- if (forStubs && file.getName().endsWith(".java")) {
- continue;
- }
-
- unit.addSource(new SourceUnit(file, unit.getConfiguration(), unit.getClassLoader(), unit.getErrorCollector()) {
- public void parse() throws CompilationFailedException {
- System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Parsing " + file.getName() + "...");
- super.parse();
- System.out.println(GroovyRtConstants.CLEAR_PRESENTABLE);
- }
- });
- }
- }
-
- private static void runPatchers(List<CompilationUnitPatcher> patchers, List<CompilerMessage> compilerMessages, CompilationUnit unit, final AstAwareResourceLoader loader, List<File> srcFiles) {
- if (!patchers.isEmpty()) {
- for (CompilationUnitPatcher patcher : patchers) {
- try {
- patcher.patchCompilationUnit(unit, loader, srcFiles.toArray(new File[srcFiles.size()]));
- }
- catch (LinkageError e) {
- addExceptionInfo(compilerMessages, e, "Couldn't run " + patcher.getClass().getName());
- }
- }
- }
- }
-
- private static void reportNotCompiledItems(Collection<File> toRecompile) {
- for (File file : toRecompile) {
- System.out.print(GroovyRtConstants.TO_RECOMPILE_START);
- System.out.print(file.getAbsolutePath());
- System.out.print(GroovyRtConstants.TO_RECOMPILE_END);
- System.out.println();
- }
- }
-
- private static void reportCompiledItems(List<GroovyCompilerWrapper.OutputItem> compiledFiles) {
- for (GroovyCompilerWrapper.OutputItem compiledFile : compiledFiles) {
- /*
- * output path
- * source file
- * output root directory
- */
- System.out.print(GroovyRtConstants.COMPILED_START);
- System.out.print(compiledFile.getOutputPath());
- System.out.print(GroovyRtConstants.SEPARATOR);
- System.out.print(compiledFile.getSourceFile());
- System.out.print(GroovyRtConstants.COMPILED_END);
- System.out.println();
- }
- }
-
- private static void printMessage(CompilerMessage message) {
- System.out.print(GroovyRtConstants.MESSAGES_START);
- System.out.print(message.getCategory());
- System.out.print(GroovyRtConstants.SEPARATOR);
- System.out.print(message.getMessage());
- System.out.print(GroovyRtConstants.SEPARATOR);
- System.out.print(message.getUrl());
- System.out.print(GroovyRtConstants.SEPARATOR);
- System.out.print(message.getLineNum());
- System.out.print(GroovyRtConstants.SEPARATOR);
- System.out.print(message.getColumnNum());
- System.out.print(GroovyRtConstants.SEPARATOR);
- System.out.print(GroovyRtConstants.MESSAGES_END);
- System.out.println();
- }
-
- private static void addExceptionInfo(List<CompilerMessage> compilerMessages, Throwable e, String message) {
- final StringWriter writer = new StringWriter();
- e.printStackTrace(new PrintWriter(writer));
- compilerMessages.add(new CompilerMessage(GroovyCompilerMessageCategories.WARNING, message + ":\n" + writer, "<exception>", -1, -1));
- }
-
- private static CompilationUnit createCompilationUnit(final boolean forStubs,
- final CompilerConfiguration config,
- final String finalOutput, final GroovyClassLoader classLoader) {
-
- final GroovyClassLoader transformLoader = new GroovyClassLoader(classLoader) {
- public Enumeration<URL> getResources(String name) throws IOException {
- if (name.endsWith("org.codehaus.groovy.transform.ASTTransformation")) {
- final Enumeration<URL> resources = super.getResources(name);
- final ArrayList<URL> list = Collections.list(resources);
- for (Iterator iterator = list.iterator(); iterator.hasNext();) {
- final URL url = (URL)iterator.next();
- try {
- final String file = new File(new URI(url.toString())).getCanonicalPath();
- if (file.startsWith(finalOutput) || file.startsWith("/" + finalOutput)) {
- iterator.remove();
- }
- }
- catch (Exception ignored) {
- System.out.println("Invalid URI syntax: " + url.toString());
- }
- }
- return Collections.enumeration(list);
- }
- return super.getResources(name);
- }
- };
-
- try {
- if (forStubs) {
- return createStubGenerator(config, classLoader, transformLoader);
- }
- }
- catch (NoClassDefFoundError ignore) { // older groovy distributions just don't have stub generation capability
- }
-
- CompilationUnit unit;
- try {
- unit = new CompilationUnit(config, null, classLoader, transformLoader) {
-
- public void gotoPhase(int phase) throws CompilationFailedException {
- super.gotoPhase(phase);
- if (phase <= Phases.ALL) {
- System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: " + getPhaseDescription());
- }
- }
- };
- }
- catch (NoSuchMethodError e) {
- //groovy 1.5.x
- unit = new CompilationUnit(config, null, classLoader) {
-
- public void gotoPhase(int phase) throws CompilationFailedException {
- super.gotoPhase(phase);
- if (phase <= Phases.ALL) {
- System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: " + getPhaseDescription());
- }
- }
- };
- }
- return unit;
- }
-
- private static CompilationUnit createStubGenerator(final CompilerConfiguration config, final GroovyClassLoader classLoader, final GroovyClassLoader transformLoader) {
- JavaAwareCompilationUnit unit = new JavaAwareCompilationUnit(config, classLoader) {
- private boolean annoRemovedAdded;
-
- public GroovyClassLoader getTransformLoader() {
- return transformLoader;
- }
-
- @Override
- public void addPhaseOperation(PrimaryClassNodeOperation op, int phase) {
- if (!annoRemovedAdded && phase == Phases.CONVERSION && op.getClass().getName().startsWith("org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit$")) {
- annoRemovedAdded = true;
- super.addPhaseOperation(new PrimaryClassNodeOperation() {
- @Override
- public void call(final SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
- final ClassCodeVisitorSupport annoRemover = new ClassCodeVisitorSupport() {
- @Override
- protected SourceUnit getSourceUnit() {
- return source;
- }
-
- public void visitClass(ClassNode node) {
- if (node.isEnum()) {
- node.setModifiers(node.getModifiers() & ~Opcodes.ACC_FINAL);
- }
- super.visitClass(node);
- }
-
- @Override
- public void visitField(FieldNode fieldNode) {
- Expression valueExpr = fieldNode.getInitialValueExpression();
- if (valueExpr instanceof ConstantExpression && ClassHelper.STRING_TYPE.equals(valueExpr.getType())) {
- fieldNode.setInitialValueExpression(new MethodCallExpression(valueExpr, "toString", new ListExpression()));
- }
- super.visitField(fieldNode);
- }
-
- @Override
- public void visitAnnotations(AnnotatedNode node) {
- List<AnnotationNode> annotations = node.getAnnotations();
- if (!annotations.isEmpty()) {
- annotations.clear();
- }
- super.visitAnnotations(node);
- }
- };
- try {
- annoRemover.visitClass(classNode);
- }
- catch (LinkageError ignored) {
- }
- }
- }, phase);
- }
-
- super.addPhaseOperation(op, phase);
- }
-
- public void gotoPhase(int phase) throws CompilationFailedException {
- if (phase == Phases.SEMANTIC_ANALYSIS) {
- System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Generating Groovy stubs...");
- // clear javaSources field so that no javac is invoked
- try {
- Field field = JavaAwareCompilationUnit.class.getDeclaredField("javaSources");
- field.setAccessible(true);
- LinkedList javaSources = (LinkedList)field.get(this);
- javaSources.clear();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- else if (phase <= Phases.ALL) {
- System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovy stub generator: " + getPhaseDescription());
- }
-
- super.gotoPhase(phase);
- }
-
- };
- unit.addSources(new String[]{"SomeClass.java"});
- return unit;
- }
-
- static GroovyClassLoader buildClassLoaderFor(final CompilerConfiguration compilerConfiguration, final AstAwareResourceLoader resourceLoader) {
- GroovyClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<GroovyClassLoader>() {
- public GroovyClassLoader run() {
- return new GroovyClassLoader(getClass().getClassLoader(), compilerConfiguration) {
- public Class loadClass(String name, boolean lookupScriptFiles, boolean preferClassOverScript)
- throws ClassNotFoundException, CompilationFailedException {
- Class aClass;
- try {
- aClass = super.loadClass(name, lookupScriptFiles, preferClassOverScript);
- }
- catch (NoClassDefFoundError e) {
- throw new ClassNotFoundException(name);
- }
- catch (LinkageError e) {
- throw new RuntimeException("Problem loading class " + name, e);
- }
-
- ensureWellFormed(aClass, new HashSet<Class>());
-
- return aClass;
- }
-
- private void ensureWellFormed(Type aClass, Set<Class> visited) throws ClassNotFoundException {
- if (aClass instanceof Class) {
- ensureWellFormed((Class)aClass, visited);
- }
- else if (aClass instanceof ParameterizedType) {
- ensureWellFormed(((ParameterizedType)aClass).getOwnerType(), visited);
- for (Type type : ((ParameterizedType)aClass).getActualTypeArguments()) {
- ensureWellFormed(type, visited);
- }
- }
- else if (aClass instanceof WildcardType) {
- for (Type type : ((WildcardType)aClass).getLowerBounds()) {
- ensureWellFormed(type, visited);
- }
- for (Type type : ((WildcardType)aClass).getUpperBounds()) {
- ensureWellFormed(type, visited);
- }
- }
- else if (aClass instanceof GenericArrayType) {
- ensureWellFormed(((GenericArrayType)aClass).getGenericComponentType(), visited);
- }
- }
- private void ensureWellFormed(Class aClass, Set<Class> visited) throws ClassNotFoundException {
- String name = aClass.getName();
- if (resourceLoader.getSourceFile(name) != null && visited.add(aClass)) {
- try {
- for (Method method : aClass.getDeclaredMethods()) {
- ensureWellFormed(method.getGenericReturnType(), visited);
- for (Type type : method.getGenericExceptionTypes()) {
- ensureWellFormed(type, visited);
- }
- for (Type type : method.getGenericParameterTypes()) {
- ensureWellFormed(type, visited);
- }
- }
- for (Constructor method : aClass.getDeclaredConstructors()) {
- for (Type type : method.getGenericExceptionTypes()) {
- ensureWellFormed(type, visited);
- }
- for (Type type : method.getGenericParameterTypes()) {
- ensureWellFormed(type, visited);
- }
- }
-
- for (Field field : aClass.getDeclaredFields()) {
- ensureWellFormed(field.getGenericType(), visited);
- }
-
- Type superclass = aClass.getGenericSuperclass();
- if (superclass != null) {
- ensureWellFormed(aClass, visited);
- }
-
- for (Type intf : aClass.getGenericInterfaces()) {
- ensureWellFormed(intf, visited);
- }
-
- aClass.getAnnotations();
- Package aPackage = aClass.getPackage();
- if (aPackage != null) {
- aPackage.getAnnotations();
- }
- }
- catch (LinkageError e) {
- throw new ClassNotFoundException(name);
- }
- catch (TypeNotPresentException e) {
- throw new ClassNotFoundException(name);
- }
- }
- }
- };
- }
- });
- classLoader.setResourceLoader(resourceLoader);
- return classLoader;
- }
-
}
diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index 02f721375eaa..ba3405511934 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -35,7 +35,7 @@
interface="org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor"/>
<extensionPoint name="variableEnhancer" interface="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrVariableEnhancer"/>
<extensionPoint name="referenceTypeEnhancer" interface="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrReferenceTypeEnhancer"/>
- <extensionPoint name="typeConverter" interface="org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter"/>
+ <extensionPoint name="typeConverter" interface="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrTypeConverter"/>
<extensionPoint name="expectedTypesContributor"
interface="org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesContributor"/>
<extensionPoint name="classSubstitutor" interface="org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor"/>
@@ -75,6 +75,8 @@
<extensionPoint name="methodMayBeStaticInspectionFilter" interface="org.jetbrains.plugins.groovy.codeInspection.declaration.GrMethodMayBeStaticInspectionFilter"/>
<extensionPoint name="customAnnotationChecker" interface="org.jetbrains.plugins.groovy.annotator.CustomAnnotationChecker"/>
+
+ <extensionPoint name="convertToJava.customMethodInvocator" interface="org.jetbrains.plugins.groovy.refactoring.convertToJava.invocators.CustomMethodInvocator"/>
</extensionPoints>
<extensions defaultExtensionNs="org.intellij.groovy">
@@ -143,8 +145,9 @@
<variableEnhancer implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureAsAnonymousParameterEnhancer"/>
- <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.GrContainerTypeConverter"/>
- <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.types.GrStringTypeConverter"/>
+ <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrContainerTypeConverter"/>
+ <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrStringTypeConverter"/>
+ <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrBooleanTypeConverter"/>
<typeConverter implementation="org.jetbrains.plugins.groovy.gpp.GppTypeConverter"/>
<expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
@@ -167,6 +170,9 @@
<customAnnotationChecker implementation="org.jetbrains.plugins.groovy.annotator.GrAliasAnnotationChecker"/>
<customAnnotationChecker implementation="org.jetbrains.plugins.groovy.annotator.AnnotationCollectorChecker" order="first"/>
<customAnnotationChecker implementation="org.jetbrains.plugins.groovy.annotator.DelegatesToAnnotationChecker"/>
+
+ <convertToJava.customMethodInvocator implementation="org.jetbrains.plugins.groovy.refactoring.convertToJava.invocators.MapGetterSetterInvocator"/>
+ <customAnnotationChecker implementation="org.jetbrains.plugins.groovy.annotator.TypeCheckedAnnotationChecker"/>
</extensions>
<extensions defaultExtensionNs="com.intellij.properties">
@@ -174,6 +180,8 @@
</extensions>
<extensions defaultExtensionNs="com.intellij">
+ <psi.clsCustomNavigationPolicy implementation="org.jetbrains.plugins.groovy.codeInsight.GroovyClsCustomNavigationPolicy"/>
+
<moduleBuilder builderClass="org.jetbrains.plugins.groovy.config.GroovyAwareModuleBuilder"/>
<pom.declarationSearcher implementation="org.jetbrains.plugins.groovy.geb.GebContentDeclarationSearcher"/>
@@ -250,7 +258,8 @@
<statementUpDownMover implementation="org.jetbrains.plugins.groovy.editor.actions.GroovyStatementMover"/>
<joinLinesHandler implementation="org.jetbrains.plugins.groovy.editor.actions.joinLines.GrVariableJoinLinesHandler"/>
- <joinLinesHandler implementation="org.jetbrains.plugins.groovy.editor.actions.joinLines.GrJoinIfHandler"/>
+ <joinLinesHandler implementation="org.jetbrains.plugins.groovy.editor.actions.joinLines.GrJoinBlockStatementHandler"/>
+ <joinLinesHandler implementation="org.jetbrains.plugins.groovy.editor.actions.joinLines.GrJoinControlStatementHandler"/>
<joinLinesHandler implementation="org.jetbrains.plugins.groovy.editor.actions.joinLines.GrJoinStatementsHandler"/>
<applicationService serviceInterface="org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings"
@@ -259,7 +268,7 @@
<!-- Groovy language -->
<syntaxHighlighter key="Groovy" implementationClass="org.jetbrains.plugins.groovy.highlighter.GroovySyntaxHighlighter"/>
- <annotator language="Groovy" implementationClass="org.jetbrains.plugins.groovy.annotator.GroovyAnnotator"/>
+ <annotator language="Groovy" implementationClass="org.jetbrains.plugins.groovy.annotator.GrAnnotatorImpl"/>
<annotator language="Groovy" implementationClass="org.jetbrains.plugins.groovy.dsl.GroovyDslAnnotator"/>
<lang.psiStructureViewFactory language="Groovy"
@@ -313,8 +322,9 @@
implementationClass="org.jetbrains.plugins.groovy.overrideImplement.GroovyImplementMethodsHandler"/>
<methodImplementor implementation="org.jetbrains.plugins.groovy.overrideImplement.GroovyMethodImplementor"/>
- <codeInsight.parameterInfo language="Groovy"
- implementationClass="org.jetbrains.plugins.groovy.lang.parameterInfo.GroovyParameterInfoHandler"/>
+ <codeInsight.parameterInfo language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.parameterInfo.GroovyParameterInfoHandler"/>
+ <codeInsight.parameterInfo language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.parameterInfo.GroovyAnnotationAttributeInfoHandler"/>
+ <codeInsight.parameterInfo language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.parameterInfo.GroovyTypeParameterInfoHandler"/>
<refactoring.inlineHandler language="Groovy" implementationClass="org.jetbrains.plugins.groovy.refactoring.inline.GroovyInlineHandler"/>
<inlineActionHandler implementation="org.jetbrains.plugins.groovy.refactoring.inline.GroovyInlineLocalHandler"/>
@@ -428,7 +438,6 @@
<definitionsSearch implementation="org.jetbrains.plugins.groovy.findUsages.GroovyImplementationSearch"/>
<targetElementEvaluator language="Groovy" implementationClass="org.jetbrains.plugins.groovy.codeInsight.GroovyTargetElementEvaluator"/>
- <targetElementEvaluator language="JAVA" implementationClass="org.jetbrains.plugins.groovy.codeInsight.JavaClsMethodElementEvaluator"/>
<fileTemplateGroup implementation="org.jetbrains.plugins.groovy.actions.GroovyTemplatesFactory"/>
@@ -533,6 +542,11 @@
bundle="org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle"
key="no.return.display.name" groupKey="groovy.dfa.issues" enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection"/>
+ <localInspection language="Groovy" groupPath="Groovy" shortName="TypeCustomizer"
+ displayName="Type customizer inspection"
+ bundle="org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle"
+ groupKey="other" enabledByDefault="true" level="WARNING"
+ implementationClass="org.jetbrains.plugins.groovy.codeInspection.resources.TypeCustomizerInspection"/>
<localInspection language="Groovy" groupPath="Groovy" shortName="GroovyAssignabilityCheck" displayName="Incompatible type assignments"
groupName="Assignment issues"
enabledByDefault="true" level="WARNING"
@@ -812,7 +826,7 @@
implementationClass="org.jetbrains.plugins.groovy.codeInspection.confusing.GrReassignedInClosureLocalVarInspection"/>
<localInspection language="Groovy" groupPath="Groovy" shortName="UnnecessaryQualifiedReference"
bundle="org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle"
- key="unnecessary.qualified.reference" groupName="Potentially confusing code constructs" enabledByDefault="false"
+ key="unnecessary.qualified.reference" groupName="Potentially confusing code constructs" enabledByDefault="true"
level="WARNING"
implementationClass="org.jetbrains.plugins.groovy.codeInspection.confusing.UnnecessaryQualifiedReferenceInspection"/>
<localInspection language="Groovy" groupPath="Groovy" shortName="GroovyEmptyStatementBody" displayName="Statement with empty body"
@@ -1431,49 +1445,33 @@
text="Exclude from stub generation" description="Don't generate Java stubs for this Groovy file on compilation">
<add-to-group group-id="EditorTabPopupMenu" anchor="after" relative-to-action="RenameJavaFileToGroovyFileAction"/>
</action>
- <action id="org.jetbrains.plugins.groovy.actions.generate.equals.GroovyGenerateEqualsAction"
- class="org.jetbrains.plugins.groovy.actions.generate.equals.GroovyGenerateEqualsAction"
- text="equals() and hashCode()" description="Action generates equals and hashCode now">
- <add-to-group group-id="GenerateGroup" anchor="first"/>
- </action>
-
-
- <action id="org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGeneratePropertyMissingAction"
- class="org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGeneratePropertyMissingAction"
- text="propertyMissing()" description="Action generates propertyMissing()">
- <add-to-group group-id="GenerateGroup" anchor="first"/>
- </action>
-
- <action id="org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGenerateMethodMissingAction"
- class="org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGenerateMethodMissingAction"
- text="methodMissing()" description="Action generates propertyMissing()">
- <add-to-group group-id="GenerateGroup" anchor="first"/>
- </action>
- <action id="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterSetterAction"
- class="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterSetterAction"
- text="Getter and Setter" description="Generates getter">
- <add-to-group group-id="GenerateGroup" anchor="first"/>
- </action>
-
- <action id="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateSetterAction"
- class="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateSetterAction"
- text="Setter" description="Generates setter">
- <add-to-group group-id="GenerateGroup" anchor="first"/>
- </action>
-
- <action id="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterAction"
- class="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterAction"
- text="Getter" description="Generates getter">
- <add-to-group group-id="GenerateGroup" anchor="first"/>
- </action>
-
- <action id="org.jetbrains.plugins.groovy.actions.generate.constructors.GroovyGenerateConstructorAction"
- class="org.jetbrains.plugins.groovy.actions.generate.constructors.GroovyGenerateConstructorAction"
- text="Constructor" description="Generates constructor">
- <add-to-group group-id="GenerateGroup" anchor="first"/>
- </action>
+ <group id="GroovyGenerateGroup1">
+ <action id="org.jetbrains.plugins.groovy.actions.generate.constructors.GroovyGenerateConstructorAction"
+ class="org.jetbrains.plugins.groovy.actions.generate.constructors.GroovyGenerateConstructorAction"
+ text="Constructor" description="Generates constructor"/>
+ <action id="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterAction"
+ class="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterAction"
+ text="Getter" description="Generates getter"/>
+ <action id="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateSetterAction"
+ class="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateSetterAction"
+ text="Setter" description="Generates setter"/>
+ <action id="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterSetterAction"
+ class="org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterSetterAction"
+ text="Getter and Setter" description="Generates getter"/>
+ <action id="org.jetbrains.plugins.groovy.actions.generate.equals.GroovyGenerateEqualsAction"
+ class="org.jetbrains.plugins.groovy.actions.generate.equals.GroovyGenerateEqualsAction"
+ text="equals() and hashCode()" description="Action generates equals and hashCode now"/>
+ <action id="org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGenerateMethodMissingAction"
+ class="org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGenerateMethodMissingAction"
+ text="methodMissing()" description="Action generates propertyMissing()"/>
+ <action id="org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGeneratePropertyMissingAction"
+ class="org.jetbrains.plugins.groovy.actions.generate.missing.GroovyGeneratePropertyMissingAction"
+ text="propertyMissing()" description="Action generates propertyMissing()"/>
+
+ <add-to-group group-id="GenerateGroup" anchor="after" relative-to-action="JavaGenerateGroup1"/>
+ </group>
<action id="Groovy.Doc.Generating"
class="org.jetbrains.plugins.groovy.doc.actions.GenerateGroovyDocAction"
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
index a2db4c7d1499..754542d7d0b5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
@@ -355,3 +355,5 @@ tuple.declaration.should.end.with.def.modifier=Tuple declaration should end with
injection.should.not.contain.line.feeds=GString injection must not contain line feeds
collection.literal.contains.named.argument.and.expression.items=Collection literal contains named and expression arguments at the same time
annotation.collector.cannot.have.attributes=Annotation type annotated with @AnnotationCollector cannot have attributes
+annotation.expected=Annotation expected
+annotation.type.cannot.be.inner=Annotation type cannot be inner
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/AnnotationCollectorChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/AnnotationCollectorChecker.java
index c46968c2f941..e866454026d6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/AnnotationCollectorChecker.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/AnnotationCollectorChecker.java
@@ -47,9 +47,7 @@ public class AnnotationCollectorChecker extends CustomAnnotationChecker {
if (clazz == null) return true;
final GrAnnotationNameValuePair[] attributes = annotation.getParameterList().getAttributes();
CustomAnnotationChecker.checkAnnotationArguments(errors, clazz, annotation.getClassReference(), attributes, false);
- for (Map.Entry<PsiElement, String> entry : errors.entrySet()) {
- holder.createErrorAnnotation(entry.getKey(), entry.getValue());
- }
+ highlightErrors(holder, errors);
return true;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/CustomAnnotationChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/CustomAnnotationChecker.java
index 6718f8c4e504..082ec4d3fcda 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/CustomAnnotationChecker.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/CustomAnnotationChecker.java
@@ -53,13 +53,10 @@ public abstract class CustomAnnotationChecker {
@Nullable
public static String isAnnotationApplicable(@NotNull GrAnnotation annotation, final PsiElement parent) {
- PsiElement owner = parent.getParent();
-
- final PsiElement ownerToUse = parent instanceof PsiModifierList ? owner : parent;
-
- String[] elementTypeFields = GrAnnotationImpl.getApplicableElementTypeFields(ownerToUse);
- if (elementTypeFields != null && !GrAnnotationImpl.isAnnotationApplicableTo(annotation, false, elementTypeFields)) {
- final String annotationTargetText = JavaErrorMessages.message("annotation.target." + elementTypeFields[0]);
+ PsiElement ownerToUse = parent instanceof PsiModifierList ? parent.getParent() : parent;
+ PsiAnnotation.TargetType[] elementTypeFields = GrAnnotationImpl.getApplicableElementTypeFields(ownerToUse);
+ if (elementTypeFields.length != 0 && !GrAnnotationImpl.isAnnotationApplicableTo(annotation, elementTypeFields)) {
+ String annotationTargetText = JavaErrorMessages.message("annotation.target." + elementTypeFields[0]);
GrCodeReferenceElement ref = annotation.getClassReference();
return JavaErrorMessages.message("annotation.not.applicable", ref.getText(), annotationTargetText);
}
@@ -193,4 +190,10 @@ public abstract class CustomAnnotationChecker {
final PsiType componentType = ((PsiArrayType)type).getComponentType();
return checkAnnoTypeAssignable(componentType, rtype, context, skipArrays);
}
+
+ public static void highlightErrors(AnnotationHolder holder, Map<PsiElement, String> errors) {
+ for (Map.Entry<PsiElement, String> entry : errors.entrySet()) {
+ holder.createErrorAnnotation(entry.getKey(), entry.getValue());
+ }
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/FieldAnnotationChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/FieldAnnotationChecker.java
index c8b6ada1f4b3..db27997dd239 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/FieldAnnotationChecker.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/FieldAnnotationChecker.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.annotator;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiAnnotationOwner;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifierList;
@@ -44,22 +45,17 @@ public class FieldAnnotationChecker extends CustomAnnotationChecker {
checkScriptField(holder, annotation);
- PsiElement parent = annotation.getParent();
- PsiElement owner = parent.getParent();
-
- final PsiElement ownerToUse = parent instanceof PsiModifierList ? owner : parent;
-
+ PsiElement annoParent = annotation.getParent();
+ PsiElement ownerToUse = annoParent instanceof PsiModifierList ? annoParent.getParent() : annoParent;
if (!(ownerToUse instanceof GrVariableDeclaration) ||
!GroovyRefactoringUtil.isLocalVariable(((GrVariableDeclaration)ownerToUse).getVariables()[0])) {
return false;
}
- String[] elementTypeFields = {"LOCAL_VARIABLE"};
-
- final GrCodeReferenceElement ref = annotation.getClassReference();
-
- if (!GrAnnotationImpl.isAnnotationApplicableTo(annotation, false, elementTypeFields)) {
- String description = JavaErrorMessages.message("annotation.not.applicable", ref.getText(), JavaErrorMessages.message("annotation.target." + elementTypeFields[0]));
+ if (!GrAnnotationImpl.isAnnotationApplicableTo(annotation, PsiAnnotation.TargetType.LOCAL_VARIABLE)) {
+ GrCodeReferenceElement ref = annotation.getClassReference();
+ String target = JavaErrorMessages.message("annotation.target.LOCAL_VARIABLE");
+ String description = JavaErrorMessages.message("annotation.not.applicable", ref.getText(), target);
holder.createErrorAnnotation(ref, description);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAnnotatorImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAnnotatorImpl.java
new file mode 100644
index 000000000000..9fc467ba78c7
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAnnotatorImpl.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.annotator;
+
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.lang.annotation.Annotator;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * @author Max Medvedev
+ */
+public class GrAnnotatorImpl implements Annotator {
+ @Override
+ public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
+ if (element instanceof GroovyPsiElement) {
+ final GroovyAnnotator annotator = new GroovyAnnotator(holder);
+ ((GroovyPsiElement)element).accept(annotator);
+ if (PsiUtil.isCompileStatic(element)) {
+ GroovyAssignabilityCheckInspection.checkElement((GroovyPsiElement)element, holder);
+ }
+ }
+ else {
+ final PsiElement parent = element.getParent();
+ if (parent instanceof GrMethod) {
+ if (element.equals(((GrMethod)parent).getNameIdentifierGroovy()) && ((GrMethod)parent).getReturnTypeElementGroovy() == null) {
+ GroovyAnnotator.checkMethodReturnType((GrMethod)parent, element, holder);
+ }
+ }
+ else if (parent instanceof GrField) {
+ final GrField field = (GrField)parent;
+ if (element.equals(field.getNameIdentifierGroovy())) {
+ final GrAccessorMethod[] getters = field.getGetters();
+ for (GrAccessorMethod getter : getters) {
+ GroovyAnnotator.checkMethodReturnType(getter, field.getNameIdentifierGroovy(), holder);
+ }
+
+ final GrAccessorMethod setter = field.getSetter();
+ if (setter != null) {
+ GroovyAnnotator.checkMethodReturnType(setter, field.getNameIdentifierGroovy(), holder);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java
index 8e8597e6aa79..4d23980e30ac 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -78,6 +79,7 @@ public class GrReferenceHighlighter extends TextEditorHighlightingPass {
private void visit(GrReferenceElement element) {
+ ProgressManager.checkCanceled();
final PsiElement resolved = element.resolve();
final TextAttributesKey attribute = GrHighlightUtil.getDeclarationHighlightingAttribute(resolved, element);
if (attribute != null) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
index a1ec3e409b5a..9357802f1866 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
@@ -25,7 +25,6 @@ import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
-import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.IndexNotReadyException;
@@ -47,7 +46,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.annotator.intentions.*;
-import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection;
import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil;
@@ -81,7 +79,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.*;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAnnotationMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.types.*;
@@ -89,14 +90,12 @@ import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.modifiers.GrAnnotationCollector;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
-import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter;
-import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrScriptField;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ast.GrInheritConstructorContributor;
-import org.jetbrains.plugins.groovy.lang.resolve.processors.PropertyResolverProcessor;
import java.util.*;
@@ -107,43 +106,13 @@ import static org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter.*;
* @author ven
*/
@SuppressWarnings({"unchecked"})
-public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
+public class GroovyAnnotator extends GroovyElementVisitor {
private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.annotator.GroovyAnnotator");
- private AnnotationHolder myHolder;
+ private final AnnotationHolder myHolder;
- public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
- if (element instanceof GroovyPsiElement) {
- myHolder = holder;
- ((GroovyPsiElement)element).accept(this);
- if (PsiUtil.isCompileStatic(element)) {
- GroovyAssignabilityCheckInspection.checkElement((GroovyPsiElement)element, holder);
- }
- myHolder = null;
- }
- else {
- final PsiElement parent = element.getParent();
- if (parent instanceof GrMethod) {
- if (element.equals(((GrMethod)parent).getNameIdentifierGroovy()) &&
- ((GrMethod)parent).getReturnTypeElementGroovy() == null) {
- checkMethodReturnType((GrMethod)parent, element, holder);
- }
- }
- else if (parent instanceof GrField) {
- final GrField field = (GrField)parent;
- if (element.equals(field.getNameIdentifierGroovy())) {
- final GrAccessorMethod[] getters = field.getGetters();
- for (GrAccessorMethod getter : getters) {
- checkMethodReturnType(getter, field.getNameIdentifierGroovy(), holder);
- }
-
- final GrAccessorMethod setter = field.getSetter();
- if (setter != null) {
- checkMethodReturnType(setter, field.getNameIdentifierGroovy(), holder);
- }
- }
- }
- }
+ public GroovyAnnotator(@NotNull AnnotationHolder holder) {
+ myHolder = holder;
}
@Override
@@ -222,25 +191,12 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
final GrCatchClause[] clauses = statement.getCatchClauses();
List<PsiType> usedExceptions = new ArrayList<PsiType>();
- final PsiClassType throwable = PsiType.getJavaLangThrowable(statement.getManager(), statement.getResolveScope());
-
for (GrCatchClause clause : clauses) {
final GrParameter parameter = clause.getParameter();
if (parameter == null) continue;
final GrTypeElement typeElement = parameter.getTypeElementGroovy();
-
- PsiType type = typeElement != null ? typeElement.getType() : null;
- if (type == null) {
- type = throwable;
- }
-
- if (!throwable.isAssignableFrom(type)) {
- LOG.assertTrue(typeElement != null);
- myHolder.createErrorAnnotation(typeElement,
- GroovyBundle.message("catch.statement.parameter.type.should.be.a.subclass.of.throwable"));
- continue;
- }
+ PsiType type = typeElement != null ? typeElement.getType() : TypesUtil.createType(CommonClassNames.JAVA_LANG_EXCEPTION, statement);
if (typeElement instanceof GrDisjunctionTypeElement) {
final GrTypeElement[] elements = ((GrDisjunctionTypeElement)typeElement).getTypeElements();
@@ -274,6 +230,22 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
}
@Override
+ public void visitCatchClause(GrCatchClause clause) {
+ final GrParameter parameter = clause.getParameter();
+ if (parameter == null) return;
+
+ final GrTypeElement typeElement = parameter.getTypeElementGroovy();
+ if (typeElement != null) {
+ final PsiType type = typeElement.getType();
+ if (type instanceof PsiClassType && ((PsiClassType)type).resolve() == null) return; //don't highlight unresolved types
+ final PsiClassType throwable = TypesUtil.createType(CommonClassNames.JAVA_LANG_THROWABLE, clause);
+ if (!throwable.isAssignableFrom(type)) {
+ myHolder.createErrorAnnotation(typeElement, GroovyBundle.message("catch.statement.parameter.type.should.be.a.subclass.of.throwable"));
+ }
+ }
+ }
+
+ @Override
public void visitVariableDeclaration(GrVariableDeclaration variableDeclaration) {
if (variableDeclaration.isTuple()) {
final GrModifierList list = variableDeclaration.getModifierList();
@@ -488,25 +460,30 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
checkInnerMethod(myHolder, method);
checkOptionalParametersInAbstractMethod(myHolder, method);
+ final PsiElement nameIdentifier = method.getNameIdentifierGroovy();
+ if (nameIdentifier.getNode().getElementType() == GroovyTokenTypes.mSTRING_LITERAL) {
+ checkStringLiteral(nameIdentifier, nameIdentifier.getText());
+ }
+
GrOpenBlock block = method.getBlock();
if (block != null && TypeInferenceHelper.isTooComplexTooAnalyze(block)) {
- myHolder.createWeakWarningAnnotation(method.getNameIdentifierGroovy(),
+ myHolder.createWeakWarningAnnotation(nameIdentifier,
GroovyBundle.message("method.0.is.too.complex.too.analyze", method.getName()));
}
final PsiClass containingClass = method.getContainingClass();
if (method.isConstructor()) {
if (containingClass instanceof GrAnonymousClassDefinition) {
- myHolder.createErrorAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("constructors.are.not.allowed.in.anonymous.class"));
+ myHolder.createErrorAnnotation(nameIdentifier, GroovyBundle.message("constructors.are.not.allowed.in.anonymous.class"));
}
else if (containingClass != null && containingClass.isInterface()) {
- myHolder.createErrorAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("constructors.are.not.allowed.in.interface"));
+ myHolder.createErrorAnnotation(nameIdentifier, GroovyBundle.message("constructors.are.not.allowed.in.interface"));
}
}
if (!method.hasModifierProperty(ABSTRACT) && method.getBlock() == null && !method.hasModifierProperty(NATIVE)) {
final Annotation annotation =
- myHolder.createErrorAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("not.abstract.method.should.have.body"));
+ myHolder.createErrorAnnotation(nameIdentifier, GroovyBundle.message("not.abstract.method.should.have.body"));
annotation.registerFix(new AddMethodBodyFix(method));
}
@@ -616,48 +593,13 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
}
- PsiNamedElement duplicate;
- if (ResolveUtil.isScriptField(variable)) {
- final String name = variable.getName();
+ PsiNamedElement duplicate = ResolveUtil.findDuplicate(variable);
- int count = 0;
- final GroovyScriptClass script = (GroovyScriptClass)((GroovyFile)variable.getContainingFile()).getScriptClass();
- for (GrScriptField field : GrScriptField.getScriptFields(script)) {
- if (name.equals(field.getName())) count++;
- }
- duplicate = count > 1 ? GrScriptField.getScriptField(variable) : null;
- }
- else {
- duplicate = ResolveUtil
- .resolveExistingElement(variable, new DuplicateVariablesProcessor(variable), GrReferenceExpression.class, GrVariable.class);
- if (duplicate == null) {
- if (variable instanceof GrParameter) {
- @SuppressWarnings({"ConstantConditions"})
- final PsiElement context = variable.getContext().getContext();
- if (context instanceof GrClosableBlock) {
- duplicate = ResolveUtil.resolveExistingElement((GroovyPsiElement)context.getParent(), new DuplicateVariablesProcessor(variable),
- GrVariable.class, GrReferenceExpression.class);
- }
- else if (context instanceof GrMethod && !(context.getParent() instanceof GroovyFile)) {
- duplicate =
- ResolveUtil.resolveExistingElement(((GroovyPsiElement)context.getParent()), new DuplicateVariablesProcessor(variable),
- GrVariable.class, GrReferenceExpression.class);
- }
- }
- }
- if (duplicate instanceof GrLightParameter && "args".equals(duplicate.getName())) {
- duplicate = null;
- }
- }
-
-
- if (duplicate instanceof GrVariable) {
- if ((variable instanceof GrField || ResolveUtil.isScriptField(variable)) /*&& duplicate instanceof PsiField*/ ||
- !(duplicate instanceof GrField)) {
- final String key = duplicate instanceof GrField ? "field.already.defined" : "variable.already.defined";
- myHolder.createErrorAnnotation(variable.getNameIdentifierGroovy(), GroovyBundle.message(key, variable.getName()));
- }
+ if (duplicate instanceof GrVariable &&
+ (variable instanceof GrField || ResolveUtil.isScriptField(variable) || !(duplicate instanceof GrField))) {
+ final String key = duplicate instanceof GrField ? "field.already.defined" : "variable.already.defined";
+ myHolder.createErrorAnnotation(variable.getNameIdentifierGroovy(), GroovyBundle.message(key, variable.getName()));
}
PsiType type = variable.getDeclaredType();
@@ -922,7 +864,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
holder.createErrorAnnotation(element, GroovyBundle.message("unexpected.attribute.type.0", element.getType()));
}
- private static void checkMethodReturnType(PsiMethod method, PsiElement toHighlight, AnnotationHolder holder) {
+ static void checkMethodReturnType(PsiMethod method, PsiElement toHighlight, AnnotationHolder holder) {
final HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature();
final List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
@@ -1806,6 +1748,10 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
}
}
+ if (typeDefinition.isAnnotationType() && typeDefinition.getContainingClass() != null) {
+ holder.createErrorAnnotation(typeDefinition.getNameIdentifierGroovy(), GroovyBundle.message("annotation.type.cannot.be.inner"));
+ }
+
checkDuplicateClass(typeDefinition, holder);
checkCyclicInheritance(holder, typeDefinition);
@@ -1904,40 +1850,5 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
private static boolean isScriptGeneratedClass(PsiClass[] allClasses) {
return allClasses.length == 2 && (allClasses[0] instanceof GroovyScriptClass || allClasses[1] instanceof GroovyScriptClass);
}
-
- public static class DuplicateVariablesProcessor extends PropertyResolverProcessor {
- private boolean myBorderPassed;
- private final boolean myHasVisibilityModifier;
-
- public DuplicateVariablesProcessor(GrVariable variable) {
- super(variable.getName(), variable);
- myBorderPassed = false;
- myHasVisibilityModifier = hasExplicitVisibilityModifiers(variable);
- }
-
- private static boolean hasExplicitVisibilityModifiers(GrVariable variable) {
- final GrModifierList modifierList = variable.getModifierList();
- return modifierList != null && modifierList.hasExplicitVisibilityModifiers();
- }
-
- @Override
- public boolean execute(@NotNull PsiElement element, ResolveState state) {
- if (myBorderPassed) {
- return false;
- }
- if (element instanceof GrVariable && hasExplicitVisibilityModifiers((GrVariable)element) != myHasVisibilityModifier) {
- return true;
- }
- return super.execute(element, state);
- }
-
- @Override
- public void handleEvent(Event event, Object associated) {
- if (event == ResolveUtil.DECLARATION_SCOPE_PASSED) {
- myBorderPassed = true;
- }
- super.handleEvent(event, associated);
- }
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/TypeCheckedAnnotationChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/TypeCheckedAnnotationChecker.java
new file mode 100644
index 000000000000..aa9877062a4a
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/TypeCheckedAnnotationChecker.java
@@ -0,0 +1,53 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.annotator;
+
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
+
+import java.util.Map;
+
+/**
+ * @author Max Medvedev
+ */
+public class TypeCheckedAnnotationChecker extends CustomAnnotationChecker {
+ @Override
+ public boolean checkArgumentList(@NotNull AnnotationHolder holder, @NotNull GrAnnotation annotation) {
+ final GrCodeReferenceElement classReference = annotation.getClassReference();
+ PsiElement resolved = classReference.resolve();
+ if (!(resolved instanceof PsiClass &&
+ GroovyCommonClassNames.GROOVY_TRANSFORM_TYPE_CHECKED.equals(((PsiClass)resolved).getQualifiedName()))) {
+ return false;
+ }
+
+ if (!GroovyConfigUtils.GROOVY2_1_0.equals(GroovyConfigUtils.getInstance().getSDKVersion(annotation))) return false;
+
+ GrAnnotationNameValuePair[] attributes = annotation.getParameterList().getAttributes();
+ Map<PsiElement, String> errorMap = ContainerUtil.newHashMap();
+ CustomAnnotationChecker.checkAnnotationArguments(errorMap, (PsiClass)resolved, classReference, attributes, false);
+ highlightErrors(holder, errorMap);
+
+ return true;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java
index 0a5b7d2afb20..844aefb53ec4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java
@@ -35,12 +35,14 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.actions.GroovyTemplates;
import org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle;
import org.jetbrains.plugins.groovy.intentions.base.IntentionUtils;
+import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
@@ -82,17 +84,18 @@ public abstract class CreateClassFix {
PsiDirectory targetDirectory = getTargetDirectory(project, qualifier, name, module, getText());
if (targetDirectory == null) return;
- GrTypeDefinition targetClass = createClassByType(targetDirectory, name, manager, myRefElement, GroovyTemplates.GROOVY_CLASS);
+ final GrTypeDefinition targetClass = createClassByType(targetDirectory, name, manager, myRefElement, GroovyTemplates.GROOVY_CLASS);
if (targetClass == null) return;
PsiType[] argTypes = getArgTypes(myRefElement);
if (argTypes != null && argTypes.length > 0) {
generateConstructor(myRefElement, name, argTypes, targetClass, project);
+ bindRef(targetClass, myRefElement);
}
else {
+ bindRef(targetClass, myRefElement);
putCursor(project, targetClass.getContainingFile(), targetClass);
}
- addImportForClass(groovyFile, qualifier, targetClass);
}
};
}
@@ -147,8 +150,9 @@ public abstract class CreateClassFix {
PsiElement qualifier = myRefElement.getQualifier();
- if (qualifier == null) {
- createTopLevelClass(project, file, groovyFile);
+ if (qualifier == null ||
+ qualifier instanceof GrReferenceElement && ((GrReferenceElement)qualifier).resolve() instanceof PsiPackage) {
+ createTopLevelClass(project, groovyFile);
}
else {
createInnerClass(project, editor, qualifier);
@@ -157,7 +161,7 @@ public abstract class CreateClassFix {
private void createInnerClass(Project project, final Editor editor, PsiElement qualifier) {
PsiElement resolved = resolveQualifier(qualifier);
- assert resolved != null;
+ if (!(resolved instanceof PsiClass)) return;
JVMElementFactory factory = JVMElementFactories.getFactory(resolved.getLanguage(), project);
if (factory == null) return;
@@ -180,7 +184,6 @@ public abstract class CreateClassFix {
AccessToken lock = ApplicationManager.getApplication().acquireWriteActionLock(CreateClassFix.class);
try {
- if (!(resolved instanceof PsiClass)) return;
CodeInsightUtilBase.preparePsiElementForWrite(resolved);
PsiClass added = (PsiClass)resolved.add(template);
@@ -205,6 +208,12 @@ public abstract class CreateClassFix {
if (type instanceof PsiClassType) {
return ((PsiClassType)type).resolve();
}
+ else if (qualifier instanceof GrReferenceExpression) {
+ final PsiElement resolved = ((GrReferenceExpression)qualifier).resolve();
+ if (resolved instanceof PsiClass || resolved instanceof PsiPackage) {
+ return resolved;
+ }
+ }
}
return null;
@@ -226,8 +235,8 @@ public abstract class CreateClassFix {
}
}
- private void createTopLevelClass(Project project, PsiFile file, GroovyFileBase groovyFile) {
- final String pack = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : "";
+ private void createTopLevelClass(@NotNull Project project, @NotNull GroovyFileBase file) {
+ final String pack = getPackage(file);
final PsiManager manager = PsiManager.getInstance(project);
final String name = myRefElement.getReferenceName();
assert name != null;
@@ -236,11 +245,23 @@ public abstract class CreateClassFix {
if (targetDirectory == null) return;
String templateName = getTemplateName(getType());
- PsiClass targetClass = createClassByType(targetDirectory, name, manager, myRefElement, templateName);
- if (targetClass != null) {
- addImportForClass(groovyFile, pack, targetClass);
- putCursor(project, targetClass.getContainingFile(), targetClass);
+ final PsiClass targetClass = createClassByType(targetDirectory, name, manager, myRefElement, templateName);
+ if (targetClass == null) return;
+
+ bindRef(targetClass, myRefElement);
+ putCursor(project, targetClass.getContainingFile(), targetClass);
+ }
+
+ @NotNull
+ private String getPackage(@NotNull PsiClassOwner file) {
+ final PsiElement qualifier = myRefElement.getQualifier();
+ if (qualifier instanceof GrReferenceElement) {
+ final PsiElement resolved = ((GrReferenceElement)qualifier).resolve();
+ if (resolved instanceof PsiPackage) {
+ return ((PsiPackage)resolved).getQualifiedName();
+ }
}
+ return file instanceof GroovyFile ? file.getPackageName() : "";
}
@Override
@@ -257,6 +278,16 @@ public abstract class CreateClassFix {
};
}
+ private static void bindRef(@NotNull final PsiClass targetClass, @NotNull final GrReferenceElement ref) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ final PsiElement newRef = ref.bindToElement(targetClass);
+ GrReferenceAdjuster.shortenReferences(newRef);
+ }
+ });
+ }
+
private static String getTemplateName(CreateClassKind createClassKind) {
switch (createClassKind) {
case ENUM:
@@ -271,22 +302,4 @@ public abstract class CreateClassFix {
return null;
}
}
-
- protected static void addImportForClass(@NotNull GroovyFileBase groovyFile, @NotNull String qualifier, @NotNull PsiClass targetClass)
- throws IncorrectOperationException {
- // add import for created class
- String qualifiedName = targetClass.getQualifiedName();
- if (qualifiedName != null && qualifiedName.contains(".")) {
- String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
- if (!packageName.equals(qualifier)) {
- final AccessToken accessToken = WriteAction.start();
- try {
- groovyFile.addImportForClass(targetClass);
- }
- finally {
- accessToken.finish();
- }
- }
- }
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromUsageFix.java
index afa635b152cd..a3f80366c5d0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromUsageFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromUsageFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,14 +15,10 @@
*/
package org.jetbrains.plugins.groovy.annotator.intentions;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiModifier;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyBundle;
@@ -34,13 +30,10 @@ import org.jetbrains.plugins.groovy.lang.psi.util.StaticChecker;
/**
* @author ven
*/
-public class CreateFieldFromUsageFix implements IntentionAction {
- private final CreateFieldFix myFix;
- private final GrReferenceExpression myRefExpression;
+public class CreateFieldFromUsageFix extends GrCreateFromUsageBaseFix {
- public CreateFieldFromUsageFix(GrReferenceExpression refExpression, PsiClass targetClass) {
- myFix = new CreateFieldFix(targetClass);
- myRefExpression = refExpression;
+ public CreateFieldFromUsageFix(GrReferenceExpression refExpression) {
+ super(refExpression);
}
@NotNull
@@ -48,24 +41,21 @@ public class CreateFieldFromUsageFix implements IntentionAction {
return GroovyBundle.message("create.from.usage.family.name");
}
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return myFix.isAvailable() && myRefExpression.isValid();
- }
-
@Nullable
private String getFieldName() {
- return myRefExpression.getReferenceName();
+ return getRefExpr().getReferenceName();
}
- private String[] generateModifiers() {
- if (myRefExpression != null && StaticChecker.isInStaticContext(myRefExpression, myFix.getTargetClass())) {
+ private String[] generateModifiers(@NotNull PsiClass targetClass) {
+ final GrReferenceExpression myRefExpression = getRefExpr();
+ if (myRefExpression != null && StaticChecker.isInStaticContext(myRefExpression, targetClass)) {
return new String[]{PsiModifier.STATIC};
}
return ArrayUtil.EMPTY_STRING_ARRAY;
}
private TypeConstraint[] calculateTypeConstrains() {
- return GroovyExpectedTypesProvider.calculateTypeConstraints(myRefExpression);
+ return GroovyExpectedTypesProvider.calculateTypeConstraints(getRefExpr());
}
@NotNull
@@ -74,12 +64,18 @@ public class CreateFieldFromUsageFix implements IntentionAction {
}
@Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- myFix.doFix(project, generateModifiers(), getFieldName(), calculateTypeConstrains(), myRefExpression);
+ protected void invokeImpl(Project project, @NotNull PsiClass targetClass) {
+ final CreateFieldFix fix = new CreateFieldFix(targetClass);
+ fix.doFix(targetClass.getProject(), generateModifiers(targetClass), getFieldName(), calculateTypeConstrains(), getRefExpr());
}
@Override
public boolean startInWriteAction() {
return true;
}
+
+ @Override
+ protected boolean canBeTargetClass(PsiClass psiClass) {
+ return super.canBeTargetClass(psiClass) && !psiClass.isInterface() && !psiClass.isAnnotationType();
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateGetterFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateGetterFromUsageFix.java
new file mode 100644
index 000000000000..f897b7fd2595
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateGetterFromUsageFix.java
@@ -0,0 +1,50 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.annotator.intentions;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
+
+/**
+ * @author Max Medvedev
+ */
+public class CreateGetterFromUsageFix extends CreateMethodFromUsageFix {
+ public CreateGetterFromUsageFix(@NotNull GrReferenceExpression refExpression, @NotNull PsiClass targetClass) {
+ super(refExpression);
+ }
+
+ @NotNull
+ @Override
+ protected TypeConstraint[] getReturnTypeConstraints() {
+ return GroovyExpectedTypesProvider.calculateTypeConstraints(getRefExpr());
+ }
+
+ @Override
+ protected PsiType[] getArgumentTypes() {
+ return PsiType.EMPTY_ARRAY;
+ }
+
+ @NotNull
+ @Override
+ protected String getMethodName() {
+ return GroovyPropertyUtils.getGetterNameNonBoolean(getRefExpr().getReferenceName());
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java
index 438e9abd0f6a..f6dddae26eaa 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java
@@ -18,11 +18,9 @@ package org.jetbrains.plugins.groovy.annotator.intentions;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.generation.PsiGenerationInfo;
import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyBundle;
@@ -42,57 +40,61 @@ import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression;
/**
* @author ven
*/
-public class CreateMethodFromUsageFix implements IntentionAction {
- private final PsiClass myTargetClass;
- private final GrReferenceExpression myRefExpression;
+public class CreateMethodFromUsageFix extends GrCreateFromUsageBaseFix implements IntentionAction {
- public CreateMethodFromUsageFix(GrReferenceExpression refExpression, PsiClass targetClass) {
- myRefExpression = refExpression;
- myTargetClass = targetClass;
+ public CreateMethodFromUsageFix(@NotNull GrReferenceExpression refExpression) {
+ super(refExpression);
}
@NotNull
public String getText() {
- return GroovyBundle.message("create.method.from.usage", myRefExpression.getReferenceName());
+ return GroovyBundle.message("create.method.from.usage", getMethodName());
}
- @NotNull
- public String getFamilyName() {
- return GroovyBundle.message("create.from.usage.family.name");
- }
-
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return myTargetClass.isValid() && myRefExpression.isValid() && myTargetClass.isWritable();
- }
-
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- final JVMElementFactory factory = JVMElementFactories.getFactory(myTargetClass.getLanguage(), project);
+ protected void invokeImpl(Project project, @NotNull PsiClass targetClass) {
+ final JVMElementFactory factory = JVMElementFactories.getFactory(targetClass.getLanguage(), targetClass.getProject());
assert factory != null;
- PsiMethod method = factory.createMethod(myRefExpression.getReferenceName(), PsiType.VOID);
- if (StaticChecker.isInStaticContext(myRefExpression, myTargetClass)) {
+ PsiMethod method = factory.createMethod(getMethodName(), PsiType.VOID);
+
+ final GrReferenceExpression ref = getRefExpr();
+ if (StaticChecker.isInStaticContext(ref, targetClass)) {
method.getModifierList().setModifierProperty(PsiModifier.STATIC, true);
}
- PsiType[] argTypes = PsiUtil.getArgumentTypes(myRefExpression, false);
+ PsiType[] argTypes = getArgumentTypes();
assert argTypes != null;
ChooseTypeExpression[] paramTypesExpressions = setupParams(method, argTypes, factory);
- TypeConstraint[] constraints = GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression)myRefExpression.getParent());
+ TypeConstraint[] constraints = getReturnTypeConstraints();
final PsiGenerationInfo<PsiMethod> info = OverrideImplementUtil.createGenerationInfo(method);
- info.insert(myTargetClass, findInsertionAnchor(info), false);
+ info.insert(targetClass, findInsertionAnchor(info, targetClass), false);
method = info.getPsiMember();
- if (shouldBeAbstract(myTargetClass)) {
+ if (shouldBeAbstract(targetClass)) {
method.getBody().delete();
- if (!myTargetClass.isInterface()) {
+ if (!targetClass.isInterface()) {
method.getModifierList().setModifierProperty(PsiModifier.ABSTRACT, true);
}
}
- final PsiElement context = PsiTreeUtil.getParentOfType(myRefExpression, PsiClass.class, PsiMethod.class, PsiFile.class);
- IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, myTargetClass, constraints, false, context);
+ final PsiElement context = PsiTreeUtil.getParentOfType(ref, PsiClass.class, PsiMethod.class, PsiFile.class);
+ IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, constraints, false, context);
+ }
+
+ @NotNull
+ protected TypeConstraint[] getReturnTypeConstraints() {
+ return GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression)getRefExpr().getParent());
+ }
+
+ protected PsiType[] getArgumentTypes() {
+ return PsiUtil.getArgumentTypes(getRefExpr(), false);
+ }
+
+ @NotNull
+ protected String getMethodName() {
+ return getRefExpr().getReferenceName();
}
protected boolean shouldBeAbstract(PsiClass aClass) {
@@ -100,33 +102,31 @@ public class CreateMethodFromUsageFix implements IntentionAction {
}
@Nullable
- private PsiElement findInsertionAnchor(PsiGenerationInfo<PsiMethod> info) {
- PsiElement parent = myTargetClass instanceof GroovyScriptClass ? ((GroovyScriptClass)myTargetClass).getContainingFile() : myTargetClass;
- if (PsiTreeUtil.isAncestor(parent, myRefExpression, false)) {
- return info.findInsertionAnchor(myTargetClass, myRefExpression);
+ private PsiElement findInsertionAnchor(PsiGenerationInfo<PsiMethod> info,
+ PsiClass targetClass) {
+ PsiElement parent = targetClass instanceof GroovyScriptClass ? ((GroovyScriptClass)targetClass).getContainingFile() : targetClass;
+ if (PsiTreeUtil.isAncestor(parent, getRefExpr(), false)) {
+ return info.findInsertionAnchor(targetClass, getRefExpr());
}
else {
return null;
}
}
- private ChooseTypeExpression[] setupParams(PsiMethod method, PsiType[] argTypes, JVMElementFactory factory) {
+ @NotNull
+ private ChooseTypeExpression[] setupParams(@NotNull PsiMethod method, @NotNull PsiType[] argTypes, @NotNull JVMElementFactory factory) {
final PsiParameterList parameterList = method.getParameterList();
ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length];
for (int i = 0; i < argTypes.length; i++) {
PsiType argType = TypesUtil.unboxPrimitiveTypeWrapper(argTypes[i]);
- if (argType == null || argType == PsiType.NULL) argType = TypesUtil.getJavaLangObject(myRefExpression);
+ if (argType == null || argType == PsiType.NULL) argType = TypesUtil.getJavaLangObject(getRefExpr());
final PsiParameter p = factory.createParameter("o", argType);
parameterList.add(p);
TypeConstraint[] constraints = {SupertypeConstraint.create(argType)};
boolean isGroovy = method.getLanguage() == GroovyFileType.GROOVY_LANGUAGE;
- paramTypesExpressions[i] = new ChooseTypeExpression(constraints, myRefExpression.getManager(), isGroovy, method.getResolveScope());
+ paramTypesExpressions[i] = new ChooseTypeExpression(constraints, method.getManager(), isGroovy, method.getResolveScope());
}
return paramTypesExpressions;
}
-
- public boolean startInWriteAction() {
- return true;
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java
index 0ae762772e91..52bfe5eaa1f8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -138,7 +138,7 @@ public class CreateParameterFromUsageFix extends Intention implements IntentionA
public void run() {
if (project.isDisposed()) return;
- final String name = ref.getName();
+ final String name = ref.getReferenceName();
final Set<PsiType> types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(ref);
PsiType unboxed = types.isEmpty() ? null : TypesUtil.unboxPrimitiveTypeWrapper(types.iterator().next());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateSetterFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateSetterFromUsageFix.java
new file mode 100644
index 000000000000..da0689b98c33
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateSetterFromUsageFix.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 org.jetbrains.plugins.groovy.annotator.intentions;
+
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SubtypeConstraint;
+import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * @author Max Medvedev
+ */
+public class CreateSetterFromUsageFix extends CreateMethodFromUsageFix {
+ public CreateSetterFromUsageFix(@NotNull GrReferenceExpression refExpression) {
+ super(refExpression);
+ }
+
+ @NotNull
+ @Override
+ protected TypeConstraint[] getReturnTypeConstraints() {
+ return new TypeConstraint[]{SubtypeConstraint.create(PsiType.VOID)};
+ }
+
+ @Override
+ protected PsiType[] getArgumentTypes() {
+ final GrReferenceExpression ref = getRefExpr();
+ assert PsiUtil.isLValue(ref);
+ PsiType initializer = TypeInferenceHelper.getInitializerFor(ref);
+ if (initializer == null || initializer == PsiType.NULL) {
+ initializer = TypesUtil.getJavaLangObject(ref);
+ }
+ return new PsiType[]{initializer};
+ }
+
+ @NotNull
+ @Override
+ protected String getMethodName() {
+ return GroovyPropertyUtils.getSetterName(getRefExpr().getReferenceName());
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrCreateFromUsageBaseFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrCreateFromUsageBaseFix.java
new file mode 100644
index 000000000000..d85430001f3c
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrCreateFromUsageBaseFix.java
@@ -0,0 +1,153 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.annotator.intentions;
+
+import com.intellij.codeInsight.daemon.QuickFixBundle;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.ide.util.PsiClassListCellRenderer;
+import com.intellij.ide.util.PsiElementListCellRenderer;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.PopupChooserBuilder;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.SmartPointerManager;
+import com.intellij.psi.SmartPsiElementPointer;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.GroovyBundle;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection.isPropertyAccessInStaticMethod;
+
+/**
+ * @author Max Medvedev
+ */
+public abstract class GrCreateFromUsageBaseFix implements IntentionAction {
+ protected final SmartPsiElementPointer<GrReferenceExpression> myRefExpression;
+
+ public GrCreateFromUsageBaseFix(@NotNull GrReferenceExpression refExpression) {
+ myRefExpression = SmartPointerManager.getInstance(refExpression.getProject()).createSmartPsiElementPointer(refExpression);
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return GroovyBundle.message("create.from.usage.family.name");
+ }
+
+ protected GrReferenceExpression getRefExpr() {
+ return myRefExpression.getElement();
+ }
+
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ final GrReferenceExpression element = myRefExpression.getElement();
+ if (element == null || !element.isValid()) {
+ return false;
+ }
+
+ List<PsiClass> targetClasses = getTargetClasses();
+ return !targetClasses.isEmpty();
+ }
+
+ public boolean startInWriteAction() {
+ return true;
+ }
+
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ final List<PsiClass> classes = getTargetClasses();
+ if (classes.size() == 1) {
+ invokeImpl(project, classes.get(0));
+ }
+ else if (!classes.isEmpty()) {
+ chooseClass(classes, editor);
+ }
+ }
+
+ private void chooseClass(List<PsiClass> classes, Editor editor) {
+ final Project project = classes.get(0).getProject();
+
+ final JList list = new JBList(classes);
+ PsiElementListCellRenderer renderer = new PsiClassListCellRenderer();
+ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ list.setCellRenderer(renderer);
+ final PopupChooserBuilder builder = new PopupChooserBuilder(list);
+ renderer.installSpeedSearch(builder);
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ int index = list.getSelectedIndex();
+ if (index < 0) return;
+ final PsiClass aClass = (PsiClass)list.getSelectedValue();
+ CommandProcessor.getInstance().executeCommand(project, new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ invokeImpl(project, aClass);
+ }
+ });
+ }
+ }, getText(), null);
+ }
+ };
+
+ builder.
+ setTitle(QuickFixBundle.message("target.class.chooser.title")).
+ setItemChoosenCallback(runnable).
+ createPopup().
+ showInBestPositionFor(editor);
+ }
+
+ protected abstract void invokeImpl(Project project, @NotNull PsiClass targetClass);
+
+ private List<PsiClass> getTargetClasses() {
+ final GrReferenceExpression ref = getRefExpr();
+ final boolean compileStatic = PsiUtil.isCompileStatic(ref) || isPropertyAccessInStaticMethod(ref);
+ final PsiClass targetClass = QuickfixUtil.findTargetClass(ref, compileStatic);
+ if (targetClass == null || !canBeTargetClass(targetClass)) return Collections.emptyList();
+
+ final ArrayList<PsiClass> classes = new ArrayList<PsiClass>();
+ collectSupers(targetClass, classes);
+ return classes;
+ }
+
+ private void collectSupers(PsiClass psiClass, ArrayList<PsiClass> classes) {
+ classes.add(psiClass);
+
+ final PsiClass[] supers = psiClass.getSupers();
+ for (PsiClass aSuper : supers) {
+ if (classes.contains(aSuper)) continue;
+ if (canBeTargetClass(aSuper)) {
+ collectSupers(aSuper, classes);
+ }
+ }
+ }
+
+ protected boolean canBeTargetClass(PsiClass psiClass) {
+ return psiClass.getManager().isInProject(psiClass);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java
index 6a3ebc8b3c2c..604ac2f734bd 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,7 +74,7 @@ public class QuickfixUtil {
if (!(qualifierExpression instanceof GrReferenceExpression)) return false;
GrReferenceExpression referenceExpression = (GrReferenceExpression)qualifierExpression;
- GroovyPsiElement resolvedElement = ResolveUtil.resolveProperty(referenceExpression, referenceExpression.getName());
+ GroovyPsiElement resolvedElement = ResolveUtil.resolveProperty(referenceExpression, referenceExpression.getReferenceName());
if (resolvedElement == null) return false;
if (resolvedElement instanceof PsiClass) return true;
@@ -190,7 +190,7 @@ public class QuickfixUtil {
}
settings.setContainingClassName(className);
- settings.setName(referenceExpression.getName());
+ settings.setName(referenceExpression.getReferenceName());
if (isCall(referenceExpression)) {
List<PsiType> unboxedTypes = new ArrayList<PsiType>();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicMethodFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicMethodFix.java
index b130395c0f16..211560400f09 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicMethodFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicMethodFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ public class DynamicMethodFix implements IntentionAction, LowPriorityAction {
}
private String calcSignature(final PsiType[] argTypes) {
- StringBuilder builder = new StringBuilder(" '").append(myReferenceExpression.getName());
+ StringBuilder builder = new StringBuilder(" '").append(myReferenceExpression.getReferenceName());
builder.append("(");
for (int i = 0; i < argTypes.length; i++) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicPropertyFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicPropertyFix.java
index a4f837983d39..13849c9b3f1e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicPropertyFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicPropertyFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,7 +69,7 @@ public class DynamicPropertyFix extends GroovyFix implements IntentionAction, Lo
@Nullable
private String getRefName() {
if (myReferenceExpression != null) {
- return myReferenceExpression.getName();
+ return myReferenceExpression.getReferenceName();
}
else {
return myArgumentLabel.getName();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/JavaClsMethodElementEvaluator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyClsCustomNavigationPolicy.java
index b005d1fc70d8..27e5e6bca5e2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/JavaClsMethodElementEvaluator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyClsCustomNavigationPolicy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,39 +15,27 @@
*/
package org.jetbrains.plugins.groovy.codeInsight;
-import com.intellij.codeInsight.TargetElementEvaluator;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiReference;
-import com.intellij.psi.PsiReferenceExpression;
+import com.intellij.psi.impl.compiled.ClsCustomNavigationPolicyEx;
import com.intellij.psi.impl.compiled.ClsMethodImpl;
+import com.intellij.psi.impl.light.LightElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.GroovyFileType;
/**
* @author Max Medvedev
*/
-public class JavaClsMethodElementEvaluator implements TargetElementEvaluator {
+public class GroovyClsCustomNavigationPolicy extends ClsCustomNavigationPolicyEx {
@Override
- public boolean includeSelfInGotoImplementation(@NotNull PsiElement element) {
- return false;
- }
-
- /**
- * used to resolve generated methods with source code
- */
@Nullable
- @Override
- public PsiElement getElementByReference(PsiReference ref, int flags) {
- if (ref instanceof PsiReferenceExpression) {
- PsiElement resolved = ref.resolve();
- if (resolved instanceof ClsMethodImpl) {
- PsiMethod source = ((ClsMethodImpl)resolved).getSourceMirrorMethod();
- if (source != null) {
- return source.getNavigationElement();
- }
- }
+ public PsiElement getNavigationElement(@NotNull ClsMethodImpl clsMethod) {
+ PsiMethod source = clsMethod.getSourceMirrorMethod();
+ if (source instanceof LightElement && source.getLanguage() == GroovyFileType.GROOVY_LANGUAGE) {
+ return source.getNavigationElement();
}
+
return null;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyTargetElementEvaluator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyTargetElementEvaluator.java
index f0346dc94384..c56e8e14f038 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyTargetElementEvaluator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyTargetElementEvaluator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ public class GroovyTargetElementEvaluator implements TargetElementEvaluator {
public static final Key<Object> NAVIGATION_ELEMENT_IS_NOT_TARGET = Key.create("GroovyTargetElementEvaluator.DONT_FOLLOW_NAVIGATION_ELEMENT");
public boolean includeSelfInGotoImplementation(@NotNull PsiElement element) {
- return false;
+ return true;
}
public PsiElement getElementByReference(PsiReference ref, int flags) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/navigation/actions/GroovyGotoSuperHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/navigation/actions/GroovyGotoSuperHandler.java
index 3a893d04a522..dbf5cc103613 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/navigation/actions/GroovyGotoSuperHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/navigation/actions/GroovyGotoSuperHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,10 +15,10 @@
*/
package org.jetbrains.plugins.groovy.codeInsight.navigation.actions;
-import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.navigation.GotoTargetHandler;
import com.intellij.codeInsight.navigation.actions.GotoSuperAction;
+import com.intellij.lang.LanguageCodeInsightActionHandler;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -30,6 +30,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyBundle;
+import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
@@ -39,7 +40,7 @@ import java.util.*;
/**
* @author Medvedev Max
*/
-public class GroovyGotoSuperHandler extends GotoTargetHandler implements CodeInsightActionHandler {
+public class GroovyGotoSuperHandler extends GotoTargetHandler implements LanguageCodeInsightActionHandler {
private static final Logger LOG = Logger.getInstance(GroovyGotoSuperHandler.class);
@@ -127,4 +128,9 @@ public class GroovyGotoSuperHandler extends GotoTargetHandler implements CodeIns
return PsiMethod.EMPTY_ARRAY;
}
+
+ @Override
+ public boolean isValidFor(Editor editor, PsiFile file) {
+ return file != null && GroovyFileType.GROOVY_FILE_TYPE.equals(file.getFileType());
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
index 9e8789a03029..4fb8fcf16e0f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
@@ -31,6 +31,7 @@ second.unsafe.call=Second unsafe call
call.can.throw.npe=Calling chain can throw NullPointerException
groovy.dfa.issues=Data flow issues
+other=Other
unused.assignment=Unused Assignment
unused.assignment.tooltip=Assignment is not used
@@ -68,7 +69,7 @@ access.to.inaccessible.element=Access to inaccessible element
type.doesnt.contain.method=Type ''{0}'' cannot be iterated in range because it does not have method ''{1}''
incorrect.range.argument=Incorrect range arguments
-type.doesnt.implemnt.comparable=Type ''{0}'' doesnt implement Comparable
+type.doesnt.implemnt.comparable=Type ''{0}'' doesn't implement Comparable
add.method=Add method ''{0}()'' to class ''{1}''
implement.class=Implement {0}
fix.class=Fix class {0}
@@ -98,4 +99,7 @@ highlight.if.groovy.object.methods.overridden=Highlight references from class ov
highlight.if.missing.methods.declared=Highlight references from class declaring missingMethod() or missingProperty()
gr.package.inspection.check.scripts=Check scripts
gr.package=Package mismatch
-java.style.property.access=Java-style accessor invocation \ No newline at end of file
+java.style.property.access=Java-style accessor invocation
+type.customizer.is.not.marked.as.a.resource.file=Type customizer script is not marked as compiler resources
+add.to.resources=Add to resources
+add.type.customizer.to.resources=Add type customizer script to resources \ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
index c18ce2badd36..ee5aad946f4f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
@@ -403,7 +403,8 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
e);
}
- private static PsiElement getElementToHighlight(PsiElement refElement, GrArgumentList argList) {
+ @NotNull
+ private static PsiElement getElementToHighlight(@NotNull PsiElement refElement, @Nullable GrArgumentList argList) {
PsiElement elementToHighlight = argList;
if (elementToHighlight == null || elementToHighlight.getTextLength() == 0) elementToHighlight = refElement;
return elementToHighlight;
@@ -520,12 +521,14 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
checkMethodCall(expression, expression.getInvokedExpression());
}
- private boolean checkCannotInferArgumentTypes(PsiElement referenceExpression) {
- if (PsiUtil.getArgumentTypes(referenceExpression, true) != null) return true;
-
- registerError(getElementToHighlight(referenceExpression, PsiUtil.getArgumentsList(referenceExpression)),
- GroovyBundle.message("cannot.infer.argument.types"), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.WEAK_WARNING);
- return false;
+ private boolean checkCannotInferArgumentTypes(PsiElement place) {
+ if (PsiUtil.getArgumentTypes(place, true) != null) {
+ return true;
+ }
+ else {
+ highlightUnknownArgs(place);
+ return false;
+ }
}
@Override
@@ -851,9 +854,9 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
return null;
}
- private void highlightUnknownArgs(GroovyPsiElement place) {
- registerError(getElementToHighlight(place, PsiUtil.getArgumentsList(place)), GroovyBundle.message("cannot.infer.argument.types"),
- LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.WEAK_WARNING);
+ private void highlightUnknownArgs(@NotNull PsiElement place) {
+ final PsiElement toHighlight = getElementToHighlight(place, PsiUtil.getArgumentsList(place));
+ registerError(toHighlight, GroovyBundle.message("cannot.infer.argument.types"), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.WEAK_WARNING);
}
}
@@ -893,40 +896,42 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
@Override
protected void registerError(@NotNull final PsiElement location,
@NotNull final String description,
- @NotNull final LocalQuickFix[] fixes,
+ @Nullable final LocalQuickFix[] fixes,
final ProblemHighlightType highlightType) {
Annotation annotation = myHolder.createErrorAnnotation(location, description);
- for (final LocalQuickFix fix : fixes) {
- annotation.registerFix(new IntentionAction() {
- @NotNull
- @Override
- public String getText() {
- return fix.getName();
- }
+ if (fixes != null) {
+ for (final LocalQuickFix fix : fixes) {
+ annotation.registerFix(new IntentionAction() {
+ @NotNull
+ @Override
+ public String getText() {
+ return fix.getName();
+ }
- @NotNull
- @Override
- public String getFamilyName() {
- return fix.getFamilyName();
- }
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return fix.getFamilyName();
+ }
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return true;
- }
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ return true;
+ }
- @Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- InspectionManager manager = InspectionManager.getInstance(project);
- ProblemDescriptor descriptor = manager.createProblemDescriptor(location, description, fixes, highlightType, fixes.length == 1, false);
- fix.applyFix(project, descriptor);
- }
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ InspectionManager manager = InspectionManager.getInstance(project);
+ ProblemDescriptor descriptor = manager.createProblemDescriptor(location, description, fixes, highlightType, fixes.length == 1, false);
+ fix.applyFix(project, descriptor);
+ }
- @Override
- public boolean startInWriteAction() {
- return true;
- }
- });
+ @Override
+ public boolean startInWriteAction() {
+ return true;
+ }
+ });
+ }
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInArgumentCheckInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInArgumentCheckInspection.java
index 9c4a4f5eff25..8e84d0f99207 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInArgumentCheckInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInArgumentCheckInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,11 +32,10 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt
* @author Max Medvedev
*/
public class GroovyInArgumentCheckInspection extends BaseInspection {
- private MyVisitor MY_VISITOR = new MyVisitor();
-
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
- return MY_VISITOR;
+ return new MyVisitor();
}
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrFieldAlreadyDefinedInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrFieldAlreadyDefinedInspection.java
index 1d47628ac06a..c55ebc3f3a0d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrFieldAlreadyDefinedInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrFieldAlreadyDefinedInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,22 +19,17 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyBundle;
-import org.jetbrains.plugins.groovy.annotator.GroovyAnnotator;
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.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
/**
* @author Maxim.Medvedev
*/
public class GrFieldAlreadyDefinedInspection extends BaseInspection {
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new MyVisitor();
@@ -63,24 +58,12 @@ public class GrFieldAlreadyDefinedInspection extends BaseInspection {
private static class MyVisitor extends BaseInspectionVisitor {
@Override
- public void visitVariable(GrVariable variable) {
- super.visitVariable(variable);
- if (variable instanceof GrField) return;
-
- GroovyPsiElement duplicate = ResolveUtil
- .resolveExistingElement(variable, new GroovyAnnotator.DuplicateVariablesProcessor(variable), GrVariable.class,
- GrReferenceExpression.class);
- if (duplicate == null && variable instanceof GrParameter) {
- final PsiElement parent = variable.getParent().getParent();
- if (parent instanceof GrClosableBlock) {
- duplicate = ResolveUtil
- .resolveExistingElement((GrClosableBlock)parent, new GroovyAnnotator.DuplicateVariablesProcessor(variable), GrVariable.class,
- GrReferenceExpression.class);
- }
- }
+ public void visitField(GrField field) {
+ super.visitField(field);
+ PsiElement duplicate = ResolveUtil.findDuplicate(field);
if (duplicate instanceof GrField) {
- registerError(variable.getNameIdentifierGroovy(), variable.getName());
+ registerError(field.getNameIdentifierGroovy(), field.getName());
}
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java
index 39629d585163..d4a4adfb0b22 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/UnnecessaryQualifiedReferenceInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiModifier;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
@@ -30,6 +31,7 @@ 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.codeInspection.GroovyInspectionBundle;
+import org.jetbrains.plugins.groovy.codeStyle.GroovyCodeStyleSettings;
import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
@@ -153,6 +155,10 @@ public class UnnecessaryQualifiedReferenceInspection extends BaseInspection {
final PsiElement resolved = ref.resolve();
if (!(resolved instanceof PsiClass)) return false;
+ if (((PsiClass)resolved).getContainingClass() != null &&
+ !CodeStyleSettingsManager.getSettings(resolved.getProject()).getCustomSettings(GroovyCodeStyleSettings.class).INSERT_INNER_CLASS_IMPORTS) {
+ return false;
+ }
final String name = ((PsiClass)resolved).getName();
if (name == null) return false;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/resources/TypeCustomizerInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/resources/TypeCustomizerInspection.java
new file mode 100644
index 000000000000..e55cc758c4ef
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/resources/TypeCustomizerInspection.java
@@ -0,0 +1,129 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.codeInspection.resources;
+
+import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.compiler.CompilerConfiguration;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+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.GroovyFile;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+
+import java.util.HashSet;
+
+/**
+ * @author Max Medvedev
+ */
+public class TypeCustomizerInspection extends BaseInspection {
+ @NotNull
+ @Override
+ protected BaseInspectionVisitor buildVisitor() {
+ return new BaseInspectionVisitor() {
+ @Override
+ public void visitFile(GroovyFileBase file) {
+ if (!CompilerConfiguration.getInstance(file.getProject()).isResourceFile(file.getVirtualFile())) {
+ if (fileSeemsToBeTypeCustomizer(file)) {
+ final LocalQuickFix[] fixes = {new AddToResourceFix(file)};
+ final String message = GroovyInspectionBundle.message("type.customizer.is.not.marked.as.a.resource.file");
+ registerError(file, message, fixes, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
+ }
+ }
+ }
+ };
+ }
+
+
+ private static final HashSet<String> CUSTOMIZER_EVENT_NAMES = ContainerUtil
+ .newHashSet("setup", "finish", "unresolvedVariable", "unresolvedProperty", "unresolvedAttribute", "beforeMethodCall", "afterMethodCall",
+ "onMethodSelection", "methodNotFound", "beforeVisitMethod", "afterVisitMethod", "beforeVisitClass", "afterVisitClass",
+ "incompatibleAssignment");
+
+
+ public static boolean fileSeemsToBeTypeCustomizer(@NotNull final PsiFile file) {
+ if (file instanceof GroovyFile && ((GroovyFile)file).isScript()) {
+ for (GrStatement statement : ((GroovyFile)file).getStatements()) {
+ if (statement instanceof GrMethodCall) {
+ GrExpression invoked = ((GrMethodCall)statement).getInvokedExpression();
+ if (invoked instanceof GrReferenceExpression &&
+ !((GrReferenceExpression)invoked).isQualified() &&
+ isCustomizerEvent(((GrReferenceExpression)invoked).getReferenceName())) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+ private static boolean isCustomizerEvent(@Nullable String name) {
+ return CUSTOMIZER_EVENT_NAMES.contains(name);
+ }
+
+ private static class AddToResourceFix implements LocalQuickFix {
+ private final PsiFile myFile;
+
+ public AddToResourceFix(PsiFile file) {
+ myFile = file;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return GroovyInspectionBundle.message("add.to.resources");
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return GroovyInspectionBundle.message("add.type.customizer.to.resources");
+ }
+
+ @Override
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ final VirtualFile virtualFile = myFile.getVirtualFile();
+ if (virtualFile == null) return;
+
+ VirtualFile sourceRoot = ProjectRootManager.getInstance(project).getFileIndex().getSourceRootForFile(virtualFile);
+ final VirtualFile projectRoot = project.getBaseDir();
+ if (sourceRoot == null) {
+ final String path = VfsUtilCore.getRelativePath(virtualFile, projectRoot, '/');
+ CompilerConfiguration.getInstance(project).addResourceFilePattern(path);
+ }
+ else {
+ final String path = VfsUtilCore.getRelativePath(virtualFile, sourceRoot, '/');
+ final String sourceRootPath = VfsUtilCore.getRelativePath(sourceRoot, projectRoot, '/');
+ CompilerConfiguration.getInstance(project).addResourceFilePattern(sourceRootPath + ':' + path);
+ }
+ DaemonCodeAnalyzer.getInstance(project).restart(myFile);
+ }
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java
index cc1708272f77..dcfe7a5bfd9e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java
@@ -224,7 +224,7 @@ public class GrUnresolvedAccessInspection extends GroovySuppressableInspectionTo
if (cannotBeDynamic || shouldHighlightAsUnresolved(ref)) {
HighlightInfo info = createAnnotationForRef(ref, cannotBeDynamic, GroovyBundle.message("cannot.resolve", ref.getReferenceName()));
- LOG.assertTrue(info != null);
+ if (info == null) return null;
HighlightDisplayKey displayKey = HighlightDisplayKey.find(SHORT_NAME);
if (ref.getParent() instanceof GrMethodCall) {
@@ -360,7 +360,7 @@ public class GrUnresolvedAccessInspection extends GroovySuppressableInspectionTo
return results[0];
}
- private static boolean isPropertyAccessInStaticMethod(GrReferenceExpression referenceExpression) {
+ public static boolean isPropertyAccessInStaticMethod(GrReferenceExpression referenceExpression) {
if (referenceExpression.getParent() instanceof GrMethodCall || referenceExpression.getQualifier() != null) return false;
GrMember context = PsiTreeUtil.getParentOfType(referenceExpression, GrMember.class, true, GrClosableBlock.class);
return (context instanceof GrMethod || context instanceof GrClassInitializer) && context.hasModifierProperty(STATIC);
@@ -412,12 +412,18 @@ public class GrUnresolvedAccessInspection extends GroovySuppressableInspectionTo
if (!compileStatic) {
addDynamicAnnotation(info, refExpr, key);
}
- if (targetClass.isWritable()) {
- QuickFixAction.registerQuickFixAction(info, new CreateFieldFromUsageFix(refExpr, targetClass), key);
- if (refExpr.getParent() instanceof GrCall && refExpr.getParent() instanceof GrExpression) {
- QuickFixAction.registerQuickFixAction(info, new CreateMethodFromUsageFix(refExpr, targetClass), key);
- }
+ QuickFixAction.registerQuickFixAction(info, new CreateFieldFromUsageFix(refExpr), key);
+
+ if (PsiUtil.isAccessedForReading(refExpr)) {
+ QuickFixAction.registerQuickFixAction(info, new CreateGetterFromUsageFix(refExpr, targetClass), key);
+ }
+ if (PsiUtil.isLValue(refExpr)) {
+ QuickFixAction.registerQuickFixAction(info, new CreateSetterFromUsageFix(refExpr), key);
+ }
+
+ if (refExpr.getParent() instanceof GrCall && refExpr.getParent() instanceof GrExpression) {
+ QuickFixAction.registerQuickFixAction(info, new CreateMethodFromUsageFix(refExpr), key);
}
if (!refExpr.isQualified()) {
@@ -463,7 +469,7 @@ public class GrUnresolvedAccessInspection extends GroovySuppressableInspectionTo
QuickFixAction.registerQuickFixAction(info, new GroovyAddImportAction(refElement), key);
}
- private static void registerCreateClassByTypeFix(GrReferenceElement refElement,
+ private static void registerCreateClassByTypeFix(@NotNull GrReferenceElement refElement,
@Nullable HighlightInfo info,
final HighlightDisplayKey key) {
GrPackageDefinition packageDefinition = PsiTreeUtil.getParentOfType(refElement, GrPackageDefinition.class);
@@ -474,7 +480,7 @@ public class GrUnresolvedAccessInspection extends GroovySuppressableInspectionTo
refElement.getManager().areElementsEquivalent(((GrNewExpression)parent).getReferenceElement(), refElement)) {
QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFromNewAction((GrNewExpression)parent), key);
}
- else {
+ else if (canBeClassOrPackage(refElement)) {
if (shouldBeInterface(refElement)) {
QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE), key);
}
@@ -494,6 +500,10 @@ public class GrUnresolvedAccessInspection extends GroovySuppressableInspectionTo
}
}
+ private static boolean canBeClassOrPackage(@NotNull GrReferenceElement refElement) {
+ return !(refElement instanceof GrReferenceExpression) || ResolveUtil.canBeClassOrPackage((GrReferenceExpression)refElement);
+ }
+
private static boolean shouldBeAnnotation(GrReferenceElement element) {
return element.getParent() instanceof GrAnnotation;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/JavaStylePropertiesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/JavaStylePropertiesUtil.java
index e2167aa82739..723b59fb2b74 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/JavaStylePropertiesUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/JavaStylePropertiesUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ public class JavaStylePropertiesUtil {
public static void fixJavaStyleProperty(GrMethodCall call) {
GrExpression invoked = call.getInvokedExpression();
- String accessorName = ((GrReferenceExpression)invoked).getName();
+ String accessorName = ((GrReferenceExpression)invoked).getReferenceName();
if (isGetterInvocation(call) && invoked instanceof GrReferenceExpression) {
final GrExpression newCall = genRefForGetter(call, accessorName);
call.replaceWithExpression(newCall, true);
@@ -109,7 +109,7 @@ public class JavaStylePropertiesUtil {
return false;
}
- GrAssignmentExpression assignment = genRefForSetter(call, refExpr.getName());
+ GrAssignmentExpression assignment = genRefForSetter(call, refExpr.getReferenceName());
GrExpression value = assignment.getLValue();
if (value instanceof GrReferenceExpression &&
call.getManager().areElementsEquivalent(((GrReferenceExpression)value).resolve(), method)) {
@@ -137,7 +137,7 @@ public class JavaStylePropertiesUtil {
return false;
}
- GrExpression ref = genRefForGetter(call, ((GrReferenceExpression)expr).getName());
+ GrExpression ref = genRefForGetter(call, ((GrReferenceExpression)expr).getReferenceName());
if (ref instanceof GrReferenceExpression) {
PsiElement resolved = ((GrReferenceExpression)ref).resolve();
PsiManager manager = call.getManager();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java
index 670983e334be..f0d26c9840cc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java
@@ -224,7 +224,7 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
toRecompile.add(vFile);
}
- for (CompilerMessage compilerMessage : processHandler.getCompilerMessages()) {
+ for (CompilerMessage compilerMessage : processHandler.getCompilerMessages(module.getName())) {
final String url = compilerMessage.getSourcePath();
compileContext.addMessage(getMessageCategory(compilerMessage), compilerMessage.getMessageText(),
url == null ? null : VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(url)),
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.java
index 1ee00c24317a..b25325585764 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,6 +54,7 @@ public abstract class GroovyConfigUtils extends AbstractConfigUtils {
public static final String GROOVY1_7 = "1.7";
public static final String GROOVY1_8 = "1.8";
public static final String GROOVY2_0 = "2.0";
+ public static final String GROOVY2_1_0 = "2.1.0";
private GroovyConfigUtils() {
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/ConfigSlurperMapContentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/ConfigSlurperMapContentProvider.java
index d07a8b4e9626..5b513c9ab904 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/ConfigSlurperMapContentProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/ConfigSlurperMapContentProvider.java
@@ -1,8 +1,22 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.configSlurper;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
-import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
@@ -38,7 +52,7 @@ public class ConfigSlurperMapContentProvider extends GroovyMapContentProvider {
if (!(resolvedQualifier instanceof GrReferenceExpression)) return null;
GrReferenceExpression expr = (GrReferenceExpression)resolvedQualifier;
- path.add(expr.getName());
+ path.add(expr.getReferenceName());
resolvedQualifier = expr.getQualifierExpression();
if (resolvedQualifier instanceof GrReferenceExpression) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/GroovyMapValueTypeEnhancer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/GroovyMapValueTypeEnhancer.java
index 2b9d908190b1..8030d5f75431 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/GroovyMapValueTypeEnhancer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/configSlurper/GroovyMapValueTypeEnhancer.java
@@ -1,3 +1,18 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.configSlurper;
import com.intellij.psi.CommonClassNames;
@@ -41,7 +56,7 @@ public class GroovyMapValueTypeEnhancer extends GrReferenceTypeEnhancer {
return null;
}
- String key = ref.getName();
+ String key = ref.getReferenceName();
if (key == null) return null;
for (GroovyMapContentProvider provider : GroovyMapContentProvider.EP_NAME.getExtensions()) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java
index b4d9d73d816a..63806a577a06 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/CustomMembersGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.dsl.dsltop.GdslMembersProvider;
import org.jetbrains.plugins.groovy.dsl.holders.CompoundMembersHolder;
import org.jetbrains.plugins.groovy.dsl.holders.CustomMembersHolder;
+import org.jetbrains.plugins.groovy.dsl.holders.DeclarationType;
import org.jetbrains.plugins.groovy.dsl.holders.NonCodeMembersHolder;
import org.jetbrains.plugins.groovy.dsl.toplevel.ClassContextFilter;
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
@@ -52,14 +53,14 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM
private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.dsl.CustomMembersGenerator");
private static final GdslMembersProvider[] PROVIDERS = GdslMembersProvider.EP_NAME.getExtensions();
public static final String THROWS = "throws";
- private final Set<Map> myMethods = new HashSet<Map>();
+ private final List<Map> myDeclarations = ContainerUtil.newArrayList();
private final Project myProject;
private final CompoundMembersHolder myDepot = new CompoundMembersHolder();
private final GroovyClassDescriptor myDescriptor;
@Nullable private final Map<String, List> myBindings;
private final PsiClass myPsiClass;
- public CustomMembersGenerator(GroovyClassDescriptor descriptor, PsiType type, @Nullable Map<String, List> bindings) {
+ public CustomMembersGenerator(@NotNull GroovyClassDescriptor descriptor, @Nullable PsiType type, @Nullable Map<String, List> bindings) {
myDescriptor = descriptor;
myBindings = bindings;
myProject = descriptor.getProject();
@@ -96,11 +97,11 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM
@Nullable
public CustomMembersHolder getMembersHolder() {
- if (!myMethods.isEmpty()) {
+ if (!myDeclarations.isEmpty()) {
addMemberHolder(new CustomMembersHolder() {
@Override
public boolean processMembers(GroovyClassDescriptor descriptor, PsiScopeProcessor processor, ResolveState state) {
- return NonCodeMembersHolder.generateMembers(myMethods, descriptor.justGetPlaceFile()).processMembers(descriptor, processor, state);
+ return NonCodeMembersHolder.generateMembers(myDeclarations, descriptor.justGetPlaceFile()).processMembers(descriptor, processor, state);
}
});
}
@@ -164,7 +165,8 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM
public void method(Map<Object, Object> args) {
parseMethod(args);
- myMethods.add(args);
+ args.put("declarationType", DeclarationType.METHOD);
+ myDeclarations.add(args);
}
public void methodCall(Closure<Map<Object, Object>> generator) {
@@ -206,7 +208,7 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM
}
@SuppressWarnings("unchecked")
- private void parseMethod(Map args) {
+ private static void parseMethod(Map args) {
String type = stringifyType(args.get("type"));
args.put("type", type);
@@ -245,20 +247,28 @@ public class CustomMembersGenerator extends GroovyObjectSupport implements GdslM
args.put(THROWS, Collections.singletonList(stringifyType(toThrow)));
}
- /*PsiClass aClass = getPsiClass();
- if (aClass != null && aClass.getQualifiedName() != null) {
- args.put("containingClass", aClass.getQualifiedName());
- }*/
}
+ @SuppressWarnings("UnusedDeclaration")
public void closureInMethod(Map<Object, Object> args) {
parseMethod(args);
final Object method = args.get("method");
if (method instanceof Map) {
parseMethod((Map)method);
}
- args.put("closure", true);
- myMethods.add(args);
+ args.put("declarationType", DeclarationType.CLOSURE);
+ myDeclarations.add(args);
+ }
+
+ public void variable(Map<Object, Object> args) {
+ parseVariable(args);
+ myDeclarations.add(args);
+ }
+
+ private void parseVariable(Map<Object, Object> args) {
+ String type = stringifyType(args.get("type"));
+ args.put("type", type);
+ args.put("declarationType", DeclarationType.VARIABLE);
}
private static String stringifyType(Object type) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyClassDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyClassDescriptor.java
index 2fd873cc38f6..4b51addb4dc4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyClassDescriptor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyClassDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -81,6 +81,7 @@ public class GroovyClassDescriptor {
return myPlace;
}
+ @NotNull
public PsiType getPsiType() {
affectingFactors.add(Factor.qualifierType);
return myPsiType;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy
index 04ed1c1917f8..1db5502306e4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslExecutor.groovy
@@ -1,3 +1,18 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.dsl
import com.intellij.openapi.application.ApplicationInfo
@@ -6,8 +21,10 @@ import com.intellij.openapi.util.text.StringUtil
import com.intellij.patterns.ElementPattern
import com.intellij.patterns.PsiJavaPatterns
import com.intellij.psi.PsiType
+import com.intellij.util.ObjectUtils
import com.intellij.util.ProcessingContext
-import java.lang.reflect.Modifier
+import com.intellij.util.containers.MultiMap
+import org.jetbrains.annotations.Nullable
import org.jetbrains.plugins.groovy.dsl.holders.CompoundMembersHolder
import org.jetbrains.plugins.groovy.dsl.psi.PsiEnhancerCategory
import org.jetbrains.plugins.groovy.dsl.toplevel.CompositeContextFilter
@@ -17,7 +34,8 @@ import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.AnnotatedScope
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClassScope
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ClosureScope
import org.jetbrains.plugins.groovy.dsl.toplevel.scopes.ScriptScope
-import com.intellij.util.ObjectUtils
+
+import java.lang.reflect.Modifier
/**
* @author ilyas
@@ -27,6 +45,8 @@ public class GroovyDslExecutor {
static final def cats = PsiEnhancerCategory.EP_NAME.extensions.collect { it.class }
final List<Pair<ContextFilter, Closure>> enhancers = ObjectUtils.assertNotNull([])
+ private MultiMap staticInfo = null
+
private final String myFileName;
static final String ideaVersion
private boolean locked = false
@@ -87,6 +107,11 @@ public class GroovyDslExecutor {
mc.supportsVersion = { ver -> return supportsVersion(ver) }
mc.assertVersion = { ver -> if (!supportsVersion(ver)) throw new InvalidVersionException() }
+ mc.scriptSuperClass = { Map args ->
+ if (staticInfo == null) staticInfo = MultiMap.create()
+ staticInfo.putValue('scriptSuperClass', args)
+ }
+
oldStylePrimitives(mc)
mc.initialize()
@@ -101,7 +126,7 @@ public class GroovyDslExecutor {
locked = true
}
- private boolean supportsVersion(ver) {
+ private static boolean supportsVersion(ver) {
if (ver instanceof String) {
return StringUtil.compareVersionNumbers(ideaVersion, ver) >= 0
}
@@ -118,14 +143,14 @@ public class GroovyDslExecutor {
private static class InvalidVersionException extends Exception {}
- private def handleImplicitBind(arg) {
+ private static def handleImplicitBind(arg) {
if (arg instanceof Map && arg.size() == 1 && arg.keySet().iterator().next() instanceof String && arg.values().iterator().next() instanceof DslPointcut) {
return DslPointcut.bind(arg)
}
return arg
}
- private void oldStylePrimitives(MetaClass mc) {
+ private static void oldStylePrimitives(MetaClass mc) {
/**
* Context definition
*/
@@ -178,4 +203,8 @@ public class GroovyDslExecutor {
return "${super.toString()}; file = $myFileName";
}
+ @Nullable
+ MultiMap getStaticInfo() {
+ staticInfo
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
index 81c831d3b2cf..2eedaf4018dc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
+import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
@@ -28,6 +29,7 @@ import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileAdapter;
@@ -48,6 +50,7 @@ import com.intellij.util.ExceptionUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.ConcurrentMultiMap;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.indexing.*;
import com.intellij.util.io.EnumeratorStringDescriptor;
@@ -56,6 +59,10 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.annotator.GroovyFrameworkConfigNotification;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import javax.swing.event.HyperlinkEvent;
@@ -69,6 +76,7 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Pattern;
/**
* @author peter
@@ -223,6 +231,72 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
return pair.first;
}
+ @Nullable
+ public static PsiClassType pocessScriptSuperClasses(@NotNull GroovyFile scriptFile) {
+ if (!scriptFile.isScript()) return null;
+
+ final VirtualFile virtualFile = scriptFile.getVirtualFile();
+ if (virtualFile == null) return null;
+ final String filePath = virtualFile.getPath();
+
+
+ List<Trinity<String, String, GroovyDslScript>> supers = ContainerUtil.newArrayList();
+ final Project project = scriptFile.getProject();
+ for (GroovyDslScript script : getDslScripts(project)) {
+ final MultiMap staticInfo = script.getStaticInfo();
+ final Collection infos = staticInfo != null ? staticInfo.get("scriptSuperClass") : Collections.emptyList();
+
+ for (Object info : infos) {
+ if (info instanceof Map) {
+ final Map map = (Map)info;
+
+ final Object _pattern = map.get("pattern");
+ final Object _superClass = map.get("superClass");
+
+ if (_pattern instanceof String && _superClass instanceof String) {
+ final String pattern = (String)_pattern;
+ final String superClass = (String)_superClass;
+
+ try {
+ if (Pattern.matches(".*" + pattern, filePath)) {
+ supers.add(Trinity.create(superClass, pattern, script));
+ }
+ }
+ catch (RuntimeException e) {
+ script.handleDslError(e);
+ }
+ }
+ }
+ }
+ }
+
+ if (!supers.isEmpty()) {
+ final String className = supers.get(0).first;
+ final GroovyDslScript script = supers.get(0).third;
+ try {
+ return TypesUtil.createTypeByFQClassName(className, scriptFile);
+ }
+ catch (ProcessCanceledException e) {
+ throw e;
+ }
+ catch (RuntimeException e) {
+ script.handleDslError(e);
+ return null;
+ }
+ }
+ /*else if (supers.size() > 1) {
+ StringBuilder buffer = new StringBuilder("Several script super class patterns match file ").append(filePath).append(". <p> ");
+ for (Trinity<String, String, GroovyDslScript> aSuper : supers) {
+ buffer.append(aSuper.third.getFilePath()).append(" ").append(aSuper.second).append('\n');
+ }
+ NOTIFICATION_GROUP.createNotification("DSL script execution error", buffer.toString(), NotificationType.ERROR, null).notify(project);
+ return null;
+ }*/
+ else {
+ return null;
+ }
+ }
+
public static boolean processExecutors(PsiType psiType, PsiElement place, final PsiScopeProcessor processor, ResolveState state) {
if (insideAnnotation(place)) {
// Basic filter, all DSL contexts are applicable for reference expressions only
@@ -260,10 +334,12 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
return true;
}
- private static boolean insideAnnotation(PsiElement place) {
+ private static boolean insideAnnotation(@Nullable PsiElement place) {
while (place != null) {
if (place instanceof PsiAnnotation) return true;
- if (place instanceof PsiFile) return false;
+ if (place instanceof GrClosableBlock ||
+ place instanceof GrTypeDefinition ||
+ place instanceof PsiFile) return false;
place = place.getParent();
}
return false;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java
index 65c595998602..8ad5d2989d66 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslScript.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ProcessingContext;
+import com.intellij.util.containers.MultiMap;
import groovy.lang.Closure;
import org.codehaus.groovy.runtime.InvokerInvocationException;
import org.jetbrains.annotations.NotNull;
@@ -140,7 +141,7 @@ public class GroovyDslScript {
return false;
}
- private boolean handleDslError(Throwable e) {
+ public boolean handleDslError(Throwable e) {
if (project.isDisposed() || ApplicationManager.getApplication().isUnitTestMode()) {
return true;
}
@@ -154,4 +155,9 @@ public class GroovyDslScript {
public String toString() {
return "GroovyDslScript: " + myPath;
}
+
+ @Nullable
+ public MultiMap getStaticInfo() {
+ return executor.getStaticInfo();
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/dsltop/GroovyDslDefaultMembers.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/dsltop/GroovyDslDefaultMembers.java
index 431242407143..5463320bce7a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/dsltop/GroovyDslDefaultMembers.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/dsltop/GroovyDslDefaultMembers.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -170,7 +170,7 @@ public class GroovyDslDefaultMembers implements GdslMembersProvider {
if (call instanceof GrMethodCall) {
final GrExpression expr = ((GrMethodCall)call).getInvokedExpression();
if (expr instanceof GrReferenceExpression) {
- return ((GrReferenceExpression)expr).getName();
+ return ((GrReferenceExpression)expr).getReferenceName();
}
}
return null;
diff --git a/plugins/groovy/testdata/resolve/class/innerClassIsNotResolvedInAnonymous/A.groovy b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/DeclarationType.java
index 7708be942ba4..1d0244c28862 100644
--- a/plugins/groovy/testdata/resolve/class/innerClassIsNotResolvedInAnonymous/A.groovy
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/DeclarationType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import p.Super
+package org.jetbrains.plugins.groovy.dsl.holders;
-def an = new Super() {
- def foo(Inn<ref>er i) {
-
- }
-} \ No newline at end of file
+/**
+ * @author Max Medvedev
+ */
+public enum DeclarationType {
+ METHOD, CLOSURE, VARIABLE
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java
index 1fd66139f1c7..df3609da7ba0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/holders/NonCodeMembersHolder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,11 +29,12 @@ import org.jetbrains.plugins.groovy.dsl.GroovyClassDescriptor;
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
import org.jetbrains.plugins.groovy.lang.completion.closureParameters.ClosureDescriptor;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightVariable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* @author peter
@@ -41,13 +42,13 @@ import java.util.Set;
public class NonCodeMembersHolder implements CustomMembersHolder {
public static final Key<String> DOCUMENTATION = Key.create("GdslDocumentation");
public static final Key<String> DOCUMENTATION_URL = Key.create("GdslDocumentationUrl");
- private final List<PsiElement> myMethods = new ArrayList<PsiElement>();
+ private final List<PsiElement> myDeclarations = new ArrayList<PsiElement>();
- public static NonCodeMembersHolder generateMembers(Set<Map> methods, final PsiFile place) {
- Map<Set<Map>, NonCodeMembersHolder> map = CachedValuesManager.getManager(place.getProject()).getCachedValue(
- place, new CachedValueProvider<Map<Set<Map>, NonCodeMembersHolder>>() {
- public Result<Map<Set<Map>, NonCodeMembersHolder>> compute() {
- final Map<Set<Map>, NonCodeMembersHolder> map = new ConcurrentSoftHashMap<Set<Map>, NonCodeMembersHolder>();
+ public static NonCodeMembersHolder generateMembers(List<Map> methods, final PsiFile place) {
+ Map<List<Map>, NonCodeMembersHolder> map = CachedValuesManager.getManager(place.getProject()).getCachedValue(
+ place, new CachedValueProvider<Map<List<Map>, NonCodeMembersHolder>>() {
+ public Result<Map<List<Map>, NonCodeMembersHolder>> compute() {
+ final Map<List<Map>, NonCodeMembersHolder> map = new ConcurrentSoftHashMap<List<Map>, NonCodeMembersHolder>();
return Result.create(map, PsiModificationTracker.MODIFICATION_COUNT);
}
});
@@ -59,22 +60,33 @@ public class NonCodeMembersHolder implements CustomMembersHolder {
return result;
}
- private NonCodeMembersHolder(Set<Map> data, PsiElement place) {
+ private NonCodeMembersHolder(List<Map> data, PsiElement place) {
final PsiManager manager = place.getManager();
for (Map prop : data) {
- if (prop.get("closure") == Boolean.TRUE) {
+ final Object decltype = prop.get("declarationType");
+ if (decltype == DeclarationType.CLOSURE) {
PsiElement closureDescriptor = createClosureDescriptor(prop, place, manager);
if (closureDescriptor != null) {
- myMethods.add(closureDescriptor);
+ myDeclarations.add(closureDescriptor);
}
}
+ else if (decltype == DeclarationType.VARIABLE) {
+ myDeclarations.add(createVariable(prop, place, manager));
+ }
else {
+ //declarationType == DeclarationType.METHOD
final PsiElement method = createMethod(prop, place, manager);
- myMethods.add(method);
+ myDeclarations.add(method);
}
}
}
+ private static PsiElement createVariable(Map prop, PsiElement place, PsiManager manager) {
+ String name = String.valueOf(prop.get("name"));
+ final String type = String.valueOf(prop.get("type"));
+ return new GrLightVariable(manager, name, type, Collections.<PsiElement>emptyList(), place.getContainingFile());
+ }
+
@Nullable
private static PsiElement createClosureDescriptor(Map prop, PsiElement place, PsiManager manager) {
final ClosureDescriptor closure = new ClosureDescriptor(manager);
@@ -189,7 +201,7 @@ public class NonCodeMembersHolder implements CustomMembersHolder {
}
public boolean processMembers(GroovyClassDescriptor descriptor, PsiScopeProcessor processor, ResolveState state) {
- for (PsiElement method : myMethods) {
+ for (PsiElement method : myDeclarations) {
if (!processor.execute(method, state)) {
return false;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/scopes/Scope.groovy b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/scopes/Scope.groovy
index 46f63f26d04e..8549d3655a46 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/scopes/Scope.groovy
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/scopes/Scope.groovy
@@ -1,15 +1,34 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.dsl.toplevel.scopes
-import com.intellij.patterns.PlatformPatterns
-import com.intellij.patterns.PsiJavaPatterns
-import com.intellij.patterns.StandardPatterns
import com.intellij.psi.SyntheticElement
import org.jetbrains.plugins.groovy.dsl.toplevel.*
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall
-import org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames
+
+import static com.intellij.patterns.PlatformPatterns.*
+import static com.intellij.patterns.PsiJavaPatterns.psiClass
+import static com.intellij.patterns.StandardPatterns.*
+import static org.jetbrains.plugins.groovy.lang.psi.patterns.GrAnnotationPattern.annotation
+import static org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns.groovyScript
+import static org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns.methodCall
+
/**
* @author ilyas
*/
@@ -26,11 +45,11 @@ class ClassScope extends Scope {
List<ContextFilter> createFilters(Map args) {
if (namePattern) {
- def match = PlatformPatterns.string().matches(namePattern)
- return [new PlaceContextFilter(PsiJavaPatterns.psiElement().inside(
- PlatformPatterns.or(
- PsiJavaPatterns.psiClass().withQualifiedName(match),
- PsiJavaPatterns.psiClass().withName(match))))]
+ def match = string().matches(namePattern)
+ return [new PlaceContextFilter(psiElement().inside(
+ or(
+ psiClass().withQualifiedName(match),
+ psiClass().withName(match))))]
}
return []
}
@@ -40,33 +59,49 @@ class ClassScope extends Scope {
class ClosureScope extends Scope {
private final boolean isArg
- private final boolean isTransparent
+
+ final String methodName
+ final String annotationName
ClosureScope(Map args) {
- isArg = args && args.isArgument ? args.isArgument : false
- isTransparent = args && args.transparent ? args.transparent : false
+ isArg = args?.isArgument
+ methodName = args?.methodName
+ annotationName = args?.annotationName
}
def isArg() {
isArg
}
- def transparent() {
- isTransparent
- }
-
List<ContextFilter> createFilters(Map args) {
def result = []
- result << new PlaceContextFilter(PsiJavaPatterns.psiElement().inside(GrClosableBlock))
+ result << new PlaceContextFilter(psiElement().inside(GrClosableBlock))
- if (((ClosureScope) args.scope).isArg()) {
- // Filter for call parameter
- result << new PlaceContextFilter(PsiJavaPatterns.psiElement().inside(
- PsiJavaPatterns.psiElement(GrClosableBlock).withParent(
- PlatformPatterns.or(
- PsiJavaPatterns.psiElement(GrCall),
- PsiJavaPatterns.psiElement(GrArgumentList).withParent(GrCall)))))
+ final scope = (ClosureScope)args.scope
+ if (scope.isArg()) {
+ result << new PlaceContextFilter(
+ psiElement().inside(
+ psiElement(GrClosableBlock).withParent(
+ or(
+ psiElement(GrCall),
+ psiElement(GrArgumentList).withParent(GrCall)))))
+ }
+
+ if (scope.methodName != null) {
+ result << new PlaceContextFilter(psiElement().inside(
+ psiElement(GrClosableBlock).withParent(
+ or(
+ methodCall().withMethodName(scope.methodName),
+ psiElement(GrArgumentList).withParent(
+ methodCall().withMethodName(scope.methodName))))))
+
+ }
+
+ if (scope.annotationName != null) {
+ result << new PlaceContextFilter(psiElement().inside(
+ psiElement(GrClosableBlock).inside(
+ annotation().withQualifiedName(scope.annotationName))))
}
// Enhance only unqualified expressions
@@ -87,7 +122,8 @@ class ScriptScope extends Scope {
if (args) {
if (args.name) {
namePattern = args.name
- } else if (args.extension) {
+ }
+ else if (args.extension) {
extension = args.extension
}
}
@@ -95,20 +131,20 @@ class ScriptScope extends Scope {
List<ContextFilter> createFilters(Map args) {
def result = []
- def scriptPattern = GroovyPatterns.groovyScript()
+ def scriptPattern = groovyScript()
if (extension) {
- scriptPattern = scriptPattern.withVirtualFile(PlatformPatterns.virtualFile().withExtension(extension))
+ scriptPattern = scriptPattern.withVirtualFile(virtualFile().withExtension(extension))
}
result << new FileContextFilter(scriptPattern)
// Name matcher
if (namePattern) {
- result << new FileContextFilter(PlatformPatterns.psiFile().withName(PlatformPatterns.string().matches(namePattern)))
+ result << new FileContextFilter(psiFile().withName(string().matches(namePattern)))
}
// Process unqualified references only
if (!args.ctype) {
- result << ClassContextFilter.fromClassPattern(PsiJavaPatterns.psiClass().and(StandardPatterns.instanceOf(SyntheticElement)))
+ result << ClassContextFilter.fromClassPattern(psiClass().and(instanceOf(SyntheticElement)))
}
return result
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyQuoteHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyQuoteHandler.java
index 18078968b3d4..a3abaa200b67 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyQuoteHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyQuoteHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,6 +63,7 @@ public class GroovyQuoteHandler implements MultiCharQuoteHandler {
final IElementType tokenType = iterator.getTokenType();
if (tokenType == mSTRING_LITERAL || tokenType == mGSTRING_BEGIN || tokenType == mGSTRING_LITERAL || tokenType == mGSTRING_CONTENT) {
final Document document = iterator.getDocument();
+ if (document == null) return false;
final String literal = document.getText().substring(iterator.getStart(), offset + 1);
if ("'''".equals(literal) || "\"\"\"".equals(literal) || "'".equals(literal) || "\"".equals(literal)) {
return true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinBlockStatementHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinBlockStatementHandler.java
new file mode 100644
index 000000000000..d88f034ae2b5
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinBlockStatementHandler.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.editor.actions.joinLines;
+
+import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate;
+import com.intellij.openapi.editor.Document;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
+
+public class GrJoinBlockStatementHandler implements JoinLinesHandlerDelegate {
+ @Override
+ public int tryJoinLines(Document document, PsiFile file, int start, int end) {
+ if (!(file instanceof GroovyFileBase)) return CANNOT_JOIN;
+
+ final PsiElement startElement = file.findElementAt(start);
+ if (startElement == null || startElement.getNode().getElementType() != GroovyTokenTypes.mLCURLY) return CANNOT_JOIN;
+
+ final PsiElement parent = startElement.getParent();
+ if (!(parent instanceof GrOpenBlock)) return CANNOT_JOIN;
+
+ final GrStatement[] statements = ((GrOpenBlock)parent).getStatements();
+ if (statements.length != 1) return CANNOT_JOIN;
+
+ final PsiElement parent1 = parent.getParent();
+ if (!(parent1 instanceof GrBlockStatement)) return CANNOT_JOIN;
+
+ final PsiElement parent2 = parent1.getParent();
+ if (!(parent2 instanceof GrIfStatement) && !(parent2 instanceof GrWhileStatement) && !(parent2 instanceof GrForStatement)) {
+ return CANNOT_JOIN;
+ }
+
+ final GrStatement statement = ((GrBlockStatement)parent1).replaceWithStatement(statements[0]);
+ return statement.getTextRange().getStartOffset();
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinControlStatementHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinControlStatementHandler.java
new file mode 100644
index 000000000000..f284f1baf27b
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinControlStatementHandler.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.editor.actions.joinLines;
+
+import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate;
+import com.intellij.openapi.editor.Document;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
+
+public class GrJoinControlStatementHandler implements JoinLinesHandlerDelegate {
+ @Override
+ public int tryJoinLines(Document document, PsiFile file, int start, int end) {
+ if (!(file instanceof GroovyFileBase)) return CANNOT_JOIN;
+
+ final PsiElement startElement = file.findElementAt(start);
+ if (startElement == null || !startElement.getNode().getElementType().equals(GroovyTokenTypes.mRPAREN)) return CANNOT_JOIN;
+
+ final PsiElement parent = startElement.getParent();
+ if (!(parent instanceof GrIfStatement || parent instanceof GrWhileStatement || parent instanceof GrForStatement)) return CANNOT_JOIN;
+
+ GrStatement inner;
+ if (parent instanceof GrIfStatement) {
+ inner = ((GrIfStatement)parent).getThenBranch();
+ }
+ else if (parent instanceof GrWhileStatement) {
+ inner = ((GrWhileStatement)parent).getBody();
+ }
+ else /*if (parent instanceof GrForStatement)*/ {
+ inner = ((GrForStatement)parent).getBody();
+ }
+
+
+ if (inner instanceof GrBlockStatement) return CANNOT_JOIN;
+
+ document.replaceString(start + 1, end, " ");
+ return start + 2;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinIfHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinIfHandler.java
deleted file mode 100644
index 642bf739d023..000000000000
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinIfHandler.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.plugins.groovy.editor.actions.joinLines;
-
-import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate;
-import com.intellij.openapi.editor.Document;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.util.PsiTreeUtil;
-import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
-import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
-
-public class GrJoinIfHandler implements JoinLinesHandlerDelegate {
- @Override
- public int tryJoinLines(Document document, PsiFile file, int start, int end) {
- if (!(file instanceof GroovyFileBase)) return CANNOT_JOIN;
-
- final PsiElement element = file.findElementAt(end);
-
- final GrStatementOwner statementOwner = PsiTreeUtil.getParentOfType(element, GrStatementOwner.class, true, GroovyFileBase.class);
- if (statementOwner == null) return CANNOT_JOIN;
- if (statementOwner.getStatements().length > 1) return CANNOT_JOIN;
-
- final PsiElement parent = statementOwner.getParent();
- if (!(parent instanceof GrBlockStatement)) return CANNOT_JOIN;
-
- final PsiElement pparent = parent.getParent();
- if (!(pparent instanceof GrIfStatement)) return CANNOT_JOIN;
-
- final GrIfStatement ifStatement = (GrIfStatement)pparent;
- if (parent == ifStatement.getThenBranch() || parent == ifStatement.getElseBranch()) {
- final GrStatement statement = ((GrBlockStatement)(parent)).replaceWithStatement(statementOwner.getStatements()[0]);
- return statement.getTextRange().getStartOffset();
- }
-
- return CANNOT_JOIN;
- }
-}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinStatementsHandler.groovy b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinStatementsHandler.groovy
deleted file mode 100644
index de02367ac38f..000000000000
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinStatementsHandler.groovy
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.plugins.groovy.editor.actions.joinLines
-
-import com.intellij.psi.PsiDocumentManager
-import org.jetbrains.annotations.NotNull
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement
-import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil
-
-/**
- * @author Max Medvedev
- */
-class GrJoinStatementsHandler extends GrJoinLinesHandlerBase {
- @Override
- int tryJoinStatements(@NotNull GrStatement first, @NotNull GrStatement second) {
- final semi = PsiImplUtil.findTailingSemicolon(first)
-
- final document = PsiDocumentManager.getInstance(first.project).getDocument(first.containingFile)
- final endOffset = second.textRange.startOffset
- if (semi != null) {
- final offset = semi.textRange.endOffset
- document.replaceString(offset, endOffset, ' ')
- return offset + 1
- }
- else {
- final offset = first.textRange.endOffset
- document.replaceString(offset, endOffset, '; ')
- return offset + 2
- }
- }
-}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinStatementsHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinStatementsHandler.java
new file mode 100644
index 000000000000..f63bbb278b75
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/joinLines/GrJoinStatementsHandler.java
@@ -0,0 +1,48 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.editor.actions.joinLines;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
+
+/**
+ * @author Max Medvedev
+ */
+public class GrJoinStatementsHandler extends GrJoinLinesHandlerBase {
+ @Override
+ public int tryJoinStatements(@NotNull GrStatement first, @NotNull GrStatement second) {
+ final PsiElement semi = PsiImplUtil.findTailingSemicolon(first);
+
+ final Document document = PsiDocumentManager.getInstance(first.getProject()).getDocument(first.getContainingFile());
+ if (document == null) return CANNOT_JOIN;
+ final Integer endOffset = second.getTextRange().getStartOffset();
+ if (semi != null) {
+ final Integer offset = semi.getTextRange().getEndOffset();
+ document.replaceString(offset, endOffset, " ");
+ return offset + 1;
+ }
+ else {
+ final Integer offset = first.getTextRange().getEndOffset();
+ document.replaceString(offset, endOffset, "; ");
+ return offset + 2;
+ }
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java
index be6a13004210..d74aa376831c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java
@@ -144,7 +144,7 @@ public class AntTasksProvider {
private final Future<Map<String, Class>> myFuture;
public AntClassLoader(ArrayList<URL> urls) {
- super(urls, null, false, false, true);
+ super(urls, null, false, false, true, false);
myFuture = ApplicationManager.getApplication().executeOnPooledThread(new Callable<Map<String, Class>>() {
@Override
public Map<String, Class> call() throws Exception {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java
index 97cfcbd8b33a..7c8714897b5b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.dsl.toplevel.AnnotatedContextFilter;
import org.jetbrains.plugins.groovy.findUsages.LiteralConstructorReference;
-import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
@@ -31,6 +30,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrTypeConverter;
/**
* @author peter
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonToolWindowFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonToolWindowFactory.java
index c7b7f8ee44dd..35666cd98c42 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonToolWindowFactory.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonToolWindowFactory.java
@@ -16,13 +16,13 @@
package org.jetbrains.plugins.groovy.griffon;
+import com.intellij.icons.AllIcons;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
@@ -137,16 +137,12 @@ public class GriffonToolWindowFactory extends MvcToolWindowDescriptor {
private static final Map<String, GriffonDirectoryMetadata> DIRECTORY_METADATA = new LinkedHashMap<String, GriffonDirectoryMetadata>();
static {
- DIRECTORY_METADATA.put("models", new GriffonDirectoryMetadata("Models", loadIcon("folder-models"), 20));
- DIRECTORY_METADATA.put("views", new GriffonDirectoryMetadata("Views", loadIcon("folder-views"), 30));
- DIRECTORY_METADATA.put("controllers", new GriffonDirectoryMetadata("Controllers", loadIcon("folder-controllers"), 40));
- DIRECTORY_METADATA.put("services", new GriffonDirectoryMetadata("Services", loadIcon("folder-services"), 50));
- DIRECTORY_METADATA.put("lifecycle", new GriffonDirectoryMetadata("Lifecycle", loadIcon("folder-lifecycle"), 60));
- DIRECTORY_METADATA.put("conf", new GriffonDirectoryMetadata("Configuration", loadIcon("folder-conf"), 65));
- }
-
- private static Icon loadIcon(String name) {
- return IconLoader.getIcon("/icons/griffon/" + name + ".png");
+ DIRECTORY_METADATA.put("models", new GriffonDirectoryMetadata("Models", JetgroovyIcons.Mvc.ModelsNode, 20));
+ DIRECTORY_METADATA.put("views", new GriffonDirectoryMetadata("Views", JetgroovyIcons.Groovy.Groovy_16x16, 30));
+ DIRECTORY_METADATA.put("controllers", new GriffonDirectoryMetadata("Controllers", AllIcons.Nodes.KeymapTools, 40));
+ DIRECTORY_METADATA.put("services", new GriffonDirectoryMetadata("Services", JetgroovyIcons.Mvc.Service, 50));
+ DIRECTORY_METADATA.put("lifecycle", new GriffonDirectoryMetadata("Lifecycle", JetgroovyIcons.Groovy.Groovy_16x16, 60));
+ DIRECTORY_METADATA.put("conf", new GriffonDirectoryMetadata("Configuration", JetgroovyIcons.Mvc.Config_folder_closed, 65));
}
private static class GriffonDirectoryMetadata {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/DefaultHighlighter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/DefaultHighlighter.java
index 84f16ad06749..4bde4d6628d8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/DefaultHighlighter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/highlighter/DefaultHighlighter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,8 +17,9 @@
package org.jetbrains.plugins.groovy.highlighter;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
+import com.intellij.ide.highlighter.JavaHighlightingColors;
+import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.editor.HighlighterColors;
-import com.intellij.openapi.editor.SyntaxHighlighterColors;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.EffectType;
@@ -92,62 +93,58 @@ public class DefaultHighlighter {
static final String LABEL_ID = "Label";
public static final TextAttributesKey LINE_COMMENT =
- TextAttributesKey.createTextAttributesKey(LINE_COMMENT_ID, SyntaxHighlighterColors.LINE_COMMENT.getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(LINE_COMMENT_ID, DefaultLanguageHighlighterColors.LINE_COMMENT);
public static final TextAttributesKey ANNOTATION =
- TextAttributesKey.createTextAttributesKey(ANNOTATION_ID, HighlightInfoType.ANNOTATION_NAME.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(ANNOTATION_ID, HighlightInfoType.ANNOTATION_NAME.getAttributesKey());
public static final TextAttributesKey LOCAL_VARIABLE =
- TextAttributesKey.createTextAttributesKey("Groovy var", HighlightInfoType.LOCAL_VARIABLE.getAttributesKey().getDefaultAttributes());
-
- public static final TextAttributesKey REASSIGNED_LOCAL_VARIABLE =
- TextAttributesKey.createTextAttributesKey("Groovy reassigned var",
- HighlightInfoType.REASSIGNED_LOCAL_VARIABLE.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey("Groovy var", HighlightInfoType.LOCAL_VARIABLE.getAttributesKey());
+ public static final TextAttributesKey REASSIGNED_LOCAL_VARIABLE =
+ TextAttributesKey.createTextAttributesKey("Groovy reassigned var", HighlightInfoType.REASSIGNED_LOCAL_VARIABLE.getAttributesKey());
+
public static final TextAttributesKey PARAMETER =
- TextAttributesKey.createTextAttributesKey("Groovy parameter", HighlightInfoType.PARAMETER.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey("Groovy parameter", HighlightInfoType.PARAMETER.getAttributesKey());
public static final TextAttributesKey REASSIGNED_PARAMETER =
- TextAttributesKey.createTextAttributesKey("Groovy reassigned parameter",
- HighlightInfoType.REASSIGNED_PARAMETER.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey("Groovy reassigned parameter", HighlightInfoType.REASSIGNED_PARAMETER.getAttributesKey());
public static final TextAttributesKey METHOD_DECLARATION =
- TextAttributesKey.createTextAttributesKey("Groovy method declaration",
- HighlightInfoType.METHOD_DECLARATION.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey("Groovy method declaration", HighlightInfoType.METHOD_DECLARATION.getAttributesKey());
public static final TextAttributesKey CONSTRUCTOR_DECLARATION = TextAttributesKey
- .createTextAttributesKey("Groovy constructor declaration",
- HighlightInfoType.CONSTRUCTOR_DECLARATION.getAttributesKey().getDefaultAttributes());
+ .createTextAttributesKey("Groovy constructor declaration", HighlightInfoType.CONSTRUCTOR_DECLARATION.getAttributesKey());
public static final TextAttributesKey INSTANCE_FIELD =
- TextAttributesKey.createTextAttributesKey(INSTANCE_FIELD_ID, HighlightInfoType.INSTANCE_FIELD.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(INSTANCE_FIELD_ID, HighlightInfoType.INSTANCE_FIELD.getAttributesKey());
public static final TextAttributesKey METHOD_CALL =
- TextAttributesKey.createTextAttributesKey(METHOD_CALL_ID, HighlightInfoType.METHOD_CALL.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(METHOD_CALL_ID, HighlightInfoType.METHOD_CALL.getAttributesKey());
public static final TextAttributesKey CONSTRUCTOR_CALL = TextAttributesKey
- .createTextAttributesKey("Groovy constructor call", HighlightInfoType.CONSTRUCTOR_CALL.getAttributesKey().getDefaultAttributes());
+ .createTextAttributesKey("Groovy constructor call", HighlightInfoType.CONSTRUCTOR_CALL.getAttributesKey());
public static final TextAttributesKey STATIC_FIELD =
- TextAttributesKey.createTextAttributesKey(STATIC_FIELD_ID, HighlightInfoType.STATIC_FINAL_FIELD.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(STATIC_FIELD_ID, HighlightInfoType.STATIC_FINAL_FIELD.getAttributesKey());
public static final TextAttributesKey STATIC_METHOD_ACCESS =
- TextAttributesKey.createTextAttributesKey(STATIC_METHOD_ACCESS_ID, HighlightInfoType.STATIC_METHOD.getAttributesKey().getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(STATIC_METHOD_ACCESS_ID, HighlightInfoType.STATIC_METHOD.getAttributesKey());
public static final TextAttributesKey BLOCK_COMMENT =
- TextAttributesKey.createTextAttributesKey(BLOCK_COMMENT_ID, SyntaxHighlighterColors.JAVA_BLOCK_COMMENT.getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(BLOCK_COMMENT_ID, JavaHighlightingColors.JAVA_BLOCK_COMMENT);
public static final TextAttributesKey DOC_COMMENT_CONTENT =
- TextAttributesKey.createTextAttributesKey(DOC_COMMENT_ID, SyntaxHighlighterColors.DOC_COMMENT.getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(DOC_COMMENT_ID, JavaHighlightingColors.DOC_COMMENT);
public static final TextAttributesKey DOC_COMMENT_TAG =
- TextAttributesKey.createTextAttributesKey(DOC_COMMENT_TAG_ID, SyntaxHighlighterColors.DOC_COMMENT_TAG.getDefaultAttributes());
+ TextAttributesKey.createTextAttributesKey(DOC_COMMENT_TAG_ID, JavaHighlightingColors.DOC_COMMENT_TAG);
public static final TextAttributesKey CLASS_REFERENCE =
- TextAttributesKey.createTextAttributesKey(CLASS_REFERENCE_ID, HighlighterColors.TEXT.getDefaultAttributes().clone());
+ TextAttributesKey.createTextAttributesKey(CLASS_REFERENCE_ID, HighlighterColors.TEXT);
public static final TextAttributesKey TYPE_PARAMETER =
- TextAttributesKey.createTextAttributesKey(TYPE_PARAMETER_ID, CodeInsightColors.TYPE_PARAMETER_NAME_ATTRIBUTES.getDefaultAttributes().clone());
+ TextAttributesKey.createTextAttributesKey(TYPE_PARAMETER_ID, CodeInsightColors.TYPE_PARAMETER_NAME_ATTRIBUTES);
public static final TextAttributes INSTANCE_PROPERTY_REFERENCE_ATTRIBUTES = INSTANCE_FIELD.getDefaultAttributes().clone();
public static final TextAttributes STATIC_PROPERTY_REFERENCE_ATTRIBUTES = STATIC_FIELD.getDefaultAttributes().clone();
@@ -162,75 +159,64 @@ public class DefaultHighlighter {
public static final TextAttributesKey STATIC_PROPERTY_REFERENCE =
TextAttributesKey.createTextAttributesKey(STATIC_PROPERTY_REFERENCE_ID, STATIC_PROPERTY_REFERENCE_ATTRIBUTES);
- public static final TextAttributes KEYWORD_ATTRIBUTES = SyntaxHighlighterColors.KEYWORD.getDefaultAttributes().clone();
+ public static final TextAttributes KEYWORD_ATTRIBUTES = JavaHighlightingColors.KEYWORD.getDefaultAttributes().clone();
public static final TextAttributesKey KEYWORD = TextAttributesKey.createTextAttributesKey("GROOVY_" + KEYWORD_ID.toUpperCase(), KEYWORD_ATTRIBUTES);
static {
- KEYWORD_ATTRIBUTES.setForegroundColor(new Color(0, 0, 67));
+ KEYWORD_ATTRIBUTES.setForegroundColor(new JBColor(new Color(0, 0, 67), new Color(0, 0, 67)));
KEYWORD_ATTRIBUTES.setFontType(Font.BOLD);
}
- public static final TextAttributesKey NUMBER =
- TextAttributesKey.createTextAttributesKey(NUMBER_ID, SyntaxHighlighterColors.NUMBER.getDefaultAttributes());
+ public static final TextAttributesKey NUMBER = TextAttributesKey.createTextAttributesKey(NUMBER_ID, JavaHighlightingColors.NUMBER);
- public static final TextAttributesKey GSTRING =
- TextAttributesKey.createTextAttributesKey(GSTRING_ID, SyntaxHighlighterColors.STRING.getDefaultAttributes());
+ public static final TextAttributesKey GSTRING = TextAttributesKey.createTextAttributesKey(GSTRING_ID, JavaHighlightingColors.STRING);
- public static final TextAttributesKey STRING =
- TextAttributesKey.createTextAttributesKey(STRING_ID, SyntaxHighlighterColors.STRING.getDefaultAttributes());
+ public static final TextAttributesKey STRING = TextAttributesKey.createTextAttributesKey(STRING_ID, JavaHighlightingColors.STRING);
- public static final TextAttributesKey BRACES =
- TextAttributesKey.createTextAttributesKey(BRACES_ID, SyntaxHighlighterColors.BRACES.getDefaultAttributes());
+ public static final TextAttributesKey BRACES = TextAttributesKey.createTextAttributesKey(BRACES_ID, JavaHighlightingColors.BRACES);
- public static final TextAttributesKey BRACKETS =
- TextAttributesKey.createTextAttributesKey(BRACKETS_ID, SyntaxHighlighterColors.BRACKETS.getDefaultAttributes());
+ public static final TextAttributesKey BRACKETS = TextAttributesKey.createTextAttributesKey(BRACKETS_ID, JavaHighlightingColors.BRACKETS);
- public static final TextAttributesKey PARENTHESES =
- TextAttributesKey.createTextAttributesKey(PARENTHESES_ID, SyntaxHighlighterColors.PARENTHS.getDefaultAttributes());
+ public static final TextAttributesKey PARENTHESES = TextAttributesKey.createTextAttributesKey(PARENTHESES_ID, JavaHighlightingColors.PARENTHS);
- public static final TextAttributesKey OPERATION_SIGN =
- TextAttributesKey.createTextAttributesKey(OPERATION_SIGN_ID, SyntaxHighlighterColors.OPERATION_SIGN.getDefaultAttributes());
+ public static final TextAttributesKey OPERATION_SIGN = TextAttributesKey.createTextAttributesKey(OPERATION_SIGN_ID, JavaHighlightingColors.OPERATION_SIGN);
- public static final TextAttributesKey BAD_CHARACTER =
- TextAttributesKey.createTextAttributesKey(BAD_CHARACTER_ID, CodeInsightColors.UNMATCHED_BRACE_ATTRIBUTES.getDefaultAttributes());
+ public static final TextAttributesKey BAD_CHARACTER = TextAttributesKey.createTextAttributesKey(BAD_CHARACTER_ID, CodeInsightColors.UNMATCHED_BRACE_ATTRIBUTES);
public static final TextAttributes UNRESOLVED_ACCESS_ATTRIBUTES = HighlighterColors.TEXT.getDefaultAttributes().clone();
static {
- UNRESOLVED_ACCESS_ATTRIBUTES.setForegroundColor(Color.BLACK);
+ UNRESOLVED_ACCESS_ATTRIBUTES.setForegroundColor(JBColor.BLACK);
UNRESOLVED_ACCESS_ATTRIBUTES.setEffectColor(JBColor.GRAY);
UNRESOLVED_ACCESS_ATTRIBUTES.setEffectType(EffectType.LINE_UNDERSCORE);
}
+ public static final TextAttributesKey UNRESOLVED_ACCESS =
+ TextAttributesKey.createTextAttributesKey(UNRESOLVED_ACCESS_ID, UNRESOLVED_ACCESS_ATTRIBUTES);
+
+
public static final TextAttributes LITERAL_CONVERSION_ATTRIBUTES = HighlighterColors.TEXT.getDefaultAttributes().clone();
static{
LITERAL_CONVERSION_ATTRIBUTES.setForegroundColor(PlatformColors.BLUE);
LITERAL_CONVERSION_ATTRIBUTES.setFontType(Font.BOLD);
}
+ public static final TextAttributesKey LITERAL_CONVERSION =
+ TextAttributesKey.createTextAttributesKey(LITERAL_CONVERSION_ID, LITERAL_CONVERSION_ATTRIBUTES);
+
+
public static final TextAttributes MAP_KEY_ATTRIBUTES = HighlighterColors.TEXT.getDefaultAttributes().clone();
- public static final Color MAP_KEY_COLOR = new Color(0, 128, 0);
+ public static final Color MAP_KEY_COLOR = new JBColor(new Color(0, 128, 0), new Color(0, 128, 0));
static {
MAP_KEY_ATTRIBUTES.setForegroundColor(MAP_KEY_COLOR);
}
-
- public static final TextAttributesKey UNRESOLVED_ACCESS =
- TextAttributesKey.createTextAttributesKey(UNRESOLVED_ACCESS_ID, UNRESOLVED_ACCESS_ATTRIBUTES);
-
- public static final TextAttributesKey LITERAL_CONVERSION =
- TextAttributesKey.createTextAttributesKey(LITERAL_CONVERSION_ID, LITERAL_CONVERSION_ATTRIBUTES);
-
public static final TextAttributesKey MAP_KEY = TextAttributesKey.createTextAttributesKey(MAP_KEY_ID, MAP_KEY_ATTRIBUTES);
- public static final TextAttributesKey VALID_STRING_ESCAPE =
- TextAttributesKey.createTextAttributesKey(VALID_STRING_ESCAPE_ID, SyntaxHighlighterColors.VALID_STRING_ESCAPE.getDefaultAttributes());
-
- public static final TextAttributesKey INVALID_STRING_ESCAPE =
- TextAttributesKey.createTextAttributesKey(INVALID_STRING_ESCAPE_ID, SyntaxHighlighterColors.INVALID_STRING_ESCAPE.getDefaultAttributes());
+ public static final TextAttributesKey VALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey(VALID_STRING_ESCAPE_ID, JavaHighlightingColors.VALID_STRING_ESCAPE);
- public static final TextAttributes LABEL_ATTRIBUTES = HighlighterColors.TEXT.getDefaultAttributes().clone();
+ public static final TextAttributesKey INVALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey(INVALID_STRING_ESCAPE_ID, JavaHighlightingColors.INVALID_STRING_ESCAPE);
- public static final TextAttributesKey LABEL = TextAttributesKey.createTextAttributesKey(LABEL_ID, LABEL_ATTRIBUTES);
+ public static final TextAttributesKey LABEL = TextAttributesKey.createTextAttributesKey(LABEL_ID, HighlighterColors.TEXT);
private DefaultHighlighter() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java
index 0996226b84ef..5dfd7a7b011c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java
@@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil;
import org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle;
import org.jetbrains.plugins.groovy.intentions.utils.BoolUtils;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
@@ -83,6 +84,10 @@ public abstract class Intention implements IntentionAction {
@Nullable
PsiElement findMatchingElement(PsiFile file, Editor editor) {
+ if (!(file instanceof GroovyFileBase)) {
+ return null;
+ }
+
SelectionModel selectionModel = editor.getSelectionModel();
if (selectionModel.hasSelection()) {
TextRange selectionRange = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java
index 8e3ae1edd75b..685988719f43 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java
@@ -139,7 +139,9 @@ public class IntentionUtils {
if (hasNoReturnType) {
((GrMethod)method).setReturnType(PsiType.VOID);
}
- CreateFromUsageUtils.setupMethodBody(method);
+ if (method.getBody() != null) {
+ CreateFromUsageUtils.setupMethodBody(method);
+ }
if (hasNoReturnType) {
((GrMethod)method).setReturnType(null);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/EachToForIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/EachToForIntention.java
index 7c89cb30a20e..f62f6b7b3852 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/EachToForIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/EachToForIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -123,7 +123,7 @@ public class EachToForIntention extends Intention {
final GrExpression invokedExpression = expression.getInvokedExpression();
if (invokedExpression instanceof GrReferenceExpression) {
GrReferenceExpression referenceExpression = (GrReferenceExpression)invokedExpression;
- if ("each".equals(referenceExpression.getName())) {
+ if ("each".equals(referenceExpression.getReferenceName())) {
final GrArgumentList argumentList = expression.getArgumentList();
if (argumentList != null) {
if (PsiImplUtil.hasExpressionArguments(argumentList)) return false;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertClosureToMethodIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertClosureToMethodIntention.java
index b07b84e65567..660377d7ecb1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertClosureToMethodIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertClosureToMethodIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -187,7 +187,7 @@ public class ConvertClosureToMethodIntention extends Intention {
StringBuilder newRefText = new StringBuilder();
if (parent instanceof GrReferenceExpression &&
usage == ((GrReferenceExpression)parent).getQualifier() &&
- "call".equals(((GrReferenceExpression)parent).getName())) {
+ "call".equals(((GrReferenceExpression)parent).getReferenceName())) {
newRefText.append(usage.getText());
usage = parent;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionIntention.java
index 54bd5373c3ac..e0094ab31f62 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ public class IndexingMethodConversionIntention extends Intention {
GrReferenceExpression methodExpression = (GrReferenceExpression) callExpression.getInvokedExpression();
final IElementType referenceType = methodExpression.getDotTokenType();
- final String methodName = methodExpression.getName();
+ final String methodName = methodExpression.getReferenceName();
final GrExpression qualifier = methodExpression.getQualifierExpression();
if("getAt".equals(methodName)|| "get".equals(methodName))
{
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionPredicate.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionPredicate.java
index ea88baeaba19..2aa3a1ac06df 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionPredicate.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/IndexingMethodConversionPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@ class IndexingMethodConversionPredicate implements PsiElementPredicate {
if (!GroovyTokenTypes.mDOT.equals(referenceType)) {
return false;
}
- final String methodName = referenceExpression.getName();
+ final String methodName = referenceExpression.getReferenceName();
if ("getAt".equals(methodName)) {
return arguments.length == 1;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java
index eb2350b0568b..c7c9afaada9e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrSetStrongTypeIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,10 +23,7 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiClassType;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,12 +33,16 @@ import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint;
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression;
@@ -70,6 +71,10 @@ public class GrSetStrongTypeIntention extends Intention {
variables = ((GrVariableDeclaration)parent).getVariables();
elementToBuildTemplate = parent;
}
+ else if (parent instanceof GrParameter && parent.getParent() instanceof GrParameterList) {
+ variables = new GrVariable[]{(GrVariable)parent};
+ elementToBuildTemplate = parent.getParent().getParent();
+ }
else if (parent instanceof GrVariable) {
variables = new GrVariable[]{((GrVariable)parent)};
elementToBuildTemplate = parent;
@@ -92,6 +97,13 @@ public class GrSetStrongTypeIntention extends Intention {
types.add(SupertypeConstraint.create(type));
}
}
+ if (variable instanceof GrParameter) {
+ final PsiParameter parameter = (PsiParameter)variable;
+ final PsiType type = getClosureParameterType(parameter);
+ if (type != null) {
+ types.add(SupertypeConstraint.create(type));
+ }
+ }
}
}
@@ -117,6 +129,19 @@ public class GrSetStrongTypeIntention extends Intention {
}
@Nullable
+ private static PsiType getClosureParameterType(@NotNull PsiParameter parameter) {
+ final PsiElement scope = parameter.getDeclarationScope();
+ final PsiType type;
+ if (scope instanceof GrClosableBlock) {
+ type = ClosureParameterEnhancer.inferType((GrClosableBlock)scope, ((GrParameterList)parameter.getParent()).getParameterIndex(parameter));
+ }
+ else {
+ type = null;
+ }
+ return type;
+ }
+
+ @Nullable
private static PsiElement setType(PsiElement element, PsiElement parent, PsiElement elementToBuildTemplate) {
GrModifierList modifierList = getModifierList(parent);
@@ -187,6 +212,9 @@ public class GrSetStrongTypeIntention extends Intention {
else if (pparent instanceof GrForInClause) {
return PsiUtil.extractIteratedType((GrForInClause)pparent) != null;
}
+ else if (parent instanceof GrParameter && pparent instanceof GrParameterList) {
+ return getClosureParameterType((PsiParameter)parent) != null;
+ }
else {
return isVarDeclaredWithInitializer((GrVariable)parent);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java
index 1e26f828be24..10b3b40ba281 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.intentions.base.ErrorUtil;
import org.jetbrains.plugins.groovy.intentions.base.Intention;
import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
@@ -48,7 +49,7 @@ public class JavaStylePropertiesInvocationIntention extends Intention {
protected PsiElementPredicate getElementPredicate() {
return new PsiElementPredicate() {
public boolean satisfiedBy(PsiElement element) {
- return element instanceof GrMethodCall && isPropertyAccessor((GrMethodCall)element);
+ return element instanceof GrMethodCall && isPropertyAccessor((GrMethodCall)element) && !ErrorUtil.containsError(element);
}
};
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java
index 6ee3abe0e160..48e774c04e0e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -219,7 +219,7 @@ public class ConvertParameterToMapEntryIntention extends Intention {
if (resolved instanceof PsiMethod &&
GroovyPropertyUtils.isSimplePropertyGetter(((PsiMethod)resolved)) &&
//check for explicit getter call
- ((PsiMethod)resolved).getName().equals(refExpr.getName())) {
+ ((PsiMethod)resolved).getName().equals(refExpr.getReferenceName())) {
isExplicitGetterCall = true;
}
}
@@ -239,7 +239,7 @@ public class ConvertParameterToMapEntryIntention extends Intention {
PsiElement parent = refExpr.getParent();
LOG.assertTrue(parent instanceof GrCall);
parent = parent.getParent();
- if (parent instanceof GrReferenceExpression && "call".equals(((GrReferenceExpression)parent).getName())) {
+ if (parent instanceof GrReferenceExpression && "call".equals(((GrReferenceExpression)parent).getReferenceName())) {
parent = parent.getParent();
}
if (parent instanceof GrCall) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyClassNameInsertHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyClassNameInsertHandler.java
index c13b8aecec70..73f173928343 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyClassNameInsertHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyClassNameInsertHandler.java
@@ -100,12 +100,16 @@ public class GroovyClassNameInsertHandler implements InsertHandler<JavaPsiClassR
PsiArrayType.class) == null;
}
- private static boolean isInVariable(PsiElement position) {
+ private static boolean isInVariable(@Nullable PsiElement position) {
+ if (position == null) {
+ return false;
+ }
+
final PsiElement parent = position.getParent();
if (parent instanceof GrVariable) {
return ((GrVariable)parent).getTypeElementGroovy() == null && position == ((GrVariable)parent).getNameIdentifierGroovy();
}
- if (parent instanceof GrCatchClause) {
+ if (parent instanceof GrCatchClause) {
return ((GrCatchClause)parent).getParameter() == null;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java
index e7b442a4dfd1..dd7783ebd4b0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -457,10 +457,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
return;
}
- if (object instanceof GrReferenceExpression && unresolvedProps.contains(((GrReferenceExpression)object).getName())) {
- return;
- }
-
if (object instanceof PsiMember && JavaCompletionUtil.isInExcludedPackage((PsiMember)object, true)) {
return;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyReferenceCharFilter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyReferenceCharFilter.java
index 5d0eadef2bc2..6a7eb1dadd96 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyReferenceCharFilter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyReferenceCharFilter.java
@@ -15,11 +15,9 @@
*/
package org.jetbrains.plugins.groovy.lang.completion;
-import com.intellij.codeInsight.completion.JavaCharFilter;
import com.intellij.codeInsight.lookup.CharFilter;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.patterns.StandardPatterns;
import com.intellij.psi.*;
import org.jetbrains.annotations.Nullable;
@@ -72,7 +70,7 @@ public class GroovyReferenceCharFilter extends CharFilter {
}
- if (c == '[') return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP;
+ if (c == '[' || c == ']' || c == ')' || c == '>') return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP;
if (c == '<' && item.getObject() instanceof PsiClass) return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
if (c == '(' && PsiKeyword.RETURN.equals(item.getLookupString())) {
return Result.HIDE_LOOKUP;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/GroovySmartEnterProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/GroovySmartEnterProcessor.java
index 271691826c66..ae33968fae0e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/GroovySmartEnterProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/GroovySmartEnterProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,15 +31,18 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.completion.smartEnter.fixers.*;
import org.jetbrains.plugins.groovy.lang.completion.smartEnter.processors.GroovyPlainEnterProcessor;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
-import org.jetbrains.plugins.groovy.lang.psi.api.formatter.GrControlStatement;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrCatchClause;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrForStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrSwitchStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.ArrayList;
import java.util.Arrays;
@@ -85,6 +88,7 @@ public class GroovySmartEnterProcessor extends SmartEnterProcessorWithFixers {
new GrWhileBodyFixer(),
new GrForBodyFixer(),
new GrSwitchBodyFixer(),
+ new GrSynchronizedFixer(),
new GrListFixer(),
new GrMethodCallWithSingleClosureArgFixer()
);
@@ -136,48 +140,25 @@ public class GroovySmartEnterProcessor extends SmartEnterProcessorWithFixers {
@Override
public boolean doNotStepInto(PsiElement element) {
- return element instanceof PsiClass || element instanceof GrCodeBlock || element instanceof GrStatement || element instanceof GrMethod;
+ return element instanceof PsiClass ||
+ element instanceof GrCodeBlock ||
+ element instanceof GrStatement && !(element instanceof GrExpression) ||
+ PsiUtil.isExpressionStatement(element) ||
+ element instanceof GrMethod;
}
@Nullable
protected PsiElement getStatementAtCaret(Editor editor, PsiFile psiFile) {
- final PsiElement atCaret = super.getStatementAtCaret(editor, psiFile);
+ PsiElement atCaret = super.getStatementAtCaret(editor, psiFile);
if (atCaret instanceof PsiWhiteSpace) return null;
- if (atCaret == null) return null;
- GrCodeBlock codeBlock = PsiTreeUtil.getParentOfType(atCaret, GrCodeBlock.class, false, GrControlStatement.class);
- if (codeBlock instanceof GrClosableBlock && "{}".equals(codeBlock.getText())) {
- codeBlock = PsiTreeUtil.getParentOfType(codeBlock, GrCodeBlock.class, true, GrControlStatement.class);
- }
- if (codeBlock != null) {
- for (GrStatement statement : codeBlock.getStatements()) {
- if (PsiTreeUtil.isAncestor(statement, atCaret, true)) {
- return statement;
- }
- }
- }
-
- PsiElement statementAtCaret = PsiTreeUtil.getParentOfType(atCaret,
- GrStatement.class,
- GrCodeBlock.class,
- PsiMember.class,
- GrDocComment.class
- );
-
- if (statementAtCaret instanceof GrBlockStatement) return null;
- if (statementAtCaret == null) return null;
-
- GrControlStatement controlStatement = PsiTreeUtil.getParentOfType(statementAtCaret, GrControlStatement.class, false);
-
- if (controlStatement != null && !PsiTreeUtil.hasErrorElements(statementAtCaret)) {
- return controlStatement;
+ while (atCaret != null && !PsiUtil.isExpressionStatement(atCaret)) {
+ if (atCaret instanceof PsiMethod || atCaret instanceof GrDocComment) return atCaret;
+ atCaret = atCaret.getParent();
}
- return statementAtCaret instanceof GrStatement ||
- statementAtCaret instanceof GrMember
- ? statementAtCaret
- : null;
+ return atCaret;
}
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrListFixer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrListFixer.java
index 0be759c94688..01298d8c06f7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrListFixer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrListFixer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,9 +20,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.completion.smartEnter.GroovySmartEnterProcessor;
-import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
-import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
/**
* @author Maxim.Medvedev
@@ -30,10 +28,10 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
public class GrListFixer extends SmartEnterProcessorWithFixers.Fixer<GroovySmartEnterProcessor> {
@Override
public void apply(@NotNull Editor editor, @NotNull GroovySmartEnterProcessor processor, @NotNull PsiElement psiElement) {
- if (psiElement.getParent() instanceof GrListOrMap) {
- final PsiElement next = PsiUtil.skipWhitespacesAndComments(psiElement.getNextSibling(), true);
- if (next != null && !GroovyTokenTypes.mCOMMA.equals(next.getNode().getElementType())) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), ",");
+ if (psiElement instanceof GrListOrMap) {
+ final PsiElement brack = ((GrListOrMap)psiElement).getRBrack();
+ if (brack == null) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "]");
}
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrSynchronizedFixer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrSynchronizedFixer.java
new file mode 100644
index 000000000000..aeffca7f9d8a
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/fixers/GrSynchronizedFixer.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.completion.smartEnter.fixers;
+
+import com.intellij.lang.SmartEnterProcessorWithFixers;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.completion.smartEnter.GroovySmartEnterProcessor;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrSynchronizedStatement;
+
+public class GrSynchronizedFixer extends SmartEnterProcessorWithFixers.Fixer<GroovySmartEnterProcessor> {
+ public void apply(@NotNull Editor editor, @NotNull GroovySmartEnterProcessor processor, @NotNull PsiElement psiElement) {
+ GrSynchronizedStatement synchronizedStatement = PsiTreeUtil.getParentOfType(psiElement, GrSynchronizedStatement.class);
+ if (synchronizedStatement == null || synchronizedStatement.getBody() != null) return;
+
+ if (!PsiTreeUtil.isAncestor(synchronizedStatement.getMonitor(), psiElement, false)) return;
+
+
+ final Document doc = editor.getDocument();
+
+ PsiElement eltToInsertAfter = synchronizedStatement.getRParenth();
+ String text = "{\n}";
+ if (eltToInsertAfter == null) {
+ eltToInsertAfter = synchronizedStatement.getMonitor();
+ text = "){\n}";
+ }
+
+ doc.insertString(eltToInsertAfter.getTextRange().getEndOffset(), text);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java
index c7a83f888d97..1de03b3f9afb 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,8 @@ import com.intellij.codeInsight.completion.CompletionWeigher;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.light.LightElement;
-import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
@@ -96,9 +96,9 @@ public class GrKindWeigher extends CompletionWeigher {
final GrAnnotation annotation = PsiTreeUtil.getParentOfType(position, GrAnnotation.class);
if (annotation != null) {
PsiElement annoParent = annotation.getParent();
- PsiElement owner = annoParent.getParent();
- String[] elementTypeFields = GrAnnotationImpl.getApplicableElementTypeFields(annoParent instanceof PsiModifierList ? owner : annoParent);
- if (PsiAnnotationImpl.isAnnotationApplicable(false, (PsiClass)o, elementTypeFields, position.getResolveScope())) {
+ PsiElement ownerToUse = annoParent instanceof PsiModifierList ? annoParent.getParent() : annoParent;
+ PsiAnnotation.TargetType[] elementTypeFields = GrAnnotationImpl.getApplicableElementTypeFields(ownerToUse);
+ if (PsiImplUtil.findApplicableTarget((PsiClass)o, elementTypeFields) != null) {
return NotQualifiedKind.restrictedClass;
}
}
@@ -149,11 +149,11 @@ public class GrKindWeigher extends CompletionWeigher {
final PsiClass containingClass = o.getContainingClass();
return containingClass != null && TRASH_CLASSES.contains(containingClass.getQualifiedName());
}
-
+
private static boolean isAccessor(PsiMember member) {
return member instanceof PsiMethod && (GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)member) || "setProperty".equals(((PsiMethod)member).getName()));
}
-
+
private static boolean isQualifierClassMember(PsiMember member, PsiElement qualifier) {
if (!(qualifier instanceof GrExpression)) return false;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyAnnotationAttributeInfoHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyAnnotationAttributeInfoHandler.java
new file mode 100644
index 000000000000..4ef4d7016157
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyAnnotationAttributeInfoHandler.java
@@ -0,0 +1,201 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.parameterInfo;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.lang.parameterInfo.*;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.*;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.text.CharArrayUtil;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Max Medvedev
+ */
+public class GroovyAnnotationAttributeInfoHandler implements ParameterInfoHandlerWithTabActionSupport<GrAnnotationArgumentList, PsiAnnotationMethod, GrAnnotationNameValuePair> {
+
+ private static final Set<Class> ALLOWED_CLASSES = ContainerUtil.<Class>newHashSet(GrAnnotation.class);
+ private static final Set<Class<GroovyFile>> STOP_SEARCHING_CLASSES = Collections.singleton(GroovyFile.class);
+
+ @NotNull
+ @Override
+ public GrAnnotationNameValuePair[] getActualParameters(@NotNull GrAnnotationArgumentList o) {
+ return o.getAttributes();
+ }
+
+ @NotNull
+ @Override
+ public IElementType getActualParameterDelimiterType() {
+ return GroovyTokenTypes.mCOMMA;
+ }
+
+ @NotNull
+ @Override
+ public IElementType getActualParametersRBraceType() {
+ return GroovyTokenTypes.mRPAREN;
+ }
+
+ @NotNull
+ @Override
+ public Set<Class> getArgumentListAllowedParentClasses() {
+ return ALLOWED_CLASSES;
+ }
+
+ @NotNull
+ @Override
+ public Set<? extends Class> getArgListStopSearchClasses() {
+ return STOP_SEARCHING_CLASSES;
+ }
+
+ @NotNull
+ @Override
+ public Class<GrAnnotationArgumentList> getArgumentListClass() {
+ return GrAnnotationArgumentList.class;
+ }
+
+ @Override
+ public boolean couldShowInLookup() {
+ return true;
+ }
+
+ @Override
+ public Object[] getParametersForLookup(@NotNull LookupElement item, @NotNull ParameterInfoContext context) {
+ Object o = item.getObject();
+
+ if (o instanceof GroovyResolveResult) {
+ o = ((GroovyResolveResult)o).getElement();
+ }
+
+
+ if (o instanceof PsiAnnotationMethod) {
+ return ((PsiAnnotationMethod)o).getParameterList().getParameters();
+ }
+ else {
+ return GrAnnotationNameValuePair.EMPTY_ARRAY;
+ }
+ }
+
+ @Override
+ public Object[] getParametersForDocumentation(@NotNull PsiAnnotationMethod method, @NotNull ParameterInfoContext context) {
+ return new PsiAnnotationMethod[]{method};
+ }
+
+ @Override
+ public GrAnnotationArgumentList findElementForParameterInfo(@NotNull CreateParameterInfoContext context) {
+ return findAnchor(context.getEditor(), context.getFile());
+ }
+
+ @Nullable
+ private static GrAnnotationArgumentList findAnchor(@NotNull final Editor editor, @NotNull final PsiFile file) {
+ PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+ if (element == null) return null;
+
+ return PsiTreeUtil.getParentOfType(element, GrAnnotationArgumentList.class);
+ }
+
+ @Override
+ public void showParameterInfo(@NotNull GrAnnotationArgumentList argumentList, @NotNull CreateParameterInfoContext context) {
+ final GrAnnotation parent = DefaultGroovyMethods.asType(argumentList.getParent(), GrAnnotation.class);
+
+ final PsiElement resolved = parent.getClassReference().resolve();
+ if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) {
+ final PsiMethod[] methods = ((PsiClass)resolved).getMethods();
+ context.setItemsToShow(methods);
+ context.showHint(argumentList, argumentList.getTextRange().getStartOffset(), this);
+ final PsiAnnotationMethod currentMethod = findAnnotationMethod(context.getFile(), context.getEditor());
+ if (currentMethod != null) {
+ context.setHighlightedElement(currentMethod);
+ }
+ }
+ }
+
+ @Nullable
+ private static PsiAnnotationMethod findAnnotationMethod(@NotNull PsiFile file, @NotNull Editor editor) {
+ PsiNameValuePair pair = ParameterInfoUtils.findParentOfType(file, inferOffset(editor), PsiNameValuePair.class);
+ if (pair == null) return null;
+ final PsiReference reference = pair.getReference();
+ final PsiElement resolved = reference != null ? reference.resolve() : null;
+ return PsiUtil.isAnnotationMethod(resolved) ? (PsiAnnotationMethod)resolved : null;
+ }
+
+ @Override
+ public GrAnnotationArgumentList findElementForUpdatingParameterInfo(@NotNull UpdateParameterInfoContext context) {
+ return findAnchor(context.getEditor(), context.getFile());
+ }
+
+ @Override
+ public void updateParameterInfo(@NotNull GrAnnotationArgumentList o, @NotNull UpdateParameterInfoContext context) {
+ context.setHighlightedParameter(findAnnotationMethod(context.getFile(), context.getEditor()));
+ }
+
+ private static int inferOffset(@NotNull final Editor editor) {
+ CharSequence chars = editor.getDocument().getCharsSequence();
+ int offset1 = CharArrayUtil.shiftForward(chars, editor.getCaretModel().getOffset(), " \t");
+ final char character = chars.charAt(offset1);
+ if (character == ',' || character == ')') {
+ offset1 = CharArrayUtil.shiftBackward(chars, offset1 - 1, " \t");
+ }
+ return offset1;
+ }
+
+ @Override
+ public String getParameterCloseChars() {
+ return ParameterInfoUtils.DEFAULT_PARAMETER_CLOSE_CHARS;
+ }
+
+ @Override
+ public boolean tracksParameterIndex() {
+ return true;
+ }
+
+ @Override
+ public void updateUI(@NotNull PsiAnnotationMethod p, @NotNull ParameterInfoUIContext context) {
+ @NonNls StringBuilder buffer = new StringBuilder();
+ final PsiType returnType = p.getReturnType();
+ assert returnType != null;
+ buffer.append(returnType.getPresentableText());
+ buffer.append(" ");
+ int highlightStartOffset = buffer.length();
+ buffer.append(p.getName());
+ int highlightEndOffset = buffer.length();
+ buffer.append("()");
+
+ final PsiAnnotationMemberValue defaultValue = p.getDefaultValue();
+ if (defaultValue != null) {
+ buffer.append(" default ");
+ buffer.append(defaultValue.getText());
+ }
+
+
+ context.setupUIComponentPresentation(buffer.toString(), highlightStartOffset, highlightEndOffset, false, p.isDeprecated(), false, context.getDefaultParameterColor());
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyTypeParameterInfoHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyTypeParameterInfoHandler.java
new file mode 100644
index 000000000000..3ba40cf6d2f2
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyTypeParameterInfoHandler.java
@@ -0,0 +1,168 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.parameterInfo;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.lang.parameterInfo.*;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiClassType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiTypeParameter;
+import com.intellij.psi.PsiTypeParameterListOwner;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
+
+import java.util.Arrays;
+import java.util.Set;
+
+/**
+ * @author Max Medvedev
+ */
+public class GroovyTypeParameterInfoHandler implements ParameterInfoHandlerWithTabActionSupport<GrTypeArgumentList, PsiTypeParameter, GrTypeElement> {
+
+ private static final Set<Class> ALLOWED_PARENT_CLASSES = ContainerUtil.<Class>newHashSet(GrCodeReferenceElement.class);
+ private static final Set<Class> STOP_SEARCHING_CLASSES = ContainerUtil.<Class>newHashSet(GroovyFile.class);
+
+ @NotNull
+ @Override
+ public GrTypeElement[] getActualParameters(@NotNull GrTypeArgumentList o) {
+ return o.getTypeArgumentElements();
+ }
+
+ @NotNull
+ @Override
+ public IElementType getActualParameterDelimiterType() {
+ return GroovyTokenTypes.mCOMMA;
+ }
+
+ @NotNull
+ @Override
+ public IElementType getActualParametersRBraceType() {
+ return GroovyTokenTypes.mGT;
+ }
+
+ @NotNull
+ @Override
+ public Set<Class> getArgumentListAllowedParentClasses() {
+ return ALLOWED_PARENT_CLASSES;
+ }
+
+ @NotNull
+ @Override
+ public Set<? extends Class> getArgListStopSearchClasses() {
+ return STOP_SEARCHING_CLASSES;
+ }
+
+ @NotNull
+ @Override
+ public Class<GrTypeArgumentList> getArgumentListClass() {
+ return GrTypeArgumentList.class;
+ }
+
+ @Override
+ public boolean couldShowInLookup() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Object[] getParametersForDocumentation(PsiTypeParameter p, ParameterInfoContext context) {
+ return new Object[]{p};
+ }
+
+ @Nullable
+ @Override
+ public GrTypeArgumentList findElementForParameterInfo(CreateParameterInfoContext context) {
+ final GrTypeArgumentList parameterList = ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), GrTypeArgumentList.class);
+
+ if (parameterList != null) {
+ if (!(parameterList.getParent() instanceof GrCodeReferenceElement)) return null;
+ final GrCodeReferenceElement ref = ((GrCodeReferenceElement)parameterList.getParent());
+
+ final PsiElement resolved = ref.resolve();
+ if (!(resolved instanceof PsiTypeParameterListOwner)) return null;
+
+ final PsiTypeParameter[] typeParams = ((PsiTypeParameterListOwner)resolved).getTypeParameters();
+ if (typeParams.length == 0) return null;
+
+ context.setItemsToShow(typeParams);
+ return parameterList;
+ }
+
+ return null;
+ }
+
+ @Override
+ public void showParameterInfo(@NotNull GrTypeArgumentList element, CreateParameterInfoContext context) {
+ context.showHint(element, element.getTextRange().getStartOffset() + 1, this);
+ }
+
+ @Nullable
+ @Override
+ public GrTypeArgumentList findElementForUpdatingParameterInfo(UpdateParameterInfoContext context) {
+ return ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), GrTypeArgumentList.class);
+ }
+
+ @Override
+ public void updateParameterInfo(@NotNull GrTypeArgumentList o, UpdateParameterInfoContext context) {
+ int index = ParameterInfoUtils.getCurrentParameterIndex(o.getNode(), context.getOffset(), getActualParameterDelimiterType());
+ context.setCurrentParameter(index);
+ final Object[] objectsToView = context.getObjectsToView();
+ context.setHighlightedParameter(index < objectsToView.length && index >= 0 ? (PsiElement)objectsToView[index] : null);
+ }
+
+ @Nullable
+ @Override
+ public String getParameterCloseChars() {
+ return ",>";
+ }
+
+ @Override
+ public boolean tracksParameterIndex() {
+ return false;
+ }
+
+ @Override
+ public void updateUI(PsiTypeParameter p, ParameterInfoUIContext context) {
+ @NonNls StringBuilder buffer = new StringBuilder();
+ buffer.append(p.getName());
+ int highlightEndOffset = buffer.length();
+ buffer.append(" extends ");
+ buffer.append(StringUtil.join(Arrays.asList(p.getSuperTypes()), new Function<PsiClassType, String>() {
+ @Override
+ public String fun(final PsiClassType t) {
+ return t.getPresentableText();
+ }
+ }, ", "));
+
+ context.setupUIComponentPresentation(buffer.toString(), 0, highlightEndOffset, false, false, false, context.getDefaultParameterColor());
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java
index c9c3773233e4..5989f5f97735 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.annotations;
import com.intellij.lang.PsiBuilder;
import org.jetbrains.plugins.groovy.GroovyBundle;
+import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.ConditionalExpression;
@@ -61,8 +62,10 @@ public class AnnotationArguments implements GroovyElementTypes {
}
private static boolean checkIdentAndAssign(PsiBuilder builder) {
- //def is valid name identifier
- return ParserUtils.lookAhead(builder, mIDENT, mASSIGN) || ParserUtils.lookAhead(builder, kDEF, mASSIGN);
+ final PsiBuilder.Marker marker = builder.mark();
+ boolean result = ParserUtils.getToken(builder, TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS) && ParserUtils.getToken(builder, mASSIGN);
+ marker.rollbackTo();
+ return result;
}
/*
@@ -120,9 +123,7 @@ public class AnnotationArguments implements GroovyElementTypes {
PsiBuilder.Marker marker = builder.mark();
if (checkIdentAndAssign(builder)) {
- if (!ParserUtils.getToken(builder, mIDENT)) {
- ParserUtils.getToken(builder, kDEF);
- }
+ ParserUtils.getToken(builder, TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS);
ParserUtils.getToken(builder, mASSIGN);
ParserUtils.getToken(builder, mNLS);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java
index 280720d3b5a6..8ffd2bb8dd7b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -214,7 +214,10 @@ public class ParameterDeclaration implements GroovyElementTypes {
}
ParserUtils.getToken(builder, mNLS);
}
- else if (Annotation.parse(builder, parser)) {
+ else { // @
+ if (!Annotation.parse(builder, parser)) {
+ ParserUtils.wrapError(builder, GroovyBundle.message("annotation.expected"));
+ }
ParserUtils.getToken(builder, mNLS);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeArguments.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeArguments.java
index f5fed5ba064c..c2f560dca0f0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeArguments.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeArguments.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,8 +48,15 @@ public class TypeArguments implements GroovyElementTypes {
}
if (!parseArgument(builder)) {
- marker.rollbackTo();
- return false;
+ builder.error(GroovyBundle.message("type.argument.expected"));
+ if (ParserUtils.getToken(builder, mGT)) {
+ marker.done(TYPE_ARGUMENTS);
+ return true;
+ }
+ else {
+ marker.rollbackTo();
+ return false;
+ }
}
boolean hasComma = ParserUtils.lookAhead(builder, mCOMMA);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java
index 6bb96f47eb66..13605584cc2b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/GrListOrMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,10 +19,9 @@ package org.jetbrains.plugins.groovy.lang.psi.api.auxiliary;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.UserDataHolderEx;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiArrayInitializerMemberValue;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrNamedArgumentsOwner;
@@ -38,4 +37,8 @@ public interface GrListOrMap extends UserDataHolderEx, Cloneable, Iconable, PsiE
GrExpression[] getInitializers();
boolean isMap();
+
+ PsiElement getLBrack();
+
+ PsiElement getRBrack();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrNamedArgumentSearchVisitor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrNamedArgumentSearchVisitor.java
index 53fd41212f4f..1e431c1351e7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrNamedArgumentSearchVisitor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrNamedArgumentSearchVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -73,7 +73,7 @@ public class GrNamedArgumentSearchVisitor extends GroovyRecursiveElementVisitor
@Override
public void visitReferenceExpression(GrReferenceExpression referenceExpression) {
- if (myFirstArgumentName.equals(referenceExpression.getName()) && !referenceExpression.isQualified()) {
+ if (myFirstArgumentName.equals(referenceExpression.getReferenceName()) && !referenceExpression.isQualified()) {
PsiElement parent = referenceExpression.getParent();
if (parent instanceof GrReferenceExpression) {
@@ -82,12 +82,12 @@ public class GrNamedArgumentSearchVisitor extends GroovyRecursiveElementVisitor
PsiElement parentParent = parentRef.getParent();
if (parentParent instanceof GrMethodCallExpression) {
- if (METHOD_NAMES.contains(parentRef.getName())) {
+ if (METHOD_NAMES.contains(parentRef.getReferenceName())) {
extractArguments(((GrMethodCallExpression)parentParent).getArgumentList());
}
}
else {
- add(parentRef.getName());
+ add(parentRef.getReferenceName());
}
}
else if (parent instanceof GrIndexProperty) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSynchronizedStatement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSynchronizedStatement.java
index 5894eb266aa0..2253b9d918ff 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSynchronizedStatement.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSynchronizedStatement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
package org.jetbrains.plugins.groovy.lang.psi.api.statements;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.formatter.GrControlStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
@@ -26,8 +28,16 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
*/
public interface GrSynchronizedStatement extends GroovyPsiElement, GrStatement, GrControlStatement {
- public GrExpression getMonitor();
+ @Nullable
+ GrExpression getMonitor();
- public GrOpenBlock getBody();
+ @Nullable
+ GrOpenBlock getBody();
+
+ @Nullable
+ PsiElement getLParenth();
+
+ @Nullable
+ PsiElement getRParenth();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java
index 734f9e4dba9b..9b399db78a29 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,8 +36,6 @@ public interface GrArgumentList extends GroovyPsiElement, GrNamedArgumentsOwner,
GrArgumentList replaceWithArgumentList(GrArgumentList newArgList) throws IncorrectOperationException;
- boolean isIndexPropertiesList();
-
@Nullable
PsiElement getLeftParen();
@@ -46,8 +44,5 @@ public interface GrArgumentList extends GroovyPsiElement, GrNamedArgumentsOwner,
int getExpressionArgumentIndex(GrExpression arg);
- @Nullable
- GrExpression removeArgument(int argNumber);
-
GrNamedArgument addNamedArgument(GrNamedArgument namedArgument);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java
index 012944b3b0ac..902ba693bed7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/blocks/GrClosableBlock.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
+import com.intellij.psi.ResolveState;
+import com.intellij.psi.scope.PsiScopeProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
@@ -50,4 +52,10 @@ public interface GrClosableBlock extends GrExpression, GrCodeBlock, GrParameters
PsiElement getArrow();
boolean isVarArgs();
+
+ boolean processClosureDeclarations(final @NotNull PsiScopeProcessor placeProcessor,
+ final @NotNull PsiScopeProcessor nonCodeProcessor,
+ final @NotNull ResolveState _state,
+ final @Nullable PsiElement lastParent,
+ final @NotNull PsiElement place);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrReferenceExpression.java
index 8b436a1a2a12..0781a026e596 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrReferenceExpression.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrReferenceExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMember;
-import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -28,7 +27,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
/**
* @author ilyas
*/
-public interface GrReferenceExpression extends GrExpression, GrReferenceElement<GrExpression>, PsiNamedElement {
+public interface GrReferenceExpression extends GrExpression, GrReferenceElement<GrExpression> {
@Nullable
GrExpression getQualifierExpression();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ControlFlowBuilderUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ControlFlowBuilderUtil.java
index 47952de3cff9..56d59dac4d3f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ControlFlowBuilderUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ControlFlowBuilderUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,9 +24,11 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.ArrayUtilRt;
import gnu.trove.TIntHashSet;
import gnu.trove.TObjectIntHashMap;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.formatter.GrControlStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
@@ -36,6 +38,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSectio
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
+import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+import org.jetbrains.plugins.groovy.lang.resolve.processors.PropertyResolverProcessor;
+import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
import java.util.ArrayList;
import java.util.List;
@@ -283,4 +288,20 @@ public class ControlFlowBuilderUtil {
}
return true;
}
+
+ @NotNull
+ public static GroovyResolveResult[] resolveNonQualifiedRefWithoutFlow(@NotNull GrReferenceExpression ref) {
+ LOG.assertTrue(!ref.isQualified());
+
+ final String referenceName = ref.getReferenceName();
+ final ResolverProcessor processor = new PropertyResolverProcessor(referenceName, ref);
+
+ ResolveUtil.treeWalkUp(ref, processor, false);
+ final GroovyResolveResult[] candidates = processor.getCandidates();
+ if (candidates.length != 0) {
+ return candidates;
+ }
+
+ return GroovyResolveResult.EMPTY_ARRAY;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java
index b5c9f70a5c3e..26f229776195 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java
@@ -17,13 +17,13 @@ package org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl;
import com.intellij.diagnostic.LogMessageEx;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -31,6 +31,7 @@ import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
@@ -355,13 +356,27 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
}
@Nullable
- private static PsiType getNominalTypeNoRecursion(final GrExpression exception) {
- return RecursionManager.doPreventingRecursion(exception, true, new NullableComputable<PsiType>() {
- @Override
- public PsiType compute() {
- return exception.getNominalType();
+ private static PsiType getNominalTypeNoRecursion(@NotNull final GrExpression expression) {
+ if (expression instanceof GrNewExpression) {
+ return expression.getType();
+ }
+ else if (expression instanceof GrReferenceExpression && ((GrReferenceExpression)expression).getQualifier() == null) {
+ return getTypeByRef((GrReferenceExpression)expression);
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PsiType getTypeByRef(@NotNull GrReferenceExpression invoked) {
+
+ final GroovyResolveResult[] results = ControlFlowBuilderUtil.resolveNonQualifiedRefWithoutFlow(invoked);
+ if (results.length == 1) {
+ final PsiElement element = results[0].getElement();
+ if (element instanceof PsiVariable) {
+ return ((PsiVariable)element).getType();
}
- });
+ }
+ return null;
}
private void interruptFlow() {
@@ -660,6 +675,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
handlePossibleReturn(thenBranch);
thenEnd = myHead;
interruptFlow();
+ readdPendingEdge(ifStatement);
}
myHead = reduceAllNegationsIntoInstruction(ifStatement, negations);
@@ -762,28 +778,45 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
}
}
- private void checkPending(InstructionImpl instruction) {
- final PsiElement element = instruction.getElement();
- if (element == null) {
- //add all
- for (Pair<InstructionImpl, GroovyPsiElement> pair : myPending) {
- addEdge(pair.getFirst(), instruction);
- }
- myPending.clear();
+
+ @NotNull
+ private List<Pair<InstructionImpl, GroovyPsiElement>> collectCorrespondingPendingEdges(@Nullable PsiElement currentScope) {
+ if (currentScope == null) {
+ List<Pair<InstructionImpl, GroovyPsiElement>> result = myPending;
+ myPending = ContainerUtil.newArrayList();
+ return result;
}
else {
+ ArrayList<Pair<InstructionImpl, GroovyPsiElement>> targets = ContainerUtil.newArrayList();
+
for (int i = myPending.size() - 1; i >= 0; i--) {
final Pair<InstructionImpl, GroovyPsiElement> pair = myPending.get(i);
final PsiElement scopeWhenToAdd = pair.getSecond();
if (scopeWhenToAdd == null) continue;
- if (!PsiTreeUtil.isAncestor(scopeWhenToAdd, element, false)) {
- addEdge(pair.getFirst(), instruction);
+ if (!PsiTreeUtil.isAncestor(scopeWhenToAdd, currentScope, false)) {
+ targets.add(pair);
myPending.remove(i);
}
else {
break;
}
}
+ return targets;
+ }
+ }
+
+ private void checkPending(@NotNull InstructionImpl instruction) {
+ final PsiElement element = instruction.getElement();
+ List<Pair<InstructionImpl, GroovyPsiElement>> target = collectCorrespondingPendingEdges(element);
+ for (Pair<InstructionImpl, GroovyPsiElement> pair : target) {
+ addEdge(pair.getFirst(), instruction);
+ }
+ }
+
+ private void readdPendingEdge(@Nullable GroovyPsiElement newScope) {
+ final List<Pair<InstructionImpl, GroovyPsiElement>> targets = collectCorrespondingPendingEdges(newScope);
+ for (Pair<InstructionImpl, GroovyPsiElement> target : targets) {
+ addPendingEdge(newScope, target.getFirst());
}
}
@@ -1090,7 +1123,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
private void finishNode(InstructionImpl instruction) {
final InstructionImpl popped = myProcessingStack.pop();
if (!instruction.equals(popped)) {
- String description = "popped: " + popped.toString() + " , expected: " + instruction.toString();
+ String description = "popped: " + popped.toString() + " : " + popped.hashCode() + " , expected: " + instruction.toString() + " : " + instruction.hashCode();
error(description);
}
}
@@ -1114,6 +1147,15 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
public void visitTypeDefinition(final GrTypeDefinition typeDefinition) {
if (!(typeDefinition instanceof GrAnonymousClassDefinition)) return;
+ final Set<String> vars = collectUsedVariableWithoutInitialization(typeDefinition);
+
+ for (String var : vars) {
+ addNodeAndCheckPending(new ReadWriteVariableInstruction(var, typeDefinition, READ));
+ }
+ addNodeAndCheckPending(new InstructionImpl(typeDefinition));
+ }
+
+ private static Set<String> collectUsedVariableWithoutInitialization(GrTypeDefinition typeDefinition) {
final Set<String> vars = new HashSet<String>();
typeDefinition.acceptChildren(new GroovyRecursiveElementVisitor() {
private void collectVars(Instruction[] flow) {
@@ -1146,16 +1188,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
collectVars(block.getControlFlow());
}
});
-
- PsiField[] fields = typeDefinition.getAllFields();
- for (PsiField field : fields) {
- vars.remove(field.getName());
- }
-
- for (String var : vars) {
- addNodeAndCheckPending(new ReadWriteVariableInstruction(var, typeDefinition, READ));
- }
- addNodeAndCheckPending(new InstructionImpl(typeDefinition));
+ return vars;
}
public void visitVariable(GrVariable variable) {
@@ -1177,4 +1210,11 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
}
return null;
}
+
+ @Override
+ public void visitElement(GroovyPsiElement element) {
+ ProgressManager.checkCanceled();
+ super.visitElement(element);
+ }
+
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java
index 41ae01be0137..fdc459439a30 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,10 @@
package org.jetbrains.plugins.groovy.lang.psi.dataFlow.types;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.NullableComputable;
+import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
import com.intellij.psi.PsiType;
@@ -57,7 +60,7 @@ public class TypeInferenceHelper {
private static final Logger LOG = Logger.getInstance(TypeInferenceHelper.class);
private static final ThreadLocal<InferenceContext> ourInferenceContext = new ThreadLocal<InferenceContext>();
- private static <T> T doInference(Map<String, PsiType> bindings, Computable<T> computation) {
+ private static <T> T doInference(@NotNull Map<String, PsiType> bindings, @NotNull Computable<T> computation) {
InferenceContext old = ourInferenceContext.get();
ourInferenceContext.set(new InferenceContext.PartialContext(bindings));
try {
@@ -78,20 +81,27 @@ public class TypeInferenceHelper {
final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(refExpr);
if (scope == null) return null;
- return getInferenceCache(scope).getInferredType(refExpr.getReferenceName(), ControlFlowUtils
- .findRWInstruction(refExpr, scope.getControlFlow()));
+ final String referenceName = refExpr.getReferenceName();
+ if (referenceName == null) return null;
+
+ final ReadWriteVariableInstruction rwInstruction = ControlFlowUtils.findRWInstruction(refExpr, scope.getControlFlow());
+ if (rwInstruction == null) return null;
+
+ return getInferenceCache(scope).getInferredType(referenceName, rwInstruction);
}
@Nullable
- public static PsiType getInferredType(@NotNull PsiElement place, String variableName) {
+ public static PsiType getInferredType(@NotNull PsiElement place, @NotNull String variableName) {
final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(place);
if (scope == null) return null;
- return getInferenceCache(scope).getInferredType(variableName, ControlFlowUtils.findNearestInstruction(place, scope.getControlFlow()));
+ final Instruction nearest = ControlFlowUtils.findNearestInstruction(place, scope.getControlFlow());
+ if (nearest == null) return null;
+ return getInferenceCache(scope).getInferredType(variableName, nearest);
}
@NotNull
- private static InferenceCache getInferenceCache(final GrControlFlowOwner scope) {
+ private static InferenceCache getInferenceCache(@NotNull final GrControlFlowOwner scope) {
return CachedValuesManager.getManager(scope.getProject()).getCachedValue(scope, new CachedValueProvider<InferenceCache>() {
@Nullable
@Override
@@ -101,7 +111,7 @@ public class TypeInferenceHelper {
});
}
- public static boolean isTooComplexTooAnalyze(GrControlFlowOwner scope) {
+ public static boolean isTooComplexTooAnalyze(@NotNull GrControlFlowOwner scope) {
return getDefUseMaps(scope) == null;
}
@@ -131,7 +141,7 @@ public class TypeInferenceHelper {
}
@Nullable
- private static Pair<ReachingDefinitionsDfaInstance, List<DefinitionMap>> getDefUseMaps(final GrControlFlowOwner scope) {
+ private static Pair<ReachingDefinitionsDfaInstance, List<DefinitionMap>> getDefUseMaps(@NotNull final GrControlFlowOwner scope) {
return CachedValuesManager.getManager(scope.getProject()).getCachedValue(scope, new CachedValueProvider<Pair<ReachingDefinitionsDfaInstance, List<DefinitionMap>>>() {
@Override
public Result<Pair<ReachingDefinitionsDfaInstance, List<DefinitionMap>>> compute() {
@@ -269,7 +279,7 @@ public class TypeInferenceHelper {
private final Set<Instruction> myInteresting;
private final InferenceCache myCache;
- TypeDfaInstance(GrControlFlowOwner scope, Instruction[] flow, Set<Instruction> interesting, InferenceCache cache) {
+ TypeDfaInstance(@NotNull GrControlFlowOwner scope, @NotNull Instruction[] flow, @NotNull Set<Instruction> interesting, @NotNull InferenceCache cache) {
myScope = scope;
myFlow = flow;
myInteresting = interesting;
@@ -285,7 +295,7 @@ public class TypeInferenceHelper {
}
}
- private void handleMixin(final TypeDfaState state, final MixinTypeInstruction instruction) {
+ private void handleMixin(@NotNull final TypeDfaState state, @NotNull final MixinTypeInstruction instruction) {
final String varName = instruction.getVariableName();
if (varName == null) return;
@@ -318,7 +328,7 @@ public class TypeInferenceHelper {
}
}
- private void updateVariableType(TypeDfaState state, Instruction instruction, String variableName, Computable<DFAType> computation) {
+ private void updateVariableType(@NotNull TypeDfaState state, @NotNull Instruction instruction, @NotNull String variableName, @NotNull Computable<DFAType> computation) {
if (!myInteresting.contains(instruction)) {
state.removeBinding(variableName);
return;
@@ -360,8 +370,7 @@ public class TypeInferenceHelper {
}
@Nullable
- private PsiType getInferredType(@Nullable String variableName, @Nullable Instruction instruction) {
- if (instruction == null || variableName == null) return null;
+ private PsiType getInferredType(@NotNull String variableName, @NotNull Instruction instruction) {
if (tooComplex.contains(instruction)) return null;
TypeDfaState cache = varTypes.get().get(instruction.num());
@@ -385,7 +394,7 @@ public class TypeInferenceHelper {
}
@Nullable
- private List<TypeDfaState> performTypeDfa(GrControlFlowOwner owner, Instruction[] flow, Set<Instruction> interesting) {
+ private List<TypeDfaState> performTypeDfa(@NotNull GrControlFlowOwner owner, @NotNull Instruction[] flow, @NotNull Set<Instruction> interesting) {
final TypeDfaInstance dfaInstance = new TypeDfaInstance(owner, flow, interesting, this);
final TypesSemilattice semilattice = new TypesSemilattice(owner.getManager());
return new DFAEngine<TypeDfaState>(flow, dfaInstance, semilattice).performDFAWithTimeout();
@@ -415,7 +424,8 @@ public class TypeInferenceHelper {
return interesting;
}
- private Set<Pair<Instruction,String>> findDependencies(Pair<ReachingDefinitionsDfaInstance, List<DefinitionMap>> defUse,
+ @NotNull
+ private Set<Pair<Instruction,String>> findDependencies(@NotNull Pair<ReachingDefinitionsDfaInstance, List<DefinitionMap>> defUse,
@NotNull Instruction insn,
@NotNull String varName) {
DefinitionMap definitionMap = defUse.second.get(insn.num());
@@ -435,6 +445,7 @@ public class TypeInferenceHelper {
return pairs;
}
+ @NotNull
private List<Pair<Instruction, String>> findAllInstructionsInside(@NotNull PsiElement scope) {
final List<Pair<Instruction, String>> result = ContainerUtil.newArrayList();
scope.accept(new PsiRecursiveElementWalkingVisitor() {
@@ -465,7 +476,7 @@ public class TypeInferenceHelper {
});
}
- private void cacheDfaResult(List<TypeDfaState> dfaResult) {
+ private void cacheDfaResult(@NotNull List<TypeDfaState> dfaResult) {
while (true) {
List<TypeDfaState> oldTypes = varTypes.get();
if (varTypes.compareAndSet(oldTypes, addDfaResult(dfaResult, oldTypes))) {
@@ -474,7 +485,8 @@ public class TypeInferenceHelper {
}
}
- private static List<TypeDfaState> addDfaResult(List<TypeDfaState> dfaResult, List<TypeDfaState> oldTypes) {
+ @NotNull
+ private static List<TypeDfaState> addDfaResult(@NotNull List<TypeDfaState> dfaResult, @NotNull List<TypeDfaState> oldTypes) {
List<TypeDfaState> newTypes = new ArrayList<TypeDfaState>(oldTypes);
for (int i = 0; i < dfaResult.size(); i++) {
newTypes.set(i, newTypes.get(i).mergeWith(dfaResult.get(i)));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java
index b35eb881a4bd..36f239b74975 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java
@@ -24,7 +24,6 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
import com.intellij.psi.stubs.StubIndex;
-import com.intellij.psi.stubs.StubIndexImpl;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import org.jetbrains.annotations.NotNull;
@@ -51,7 +50,7 @@ class GroovyDirectInheritorsSearcher implements QueryExecutor<PsiClass, DirectCl
final String name = clazz.getName();
if (name == null) return GrTypeDefinition.EMPTY_ARRAY;
final ArrayList<PsiClass> inheritors = new ArrayList<PsiClass>();
- for (GrReferenceList list : StubIndexImpl.safeGet(GrDirectInheritorsIndex.KEY, name, clazz.getProject(), scope,
+ for (GrReferenceList list : StubIndex.getInstance().safeGet(GrDirectInheritorsIndex.KEY, name, clazz.getProject(), scope,
GrReferenceList.class)) {
final PsiElement parent = list.getParent();
if (parent instanceof GrTypeDefinition) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java
index c5184f32dc4c..eae43a063d7e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -242,6 +242,7 @@ public abstract class GroovyFileBaseImpl extends PsiFileBase implements GroovyFi
private volatile SoftReference<Instruction[]> myControlFlow = null;
public Instruction[] getControlFlow() {
+ assert isValid();
SoftReference<Instruction[]> flow = myControlFlow;
Instruction[] result = flow != null ? flow.get() : null;
if (result == null) {
@@ -350,6 +351,8 @@ public abstract class GroovyFileBaseImpl extends PsiFileBase implements GroovyFi
int start = Math.min(b1, b2);
int end = Math.max(b1, b2);
+ if (start == -1) return 0;
+
int max = 0;
int cur = 0;
for (int i = start; i < end; i++) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java
index ff4eeb01b68a..8ad0240b644b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java
@@ -218,7 +218,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
String... identifiers) {
StringBuilder text = writeModifiers(modifiers);
- if (type != null) {
+ if (type != null && type != PsiType.NULL) {
final PsiType unboxed = TypesUtil.unboxPrimitiveTypeWrapper(type);
final String typeText = getTypeText(unboxed);
text.append(typeText).append(" ");
@@ -303,9 +303,16 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
private static String getTypeText(PsiType type) {
if (!(type instanceof PsiArrayType)) {
final String canonical = type.getCanonicalText();
- return canonical != null ? canonical : type.getPresentableText();
- } else {
- return getTypeText(((PsiArrayType) type).getComponentType()) + "[]";
+ final String text = canonical != null ? canonical : type.getPresentableText();
+ if ("null".equals(text)) {
+ return "";
+ }
+ else {
+ return text;
+ }
+ }
+ else {
+ return getTypeText(((PsiArrayType)type).getComponentType()) + "[]";
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementImpl.java
index 59b0367b80c4..d1eae21e6f14 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl;
import com.intellij.extapi.psi.ASTDelegatePsiElement;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiInvalidElementAccessException;
import com.intellij.psi.impl.CheckUtil;
@@ -69,6 +70,7 @@ public abstract class GroovyPsiElementImpl extends ASTWrapperPsiElement implemen
public static void acceptGroovyChildren(PsiElement parent, GroovyElementVisitor visitor) {
PsiElement child = parent.getFirstChild();
while (child != null) {
+ ProgressManager.checkCanceled();
if (child instanceof GroovyPsiElement) {
((GroovyPsiElement) child).accept(visitor);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java
index acd55092963e..c35737ac8ed6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,7 +44,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -132,7 +131,7 @@ public class GroovyPsiManager {
return ServiceManager.getService(project, GroovyPsiManager.class);
}
- public PsiClassType createTypeByFQClassName(String fqName, GlobalSearchScope resolveScope) {
+ public PsiClassType createTypeByFQClassName(@NotNull String fqName, @NotNull GlobalSearchScope resolveScope) {
if (ourPopularClasses.contains(fqName)) {
PsiClass result = findClassWithCache(fqName, resolveScope);
if (result != null) {
@@ -143,7 +142,7 @@ public class GroovyPsiManager {
return JavaPsiFacade.getElementFactory(myProject).createTypeByFQClassName(fqName, resolveScope);
}
- public boolean isCompileStatic(PsiMember member) {
+ public boolean isCompileStatic(@NotNull PsiMember member) {
Boolean aBoolean = myCompileStatic.get(member);
if (aBoolean == null) {
aBoolean = ConcurrencyUtil.cacheOrGet(myCompileStatic, member, isCompileStaticInner(member));
@@ -151,7 +150,7 @@ public class GroovyPsiManager {
return aBoolean;
}
- private boolean isCompileStaticInner(PsiMember member) {
+ private boolean isCompileStaticInner(@NotNull PsiMember member) {
PsiModifierList list = member.getModifierList();
if (list != null) {
PsiAnnotation compileStatic = list.findAnnotation(GROOVY_TRANSFORM_COMPILE_STATIC);
@@ -164,15 +163,15 @@ public class GroovyPsiManager {
return false;
}
- private static boolean checkForPass(PsiAnnotation annotation) {
+ private static boolean checkForPass(@NotNull PsiAnnotation annotation) {
PsiAnnotationMemberValue value = annotation.findAttributeValue("value");
return value == null ||
- value instanceof GrReferenceExpression &&
- ResolveUtil.isEnumConstant((GrReferenceExpression)value, "PASS", GROOVY_TRANSFORM_TYPE_CHECKING_MODE);
+ value instanceof PsiReference &&
+ ResolveUtil.isEnumConstant((PsiReference)value, "PASS", GROOVY_TRANSFORM_TYPE_CHECKING_MODE);
}
@Nullable
- public PsiClass findClassWithCache(String fqName, GlobalSearchScope resolveScope) {
+ public PsiClass findClassWithCache(@NotNull String fqName, @NotNull GlobalSearchScope resolveScope) {
SoftReference<Map<GlobalSearchScope, PsiClass>> reference = myClassCache.get(fqName);
Map<GlobalSearchScope, PsiClass> map = reference == null ? null : reference.get();
if (map == null) {
@@ -191,14 +190,16 @@ public class GroovyPsiManager {
return result;
}
+
+ private static final PsiType UNKNOWN_TYPE = new PsiPrimitiveType("unknown type", PsiAnnotation.EMPTY_ARRAY);
@Nullable
- public <T extends GroovyPsiElement> PsiType getType(T element, Function<T, PsiType> calculator) {
+ public <T extends GroovyPsiElement> PsiType getType(@NotNull T element, @NotNull Function<T, PsiType> calculator) {
PsiType type = myCalculatedTypes.get(element);
if (type == null) {
RecursionGuard.StackStamp stamp = ourGuard.markStack();
type = calculator.fun(element);
if (type == null) {
- type = PsiType.NULL;
+ type = UNKNOWN_TYPE;
}
if (stamp.mayCacheNow()) {
type = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, element, type);
@@ -212,10 +213,11 @@ public class GroovyPsiManager {
if (!type.isValid()) {
LOG.error("Type is invalid: " + type + "; element: " + element + " of class " + element.getClass());
}
- return PsiType.NULL.equals(type) ? null : type;
+ return UNKNOWN_TYPE == type ? null : type;
}
- public GrTypeDefinition getArrayClass(PsiType type) {
+ @Nullable
+ public GrTypeDefinition getArrayClass(@NotNull PsiType type) {
final String typeText = type.getCanonicalText();
GrTypeDefinition definition = myArrayClass.get(typeText);
if (definition == null) {
@@ -233,7 +235,7 @@ public class GroovyPsiManager {
}
@Nullable
- public static PsiType inferType(@NotNull PsiElement element, Computable<PsiType> computable) {
+ public static PsiType inferType(@NotNull PsiElement element, @NotNull Computable<PsiType> computable) {
List<Object> stack = ourGuard.currentStack();
if (stack.size() > 7) { //don't end up walking the whole project PSI
ourGuard.prohibitResultCaching(stack.get(0));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java
index 0ad81d5eabc5..3f8eb9c7780a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ public interface InferenceContext {
}
@Override
- public <T> T getCachedValue(@NotNull GroovyPsiElement element, final Computable<T> computable) {
+ public <T> T getCachedValue(@NotNull GroovyPsiElement element, @NotNull final Computable<T> computable) {
CachedValuesManager manager = CachedValuesManager.getManager(element.getProject());
Key<CachedValue<T>> key = manager.getKeyForClass(computable.getClass());
return manager.getCachedValue(element, key, new CachedValueProvider<T>() {
@@ -73,7 +73,7 @@ public interface InferenceContext {
@Nullable
@Override
- public <T extends GroovyPsiElement> PsiType getExpressionType(T element, Function<T, PsiType> calculator) {
+ public <T extends GroovyPsiElement> PsiType getExpressionType(@NotNull T element, @NotNull Function<T, PsiType> calculator) {
return GroovyPsiManager.getInstance(element.getProject()).getType(element, calculator);
}
};
@@ -81,18 +81,18 @@ public interface InferenceContext {
@Nullable
PsiType getVariableType(@NotNull GrReferenceExpression ref);
- <T> T getCachedValue(@NotNull GroovyPsiElement element, Computable<T> computable);
+ <T> T getCachedValue(@NotNull GroovyPsiElement element, @NotNull Computable<T> computable);
<T extends PsiPolyVariantReference> GroovyResolveResult[] multiResolve(@NotNull T ref, boolean incomplete, ResolveCache.PolyVariantResolver<T> resolver);
@Nullable
- <T extends GroovyPsiElement> PsiType getExpressionType(T element, Function<T, PsiType> calculator);
+ <T extends GroovyPsiElement> PsiType getExpressionType(@NotNull T element, @NotNull Function<T, PsiType> calculator);
class PartialContext implements InferenceContext {
private final Map<String, PsiType> myTypes;
private final Map<PsiElement, Map<Object, Object>> myCache = newHashMap();
- public PartialContext(Map<String, PsiType> types) {
+ public PartialContext(@NotNull Map<String, PsiType> types) {
myTypes = types;
}
@@ -103,11 +103,11 @@ public interface InferenceContext {
}
@Override
- public <T> T getCachedValue(@NotNull GroovyPsiElement element, Computable<T> computable) {
+ public <T> T getCachedValue(@NotNull GroovyPsiElement element, @NotNull Computable<T> computable) {
return _getCachedValue(element, computable, computable.getClass());
}
- private <T> T _getCachedValue(PsiElement element, Computable<T> computable, Object key) {
+ private <T> T _getCachedValue(@Nullable PsiElement element, @NotNull Computable<T> computable, @NotNull Object key) {
Map<Object, Object> map = myCache.get(element);
if (map == null) {
myCache.put(element, map = newHashMap());
@@ -122,10 +122,11 @@ public interface InferenceContext {
return result;
}
+ @NotNull
@Override
public <T extends PsiPolyVariantReference> GroovyResolveResult[] multiResolve(@NotNull final T ref,
final boolean incomplete,
- final ResolveCache.PolyVariantResolver<T> resolver) {
+ @NotNull final ResolveCache.PolyVariantResolver<T> resolver) {
return _getCachedValue(ref.getElement(), new Computable<GroovyResolveResult[]>() {
@Override
public GroovyResolveResult[] compute() {
@@ -136,7 +137,7 @@ public interface InferenceContext {
@Nullable
@Override
- public <T extends GroovyPsiElement> PsiType getExpressionType(final T element, final Function<T, PsiType> calculator) {
+ public <T extends GroovyPsiElement> PsiType getExpressionType(@NotNull final T element, @NotNull final Function<T, PsiType> calculator) {
return _getCachedValue(element, new Computable<PsiType>() {
@Override
public PsiType compute() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java
index 179da97d5607..0c62786ac181 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java
@@ -106,6 +106,16 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap {
return findChildByType(MAP_LITERAL_TOKEN_SET) != null;
}
+ @Override
+ public PsiElement getLBrack() {
+ return findChildByType(GroovyTokenTypes.mLBRACK);
+ }
+
+ @Override
+ public PsiElement getRBrack() {
+ return findChildByType(GroovyTokenTypes.mRBRACK);
+ }
+
@NotNull
public GrExpression[] getInitializers() {
List<GrExpression> result = new ArrayList<GrExpression>();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java
index 8ea5f6890a00..674bfe6d66c1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java
@@ -17,11 +17,11 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation;
import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.light.LightClassReference;
-import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.util.PairFunction;
import org.jetbrains.annotations.NonNls;
@@ -51,6 +51,8 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
* @date: 04.04.2007
*/
public class GrAnnotationImpl extends GrStubElementBase<GrAnnotationStub> implements GrAnnotation, StubBasedPsiElement<GrAnnotationStub> {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl");
+
private static final PairFunction<Project, String, PsiAnnotation> ANNOTATION_CREATOR = new PairFunction<Project, String, PsiAnnotation>() {
public PsiAnnotation fun(Project project, String text) {
return GroovyPsiElementFactory.getInstance(project).createAnnotationFromText(text);
@@ -143,59 +145,54 @@ public class GrAnnotationImpl extends GrStubElementBase<GrAnnotationStub> implem
return (PsiAnnotationOwner)getParent();
}
- @Nullable
- public static String[] getApplicableElementTypeFields(PsiElement owner) {
+ @NotNull
+ public static TargetType[] getApplicableElementTypeFields(PsiElement owner) {
if (owner instanceof PsiClass) {
PsiClass aClass = (PsiClass)owner;
if (aClass.isAnnotationType()) {
- return new String[]{"ANNOTATION_TYPE", "TYPE"};
+ return new TargetType[]{TargetType.ANNOTATION_TYPE, TargetType.TYPE};
}
else if (aClass instanceof GrTypeParameter) {
- return new String[]{"TYPE_PARAMETER"};
+ return new TargetType[]{TargetType.TYPE_PARAMETER};
}
else {
- return new String[]{"TYPE"};
+ return new TargetType[]{TargetType.TYPE};
}
}
if (owner instanceof GrMethod) {
if (((PsiMethod)owner).isConstructor()) {
- return new String[]{"CONSTRUCTOR"};
+ return new TargetType[]{TargetType.CONSTRUCTOR};
}
else {
- return new String[]{"METHOD"};
+ return new TargetType[]{TargetType.METHOD};
}
}
if (owner instanceof GrVariableDeclaration) {
final GrVariable[] variables = ((GrVariableDeclaration)owner).getVariables();
- if (variables.length == 0) return null;
+ if (variables.length == 0) {
+ return TargetType.EMPTY_ARRAY;
+ }
if (variables[0] instanceof GrField || ResolveUtil.isScriptField(variables[0])) {
- return new String[]{"FIELD"};
+ return new TargetType[]{TargetType.FIELD};
}
else {
- return new String[]{"LOCAL_VARIABLE"};
+ return new TargetType[]{TargetType.LOCAL_VARIABLE};
}
}
if (owner instanceof GrParameter) {
- return new String[]{"PARAMETER"};
+ return new TargetType[]{TargetType.PARAMETER};
}
if (owner instanceof GrPackageDefinition) {
- return new String[]{"PACKAGE"};
+ return new TargetType[]{TargetType.PACKAGE};
}
if (owner instanceof GrTypeElement) {
- return new String[]{"TYPE_USE"};
+ return new TargetType[]{TargetType.TYPE_USE};
}
- return null;
+ return TargetType.EMPTY_ARRAY;
}
-
- public static boolean isAnnotationApplicableTo(GrAnnotation annotation, boolean strict, String... elementTypeFields) {
- if (elementTypeFields == null) return true;
- GrCodeReferenceElement nameRef = annotation.getClassReference();
- PsiElement resolved = nameRef.resolve();
- if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) {
- return PsiAnnotationImpl.isAnnotationApplicable(strict, (PsiClass)resolved, elementTypeFields, annotation.getResolveScope());
- }
- return !strict;
+ public static boolean isAnnotationApplicableTo(GrAnnotation annotation, @NotNull TargetType... elementTypeFields) {
+ return elementTypeFields.length == 0 || PsiImplUtil.findApplicableTarget(annotation, elementTypeFields) != null;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java
index 3d074c17f6c0..6e4028dcf0ab 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
+import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
@@ -75,7 +76,7 @@ public class GrAnnotationNameValuePairImpl extends GroovyPsiElementImpl implemen
if (child == null) return null;
IElementType type = child.getNode().getElementType();
- if (type == GroovyTokenTypes.mIDENT || type == GroovyTokenTypes.kDEF) return child;
+ if (TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS.contains(type)) return child;
return null;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSynchronizedStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSynchronizedStatementImpl.java
index 4524ae67bf5a..4311ff8d36c0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSynchronizedStatementImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSynchronizedStatementImpl.java
@@ -17,7 +17,10 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrSynchronizedStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
@@ -41,11 +44,25 @@ public class GrSynchronizedStatementImpl extends GroovyPsiElementImpl implements
return "Synchronized statement";
}
+ @Nullable
public GrExpression getMonitor() {
return findExpressionChild(this);
}
+ @Nullable
public GrOpenBlock getBody() {
return findChildByClass(GrOpenBlock.class);
}
+
+ @Nullable
+ @Override
+ public PsiElement getLParenth() {
+ return findChildByType(GroovyTokenTypes.mLPAREN);
+ }
+
+ @Nullable
+ @Override
+ public PsiElement getRParenth() {
+ return findChildByType(GroovyTokenTypes.mRPAREN);
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java
index 9790c448874c..7229bb762ae6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,14 +113,6 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume
return ((GrArgumentList)newNode.getPsi());
}
- public boolean isIndexPropertiesList() {
- PsiElement firstChild = getFirstChild();
- if (firstChild == null) return false;
- ASTNode node = firstChild.getNode();
- assert node != null;
- return node.getElementType() == GroovyTokenTypes.mLBRACK;
- }
-
@Nullable
public PsiElement getLeftParen() {
ASTNode paren = getNode().findChildByType(GroovyTokenTypes.mLPAREN);
@@ -146,16 +138,6 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume
return -1;
}
- @Nullable
- public GrExpression removeArgument(final int argNumber) {
- GrExpression[] arguments = getExpressionArguments();
- if (argNumber < 0 || arguments.length <= argNumber) return null;
-
- GrExpression expression = arguments[argNumber];
- expression.delete();
- return expression;
- }
-
public GrNamedArgument addNamedArgument(final GrNamedArgument namedArgument) {
final GrNamedArgument[] namedArguments = getNamedArguments();
final GrExpression[] args = getExpressionArguments();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java
index e7c4f2867f2c..42bed724ebbf 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,6 +47,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+import org.jetbrains.plugins.groovy.util.ResolveProfiler;
import java.util.ArrayList;
import java.util.List;
@@ -104,12 +106,19 @@ public abstract class GrBlockImpl extends LazyParseablePsiElement implements GrC
controlFlow = CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider<Instruction[]>() {
@Override
public Result<Instruction[]> compute() {
- return Result.create(new ControlFlowBuilder(getProject()).buildControlFlow(GrBlockImpl.this), getContainingFile());
+ try {
+ ResolveProfiler.start();
+ final Instruction[] flow = new ControlFlowBuilder(getProject()).buildControlFlow(GrBlockImpl.this);
+ return Result.create(flow, getContainingFile(), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
+ }
+ finally {
+ final long time = ResolveProfiler.finish();
+ ResolveProfiler.write("flow " + GrBlockImpl.this.toString() + " : " + time);
+ }
}
}, false);
controlFlow = putUserDataIfAbsent(CONTROL_FLOW, controlFlow);
}
-
return ControlFlowBuilder.assertValidPsi(controlFlow.getValue());
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java
index a6c1799efc07..27d55c6aa994 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java
@@ -77,32 +77,52 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
mySyntheticItParameter = null;
}
+ public boolean processClosureDeclarations(final @NotNull PsiScopeProcessor plainProcessor,
+ final @NotNull PsiScopeProcessor nonCodeProcessor,
+ final @NotNull ResolveState state,
+ final @Nullable PsiElement lastParent,
+ final @NotNull PsiElement place) {
+ if (lastParent == null) return true;
+
+ if (!super.processDeclarations(plainProcessor, state, lastParent, place)) return false;
+ if (!processParameters(plainProcessor, state, place)) return false;
+ if (!ResolveUtil.processElement(plainProcessor, getOwner(), state)) return false;
+ if (!processClosureClassMembers(plainProcessor, state, lastParent, place)) return false;
+ if (!processOwnerAndDelegate(plainProcessor, nonCodeProcessor, state, place)) return false;
+
+ return true;
+ }
+
public boolean processDeclarations(final @NotNull PsiScopeProcessor processor,
- final @NotNull ResolveState _state,
+ final @NotNull ResolveState state,
final @Nullable PsiElement lastParent,
final @NotNull PsiElement place) {
if (lastParent == null) return true;
- ResolveState state = _state.put(ResolverProcessor.RESOLVE_CONTEXT, this);
- if (!super.processDeclarations(processor, _state, lastParent, place)) return false;
- if (!processParameters(processor, _state, state, place)) return false;
- if (!ResolveUtil.processElement(processor, getOwner(), _state)) return false;
+ if (!super.processDeclarations(processor, state, lastParent, place)) return false;
+ if (!processParameters(processor, state, place)) return false;
+ if (!ResolveUtil.processElement(processor, getOwner(), state)) return false;
if (!processClosureClassMembers(processor, state, lastParent, place)) return false;
- if (!processOwnerAndDelegate(processor, state, place)) return false;
return true;
}
- private boolean processOwnerAndDelegate(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, @NotNull PsiElement place) {
- Boolean result = processDelegatesTo(processor, state, place);
+ private boolean processOwnerAndDelegate(@NotNull PsiScopeProcessor processor,
+ @NotNull PsiScopeProcessor nonCodeProcessor,
+ @NotNull ResolveState state,
+ @NotNull PsiElement place) {
+ Boolean result = processDelegatesTo(processor, nonCodeProcessor, state, place);
if (result != null) return result.booleanValue();
- if (!processOwner(processor, state, place)) return false;
+ if (!processOwner(processor, nonCodeProcessor, state, place)) return false;
return true;
}
@Nullable
- private Boolean processDelegatesTo(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, @NotNull PsiElement place) {
+ private Boolean processDelegatesTo(@NotNull PsiScopeProcessor processor,
+ @NotNull PsiScopeProcessor nonCodeProcessor,
+ @NotNull ResolveState state,
+ @NotNull PsiElement place) {
GrDelegatesToUtil.DelegatesToInfo info = GrDelegatesToUtil.getDelegateToInfo(place, this);
if (info == null) {
return null;
@@ -110,18 +130,18 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
switch (info.getStrategy()) {
case Closure.OWNER_FIRST:
- if (!processOwner(processor, state, place)) return false;
- if (!processDelegate(processor, state, place, info.getTypeToDelegate())) return false;
+ if (!processOwner(processor, nonCodeProcessor, state, place)) return false;
+ if (!processDelegate(processor, nonCodeProcessor, state, place, info.getTypeToDelegate())) return false;
return true;
case Closure.DELEGATE_FIRST:
- if (!processDelegate(processor, state, place, info.getTypeToDelegate())) return false;
- if (!processOwner(processor, state, place)) return false;
+ if (!processDelegate(processor, nonCodeProcessor, state, place, info.getTypeToDelegate())) return false;
+ if (!processOwner(processor, nonCodeProcessor, state, place)) return false;
return true;
case Closure.OWNER_ONLY:
- if (!processOwner(processor, state, place)) return false;
+ if (!processOwner(processor, nonCodeProcessor, state, place)) return false;
return true;
case Closure.DELEGATE_ONLY:
- if (!processDelegate(processor, state, place, info.getTypeToDelegate())) return false;
+ if (!processDelegate(processor, nonCodeProcessor, state, place, info.getTypeToDelegate())) return false;
return true;
case Closure.TO_SELF:
return true;
@@ -131,17 +151,17 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
}
private boolean processDelegate(@NotNull PsiScopeProcessor processor,
+ @NotNull PsiScopeProcessor nonCodeProcessor,
@NotNull ResolveState state,
@NotNull PsiElement place,
@Nullable final PsiType classToDelegate) {
- if (classToDelegate != null) {
- if (state.get(ResolverProcessor.RESOLVE_CONTEXT) == null) {
- state = state.put(ResolverProcessor.RESOLVE_CONTEXT, this);
- }
- return ResolveUtil.processAllDeclarations(classToDelegate, processor, state, place);
+ if (classToDelegate == null) return true;
+
+ if (state.get(ResolverProcessor.RESOLVE_CONTEXT) == null) {
+ state = state.put(ResolverProcessor.RESOLVE_CONTEXT, this);
}
- return true;
+ return ResolveUtil.processAllDeclarationsSeparately(classToDelegate, processor, nonCodeProcessor, state.put(ResolverProcessor.RESOLVE_CONTEXT, this), place);
}
private boolean processClosureClassMembers(@NotNull PsiScopeProcessor processor,
@@ -149,44 +169,35 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
@Nullable PsiElement lastParent,
@NotNull PsiElement place) {
final PsiClass closureClass = GroovyPsiManager.getInstance(getProject()).findClassWithCache(GROOVY_LANG_CLOSURE, getResolveScope());
- if (closureClass != null) {
- if (!closureClass.processDeclarations(processor, state, lastParent, place)) return false;
+ if (closureClass == null) return true;
- if (place instanceof GroovyPsiElement) {
- GrClosureType closureType = GrClosureType.create(this, false /*if it is 'true' need-to-prevent-recursion triggers*/);
- if (!ResolveUtil.processNonCodeMembers(closureType, processor, place, state)) {
- return false;
- }
- }
- }
- return true;
+ return closureClass.processDeclarations(processor, state.put(ResolverProcessor.RESOLVE_CONTEXT, this), lastParent, place);
}
private boolean processParameters(@NotNull PsiScopeProcessor processor,
- @NotNull ResolveState _state,
@NotNull ResolveState state,
@NotNull PsiElement place) {
if (hasParametersSection()) {
for (GrParameter parameter : getParameters()) {
- if (!ResolveUtil.processElement(processor, parameter, _state)) return false;
+ if (!ResolveUtil.processElement(processor, parameter, state)) return false;
}
}
else if (!isItAlreadyDeclared(place)) {
GrParameter[] synth = getSyntheticItParameter();
if (synth.length > 0) {
- if (!ResolveUtil.processElement(processor, synth[0], state)) return false;
+ if (!ResolveUtil.processElement(processor, synth[0], state.put(ResolverProcessor.RESOLVE_CONTEXT, this))) return false;
}
}
return true;
}
private boolean processOwner(@NotNull PsiScopeProcessor processor,
+ @NotNull PsiScopeProcessor nonCodeProcessor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
- if (state.get(ResolverProcessor.RESOLVE_CONTEXT) == null) {
- state = state.put(ResolverProcessor.RESOLVE_CONTEXT, this);
- }
- return ResolveUtil.treeWalkUp(getParent(), place, processor, true, state);
+ final PsiElement parent = getParent();
+ if (parent == null) return true;
+ return ResolveUtil.doTreeWalkUp(parent, place, processor, nonCodeProcessor, state);
}
private boolean isItAlreadyDeclared(@Nullable PsiElement place) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java
index 98b25ddb2dd6..50647784792f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
import icons.JetgroovyIcons;
import org.jetbrains.annotations.NotNull;
@@ -427,7 +428,7 @@ public class CompleteReferenceExpression {
return;
}
if (element instanceof GrReferenceExpression) {
- String name = ((GrReferenceExpression)element).getName();
+ String name = ((GrReferenceExpression)element).getReferenceName();
if (!myNonDeclaredVars.add(name)) return;
}
@@ -517,12 +518,22 @@ public class CompleteReferenceExpression {
final GroovyResolveResult[] results = ResolveUtil.filterSameSignatureCandidates(getCandidatesInternal());
List<GroovyResolveResult> list = new ArrayList<GroovyResolveResult>(results.length);
myPropertyNames.removeAll(myPreferredFieldNames);
+
+ Set<String> usedFields = ContainerUtil.newHashSet();
for (GroovyResolveResult result : results) {
final PsiElement element = result.getElement();
- if (element instanceof PsiField &&
- (myPropertyNames.contains(((PsiField)element).getName()) || myLocalVars.contains(((PsiField)element).getName()))) {
- continue;
+ if (element instanceof PsiField) {
+ final String name = ((PsiField)element).getName();
+ if (myPropertyNames.contains(name) ||
+ myLocalVars.contains(name) ||
+ usedFields.contains(name)) {
+ continue;
+ }
+ else {
+ usedFields.add(name);
+ }
}
+
list.add(result);
}
return list.toArray(new GroovyResolveResult[list.size()]);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java
index 843f2c2a1e5a..77f5f19684d1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -150,7 +150,7 @@ public class GrAssignmentExpressionImpl extends GrExpressionImpl implements GrAs
}
private static boolean isDeclarationAssignment(@NotNull GrReferenceExpression lRefExpr, @Nullable String nameHint) {
- if (nameHint == null || nameHint.equals(lRefExpr.getName())) {
+ if (nameHint == null || nameHint.equals(lRefExpr.getReferenceName())) {
final PsiElement target = lRefExpr.resolve(); //this is NOT quadratic since the next statement will prevent from further processing declarations upstream
if (!(target instanceof PsiVariable || target instanceof GrAccessorMethod)) {
return true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
index 1dc3ae8aa8b1..5b591e836bba 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
@@ -38,7 +38,6 @@ import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
@@ -71,6 +70,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.*;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
+import org.jetbrains.plugins.groovy.util.ResolveProfiler;
import java.util.ArrayList;
import java.util.Arrays;
@@ -185,7 +185,10 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
return fieldCandidates;
}
- if (findClassOrPackageAtFirst()) {
+
+ boolean canBeClassOrPackage = ResolveUtil.canBeClassOrPackage(this);
+
+ if (canBeClassOrPackage && findClassOrPackageAtFirst()) {
boolean preferVar = containsLocalVar(fieldCandidates);
if (!preferVar) {
ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds);
@@ -226,12 +229,12 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
}
}
if (fieldCandidates.length > 0) return fieldCandidates;
- if (classCandidates == null) {
+ if (classCandidates == null && canBeClassOrPackage ) {
ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds);
GrReferenceResolveUtil.resolveImpl(classProcessor, this);
classCandidates = classProcessor.getCandidates();
}
- if (classCandidates.length > 0) return classCandidates;
+ if (classCandidates != null && classCandidates.length > 0) return classCandidates;
if (accessorResults.size() > 0) return new GroovyResolveResult[]{accessorResults.get(0)};
return GroovyResolveResult.EMPTY_ARRAY;
}
@@ -744,22 +747,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
return PsiImplUtil.replaceExpression(this, newExpr, removeUnnecessaryParentheses);
}
- public String getName() {
- return getReferenceName();
- }
-
- public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
- PsiElement nameElement = getReferenceNameElement();
- if (nameElement == null) throw new IncorrectOperationException("ref has no name element");
-
- ASTNode node = nameElement.getNode();
- ASTNode newNameNode = GroovyPsiElementFactory.getInstance(getProject()).createReferenceNameFromText(name).getNode();
- LOG.assertTrue(newNameNode != null && node != null);
- node.getTreeParent().replaceChild(node, newNameNode);
-
- return this;
- }
-
@NotNull
private GroovyResolveResult[] doPolyResolve(boolean incompleteCode, boolean genericsMatter) {
String name = getReferenceName();
@@ -772,17 +759,24 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
if (propertyCandidates.length > 0) return propertyCandidates;
}
- switch (getKind()) {
- case METHOD_OR_PROPERTY:
- return resolveMethodOrProperty(false, null, genericsMatter);
- case TYPE_OR_PROPERTY:
- return resolveTypeOrProperty();
- case METHOD_OR_PROPERTY_OR_TYPE:
- GroovyResolveResult[] results = resolveMethodOrProperty(false, null, genericsMatter);
- if (results.length == 0) results = resolveTypeOrProperty();
- return results;
- default:
- return GroovyResolveResult.EMPTY_ARRAY;
+ try {
+ ResolveProfiler.start();
+ switch (getKind()) {
+ case METHOD_OR_PROPERTY:
+ return resolveMethodOrProperty(false, null, genericsMatter);
+ case TYPE_OR_PROPERTY:
+ return resolveTypeOrProperty();
+ case METHOD_OR_PROPERTY_OR_TYPE:
+ GroovyResolveResult[] results = resolveMethodOrProperty(false, null, genericsMatter);
+ if (results.length == 0) results = resolveTypeOrProperty();
+ return results;
+ default:
+ return GroovyResolveResult.EMPTY_ARRAY;
+ }
+ }
+ finally {
+ final long time = ResolveProfiler.finish();
+ ResolveProfiler.write("ref " + getText() + " " + hashCode() + " : " + time);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
index f10a5298d06b..b390e9830766 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
@@ -35,7 +35,6 @@ import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
@@ -49,6 +48,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
import org.jetbrains.plugins.groovy.lang.psi.impl.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureImpl;
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhancer;
+import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrTypeConverter;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.util.LightCacheKey;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java
index e0f606a06b9d..75446d8187a3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -331,8 +331,11 @@ public abstract class GrTypeDefinitionImpl extends GrStubElementBase<GrTypeDefin
private List<GrField> getSyntheticFields() {
List<GrField> fields = AST_TRANSFORM_FIELD.getCachedValue(this);
if (fields == null) {
+ final RecursionGuard.StackStamp stamp = ourGuard.markStack();
fields = AstTransformContributor.runContributorsForFields(this);
- fields = AST_TRANSFORM_FIELD.putCachedValue(this, fields);
+ if (stamp.mayCacheNow()) {
+ fields = AST_TRANSFORM_FIELD.putCachedValue(this, fields);
+ }
}
return fields;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java
index 4b426fb0abe5..1c0324271149 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -132,7 +132,19 @@ public abstract class GrMethodBaseImpl extends GrStubElementBase<GrMethodStub> i
return getParameterList().getParameters();
}
+ @Nullable
public GrTypeElement getReturnTypeElementGroovy() {
+ final GrMethodStub stub = getStub();
+ if (stub != null) {
+ final String typeText = stub.getTypeText();
+ if (typeText != null) {
+ return GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(typeText, this);
+ }
+ else {
+ return null;
+ }
+ }
+
return (GrTypeElement)findChildByType(GroovyElementTypes.TYPE_ELEMENTS);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java
index 8a8f4745343f..b981231c9aa4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrAccessorMethodImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -170,11 +170,13 @@ public class GrAccessorMethodImpl extends LightMethodBuilder implements GrAccess
private static boolean hasContradictingMethods(GrAccessorMethod proto, String fieldName, PsiClass clazz) {
if (clazz == null) return false;
PsiMethod[] methods = clazz instanceof GrTypeDefinition
- ? ((GrTypeDefinition)clazz).findCodeMethodsBySignature(proto, true)
- : clazz.findMethodsBySignature(proto, true);
+ ? ((GrTypeDefinition)clazz).findCodeMethodsByName(proto.getName(), true)
+ : clazz.findMethodsByName(proto.getName(), true);
+ final int paramCount = proto.getParameterList().getParametersCount();
for (PsiMethod method : methods) {
- if (clazz.equals(method.getContainingClass())) return true;
+ if (paramCount != method.getParameterList().getParametersCount()) continue;
+ if (clazz.equals(method.getContainingClass())) return true;
if (PsiUtil.isAccessible(clazz, method) && method.hasModifierProperty(PsiModifier.FINAL)) return true;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightVariable.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightVariable.java
index 56e369d3c876..a22b82c5607c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightVariable.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrLightVariable.java
@@ -1,3 +1,18 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
import com.intellij.psi.*;
@@ -10,6 +25,7 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import java.util.Collections;
@@ -54,7 +70,9 @@ public class GrLightVariable extends GrImplicitVariableImpl implements Navigatab
super(manager, new GrLightIdentifier(manager, name), type, false, scope);
myDeclarations = declarations;
- setNavigationElement(myDeclarations.get(0));
+ if (!myDeclarations.isEmpty()) {
+ setNavigationElement(myDeclarations.get(0));
+ }
}
private static PsiElement getDeclarationScope(PsiElement navigationElement) {
@@ -68,7 +86,12 @@ public class GrLightVariable extends GrImplicitVariableImpl implements Navigatab
@Override
public PsiFile getContainingFile() {
- return myDeclarations.get(0).getContainingFile();
+ if (!myDeclarations.isEmpty()) {
+ return myDeclarations.get(0).getContainingFile();
+ }
+ else {
+ return getDeclarationScope().getContainingFile();
+ }
}
@Override
@@ -118,6 +141,9 @@ public class GrLightVariable extends GrImplicitVariableImpl implements Navigatab
((LeafElement)textToken).replaceWithText(name);
}
+ else if (declaration instanceof GrReferenceExpression) {
+ ((GrReferenceExpression)declaration).handleElementRenameSimple(name);
+ }
}
return getNameIdentifier().replace(new GrLightIdentifier(myManager, name));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java
index b6f594f50be4..b1b21153beb9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java
@@ -33,6 +33,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.dsl.GroovyDslFileIndex;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
@@ -157,7 +158,8 @@ public class GroovyScriptClass extends LightElement implements PsiClass, Synthet
@NotNull
public PsiClassType[] getExtendsListTypes() {
- return new PsiClassType[]{ TypesUtil.createTypeByFQClassName(GroovyCommonClassNames.GROOVY_LANG_SCRIPT, this)};
+ final PsiClassType superClassFromDSL = GroovyDslFileIndex.pocessScriptSuperClasses(myFile);
+ return new PsiClassType[]{ superClassFromDSL != null ? superClassFromDSL : TypesUtil.createTypeByFQClassName(GroovyCommonClassNames.GROOVY_LANG_SCRIPT, this)};
}
@NotNull
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java
index fbb7e0bb01dc..81a9ca0f7078 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -496,14 +496,11 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
final PsiPackage aPackage = JavaPsiFacade.getInstance(ref.getProject()).findPackage(fqName);
if (aPackage != null) return new GroovyResolveResult[]{new GroovyResolveResultImpl(aPackage, true)};
}
- } else if ((kind == CLASS || kind == CLASS_OR_PACKAGE) && qualifierResolved instanceof PsiClass) {
- PsiClass[] classes = ((PsiClass) qualifierResolved).getAllInnerClasses();
- for (final PsiClass aClass : classes) {
- if (refName.equals(aClass.getName())) {
- boolean isAccessible = PsiUtil.isAccessible(ref, aClass);
- return new GroovyResolveResult[]{new GroovyResolveResultImpl(aClass, isAccessible)};
- }
- }
+ }
+ else if ((kind == CLASS || kind == CLASS_OR_PACKAGE) && qualifierResolved instanceof PsiClass) {
+ final ClassResolverProcessor processor = new ClassResolverProcessor(refName, ref);
+ qualifierResolved.processDeclarations(processor, ResolveState.initial(), null, ref);
+ return processor.getCandidates();
}
} else {
EnumSet<ClassHint.ResolveKind> kinds = kind == CLASS ? ResolverProcessor.RESOLVE_KINDS_CLASS :
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GrAnnotationPattern.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GrAnnotationPattern.java
new file mode 100644
index 000000000000..361ea7642337
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GrAnnotationPattern.java
@@ -0,0 +1,42 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.psi.patterns;
+
+import com.intellij.patterns.PatternCondition;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
+
+public class GrAnnotationPattern extends GroovyElementPattern<GrAnnotation, GrAnnotationPattern> {
+ public GrAnnotationPattern() {
+ super(GrAnnotation.class);
+ }
+
+ @NotNull
+ public static GrAnnotationPattern annotation() {
+ return new GrAnnotationPattern();
+ }
+
+ @NotNull
+ public GrAnnotationPattern withQualifiedName(@NotNull final String qname) {
+ return with(new PatternCondition<GrAnnotation>("withQualifiedName") {
+ @Override
+ public boolean accepts(@NotNull GrAnnotation annotation, ProcessingContext context) {
+ return qname.equals(annotation.getQualifiedName());
+ }
+ });
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.java
index f8807a66c361..450a7bd8b077 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.lang.psi.patterns;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PatternCondition;
-import com.intellij.patterns.PlatformPatterns;
import com.intellij.patterns.StandardPatterns;
import com.intellij.psi.PsiMethod;
import com.intellij.util.ProcessingContext;
@@ -70,7 +69,7 @@ public class GroovyMethodCallPattern extends GroovyExpressionPattern<GrCallExpre
GrReferenceExpression refExpression = (GrReferenceExpression)expression;
- return methodName.accepts(refExpression.getName(), context);
+ return methodName.accepts(refExpression.getReferenceName(), context);
}
});
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java
index 92d8d6cb2583..d6854fdea9c8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureParameterEnhancer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,10 +47,10 @@ import static com.intellij.psi.CommonClassNames.JAVA_IO_FILE;
* @author peter
*/
public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer {
- private final Map<String, String> simpleTypes = new HashMap<String, String>();
- private final Set<String> iterations = new HashSet<String>();
+ private static final Map<String, String> simpleTypes = new HashMap<String, String>();
+ private static final Set<String> iterations = new HashSet<String>();
- public ClosureParameterEnhancer() {
+ static {
simpleTypes.put("times", "java.lang.Integer");
simpleTypes.put("upto", "java.lang.Integer");
simpleTypes.put("downto", "java.lang.Integer");
@@ -103,17 +103,25 @@ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer {
iterations.add("findIndexValues");
iterations.add("findIndexOf");
iterations.add("count");
-
}
@Override
@Nullable
protected PsiType getClosureParameterType(GrClosableBlock closure, int index) {
+ if (org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isCompileStatic(closure)) {
+ return null;
+ }
+
+ return inferType(closure, index);
+ }
+
+ @Nullable
+ public static PsiType inferType(@NotNull GrClosableBlock closure, int index) {
PsiElement parent = closure.getParent();
if (parent instanceof GrStringInjection && index == 0) {
return TypesUtil.createTypeByFQClassName("java.io.StringWriter", closure);
}
-
+
if (parent instanceof GrArgumentList) parent = parent.getParent();
if (!(parent instanceof GrMethodCall)) {
return null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrBooleanTypeConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrBooleanTypeConverter.java
new file mode 100644
index 000000000000..b8a936d9e162
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrBooleanTypeConverter.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+
+/**
+ * @author Max Medvedev
+ */
+public class GrBooleanTypeConverter extends GrTypeConverter {
+ @Override
+ public boolean isAllowedInMethodCall() {
+ return false;
+ }
+
+ @Override
+ public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
+ if (PsiType.BOOLEAN.equals(lType) || lType.equalsToText(CommonClassNames.JAVA_LANG_BOOLEAN)) {
+ return !PsiType.NULL.equals(rType);
+ }
+
+
+ return null;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrContainerTypeConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrContainerTypeConverter.java
index f24565cbc131..c350d5b6a141 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrContainerTypeConverter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrContainerTypeConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.plugins.groovy.lang.psi.impl;
+package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiArrayType;
@@ -22,7 +22,6 @@ import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrStringTypeConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrStringTypeConverter.java
index c6d9e6a3f031..8400d59f3206 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrStringTypeConverter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrStringTypeConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.plugins.groovy.lang.psi.impl.types;
+package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.InheritanceUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
-import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GrTypeConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrTypeConverter.java
index dfeca81ba2cd..41f8de907101 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GrTypeConverter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/GrTypeConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.plugins.groovy.lang.psi;
+package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiClass;
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
/**
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java
index d9afcc97c48f..713196a0ea2e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GdkMethodUtil.java
@@ -262,7 +262,7 @@ public class GdkMethodUtil {
@Nullable
private static Pair<PsiClassType, GrReferenceExpression> getTypeToMixIn(GrMethodCall methodCall) {
GrExpression invoked = methodCall.getInvokedExpression();
- if (invoked instanceof GrReferenceExpression) {
+ if (invoked instanceof GrReferenceExpression && GrImportUtil.acceptName((GrReferenceExpression)invoked, "mixin")) {
PsiElement resolved = ((GrReferenceExpression)invoked).resolve();
if (resolved instanceof PsiMethod && isMixinMethod((PsiMethod)resolved)) {
GrExpression qualifier = ((GrReferenceExpression)invoked).getQualifier();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrImportUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrImportUtil.java
new file mode 100644
index 000000000000..96e02cf4bc98
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrImportUtil.java
@@ -0,0 +1,74 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.psi.util;
+
+import com.intellij.psi.PsiFile;
+import com.intellij.util.containers.MultiMapBasedOnSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
+import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.util.LightCacheKey;
+
+import java.util.Collection;
+
+/**
+ * @author Max Medvedev
+ */
+public class GrImportUtil {
+ private static final LightCacheKey<MultiMapBasedOnSet<String, String>> KEY = LightCacheKey.createByFileModificationCount();
+
+ public static boolean acceptName(GrReferenceElement ref, String expected) {
+ final String actual = ref.getReferenceName();
+ if (expected.equals(actual)) return true;
+
+ if (ref.getQualifier() != null) return false;
+
+ final PsiFile file = ref.getContainingFile();
+ if (file instanceof GroovyFile) {
+ MultiMapBasedOnSet<String, String> data = KEY.getCachedValue(file);
+ if (data == null) {
+ data = collectAliases((GroovyFile)file);
+ KEY.putCachedValue(file, data);
+ }
+
+ final Collection<String> aliases = data.get(expected);
+ return aliases.contains(actual);
+ }
+
+
+ return false;
+ }
+
+ @NotNull
+ private static MultiMapBasedOnSet<String, String> collectAliases(@NotNull GroovyFile file) {
+ MultiMapBasedOnSet<String, String> aliases = new MultiMapBasedOnSet<String, String>();
+
+ for (GrImportStatement anImport : file.getImportStatements()) {
+ if (anImport.isAliasedImport()) {
+ final GrCodeReferenceElement importReference = anImport.getImportReference();
+ if (importReference != null) {
+ final String refName = importReference.getReferenceName();
+ if (refName != null) {
+ aliases.putValue(refName, anImport.getImportedName());
+ }
+ }
+ }
+ }
+ return aliases;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
index 14aecb3dfa63..621da572a765 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -223,7 +223,7 @@ public class PsiUtil {
}
@Nullable
- public static GrArgumentList getArgumentsList(PsiElement methodRef) {
+ public static GrArgumentList getArgumentsList(@Nullable PsiElement methodRef) {
if (methodRef instanceof GrEnumConstant) return ((GrEnumConstant)methodRef).getArgumentList();
PsiElement parent = methodRef.getParent();
if (parent instanceof GrCall) {
@@ -1031,6 +1031,8 @@ public class PsiUtil {
}
public static boolean isExpressionStatement(@NotNull PsiElement expr) {
+ if (!(expr instanceof GrStatement)) return false;
+
final PsiElement parent = expr.getParent();
if (parent instanceof GrControlFlowOwner || parent instanceof GrCaseSection) return true;
if (parent instanceof GrIfStatement &&
@@ -1121,7 +1123,11 @@ public class PsiUtil {
parent instanceof GrVariable) {
return true;
}
- final GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(expr);
+ return isReturnStatement(expr);
+ }
+
+ public static boolean isReturnStatement(@NotNull PsiElement statement) {
+ final GrControlFlowOwner controlFlowOwner = ControlFlowUtils.findControlFlowOwner(statement);
if (controlFlowOwner instanceof GrOpenBlock) {
final PsiElement controlFlowOwnerParent = controlFlowOwner.getParent();
if (controlFlowOwnerParent instanceof GrMethod && ((GrMethod)controlFlowOwnerParent).isConstructor()) {
@@ -1132,7 +1138,7 @@ public class PsiUtil {
}
}
//noinspection SuspiciousMethodCalls
- return ControlFlowUtils.collectReturns(controlFlowOwner, true).contains(expr);
+ return ControlFlowUtils.collectReturns(controlFlowOwner, true).contains(statement);
}
@Nullable
@@ -1168,7 +1174,7 @@ public class PsiUtil {
GrReferenceExpression ref = (GrReferenceExpression)element;
- return !ref.isQualified() && name.equals(ref.getName());
+ return !ref.isQualified() && name.equals(ref.getReferenceName());
}
@Nullable
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/StaticChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/StaticChecker.java
index dfe566dc15a3..fc831c0dd112 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/StaticChecker.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/StaticChecker.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
@@ -34,8 +35,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe
* @author Max Medvedev
*/
public class StaticChecker {
- public static boolean isStaticsOK(PsiModifierListOwner member,
- PsiElement place,
+ public static boolean isStaticsOK(@NotNull PsiModifierListOwner member,
+ @NotNull PsiElement place,
@Nullable PsiElement resolveContext,
boolean filterStaticAfterInstanceQualifier) {
if (!(member instanceof PsiMember)) return true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java
index ede153f47a0b..5ff1ade5b9e0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@ import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import java.util.ArrayList;
@@ -86,13 +85,19 @@ public class CollectClassMembersUtil {
Map<String, List<CandidateInfo>> allMethods = new HashMap<String, List<CandidateInfo>>();
Map<String, CandidateInfo> allInnerClasses = new HashMap<String, CandidateInfo>();
- processClass(aClass, allFields, allMethods, allInnerClasses, new HashSet<PsiClass>(), PsiSubstitutor.EMPTY, includeSynthetic, true);
+ processClass(aClass, allFields, allMethods, allInnerClasses, new HashSet<PsiClass>(), PsiSubstitutor.EMPTY, includeSynthetic);
return Result.create(Trinity.create(allFields, allMethods, allInnerClasses), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
}
}, false);
}
- private static void processClass(PsiClass aClass, Map<String, CandidateInfo> allFields, Map<String, List<CandidateInfo>> allMethods, Map<String, CandidateInfo> allInnerClasses, Set<PsiClass> visitedClasses, PsiSubstitutor substitutor, boolean includeSynthetic, boolean shouldProcessInnerClasses) {
+ private static void processClass(PsiClass aClass,
+ Map<String, CandidateInfo> allFields,
+ Map<String, List<CandidateInfo>> allMethods,
+ Map<String, CandidateInfo> allInnerClasses,
+ Set<PsiClass> visitedClasses,
+ PsiSubstitutor substitutor,
+ boolean includeSynthetic) {
LOG.assertTrue(aClass.isValid());
if (!visitedClasses.add(aClass)) return;
@@ -118,12 +123,10 @@ public class CollectClassMembersUtil {
addMethod(allMethods, method, substitutor);
}
- if (shouldProcessInnerClasses) {
- for (final PsiClass inner : aClass.getInnerClasses()) {
- final String name = inner.getName();
- if (name != null && !allInnerClasses.containsKey(name)) {
- allInnerClasses.put(name, new CandidateInfo(inner, substitutor));
- }
+ for (final PsiClass inner : aClass.getInnerClasses()) {
+ final String name = inner.getName();
+ if (name != null && !allInnerClasses.containsKey(name)) {
+ allInnerClasses.put(name, new CandidateInfo(inner, substitutor));
}
}
@@ -131,8 +134,7 @@ public class CollectClassMembersUtil {
PsiClass superClass = superType.resolve();
if (superClass != null) {
final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, substitutor);
- processClass(superClass, allFields, allMethods, allInnerClasses, visitedClasses, superSubstitutor, includeSynthetic,
- shouldProcessInnerClasses && !(aClass instanceof GrAnonymousClassDefinition));
+ processClass(superClass, allFields, allMethods, allInnerClasses, visitedClasses, superSubstitutor, includeSynthetic);
}
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/DeclarationCacheKey.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/DeclarationCacheKey.java
index 55a9e7af8be7..32ed1cb1154d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/DeclarationCacheKey.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/DeclarationCacheKey.java
@@ -124,7 +124,7 @@ class DeclarationCacheKey {
@Override
public boolean process(PsiElement scope, PsiElement lastParent) {
result.add(collectScopeDeclarations(scope, lastParent));
- if (scope instanceof GrClosableBlock) return false; //closures tree walk up themselves
+ if (nonCode && scope instanceof GrClosableBlock) return false; //closures tree walk up themselves if non code declarataions are acepted
return true;
}
});
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java
index a9beffbe8a10..fc5a5cf5de7d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java
@@ -16,6 +16,8 @@
package org.jetbrains.plugins.groovy.lang.resolve;
+import com.intellij.diagnostic.LogMessageEx;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
@@ -51,6 +53,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethod
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
@@ -62,6 +65,8 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter;
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrScriptField;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
@@ -80,6 +85,8 @@ import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getSmartReturnT
*/
@SuppressWarnings({"StringBufferReplaceableByString"})
public class ResolveUtil {
+ private static final Logger LOG = Logger.getInstance(ResolveUtil.class);
+
public static final PsiScopeProcessor.Event DECLARATION_SCOPE_PASSED = new PsiScopeProcessor.Event() {};
private ResolveUtil() {
@@ -92,7 +99,7 @@ public class ResolveUtil {
* @param processNonCodeMethods - this parameter tells us if we need non code members
* @return
*/
- public static boolean treeWalkUp(@NotNull final GroovyPsiElement place,
+ public static boolean treeWalkUp(@NotNull final PsiElement place,
@NotNull final PsiScopeProcessor processor,
boolean processNonCodeMethods) {
return treeWalkUp(place, place, processor, processNonCodeMethods, ResolveState.initial());
@@ -111,19 +118,34 @@ public class ResolveUtil {
@NotNull final PsiScopeProcessor processor,
boolean processNonCodeMethods,
@NotNull final ResolveState state) {
+ try {
ClassHint hint = processor.getHint(ClassHint.KEY);
if (hint != null) {
return new DeclarationCacheKey(getNameHint(processor), hint, processNonCodeMethods, originalPlace).processCachedDeclarations(place, processor);
}
final PsiScopeProcessor nonCodeProcessor = processNonCodeMethods ? processor : null;
- return PsiTreeUtil.treeWalkUp(place, null, new PairProcessor<PsiElement, PsiElement>() {
+ return doTreeWalkUp(place, originalPlace, processor, nonCodeProcessor, state);
+ }
+ catch (StackOverflowError e) {
+ LogMessageEx.error(LOG, "StackOverflow", e, place.getContainingFile().getText());
+ throw e;
+ }
+ }
+
+ public static boolean doTreeWalkUp(@NotNull final PsiElement place,
+ @NotNull final PsiElement originalPlace,
+ @NotNull final PsiScopeProcessor processor,
+ @Nullable final PsiScopeProcessor nonCodeProcessor,
+ @NotNull final ResolveState state) {
+ final GrClosableBlock maxScope = nonCodeProcessor != null ? PsiTreeUtil.getParentOfType(place, GrClosableBlock.class, true, PsiFile.class) : null;
+
+ return PsiTreeUtil.treeWalkUp(place, maxScope, new PairProcessor<PsiElement, PsiElement>() {
@Override
public boolean process(PsiElement scope, PsiElement lastParent) {
if (!doProcessDeclarations(originalPlace, lastParent, scope, substituteProcessor(processor, scope), nonCodeProcessor, state)) {
return false;
}
- if (scope instanceof GrClosableBlock) return false; //closures tree walk up themselves
issueLevelChangeEvents(processor, scope);
return true;
}
@@ -136,7 +158,12 @@ public class ResolveUtil {
@NotNull PsiScopeProcessor plainProcessor,
@Nullable PsiScopeProcessor nonCodeProcessor,
@NotNull ResolveState state) {
- if (!scope.processDeclarations(plainProcessor, state, lastParent, place)) return false;
+ if (scope instanceof GrClosableBlock && nonCodeProcessor != null) {
+ if (!((GrClosableBlock)scope).processClosureDeclarations(plainProcessor, nonCodeProcessor, state, lastParent, place)) return false;
+ }
+ else {
+ if (!scope.processDeclarations(plainProcessor, state, lastParent, place)) return false;
+ }
if (nonCodeProcessor != null && !processScopeNonCodeMethods(place, lastParent, nonCodeProcessor, scope)) return false;
return true;
}
@@ -180,10 +207,13 @@ public class ResolveUtil {
}
if (scope instanceof GrClosableBlock) {
+ ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, scope);
+
PsiClass superClass = getLiteralSuperClass((GrClosableBlock)scope);
- if (superClass != null && !superClass.processDeclarations(processor, ResolveState.initial(), null, place)) return false;
+ if (superClass != null && !superClass.processDeclarations(processor, state, null, place)) return false;
- if (!GdkMethodUtil.categoryIteration((GrClosableBlock)scope, processor, ResolveState.initial())) return false;
+ if (!GdkMethodUtil.categoryIteration((GrClosableBlock)scope, processor, state)) return false;
+ if (!processNonCodeMembers(GrClosureType.create(((GrClosableBlock)scope), false), processor, place, state)) return false;
}
if (scope instanceof GrStatementOwner) {
@@ -222,7 +252,7 @@ public class ResolveUtil {
return nameHint.getName(ResolveState.initial());
}
- public static boolean processElement(PsiScopeProcessor processor, PsiNamedElement namedElement, ResolveState state) {
+ public static boolean processElement(@NotNull PsiScopeProcessor processor, @NotNull PsiNamedElement namedElement, @NotNull ResolveState state) {
NameHint nameHint = processor.getHint(NameHint.KEY);
String name = nameHint == null ? null : nameHint.getName(state);
if (name == null || name.equals(namedElement.getName())) {
@@ -236,6 +266,14 @@ public class ResolveUtil {
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place) {
+ return processAllDeclarationsSeparately(type, processor, processor, state, place);
+ }
+
+ public static boolean processAllDeclarationsSeparately(@NotNull PsiType type,
+ @NotNull PsiScopeProcessor processor,
+ @NotNull PsiScopeProcessor nonCodeProcessor,
+ @NotNull ResolveState state,
+ @NotNull PsiElement place) {
if (type instanceof PsiClassType) {
final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)type).resolveGenerics();
final PsiClass psiClass = resolveResult.getElement();
@@ -245,8 +283,8 @@ public class ResolveUtil {
if (!psiClass.processDeclarations(processor, state, null, place)) return false;
}
}
- if (!processNonCodeMembers(type, processor, place, state)) return false;
- if (!processCategoryMembers(place, processor, state)) return false;
+ if (!processNonCodeMembers(type, nonCodeProcessor, place, state)) return false;
+ if (!processCategoryMembers(place, nonCodeProcessor, state)) return false;
return true;
}
@@ -354,7 +392,7 @@ public class ResolveUtil {
}
@Nullable
- public static <T> T resolveExistingElement(GroovyPsiElement place, ResolverProcessor processor, Class<? extends T>... classes) {
+ public static <T> T resolveExistingElement(PsiElement place, ResolverProcessor processor, Class<? extends T>... classes) {
treeWalkUp(place, processor, true);
final GroovyResolveResult[] candidates = processor.getCandidates();
for (GroovyResolveResult candidate : candidates) {
@@ -787,7 +825,7 @@ public class ResolveUtil {
return null;
}
- public static boolean isEnumConstant(GrReferenceExpression ref, String name, String qName) {
+ public static boolean isEnumConstant(PsiReference ref, String name, String qName) {
PsiElement resolved = ref.resolve();
if (!(resolved instanceof PsiEnumConstant)) return false;
if (!name.equals(((PsiEnumConstant)resolved).getName())) return false;
@@ -829,4 +867,83 @@ public class ResolveUtil {
}
return "";
}
+
+ public static PsiNamedElement findDuplicate(@NotNull GrVariable variable) {
+ if (isScriptField(variable)) {
+ final String name = variable.getName();
+
+ int count = 0;
+ final GroovyScriptClass script = (GroovyScriptClass)((GroovyFile)variable.getContainingFile()).getScriptClass();
+ assert script != null;
+ for (GrScriptField field : GrScriptField.getScriptFields(script)) {
+ if (name.equals(field.getName())) count++;
+ }
+
+ return count > 1 ? GrScriptField.getScriptField(variable) : null;
+ }
+ else {
+ PsiNamedElement duplicate = resolveExistingElement(variable, new DuplicateVariablesProcessor(variable), GrVariable.class);
+ final PsiElement context1 = variable.getContext();
+ if (duplicate == null && variable instanceof GrParameter && context1 != null) {
+ final PsiElement context = context1.getContext();
+ if (context instanceof GrClosableBlock ||
+ context instanceof GrMethod && !(context.getParent() instanceof GroovyFile) ||
+ context instanceof GrTryCatchStatement) {
+ duplicate = resolveExistingElement(context.getParent(), new DuplicateVariablesProcessor(variable), GrVariable.class);
+ }
+ }
+ if (duplicate instanceof GrLightParameter && "args".equals(duplicate.getName())) {
+ return null;
+ }
+ else {
+ return duplicate;
+ }
+ }
+ }
+
+ public static boolean canBeClassOrPackage(final GrReferenceExpression ref) {
+ GrExpression qualifier = ref.getQualifier();
+ if (qualifier instanceof GrReferenceExpression) {
+ final PsiElement resolvedQualifier = ((GrReferenceExpression)qualifier).resolve();
+ return resolvedQualifier instanceof PsiClass || resolvedQualifier instanceof PsiPackage;
+ }
+ else {
+ return qualifier == null;
+ }
+ }
+
+ private static class DuplicateVariablesProcessor extends PropertyResolverProcessor {
+ private boolean myBorderPassed;
+ private final boolean myHasVisibilityModifier;
+
+ public DuplicateVariablesProcessor(GrVariable variable) {
+ super(variable.getName(), variable);
+ myBorderPassed = false;
+ myHasVisibilityModifier = hasExplicitVisibilityModifiers(variable);
+ }
+
+ private static boolean hasExplicitVisibilityModifiers(GrVariable variable) {
+ final GrModifierList modifierList = variable.getModifierList();
+ return modifierList != null && modifierList.hasExplicitVisibilityModifiers();
+ }
+
+ @Override
+ public boolean execute(@NotNull PsiElement element, ResolveState state) {
+ if (myBorderPassed) {
+ return false;
+ }
+ if (element instanceof GrVariable && hasExplicitVisibilityModifiers((GrVariable)element) != myHasVisibilityModifier) {
+ return true;
+ }
+ return super.execute(element, state);
+ }
+
+ @Override
+ public void handleEvent(Event event, Object associated) {
+ if (event == DECLARATION_SCOPE_PASSED) {
+ myBorderPassed = true;
+ }
+ super.handleEvent(event, associated);
+ }
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java
index b2ce9d8e6b0d..f51a5b2328e5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ public abstract class AstTransformContributor {
}
+ @NotNull
public static Collection<PsiMethod> runContributorsForMethods(@NotNull final GrTypeDefinition clazz) {
Collection<PsiMethod> result = RecursionManager.doPreventingRecursion(clazz, true, new Computable<Collection<PsiMethod>>() {
@Override
@@ -56,8 +57,9 @@ public abstract class AstTransformContributor {
return result == null ? Collections.<PsiMethod>emptyList() : result;
}
+ @NotNull
public static List<GrField> runContributorsForFields(@NotNull final GrTypeDefinition clazz) {
- List<GrField> result = RecursionManager.doPreventingRecursion(clazz, true, new Computable<List<GrField>>() {
+ List<GrField> fields = RecursionManager.doPreventingRecursion(clazz, true, new Computable<List<GrField>>() {
@Override
public List<GrField> compute() {
List<GrField> collector = new ArrayList<GrField>();
@@ -67,6 +69,6 @@ public abstract class AstTransformContributor {
return collector;
}
});
- return result == null ? Collections.<GrField>emptyList() : result;
+ return fields != null ? fields : Collections.<GrField>emptyList();
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java
index 2d74477e5088..49aa848fdeb5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@ import java.util.Collection;
public class AutoCloneContributor extends AstTransformContributor {
@Override
- public void collectMethods(@NotNull GrTypeDefinition clazz, Collection<PsiMethod> collector) {
+ public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Collection<PsiMethod> collector) {
if (PsiImplUtil.getAnnotation(clazz, GroovyCommonClassNames.GROOVY_TRANSFORM_AUTO_CLONE) == null) return;
final LightMethodBuilder clone = new LightMethodBuilder(clazz.getManager(), "clone");
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java
index 36f51decf6a3..a205adb1edda 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ import java.util.Collection;
public class AutoExternalizeContributor extends AstTransformContributor {
@Override
- public void collectMethods(@NotNull GrTypeDefinition clazz, Collection<PsiMethod> collector) {
+ public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Collection<PsiMethod> collector) {
if (!hasGeneratedImplementations(clazz)) return;
final LightMethodBuilder write = new LightMethodBuilder(clazz.getManager(), "writeExternal");
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java
index edd63bb565f7..537a4e486175 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java
@@ -41,7 +41,7 @@ import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.
public class ConstructorAnnotationsProcessor extends AstTransformContributor {
@Override
- public void collectMethods(@NotNull GrTypeDefinition typeDefinition, Collection<PsiMethod> collector) {
+ public void collectMethods(@NotNull GrTypeDefinition typeDefinition, @NotNull Collection<PsiMethod> collector) {
if (typeDefinition.getName() == null) return;
PsiModifierList modifierList = typeDefinition.getModifierList();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethod.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethod.java
index 9e6a348eaed6..8ae8eda2d1d6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethod.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,11 +27,12 @@ import org.jetbrains.annotations.Nullable;
* @author Max Medvedev
*/
public class DelegatedMethod extends LightMethod implements PsiMethod, PsiMirrorElement, OriginInfoAwareElement {
- private PsiMethod myPrototype;
+ private final PsiMethod myPrototype;
public DelegatedMethod(@NotNull PsiMethod delegate, @NotNull PsiMethod prototype) {
- super(prototype.getManager(), delegate, delegate.getContainingClass());
+ super(prototype.getManager(), delegate, delegate.getContainingClass(), delegate.getLanguage());
myPrototype = prototype;
+ setNavigationElement(myPrototype);
}
@NotNull
@@ -44,7 +45,7 @@ public class DelegatedMethod extends LightMethod implements PsiMethod, PsiMirror
@Override
public String getOriginInfo() {
PsiClass aClass = myPrototype.getContainingClass();
- if (aClass != null & aClass.getName() != null) {
+ if (aClass != null && aClass.getName() != null) {
return "delegates to " + aClass.getName();
}
return null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java
index db77019a0b45..546cdac6c644 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,7 +48,7 @@ import java.util.*;
*/
public class DelegatedMethodsContributor extends AstTransformContributor {
@Override
- public void collectMethods(@NotNull final GrTypeDefinition clazz, Collection<PsiMethod> collector) {
+ public void collectMethods(@NotNull final GrTypeDefinition clazz, @NotNull Collection<PsiMethod> collector) {
Set<PsiClass> processed = new HashSet<PsiClass>();
if (!checkForDelegate(clazz)) return;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java
index 5af151aaca7d..d8d7ba6645b7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@ import java.util.Collection;
public class GrInheritConstructorContributor extends AstTransformContributor {
@Override
- public void collectMethods(@NotNull GrTypeDefinition psiClass, Collection<PsiMethod> collector) {
+ public void collectMethods(@NotNull GrTypeDefinition psiClass, @NotNull Collection<PsiMethod> collector) {
if (psiClass.isAnonymous() || psiClass.isInterface() || psiClass.isEnum()) {
return;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java
index 1ca8c0902733..00844583a839 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,7 @@ public class LoggingContributor extends AstTransformContributor {
build();
@Override
- public void collectFields(@NotNull GrTypeDefinition psiClass, Collection<GrField> collector) {
+ public void collectFields(@NotNull GrTypeDefinition psiClass, @NotNull Collection<GrField> collector) {
GrModifierList modifierList = psiClass.getModifierList();
if (modifierList == null) return;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java
index 7b3ee914c06d..1fcda2d575c7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.lang.resolve.processors;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
@@ -36,13 +35,13 @@ public class AccessorResolverProcessor extends MethodResolverProcessor {
private final SubstitutorComputer mySubstitutorComputer;
- public AccessorResolverProcessor(String accessorName, String propertyName, GroovyPsiElement place, boolean searchForGetter) {
+ public AccessorResolverProcessor(@Nullable String accessorName, @NotNull String propertyName, @NotNull PsiElement place, boolean searchForGetter) {
this(accessorName, propertyName, place, searchForGetter, false, null, PsiType.EMPTY_ARRAY);
}
- public AccessorResolverProcessor(String accessorName,
- String propertyName,
- PsiElement place,
+ public AccessorResolverProcessor(@Nullable String accessorName,
+ @NotNull String propertyName,
+ @NotNull PsiElement place,
boolean searchForGetter,
boolean byShape,
@Nullable PsiType thisType,
@@ -54,7 +53,7 @@ public class AccessorResolverProcessor extends MethodResolverProcessor {
mySubstitutorComputer = byShape ? null : new SubstitutorComputer(thisType, PsiType.EMPTY_ARRAY, typeArguments, false, place, myPlace);
}
- public boolean execute(@NotNull PsiElement element, ResolveState state) {
+ public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
final PsiElement resolveContext = state.get(RESOLVE_CONTEXT);
String importedName = resolveContext instanceof GrImportStatement ? ((GrImportStatement)resolveContext).getImportedName() : null;
if (mySearchForGetter) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java
index 40fb862b0f3d..b96a89543647 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java
@@ -63,17 +63,23 @@ public class MethodResolverProcessor extends ResolverProcessor {
private final boolean myTypedContext;
- public MethodResolverProcessor(String name, GroovyPsiElement place, boolean isConstructor, PsiType thisType, @Nullable PsiType[] argumentTypes, PsiType[] typeArguments) {
+ public MethodResolverProcessor(@Nullable String name,
+ @NotNull GroovyPsiElement place,
+ boolean isConstructor,
+ @Nullable PsiType thisType,
+ @Nullable PsiType[] argumentTypes,
+ @Nullable PsiType[] typeArguments) {
this(name, place, isConstructor, thisType, argumentTypes, typeArguments, false, false);
}
- public MethodResolverProcessor(String name,
- PsiElement place,
+ public MethodResolverProcessor(@Nullable String name,
+ @NotNull PsiElement place,
boolean isConstructor,
- PsiType thisType,
+ @Nullable PsiType thisType,
@Nullable PsiType[] argumentTypes,
- PsiType[] typeArguments,
- boolean allVariants, final boolean byShape) {
+ @Nullable PsiType[] typeArguments,
+ boolean allVariants,
+ final boolean byShape) {
super(name, RESOLVE_KINDS_METHOD_PROPERTY, place, PsiType.EMPTY_ARRAY);
myIsConstructor = isConstructor;
myThisType = thisType;
@@ -86,7 +92,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
}
- public boolean execute(@NotNull PsiElement element, ResolveState state) {
+ public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
if (myStopExecuting) {
return false;
}
@@ -318,7 +324,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
return true;
}
- private boolean typesAgree(PsiType type1, PsiType type2) {
+ private boolean typesAgree(@NotNull PsiType type1, @NotNull PsiType type2) {
if (argumentsSupplied() && type1 instanceof PsiArrayType && !(type2 instanceof PsiArrayType)) {
type1 = ((PsiArrayType) type1).getComponentType();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java
index 93571229a258..52344759b9df 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ public class PropertyResolverProcessor extends ResolverProcessor {
@Override
public boolean execute(@NotNull PsiElement element, ResolveState state) {
- return super.execute(element, state) || state.get(RESOLVE_CONTEXT) != null;
+ return super.execute(element, state) || element instanceof PsiField;
}
@NotNull
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java
index f29c12716425..166101f42d54 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.lang.resolve.processors;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
+import com.intellij.psi.impl.light.LightElement;
import com.intellij.psi.impl.source.tree.java.PsiLocalVariableImpl;
import com.intellij.psi.scope.ElementClassHint;
import com.intellij.psi.scope.NameHint;
@@ -60,8 +61,8 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint
private List<GroovyResolveResult> myCandidates;
protected ResolverProcessor(@Nullable String name,
- EnumSet<ResolveKind> resolveTargets,
- PsiElement place,
+ @NotNull EnumSet<ResolveKind> resolveTargets,
+ @NotNull PsiElement place,
@NotNull PsiType[] typeArguments) {
myName = name;
myResolveTargetKinds = resolveTargets;
@@ -69,7 +70,7 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint
myTypeArguments = typeArguments;
}
- public boolean execute(@NotNull PsiElement element, ResolveState state) {
+ public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
if (element instanceof PsiLocalVariableImpl) { //todo a better hack
return true; // the debugger creates a Java code block context and our expressions to evaluate resolve there
}
@@ -102,25 +103,39 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint
final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE);
boolean isStaticsOK = isStaticsOK(namedElement, resolveContext, true);
addCandidate(new GroovyResolveResultImpl(namedElement, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK));
- return !isAccessible || !isStaticsOK;
+ return !(isAccessible && isStaticsOK);
}
return true;
}
- protected final void addCandidate(GroovyResolveResult candidate) {
+ protected final void addCandidate(@NotNull GroovyResolveResult candidate) {
PsiElement element = candidate.getElement();
- assert element == null || element.isValid() : "invalid resolve candidate: " + element.getClass();
+ assert element == null || element.isValid() : getElementInfo(element);
if (myCandidates == null) myCandidates = new ArrayList<GroovyResolveResult>();
myCandidates.add(candidate);
}
+ @NotNull
+ private static String getElementInfo(@NotNull PsiElement element) {
+ String text;
+ if (element instanceof LightElement) {
+ final PsiElement context = element.getContext();
+ text = context != null ? context.getText() : null;
+ }
+ else {
+ text = element.getText();
+ }
+ return "invalid resolve candidate: " + element.getClass() + ", text: " + text;
+ }
+
+ @NotNull
protected List<GroovyResolveResult> getCandidatesInternal() {
return myCandidates == null ? Collections.<GroovyResolveResult>emptyList() : myCandidates;
}
- protected boolean isAccessible(PsiNamedElement namedElement) {
+ protected boolean isAccessible(@NotNull PsiNamedElement namedElement) {
if (namedElement instanceof GrField) {
final GrField field = (GrField)namedElement;
if (PsiUtil.isAccessible(myPlace, field)) {
@@ -144,7 +159,7 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint
PsiUtil.isAccessible(myPlace, ((PsiMember)namedElement));
}
- protected boolean isStaticsOK(PsiNamedElement element, PsiElement resolveContext, boolean filterStaticAfterInstanceQualifier) {
+ protected boolean isStaticsOK(@NotNull PsiNamedElement element, @Nullable PsiElement resolveContext, boolean filterStaticAfterInstanceQualifier) {
if (resolveContext instanceof GrImportStatement) return true;
if (element instanceof PsiModifierListOwner) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java
index 4e1d21d756fa..7198f2a1ba47 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java
@@ -24,7 +24,6 @@ import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.stubs.StubIndex;
-import com.intellij.psi.stubs.StubIndexImpl;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.Processor;
@@ -97,8 +96,8 @@ public class GroovyShortNamesCache extends PsiShortNamesCache {
private List<PsiClass> addClasses(String name, GlobalSearchScope scope, boolean inSource) {
final List<PsiClass> result = new ArrayList<PsiClass>(getScriptClassesByFQName(name, scope, inSource));
- for (PsiElement psiClass : StubIndexImpl.safeGet(GrFullClassNameIndex.KEY, name.hashCode(), myProject,
- inSource ? new GrSourceFilterScope(scope) : scope, PsiClass.class)) {
+ for (PsiElement psiClass : StubIndex.getInstance().safeGet(GrFullClassNameIndex.KEY, name.hashCode(), myProject,
+ inSource ? new GrSourceFilterScope(scope) : scope, PsiClass.class)) {
//hashcode doesn't guarantee equals
if (name.equals(((PsiClass)psiClass).getQualifiedName())) {
result.add((PsiClass)psiClass);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcConsole.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcConsole.java
index e89bc9abc7a1..5630145ba68f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcConsole.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcConsole.java
@@ -48,7 +48,7 @@ import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
-import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
import icons.JetgroovyIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -147,7 +147,7 @@ public class MvcConsole implements Disposable {
final boolean closeOnDone;
final boolean showConsole;
final String[] input;
- private final List<ProcessListener> myListeners = new SmartList<ProcessListener>();
+ private final List<ProcessListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private OSProcessHandler myHandler;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
index 44190d8d0411..246321eff735 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
@@ -41,7 +41,6 @@ import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ModificationTracker;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
@@ -54,7 +53,6 @@ import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.PathsList;
import com.intellij.util.containers.ContainerUtil;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java
index 19dbd1bc2928..eba38f0454fc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -93,7 +93,7 @@ public class GroovyNameSuggestionUtil {
}
private static void generateNameByExpr(GrExpression expr, Set<String> possibleNames, NameValidator validator, boolean forStaticVariable) {
- if (expr instanceof GrReferenceExpression && ((GrReferenceExpression) expr).getName() != null) {
+ if (expr instanceof GrReferenceExpression && ((GrReferenceExpression) expr).getReferenceName() != null) {
if (PsiUtil.isThisReference(expr)) {
possibleNames.add(validator.validateName("thisInstance", true));
}
@@ -101,7 +101,7 @@ public class GroovyNameSuggestionUtil {
possibleNames.add(validator.validateName("superInstance", true));
}
GrReferenceExpression refExpr = (GrReferenceExpression) expr;
- String name = refExpr.getName();
+ String name = refExpr.getReferenceName();
if (name != null && name.toUpperCase().equals(name)) {
possibleNames.add(validator.validateName(name.toLowerCase(), true));
} else {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties
index af474f9692a3..8663a38115da 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties
@@ -173,3 +173,4 @@ rename.groovy.method=Rename Groovy method
cannot.inline.0.=Cannot inline {0}
ref.0.will.not.be.resolved.outside.of.current.context=Reference ''{0}'' will not be resolved outside of current context
cannot.rename.property.0=Cannot rename property <bold>''{0}''</bold> which overrides method <bold>''{1}''</bold>
+cannot.inline.reference.0=Cannot inline reference ''{0}''
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java
index 23222507f71f..046cdde417f8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NullUtils;
import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
@@ -49,10 +50,10 @@ class ArgumentListGenerator {
}
public void generate(@Nullable GrClosureSignature signature,
- GrExpression[] exprs,
- GrNamedArgument[] namedArgs,
- GrClosableBlock[] clArgs,
- GroovyPsiElement context) {
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] clArgs,
+ @NotNull GroovyPsiElement context) {
GrClosureSignatureUtil.ArgInfo<PsiElement>[] argInfos =
signature == null ? null : GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, clArgs, context, false, false);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java
index 97d1caba3cd3..bc6882b5ce85 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java
@@ -37,7 +37,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
@@ -384,116 +383,7 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator {
}, entries);
}
for (Map.Entry<PsiMethod, String> entry : entries) {
- PsiMethod setter = entry.getKey();
- if (setter instanceof PsiCompiledElement) setter = (PsiMethod)((PsiCompiledElement)setter).getMirror();
- String name = entry.getValue();
- PsiParameter[] parameters = setter.getParameterList().getParameters();
- PsiParameter parameter = parameters[parameters.length - 1];
- final PsiType parameterType = context.typeProvider.getParameterType(parameter);
-
-
- //type parameters
- builder.append("private static ");
- if (setter.hasTypeParameters()) {
- writeTypeParameters(builder, setter, classNameProvider);
- }
-
- if (parameterType instanceof PsiPrimitiveType) {
- builder.append(parameterType.getCanonicalText()).append(' ');
- }
- else {
- if (setter.hasTypeParameters()) {
- builder.delete(builder.length()-1, builder.length());
- //builder.removeFromTheEnd(1);
- builder.append(", ");
- }
- else {
- builder.append('<');
- }
- builder.append("Value");
- if (!parameterType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
- builder.append(" extends ");
- writeType(builder, parameterType, psiClass, classNameProvider);
- }
- builder.append('>');
- builder.append("Value ");
- }
- builder.append(name);
-
- final boolean isStatic = setter.hasModifierProperty(PsiModifier.STATIC);
-
-
- final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.project);
-
- if (!(parameterType instanceof PsiPrimitiveType)) {
- parameter = factory.createParameter(parameter.getName(), "Value", null);
- }
-
- //parameters
- parameters[parameters.length - 1] = parameter;
- PsiParameter[] actual;
- if (isStatic) {
- actual = parameters;
- }
- else {
- final String typeText;
- final PsiClass containingClass = setter.getContainingClass();
- if (containingClass == null) {
- if (setter instanceof GrGdkMethod) {
- typeText = ((GrGdkMethod)setter).getStaticMethod().getParameterList().getParameters()[0].getType().getCanonicalText();
- }
- else {
- typeText = CommonClassNames.JAVA_LANG_OBJECT;
- }
- }
- else {
- typeText = containingClass.getQualifiedName();
- }
-
- final GrParameter propOwner = factory.createParameter("propOwner", typeText, null);
-
- actual = new PsiParameter[parameters.length + 1];
- actual[0] = propOwner;
- System.arraycopy(parameters, 0, actual, 1, parameters.length);
- }
-
-
- GenerationUtil.writeParameterList(builder, actual, classNameProvider, context);
-
-
- //method body
- builder.append("{\n");
-
- //arg initialization
- context.myUsedVarNames.add("propOwner");
- final GrExpression[] args = new GrExpression[parameters.length];
- for (int i = 0; i < parameters.length; i++) {
- args[i] = factory.createExpressionFromText(parameters[i].getName());
- context.myUsedVarNames.add(parameters[i].getName());
- }
- GroovyPsiElement place;
- if (psiClass instanceof GroovyPsiElement) {
- place = (GroovyPsiElement)psiClass;
- }
- else if (psiClass instanceof GroovyScriptClass) {
- place = ((GroovyScriptClass)psiClass).getContainingFile();
- }
- else {
- LOG.error("wrong class!!!");
- place = null;
- }
- new ExpressionGenerator(builder, context).invokeMethodOn(
- setter,
- isStatic ? null : factory.createExpressionFromText("propOwner"),
- args,
- GrNamedArgument.EMPTY_ARRAY,
- GrClosableBlock.EMPTY_ARRAY,
- PsiSubstitutor.EMPTY,
- place
- );
- builder.append(";\n");
- builder.append("return ").append(parameter.getName()).append(";\n");
- builder.append("}\n");
+ new SetterWriter(builder, psiClass, entry.getKey(), entry.getValue(), classNameProvider, context).write();
}
final String name = context.getRefSetterName();
@@ -503,6 +393,8 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator {
}
}
+
+
public void writeImplementsList(StringBuilder text, PsiClass typeDefinition) {
final Collection<PsiClassType> implementsTypes = new LinkedHashSet<PsiClassType>();
Collections.addAll(implementsTypes, typeDefinition.getImplementsListTypes());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java
index 3feab9d73313..48cf405bcb18 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java
@@ -76,6 +76,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+import org.jetbrains.plugins.groovy.refactoring.convertToJava.invocators.CustomMethodInvocator;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
import static org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock.EMPTY_ARRAY;
@@ -568,38 +569,61 @@ public class ExpressionGenerator extends Generator {
private void writeAssignmentWithSetter(GrExpression qualifier, PsiMethod setter, GrAssignmentExpression assignment) {
GrExpression rValue = getRValue(assignment);
LOG.assertTrue(rValue != null);
- writeAssignmentWithSetter(qualifier, setter, new GrExpression[]{rValue}, GrNamedArgument.EMPTY_ARRAY, EMPTY_ARRAY, PsiSubstitutor.EMPTY,
- assignment);
+ writeAssignmentWithSetter(qualifier, setter, new GrExpression[]{rValue}, GrNamedArgument.EMPTY_ARRAY, EMPTY_ARRAY, PsiSubstitutor.EMPTY, assignment);
}
private void writeAssignmentWithSetter(@Nullable GrExpression qualifier,
- PsiMethod method,
- GrExpression[] exprs,
- GrNamedArgument[] namedArgs,
- GrClosableBlock[] closures,
- PsiSubstitutor substitutor,
- GrAssignmentExpression assignment) {
+ @NotNull PsiMethod method,
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] closures,
+ @NotNull PsiSubstitutor substitutor,
+ @NotNull GrAssignmentExpression assignment) {
if (PsiUtil.isExpressionUsed(assignment)) {
- String setterName = context.getSetterName(method, assignment);
- GrExpression[] args;
- if (method.hasModifierProperty(PsiModifier.STATIC)) {
- args = exprs;
+ final GrExpression rValue = assignment.getRValue();
+
+ //inline setter method invocation in case of tail statement and simple right value
+ if (PsiUtil.isExpressionStatement(assignment) && PsiUtil.isReturnStatement(assignment) && rValue != null && isVarAccess(rValue)) {
+
+ final StringBuilder assignmentBuffer = new StringBuilder();
+ new ExpressionGenerator(assignmentBuffer, context).invokeMethodOn(method, qualifier, exprs, namedArgs, closures, substitutor, assignment);
+ assignmentBuffer.append(';');
+ context.myStatements.add(assignmentBuffer.toString());
+
+ rValue.accept(this);
}
else {
- args = new GrExpression[exprs.length + 1];
- if (qualifier == null) {
- qualifier = factory.createExpressionFromText("this", assignment);
+ String setterName = context.getSetterName(method, assignment);
+ GrExpression[] args;
+ if (method.hasModifierProperty(PsiModifier.STATIC)) {
+ args = exprs;
+ }
+ else {
+ args = new GrExpression[exprs.length + 1];
+ if (qualifier == null) {
+ qualifier = factory.createExpressionFromText("this", assignment);
+ }
+ args[0] = qualifier;
+ System.arraycopy(exprs, 0, args, 1, exprs.length);
}
- args[0] = qualifier;
- System.arraycopy(exprs, 0, args, 1, exprs.length);
+ invokeMethodByName(null, setterName, args, namedArgs, closures, this, assignment);
}
- invokeMethodByName(null, setterName, args, namedArgs, closures, this, assignment);
}
else {
invokeMethodOn(method, qualifier, exprs, namedArgs, closures, substitutor, assignment);
}
}
+ private static boolean isVarAccess(@Nullable GrExpression expr) {
+ if (expr instanceof GrReferenceExpression) {
+ final PsiElement resolved = ((GrReferenceExpression)expr).resolve();
+ if (resolved instanceof PsiVariable) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void visitBinaryExpression(GrBinaryExpression expression) {
final GrExpression left = expression.getLeftOperand();
@@ -948,7 +972,7 @@ public class ExpressionGenerator extends Generator {
PsiUtil.getContextClass(referenceExpression) instanceof GroovyScriptClass) {
final GrExpression thisExpr = factory.createExpressionFromText("this", referenceExpression);
thisExpr.accept(this);
- builder.append(".getBinding().getProperty(\"").append(referenceExpression.getName()).append("\")");
+ builder.append(".getBinding().getProperty(\"").append(referenceExpression.getReferenceName()).append("\")");
return;
}
@@ -1291,14 +1315,15 @@ public class ExpressionGenerator extends Generator {
builder.append(']');
}
- public void invokeMethodOn(PsiMethod method,
+ public void invokeMethodOn(@NotNull PsiMethod method,
@Nullable GrExpression caller,
- GrExpression[] exprs,
- GrNamedArgument[] namedArgs,
- GrClosableBlock[] closures,
- PsiSubstitutor substitutor,
- GroovyPsiElement context) {
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] closures,
+ @NotNull PsiSubstitutor substitutor,
+ @NotNull GroovyPsiElement context) {
if (method instanceof GrGdkMethod) {
+ if (CustomMethodInvocator.invokeMethodOn(this, (GrGdkMethod)method, caller, exprs, namedArgs, closures, substitutor, context)) return;
GrExpression[] newArgs = new GrExpression[exprs.length + 1];
System.arraycopy(exprs, 0, newArgs, 1, exprs.length);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java
index e067001797bc..1d4982a8189a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java
@@ -153,22 +153,23 @@ public class GenerationUtil {
}
public static void invokeMethodByName(@Nullable GrExpression caller,
- String methodName,
- GrExpression[] exprs,
- GrNamedArgument[] namedArgs,
- GrClosableBlock[] closureArgs,
- ExpressionGenerator expressionGenerator,
- GroovyPsiElement psiContext) {
+ @NotNull String methodName,
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] closureArgs,
+ @NotNull ExpressionGenerator expressionGenerator,
+ @NotNull GroovyPsiElement psiContext) {
GroovyResolveResult call = resolveMethod(caller, methodName, exprs, namedArgs, closureArgs, psiContext);
invokeMethodByResolveResult(caller, call, methodName, exprs, namedArgs, closureArgs, expressionGenerator, psiContext);
}
+ @NotNull
public static GroovyResolveResult resolveMethod(@Nullable GrExpression caller,
- String methodName,
- GrExpression[] exprs,
- GrNamedArgument[] namedArgs,
- GrClosableBlock[] closureArgs,
- GroovyPsiElement psiContext) {
+ @NotNull String methodName,
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] closureArgs,
+ @NotNull GroovyPsiElement psiContext) {
GroovyResolveResult call = GroovyResolveResult.EMPTY_RESULT;
final PsiType type;
@@ -187,13 +188,13 @@ public class GenerationUtil {
}
public static void invokeMethodByResolveResult(@Nullable GrExpression caller,
- GroovyResolveResult resolveResult,
- String methodName,
- GrExpression[] exprs,
- GrNamedArgument[] namedArgs,
- GrClosableBlock[] closureArgs,
- ExpressionGenerator expressionGenerator,
- GroovyPsiElement psiContext) {
+ @NotNull GroovyResolveResult resolveResult,
+ @NotNull String methodName,
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] closureArgs,
+ @NotNull ExpressionGenerator expressionGenerator,
+ @NotNull GroovyPsiElement psiContext) {
final PsiElement resolved = resolveResult.getElement();
if (resolved instanceof PsiMethod) {
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
@@ -213,8 +214,8 @@ public class GenerationUtil {
argumentListGenerator.generate(null, exprs, namedArgs, closureArgs, psiContext);
}
- static void writeStatement(final StringBuilder codeBlockBuilder,
- StringBuilder statementBuilder,
+ static void writeStatement(@NotNull StringBuilder codeBlockBuilder,
+ @NotNull StringBuilder statementBuilder,
@Nullable GrStatement statement,
@Nullable ExpressionContext context) {
final PsiElement parent = statement == null ? null : statement.getParent();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SetterWriter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SetterWriter.java
new file mode 100644
index 000000000000..9e881bc8963c
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SetterWriter.java
@@ -0,0 +1,192 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.refactoring.convertToJava;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
+
+import static org.jetbrains.plugins.groovy.refactoring.convertToJava.GenerationUtil.writeTypeParameters;
+import static org.jetbrains.plugins.groovy.refactoring.convertToJava.TypeWriter.writeType;
+
+/**
+ * @author Max Medvedev
+ */
+public class SetterWriter {
+ private static final Logger LOG = Logger.getInstance(SetterWriter.class);
+
+ private final StringBuilder myBuffer;
+ private final PsiClass myClass;
+ private final PsiMethod mySetter;
+ private final String myName;
+ private final ClassNameProvider myClassNameProvider;
+ private final ExpressionContext myContext;
+
+ public SetterWriter(@NotNull StringBuilder builder,
+ @NotNull PsiClass psiClass,
+ @NotNull PsiMethod setter,
+ @NotNull String name,
+ @NotNull ClassNameProvider classNameProvider,
+ @NotNull ExpressionContext context) {
+ myBuffer = builder;
+ myClass = psiClass;
+ myClassNameProvider = classNameProvider;
+ myContext = context;
+ myName = name;
+
+ if (setter instanceof PsiCompiledElement) setter = (PsiMethod)((PsiCompiledElement)setter).getMirror();
+ mySetter = setter;
+ }
+
+
+ public void write() {
+ final boolean isStatic = mySetter.hasModifierProperty(PsiModifier.STATIC);
+
+ final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myContext.project);
+
+ PsiParameter[] parameters = mySetter.getParameterList().getParameters();
+ PsiParameter parameter = parameters[parameters.length - 1];
+ final PsiType parameterType = myContext.typeProvider.getParameterType(parameter);
+
+ myBuffer.append("private static ");
+ processTypeParameters(parameterType);
+
+ myBuffer.append(myName);
+
+ if (!(parameterType instanceof PsiPrimitiveType)) {
+ parameter = factory.createParameter(parameter.getName(), "Value", null);
+ }
+
+
+ PsiParameter[] actual = inferActualParameters(isStatic, parameters, parameter);
+ final GroovyPsiElement place = createStubMethod(actual);
+ GenerationUtil.writeParameterList(myBuffer, actual, myClassNameProvider, myContext);
+ writeBody(isStatic, parameters, parameter, place);
+ }
+
+ private void writeBody(boolean aStatic,
+ @NotNull PsiParameter[] parameters,
+ @NotNull PsiParameter parameter, final GroovyPsiElement place) {
+ //method body
+ myBuffer.append("{\n");
+
+ //arg initialization
+ myContext.myUsedVarNames.add("propOwner");
+ final GrExpression[] args = generateArguments(parameters, place);
+
+ new ExpressionGenerator(myBuffer, myContext).invokeMethodOn(
+ mySetter,
+ aStatic ? null : GroovyPsiElementFactory.getInstance(myContext.project).createExpressionFromText("propOwner", place),
+ args,
+ GrNamedArgument.EMPTY_ARRAY,
+ GrClosableBlock.EMPTY_ARRAY,
+ PsiSubstitutor.EMPTY,
+ place
+ );
+ myBuffer.append(";\n");
+ myBuffer.append("return ").append(parameter.getName()).append(";\n");
+ myBuffer.append("}\n");
+ }
+
+ @NotNull
+ private GrExpression[] generateArguments(@NotNull PsiParameter[] parameters, @NotNull GroovyPsiElement place) {
+ final GrExpression[] args = new GrExpression[parameters.length];
+ for (int i = 0; i < parameters.length; i++) {
+ args[i] = GroovyPsiElementFactory.getInstance(myContext.project).createExpressionFromText(parameters[i].getName(), place);
+ myContext.myUsedVarNames.add(parameters[i].getName());
+ }
+ return args;
+ }
+
+ private GroovyPsiElement createStubMethod(@NotNull PsiParameter[] parameters) {
+ StringBuilder methodText = new StringBuilder("def ").append(myName).append('(');
+ for (PsiParameter parameter : parameters) {
+ methodText.append(parameter.getType().getCanonicalText()).append(' ').append(parameter.getName()).append(',');
+ }
+ if (parameters.length > 0) methodText.deleteCharAt(methodText.length() - 1);
+ methodText.append("){}");
+ return GroovyPsiElementFactory.getInstance(myContext.project).createMethodFromText(methodText.toString(), mySetter);
+ }
+
+ @NotNull
+ private PsiParameter[] inferActualParameters(boolean aStatic,
+ @NotNull PsiParameter[] parameters,
+ @NotNull PsiParameter parameter) {
+ //parameters
+ parameters[parameters.length - 1] = parameter;
+ PsiParameter[] actual;
+ if (aStatic) {
+ actual = parameters;
+ }
+ else {
+ final String typeText;
+ final PsiClass containingClass = mySetter.getContainingClass();
+ if (containingClass == null) {
+ if (mySetter instanceof GrGdkMethod) {
+ typeText = ((GrGdkMethod)mySetter).getStaticMethod().getParameterList().getParameters()[0].getType().getCanonicalText();
+ }
+ else {
+ typeText = CommonClassNames.JAVA_LANG_OBJECT;
+ }
+ }
+ else {
+ typeText = containingClass.getQualifiedName();
+ }
+
+ final GrParameter propOwner = GroovyPsiElementFactory.getInstance(myContext.project).createParameter("propOwner", typeText, null);
+
+ actual = new PsiParameter[parameters.length + 1];
+ actual[0] = propOwner;
+ System.arraycopy(parameters, 0, actual, 1, parameters.length);
+ }
+ return actual;
+ }
+
+ private void processTypeParameters(PsiType parameterType) {
+ //type parameters
+ if (mySetter.hasTypeParameters()) {
+ writeTypeParameters(myBuffer, mySetter, myClassNameProvider);
+ }
+
+ if (parameterType instanceof PsiPrimitiveType) {
+ myBuffer.append(parameterType.getCanonicalText()).append(' ');
+ }
+ else {
+ if (mySetter.hasTypeParameters()) {
+ myBuffer.delete(myBuffer.length() - 1, myBuffer.length());
+ //builder.removeFromTheEnd(1);
+ myBuffer.append(", ");
+ }
+ else {
+ myBuffer.append('<');
+ }
+ myBuffer.append("Value");
+ if (!parameterType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
+ myBuffer.append(" extends ");
+ writeType(myBuffer, parameterType, myClass, myClassNameProvider);
+ }
+ myBuffer.append('>');
+ myBuffer.append("Value ");
+ }
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/CustomMethodInvocator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/CustomMethodInvocator.java
new file mode 100644
index 000000000000..15d66a717375
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/CustomMethodInvocator.java
@@ -0,0 +1,63 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.refactoring.convertToJava.invocators;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiSubstitutor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
+import org.jetbrains.plugins.groovy.refactoring.convertToJava.ExpressionGenerator;
+
+/**
+ * @author Max Medvedev
+ */
+public abstract class CustomMethodInvocator {
+ private static final ExtensionPointName<CustomMethodInvocator> EP_NAME =
+ ExtensionPointName.create("org.intellij.groovy.convertToJava.customMethodInvocator");
+
+ protected abstract boolean invoke(@NotNull ExpressionGenerator generator,
+ @NotNull PsiMethod method,
+ @Nullable GrExpression caller,
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] closures,
+ @NotNull PsiSubstitutor substitutor,
+ @NotNull GroovyPsiElement context);
+
+ public static boolean invokeMethodOn(@NotNull ExpressionGenerator generator,
+ @NotNull GrGdkMethod method,
+ @Nullable GrExpression caller,
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] closures,
+ @NotNull PsiSubstitutor substitutor,
+ @NotNull GroovyPsiElement context) {
+ final PsiMethod staticMethod = method.getStaticMethod();
+ for (CustomMethodInvocator invocator : EP_NAME.getExtensions()) {
+ if (invocator.invoke(generator, staticMethod, caller, exprs, namedArgs, closures, substitutor, context)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/MapGetterSetterInvocator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/MapGetterSetterInvocator.java
new file mode 100644
index 000000000000..55ab3cb91d4d
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/MapGetterSetterInvocator.java
@@ -0,0 +1,80 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.refactoring.convertToJava.invocators;
+
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
+import org.jetbrains.plugins.groovy.refactoring.convertToJava.ExpressionGenerator;
+import org.jetbrains.plugins.groovy.refactoring.convertToJava.GenerationUtil;
+
+/**
+ * @author Max Medvedev
+ */
+
+public class MapGetterSetterInvocator extends CustomMethodInvocator {
+ @Override
+ protected boolean invoke(@NotNull ExpressionGenerator generator,
+ @NotNull PsiMethod method,
+ @Nullable GrExpression caller,
+ @NotNull GrExpression[] exprs,
+ @NotNull GrNamedArgument[] namedArgs,
+ @NotNull GrClosableBlock[] closures,
+ @NotNull PsiSubstitutor substitutor,
+ @NotNull GroovyPsiElement context) {
+ if (!method.getName().equals("putAt") && !method.getName().equals("getAt")) return false;
+
+ final PsiClass clazz = method.getContainingClass();
+ if (clazz == null) return false;
+
+ final String qname = clazz.getQualifiedName();
+ if (!GroovyCommonClassNames.DEFAULT_GROOVY_METHODS.equals(qname)) return false;
+
+
+ if (caller == null) return false;
+ final PsiType type = caller.getType();
+
+ if (method.getName().equals("getAt")) {
+ if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) {
+ GenerationUtil.invokeMethodByName(caller, "get", exprs, namedArgs, closures, generator, context);
+ return true;
+ }
+ else if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_LIST)) {
+ GenerationUtil.invokeMethodByName(caller, "get", exprs, namedArgs, closures, generator, context);
+ return true;
+ }
+ }
+ else if (method.getName().equals("putAt")) {
+ if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) {
+ GenerationUtil.invokeMethodByName(caller, "put", exprs, namedArgs, closures, generator, context);
+ return true;
+ }
+ else if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_LIST)) {
+ GenerationUtil.invokeMethodByName(caller, "set", exprs, namedArgs, closures, generator, context);
+ return true;
+ }
+ }
+
+
+ return false;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java
index 2b24cbfd03fc..f674520a72a2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java
@@ -404,9 +404,9 @@ public class ExtractUtil {
PsiType paramType = info.getType();
final PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(paramType);
if (unboxed != null) paramType = unboxed;
- String paramTypeText;
- if (paramType == null || paramType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
+ String paramTypeText;
+ if (paramType == null || paramType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || paramType.equals(PsiType.NULL)) {
paramTypeText = "";
}
else {
@@ -419,21 +419,20 @@ public class ExtractUtil {
return ArrayUtil.toStringArray(params);
}
- public static String getTypeString(ExtractMethodInfoHelper helper, boolean forPresentation, String modifier) {
+ @NotNull
+ public static String getTypeString(@NotNull ExtractMethodInfoHelper helper, boolean forPresentation, @NotNull String modifier) {
+ if (!helper.specifyType()) {
+ return modifier.isEmpty() ? "def " : "";
+ }
+
PsiType type = helper.getOutputType();
- final PsiPrimitiveType outUnboxed = PsiPrimitiveType.getUnboxedType(type);
- if (outUnboxed != null) type = outUnboxed;
+ final PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(type);
+ if (unboxed != null) type = unboxed;
- String typeText = forPresentation ? type.getPresentableText() : type.getCanonicalText();
- String returnType = typeText == null || !helper.specifyType() ? "" : typeText;
+ final String returnType = StringUtil.notNullize(forPresentation ? type.getPresentableText() : type.getCanonicalText());
if (StringUtil.isEmptyOrSpaces(returnType) || "null".equals(returnType)) {
- if (modifier.length() == 0) {
- return "def ";
- }
- else {
- return "";
- }
+ return modifier.isEmpty() ? "def " : "";
}
else {
return returnType + " ";
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java
index a8c865c90ddb..f8774a3f3c5d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java
@@ -25,10 +25,13 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pass;
+import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.HelpID;
+import com.intellij.refactoring.IntroduceTargetChooser;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.ui.ConflictsDialog;
import com.intellij.refactoring.util.CommonRefactoringUtil;
@@ -60,8 +63,10 @@ import org.jetbrains.plugins.groovy.refactoring.extract.ExtractUtil;
import org.jetbrains.plugins.groovy.refactoring.extract.GroovyExtractChooser;
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
import org.jetbrains.plugins.groovy.refactoring.extract.ParameterInfo;
+import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import java.util.ArrayList;
+import java.util.List;
/**
* @author ilyas
@@ -70,17 +75,49 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler {
protected static String REFACTORING_NAME = GroovyRefactoringBundle.message("extract.method.title");
private static final Logger LOG = Logger.getInstance(GroovyExtractMethodHandler.class);
- public void invoke(@NotNull Project project, Editor editor, PsiFile file, @Nullable DataContext dataContext) {
+ public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, @Nullable DataContext dataContext) {
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
- // select editor text fragment
final SelectionModel model = editor.getSelectionModel();
- if (!model.hasSelection()) {
- model.selectLineAtCaret();
+ if (model.hasSelection()) {
+ invokeImpl(project, editor, file, model.getSelectionStart(), model.getSelectionEnd());
}
+ else {
+ final List<GrExpression> expressions = GrIntroduceHandlerBase.collectExpressions(file, editor, editor.getCaretModel().getOffset(), true);
+ final Pass<GrExpression> callback = new Callback(project, editor, file);
+ if (expressions.size() == 1) {
+ callback.pass(expressions.get(0));
+ }
+ else if (expressions.isEmpty()) {
+ model.selectLineAtCaret();
+ invokeImpl(project, editor, file, model.getSelectionStart(), model.getSelectionEnd());
+ }
+ else {
+ IntroduceTargetChooser.showChooser(editor, expressions, callback, GrIntroduceHandlerBase.GR_EXPRESSION_RENDERER);
+ }
+ }
+ }
+
+ private class Callback extends Pass<GrExpression> {
+ private final Project project;
+ private final Editor editor;
+ private final PsiFile file;
+
+
+ private Callback(Project project, Editor editor, PsiFile file) {
+ this.project = project;
+ this.editor = editor;
+ this.file = file;
+ }
+
+ public void pass(@NotNull final GrExpression selectedValue) {
+ final TextRange range = selectedValue.getTextRange();
+ invokeImpl(project, editor, file, range.getStartOffset(), range.getEndOffset());
+ }
+ }
+ private void invokeImpl(Project project, Editor editor, PsiFile file, final int startOffset, final int endOffset) {
try {
- final InitialInfo initialInfo =
- GroovyExtractChooser.invoke(project, editor, file, model.getSelectionStart(), model.getSelectionEnd(), true);
+ final InitialInfo initialInfo = GroovyExtractChooser.invoke(project, editor, file, startOffset, endOffset, true);
if (findConflicts(initialInfo)) return;
@@ -147,7 +184,7 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler {
return !dialog.isOK();
}
- private void performRefactoring(@NotNull final InitialInfo initialInfo, final Editor editor) {
+ private void performRefactoring(@NotNull final InitialInfo initialInfo, @Nullable final Editor editor) {
final PsiClass owner = PsiUtil.getContextClass(initialInfo.getStatements()[0]);
LOG.assertTrue(owner!=null);
@@ -242,7 +279,7 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler {
super.visitElement(element);
if (element instanceof GrReferenceExpression) {
GrReferenceExpression expr = (GrReferenceExpression) element;
- if (!expr.isQualified() && oldName.equals(expr.getName())) {
+ if (!expr.isQualified() && oldName.equals(expr.getReferenceName())) {
result.add(expr);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java
index 72ee582fa409..70b680712632 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java
@@ -86,13 +86,6 @@ public class GroovyInlineMethodUtil {
PsiElement element = reference.getElement();
- if (element.getContainingFile() instanceof GroovyFile) {
- if (!(isStaticMethod(method) || areInSameClass(element, method))) { // todo implement for other cases
-// showErrorMessage("Other class support will be implemented soon", myProject);
-// return null;
- }
- }
-
if (!(element instanceof GrExpression && element.getParent() instanceof GrCallExpression)) {
String message = GroovyRefactoringBundle.message("refactoring.is.available.only.for.method.calls", REFACTORING_NAME);
showErrorMessage(message, project, editor);
@@ -110,19 +103,23 @@ public class GroovyInlineMethodUtil {
GroovyRefactoringUtil.highlightOccurrences(project, editor, new GrExpression[]{call});
if (hasBadReturns(method) && !isTailMethodCall(call)) {
- String message = GroovyRefactoringBundle
- .message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow", REFACTORING_NAME);
+ String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return InlineHandler.Settings.CANNOT_INLINE_SETTINGS;
}
}
- if (method.getBlock() == null) {
- String message;
- if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
- message = GroovyRefactoringBundle.message("refactoring.cannot.be.applied.to.abstract.methods", REFACTORING_NAME);
- } else {
- message = GroovyRefactoringBundle.message("refactoring.cannot.be.applied.no.sources.attached", REFACTORING_NAME);
+ else {
+ if (hasBadReturns(method)) {
+ String message = GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow", REFACTORING_NAME);
+ showErrorMessage(message, project, editor);
+ return InlineHandler.Settings.CANNOT_INLINE_SETTINGS;
}
+ }
+
+ if (method.getBlock() == null) {
+ String message = method.hasModifierProperty(PsiModifier.ABSTRACT)
+ ? GroovyRefactoringBundle.message("refactoring.cannot.be.applied.to.abstract.methods", REFACTORING_NAME)
+ : GroovyRefactoringBundle.message("refactoring.cannot.be.applied.no.sources.attached", REFACTORING_NAME);
showErrorMessage(message, project, editor);
return InlineHandler.Settings.CANNOT_INLINE_SETTINGS;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java
index 5e76f0c6fcbe..95178e753a49 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java
@@ -82,7 +82,11 @@ public class GroovyMethodInliner implements InlineHandler.Inliner {
@Nullable
public MultiMap<PsiElement, String> getConflicts(@NotNull PsiReference reference, @NotNull PsiElement referenced) {
PsiElement element = reference.getElement();
- assert element instanceof GrExpression && element.getParent() instanceof GrCallExpression;
+ if (!(element instanceof GrExpression && element.getParent() instanceof GrCallExpression)) {
+ final MultiMap<PsiElement, String> map = new MultiMap<PsiElement, String>();
+ map.putValue(element, GroovyRefactoringBundle.message("cannot.inline.reference.0", element.getText()));
+ return map;
+ }
GrCallExpression call = (GrCallExpression) element.getParent();
Collection<GroovyInlineMethodUtil.ReferenceExpressionInfo> infos = GroovyInlineMethodUtil.collectReferenceInfo(myMethod);
return collectConflicts(call, infos);
@@ -121,7 +125,7 @@ public class GroovyMethodInliner implements InlineHandler.Inliner {
public void inlineUsage(@NotNull UsageInfo usage, @NotNull PsiElement referenced) {
PsiElement element=usage.getElement();
- assert element instanceof GrExpression && element.getParent() instanceof GrCallExpression;
+ if (!(element instanceof GrExpression && element.getParent() instanceof GrCallExpression)) return;
final Editor editor = getCurrentEditorIfApplicable(element);
@@ -366,7 +370,7 @@ public class GroovyMethodInliner implements InlineHandler.Inliner {
String name = namedElement.getName();
if (name != null) {
String newName = qualifier instanceof GrReferenceExpression ?
- InlineMethodConflictSolver.suggestNewName(name, method, call, ((GrReferenceExpression)qualifier).getName()) :
+ InlineMethodConflictSolver.suggestNewName(name, method, call, ((GrReferenceExpression)qualifier).getReferenceName()) :
InlineMethodConflictSolver.suggestNewName(name, method, call);
if (!newName.equals(namedElement.getName())) {
final Collection<PsiReference> refs = ReferencesSearch.search(namedElement, GlobalSearchScope.projectScope(namedElement.getProject()), false).findAll();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodConflictSolver.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodConflictSolver.java
index 176219c8cc7b..fb9bf953a4e3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodConflictSolver.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodConflictSolver.java
@@ -107,7 +107,7 @@ public class InlineMethodConflictSolver {
GrExpression lValue = ((GrAssignmentExpression) child).getLValue();
if (lValue instanceof GrReferenceExpression) {
GrReferenceExpression expr = (GrReferenceExpression) lValue;
- if (expr.getQualifierExpression() == null && name.equals(expr.getName())) {
+ if (expr.getQualifierExpression() == null && name.equals(expr.getReferenceName())) {
return false;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
index 303ba52de656..755e7fedfb86 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java
@@ -1,9 +1,12 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
@@ -65,6 +68,13 @@ import java.util.List;
* @author Maxim.Medvedev
*/
public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSettings> implements RefactoringActionHandler {
+ public static final Function<GrExpression, String> GR_EXPRESSION_RENDERER = new Function<GrExpression, String>() {
+ @Override
+ public String fun(@NotNull GrExpression expr) {
+ return expr.getText();
+ }
+ };
+
protected abstract String getRefactoringName();
protected abstract String getHelpID();
@@ -175,19 +185,11 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset());
}
else {
- IntroduceTargetChooser.showChooser(editor, expressions,
- new Pass<GrExpression>() {
- public void pass(final GrExpression selectedValue) {
- invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(),
- selectedValue.getTextRange().getEndOffset());
- }
- },
- new Function<GrExpression, String>() {
- @Override
- public String fun(GrExpression grExpression) {
- return grExpression.getText();
- }
- });
+ IntroduceTargetChooser.showChooser(editor, expressions, new Pass<GrExpression>() {
+ public void pass(final GrExpression selectedValue) {
+ invoke(project, editor, file, selectedValue.getTextRange().getStartOffset(), selectedValue.getTextRange().getEndOffset());
+ }
+ }, GR_EXPRESSION_RENDERER);
return;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java
index d087aadca369..750326a8e0de 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@ import org.jetbrains.plugins.groovy.actions.GroovyTemplatesFactory;
import org.jetbrains.plugins.groovy.actions.NewGroovyActionBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
@@ -242,21 +243,25 @@ public class GrIntroduceConstantDialog extends DialogWrapper
private void createUIComponents() {
myJavaVisibilityPanel = new JavaVisibilityPanel(false, true);
- if (myContext.getExpression() == null) {
- myTypeCombo = GrTypeComboBox.createTypeComboBoxWithDefType(myContext.getVar().getDeclaredType()
- );
+
+ final GrVariable var = myContext.getVar();
+ final GrExpression expression = myContext.getExpression();
+ if (expression == null) {
+ assert var != null;
+ myTypeCombo = GrTypeComboBox.createTypeComboBoxWithDefType(var.getDeclaredType(), var);
}
else {
- myTypeCombo = GrTypeComboBox.createTypeComboBoxFromExpression(myContext.getExpression());
+ myTypeCombo = GrTypeComboBox.createTypeComboBoxFromExpression(expression);
}
List<String> names = new ArrayList<String>();
- final GrVariable var = myContext.getVar();
if (var != null) {
names.add(var.getName());
}
- String[] possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(myContext.getExpression(), new GroovyVariableValidator(myContext), true);
- ContainerUtil.addAll(names, possibleNames);
+ if (expression != null) {
+ String[] possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(expression, new GroovyVariableValidator(myContext), true);
+ ContainerUtil.addAll(names, possibleNames);
+ }
myNameField = new NameSuggestionsField(ArrayUtil.toStringArray(names), myContext.getProject(), GroovyFileType.GROOVY_FILE_TYPE);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java
index f626b0893882..5aff0de40fe1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -268,6 +268,7 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce
possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(expression, validator, true);
}
else {
+ assert var != null;
possibleNames = GroovyNameSuggestionUtil.suggestVariableNameByType(var.getType(), validator);
}
List<String> list = new ArrayList<String>();
@@ -278,8 +279,7 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce
myNameField = new NameSuggestionsField(ArrayUtil.toStringArray(list), myContext.getProject(), GroovyFileType.GROOVY_FILE_TYPE);
if (expression == null) {
- myTypeComboBox = GrTypeComboBox.createTypeComboBoxWithDefType(var.getDeclaredType()
- );
+ myTypeComboBox = GrTypeComboBox.createTypeComboBoxWithDefType(var.getDeclaredType(), var);
}
else {
myTypeComboBox = GrTypeComboBox.createTypeComboBoxFromExpression(expression);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java
index c5b6ed01158e..9893626a80fd 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -313,7 +313,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper implements GrIntro
private GrTypeComboBox createTypeComboBox(GrVariable var, GrExpression expr) {
GrTypeComboBox box;
if (var != null) {
- box = GrTypeComboBox.createTypeComboBoxWithDefType(var.getDeclaredType());
+ box = GrTypeComboBox.createTypeComboBoxWithDefType(var.getDeclaredType(), var);
}
else if (expr != null) {
box = GrTypeComboBox.createTypeComboBoxFromExpression(expr);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyMemberHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyMemberHandler.java
index fe720a5fc42d..d761114ac17e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyMemberHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyMemberHandler.java
@@ -225,7 +225,7 @@ public class MoveGroovyMemberHandler implements MoveMemberHandler {
@Override
@Nullable
- public PsiElement getAnchor(@NotNull final PsiMember member, @NotNull final PsiClass targetClass) {
+ public PsiElement getAnchor(@NotNull final PsiMember member, @NotNull final PsiClass targetClass, Set<PsiMember> membersToMove) {
if (member instanceof GrField && member.hasModifierProperty(PsiModifier.STATIC)) {
final List<PsiField> referencedFields = new ArrayList<PsiField>();
final GrExpression psiExpression = ((GrField)member).getInitializerGroovy();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java
index 2536861b8baf..4fe2548ecc3f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java
@@ -46,8 +46,8 @@ public class GrTypeComboBox extends ComboBox {
private static final Logger LOG = Logger.getInstance(GrTypeComboBox.class);
- public static GrTypeComboBox createTypeComboBoxWithDefType(@Nullable PsiType type) {
- return new GrTypeComboBox(type, null, true, null, false);
+ public static GrTypeComboBox createTypeComboBoxWithDefType(@Nullable PsiType type, @NotNull PsiElement context) {
+ return new GrTypeComboBox(type, null, true, context, false);
}
public static GrTypeComboBox createTypeComboBoxFromExpression(@NotNull GrExpression expression) {
@@ -85,13 +85,12 @@ public class GrTypeComboBox extends ComboBox {
@Nullable PsiElement context,
boolean selectDef) {
LOG.assertTrue(min == null || context != null);
+ LOG.assertTrue(type == null || context != null);
if (type instanceof PsiDisjunctionType) type = ((PsiDisjunctionType)type).getLeastUpperBound();
-
Map<String, PsiType> types = Collections.emptyMap();
if (type != null) {
- assert context != null;
types = getCompatibleTypeNames(type, min, context);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java
index 7bd62c3bb8ba..abf532318f13 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java
@@ -97,7 +97,9 @@ public class DefaultGroovyScriptRunner extends GroovyScriptRunner {
if (groovyHome != null) {
groovyHome = FileUtil.toSystemDependentName(groovyHome);
}
- setGroovyHome(params, groovyHome);
+ if (groovyHome != null) {
+ setGroovyHome(params, groovyHome);
+ }
final String confPath = getConfPath(groovyHome);
params.getVMParametersList().add("-Dgroovy.starter.conf=" + confPath);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java
index 55a68e7bc69d..82f760b242db 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyRunConfigurationEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -107,8 +107,8 @@ public class GroovyRunConfigurationEditor extends SettingsEditor<GroovyScriptRun
configuration.setVMParameters(myVMParameters.getText());
configuration.setDebugEnabled(myDebugCB.isSelected());
configuration.setScriptParameters(myParameters.getText());
- configuration.setScriptPath(scriptPathField.getText());
- configuration.setWorkDir(workDirField.getText());
+ configuration.setScriptPath(scriptPathField.getText().trim());
+ configuration.setWorkDir(workDirField.getText().trim());
configuration.setEnvs(myEnvVariables.getEnvs());
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java
index fe7381e64da3..7c38456f9a33 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,10 +15,7 @@
*/
package org.jetbrains.plugins.groovy.runner;
-import com.intellij.execution.CantRunException;
-import com.intellij.execution.CommonJavaRunConfigurationParameters;
-import com.intellij.execution.ExecutionException;
-import com.intellij.execution.Executor;
+import com.intellij.execution.*;
import com.intellij.execution.configurations.*;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.process.OSProcessHandler;
@@ -145,12 +142,12 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
PathMacroManager.getInstance(getProject()).expandPaths(element);
super.readExternal(element);
readModule(element);
- scriptPath = JDOMExternalizer.readString(element, "path");
+ scriptPath = ExternalizablePath.localPathValue(JDOMExternalizer.readString(element, "path"));
vmParams = JDOMExternalizer.readString(element, "vmparams");
scriptParams = JDOMExternalizer.readString(element, "params");
final String wrk = JDOMExternalizer.readString(element, "workDir");
if (!".".equals(wrk)) {
- workDir = wrk;
+ workDir = ExternalizablePath.localPathValue(wrk);
}
isDebugEnabled = Boolean.parseBoolean(JDOMExternalizer.readString(element, "debug"));
envs.clear();
@@ -160,10 +157,10 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration<RunCo
public void writeExternal(Element element) throws WriteExternalException {
super.writeExternal(element);
writeModule(element);
- JDOMExternalizer.write(element, "path", scriptPath);
+ JDOMExternalizer.write(element, "path", ExternalizablePath.urlValue(scriptPath));
JDOMExternalizer.write(element, "vmparams", vmParams);
JDOMExternalizer.write(element, "params", scriptParams);
- JDOMExternalizer.write(element, "workDir", workDir);
+ JDOMExternalizer.write(element, "workDir", ExternalizablePath.urlValue(workDir));
JDOMExternalizer.write(element, "debug", isDebugEnabled);
JDOMExternalizer.writeMap(element, envs, null, "env");
PathMacroManager.getInstance(getProject()).collapsePathsRecursively(element);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java
index 8e91bc7d33dd..87ee64a6fff9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java
@@ -79,7 +79,7 @@ public abstract class GroovyScriptRunner {
}
}
- protected static void setGroovyHome(JavaParameters params, String groovyHome) {
+ protected static void setGroovyHome(JavaParameters params, @NotNull String groovyHome) {
params.getVMParametersList().add("-Dgroovy.home=" + groovyHome);
if (groovyHome.contains("grails")) { //a bit of a hack
params.getVMParametersList().add("-Dgrails.home=" + groovyHome);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java
index eb0d4e6e34f8..d68175b1de8d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java
@@ -1,3 +1,18 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.spock;
import com.intellij.psi.PsiElement;
@@ -236,7 +251,7 @@ public class SpockUtils {
GrReferenceExpression ref = (GrReferenceExpression)expression;
if (ref.isQualified()) return null;
- return ref.getName();
+ return ref.getReferenceName();
}
// See org.spockframework.compiler.WhereBlockRewriter#splitRow()
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockVariableDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockVariableDescriptor.java
index 5b03de4c03f9..d5fe6a7a853d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockVariableDescriptor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockVariableDescriptor.java
@@ -1,3 +1,18 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.spock;
import com.intellij.openapi.util.Computable;
@@ -112,6 +127,8 @@ public class SpockVariableDescriptor {
super(manager, name, type, navigationElement);
}
+
+
@Override
public boolean isEquivalentTo(PsiElement another) {
return super.isEquivalentTo(another)
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/ResolveProfiler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/ResolveProfiler.java
new file mode 100644
index 000000000000..0923f38cfa15
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/ResolveProfiler.java
@@ -0,0 +1,114 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.util;
+
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+/**
+ * @author Max Medvedev
+ */
+public class ResolveProfiler {
+ @NonNls private static final String PATH = "../../resolve_info/";
+ private static final boolean DISABLED = true;
+
+ private static final ThreadLocal<ThreadInfo> threadMap = new ThreadLocal<ThreadInfo>();
+ private static volatile int fileCount = 0;
+
+ private static class ThreadInfo {
+ private final String myFileName;
+ private final Deque<Long> myTimeStack = new ArrayDeque<Long>();
+
+ private String myPrefix = "";
+
+ private ThreadInfo(@NotNull String name) {
+ myFileName = name;
+ }
+
+ @NotNull
+ public String getName() {
+ return myFileName;
+ }
+
+ public void start() {
+ myTimeStack.push(System.nanoTime());
+ myPrefix += " ";
+ }
+
+ public long finish() {
+ myPrefix = myPrefix.substring(2);
+
+ final Long time = myTimeStack.pop();
+ return (System.nanoTime() - time) / 1000;
+ }
+
+ private String getPrefix() {
+ return myPrefix;
+ }
+ }
+
+ public static void start() {
+ if (DISABLED) return;
+ getThreadInfo().start();
+ }
+
+ public static long finish() {
+ if (DISABLED) return -1;
+ return getThreadInfo().finish();
+ }
+
+ public static void write(@NotNull String s) {
+ if (DISABLED) return;
+
+ final ThreadInfo threadInfo = getThreadInfo();
+ try {
+ final FileWriter writer = new FileWriter(threadInfo.getName(), true);
+ try {
+ writer.write(threadInfo.getPrefix());
+ writer.write(s);
+ writer.write('\n');
+ }
+ finally {
+ writer.close();
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ if (threadInfo.getPrefix().isEmpty()) {
+ threadMap.set(null);
+ }
+ }
+
+ @NotNull
+ private static ThreadInfo getThreadInfo() {
+ ThreadInfo info = threadMap.get();
+ if (info == null) {
+ synchronized (ResolveProfiler.class) {
+ info = new ThreadInfo(PATH + "out" + fileCount + ".txt");
+ fileCount++;
+ }
+ threadMap.set(info);
+ }
+ return info;
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
index 58f12a0049ef..da3963e9b7e1 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
@@ -528,14 +528,14 @@ class Indirect {
myFixture.addFileToProject('Bar.groovy', 'class Bar extends Foo { }')
def main = myFixture.addFileToProject('Main.groovy', 'class Main extends Bar { }').virtualFile
assertEmpty make()
- long oldBaseStamp = findClassFile("Base").modificationStamp
- long oldMainStamp = findClassFile("Main").modificationStamp
+ long oldBaseStamp = findClassFile("Base").timeStamp
+ long oldMainStamp = findClassFile("Main").timeStamp
touch(main)
touch(foo)
assertEmpty make()
- assert oldMainStamp != findClassFile("Main").modificationStamp
- assert oldBaseStamp == findClassFile("Base").modificationStamp
+ assert oldMainStamp != findClassFile("Main").timeStamp
+ assert oldBaseStamp == findClassFile("Base").timeStamp
}
public void testPartialCrossRecompile() {
@@ -805,5 +805,13 @@ string
FileUtil.delete(systemRoot);
}
}
+
+ public void "test no groovy library"() {
+ myFixture.addFileToProject("dependent/a.groovy", "");
+ addModule("dependent", true)
+
+ def messages = make()
+ assert messages.find { it.message.contains("Cannot compile Groovy files: no Groovy library is defined for module 'dependent'") }
+ }
}
}
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 c78819cee2c8..66481489f66a 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
@@ -214,7 +214,7 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
}
protected static void touch(VirtualFile file) throws IOException {
- file.setBinaryContent(file.contentsToByteArray(), file.getModificationStamp() + 1, file.getTimeStamp() + 1);
+ file.setBinaryContent(file.contentsToByteArray(), -1, file.getTimeStamp() + 1);
File ioFile = VfsUtil.virtualToIoFile(file);
assert ioFile.setLastModified(ioFile.lastModified() - 100000);
file.refresh(false, false);
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy
index 87946e96cd0f..ed22222a3b24 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.completion
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.codeInsight.completion.CompletionAutoPopupTestCase
+import com.intellij.openapi.actionSystem.IdeActions
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
@@ -199,6 +200,22 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase {
myFixture.checkResult 'import foo.Abcdefg\n\nAbcdefg <caret>'
}
+ public void "test two non-imported classes when space does not select first autopopup item"() {
+ CodeInsightSettings.instance.SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS = false
+
+ myFixture.addClass("package foo; public class Abcdefg {}")
+ myFixture.addClass("package bar; public class Abcdefg {}")
+ myFixture.configureByText 'a.groovy', 'class Foo extends <caret>'
+ type 'Abcde'
+ assert lookup.items.size() == 2
+ edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN) }
+ type ' '
+ myFixture.checkResult '''import foo.Abcdefg
+
+class Foo extends Abcdefg <caret>'''
+ }
+
+
public void testTwoNonImportedClasses() {
myFixture.addClass("package foo; public class Abcdefg {}")
myFixture.addClass("package bar; public class Abcdefg {}")
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
index a8261d7b5d92..137ff6fdf5a6 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
@@ -641,6 +641,10 @@ class A {
myFixture.checkResult "List<String> l = new ArrayList<>(<caret>)"
}
+ public void testFinishByClosingBracket() {
+ doCompletionTest "int o1, o2; array[o<caret>", "int o1, o2; array[o1]<caret>", "]", CompletionType.BASIC
+ }
+
public void testAfterNewWithInner() {
myFixture.addClass """class Zzoo {
static class Impl {}
@@ -1716,4 +1720,18 @@ class Baz {}''', '', CompletionType.BASIC, CompletionResult.contain, 'xxx', 'yyy
myFixture.completeBasic()
myFixture.assertPreferredCompletionItems 0, "message", "messages"
}
+
+ void testFieldCompletionFromJavaClass() {
+ myFixture.addClass("""\
+class Base {
+ static public Base foo;
+}
+
+class Inheritor extends Base {
+ static public Inheritor foo;
+}
+""")
+
+ doVariantableTest('Inheritor.fo<caret>','', CompletionType.BASIC, CompletionResult.equal, 'foo', 'forName', 'forName')
+ }
} \ No newline at end of file
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy
index 368f3b1b6e3c..3b759b2f4a8a 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyDslTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -245,6 +245,54 @@ public class MyCategory {
myFixture.configureByText 'a.groovy', '"".fo<caret>o'
myFixture.completeBasic()
assert generateDoc().contains('Some doc2')
- assert generateDoc().contains('setFoo')
+ assert generateDoc().contains('getFoo')
+ }
+
+ public void testVariableInAnnotationClosureContext() {
+ addGdsl '''
+ contributor(scope: closureScope(annotationName:'Ensures')) {
+ variable(name: 'result', type:'java.lang.Object')
+ }
+ '''
+
+ myFixture.configureByText('a.groovy', '''\
+ @interface Ensures {}
+
+ @Ensures({re<caret>sult == 2})
+ def foo() {}
+ ''')
+
+ assertNotNull(myFixture.getReferenceAtCaretPosition().resolve())
+ }
+
+ public void testVariableInMethodCallClosureContext() {
+ addGdsl '''
+ contributor(scope: closureScope(methodName:'ensures')) {
+ variable(name: 'result', type:'java.lang.Object')
+ }
+ '''
+
+ myFixture.configureByText('a.groovy', '''\
+ ensures{re<caret>sult == 2}
+ ''')
+
+ assertNotNull(myFixture.getReferenceAtCaretPosition().resolve())
+ }
+
+ void testScriptSuperClass() {
+ myFixture.addClass('''\
+ public class Abc {
+ public void foo() {}
+ }
+ ''')
+ addGdsl('''
+ scriptSuperClass(pattern: 'a.groovy', superClass: 'Abc')
+ ''')
+
+ myFixture.configureByText('a.groovy', '''\
+ fo<caret>o()
+ ''')
+
+ assertNotNull(myFixture.getReferenceAtCaretPosition().resolve())
}
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy
index ac45518d7f49..6fb85ec7d106 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/AbstractGebLightTestCase.groovy
@@ -29,7 +29,7 @@ import org.jetbrains.plugins.groovy.util.TestUtils
/**
* @author Sergey Evdokimov
*/
-class AbstractGebLightTestCase extends LightCodeInsightFixtureTestCase {
+abstract class AbstractGebLightTestCase extends LightCodeInsightFixtureTestCase {
static descriptor = new GebProjectDescriptor()
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy
index 812479cd0c5c..c733fcf74295 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/geb/GebTestsTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -90,11 +90,11 @@ class A extends geb.Page {
static at = {
int x = bbb
- Boolean s = <warning>bbb</warning>
+ Boolean s = bbb
}
static content = {
- someField<warning>()</warning>
+ someField<warning descr="'someField' cannot be applied to '()'">()</warning>
aaa { "Aaa" }
bbb { aaa.length() }
ccc(required: false) { aaa.length() }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/JoinLineTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/JoinLineTest.groovy
index 333184414479..934dca39742d 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/JoinLineTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/JoinLineTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,11 @@
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.actions
+
import com.intellij.openapi.actionSystem.IdeActions
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings
import org.jetbrains.plugins.groovy.GroovyFileType
+
/**
* @author Max Medvedev
*/
@@ -31,7 +34,7 @@ def a = 4;
''')
}
- void testVar2() {
+ void testVar2() {
doTest('''\
d<caret>ef a, b;
a = 4
@@ -49,7 +52,7 @@ def a = 4
''')
}
- void testVar4() {
+ void testVar4() {
doTest('''\
d<caret>ef a, b
a = 4
@@ -102,6 +105,31 @@ print 2; <caret>print 2
''')
}
+ void testFor() {
+ doTest('''\
+for (;a<caret>;) {
+ print 2
+} ''', '''\
+for (;a;) <caret>print 2''')
+ }
+
+ void testIfWithForceBraces() {
+ def current = getCurrentCodeStyleSettings().IF_BRACE_FORCE
+ try {
+ getCurrentCodeStyleSettings().IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS
+ doTest('''\
+if (a)
+ print 2
+''', '''\
+if (a) <caret>print 2
+''')
+ }
+ finally {
+ getCurrentCodeStyleSettings().IF_BRACE_FORCE = current
+ }
+
+ }
+
private void doTest(String before, String after) {
myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, before);
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy
index 6e348627c450..7ab6e1056e24 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/actions/generate/GroovyGenerateMembersTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.plugins.groovy.lang.actions.generate;
+package org.jetbrains.plugins.groovy.lang.actions.generate
+import com.intellij.codeInsight.generation.*
import com.intellij.openapi.application.Result
import com.intellij.openapi.application.RunResult
import com.intellij.openapi.command.WriteCommandAction
@@ -28,7 +29,6 @@ import org.jetbrains.annotations.Nullable
import org.jetbrains.plugins.groovy.actions.generate.accessors.GroovyGenerateGetterSetterAction
import org.jetbrains.plugins.groovy.actions.generate.constructors.GroovyGenerateConstructorHandler
import org.jetbrains.plugins.groovy.util.TestUtils
-import com.intellij.codeInsight.generation.*
/**
* @author peter
@@ -203,7 +203,8 @@ class Test {
@Nullable
def foo
- @Nullable getFoo() {
+ @Nullable
+ getFoo() {
return foo
}
}'''
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy
index 2e717ac1955e..d902a3d96393 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy
@@ -79,6 +79,7 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase {
public void testStringInjectionWithParam() { doTest() }
public void testUnaryExpressionInReturn() { doTest() }
public void testBinaryExpressionInReturn() { doTest() }
+ public void testPendingFromIf() { doTest() }
public void doTest() {
final List<String> input = TestUtils.readInput(testDataPath + getTestName(true) + ".test");
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java
index 277a3195e73f..9571cf40eee9 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.dynamic;
import com.intellij.codeInsight.intention.IntentionAction;
@@ -37,7 +52,7 @@ public class DynamicTest extends JavaCodeInsightFixtureTestCase {
final String[] methodArgumentsNames = QuickfixUtil.getMethodArgumentsNames(getProject(), psiTypes);
final List<ParamInfo> pairs = QuickfixUtil.swapArgumentsAndTypes(methodArgumentsNames, psiTypes);
- assertNotNull(getDClassElement().getMethod(referenceExpression.getName(), QuickfixUtil.getArgumentsTypes(pairs)));
+ assertNotNull(getDClassElement().getMethod(referenceExpression.getReferenceName(), QuickfixUtil.getArgumentsTypes(pairs)));
}
@NotNull
@@ -49,7 +64,7 @@ public class DynamicTest extends JavaCodeInsightFixtureTestCase {
}
public void testProperty() throws Throwable {
- final String name = doDynamicFix().getName();
+ final String name = doDynamicFix().getReferenceName();
assert getDClassElement().getPropertyByName(name) != null;
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy
index c1bdd08cfa6c..739d4904612b 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy
@@ -503,4 +503,13 @@ Money d = [amount: 100, currency:'USA']
''')
}
+ void testBooleanIsAssignableToAny() {
+ testHighlighting('''\
+ boolean b1 = new Object()
+ boolean b2 = <warning descr="Cannot assign 'null' to 'boolean'">null</warning>
+ Boolean b3 = new Object()
+ Boolean b4 = null
+''')
+ }
+
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy
index 42e250f45e38..8d5a50964f6f 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy
@@ -427,7 +427,7 @@ catch (<warning descr="Exception 'java.io.IOException' has already been caught">
testHighlighting('''\
try {}
catch (e){}
-catch (<warning descr="Exception 'java.lang.Throwable' has already been caught">e</warning>){}
+catch (<warning descr="Exception 'java.lang.Exception' has already been caught">e</warning>){}
''')
}
@@ -1133,4 +1133,48 @@ print(<error descr="Collection literal contains named and expression arguments a
}
''')
}
+
+ void testClosureParameterInferenceDoesNotWorkIfComplieStatic() {
+ addCompileStatic()
+ myFixture.enableInspections(GrUnresolvedAccessInspection)
+ testHighlighting('''
+@groovy.transform.CompileStatic
+def foo() {
+ final collector = [1, 2].find {a ->
+ a.<error descr="Cannot resolve symbol 'intValue'">intValue</error>()
+ }
+}
+''')
+ }
+
+ void testIllegalLiteralName() {
+ testHighlighting('''
+def <error descr="Illegal escape character in string literal">'a\\obc'</error>() {
+
+}
+''')
+ }
+
+ void testExceptionParameterAlreadyDeclared() {
+ testHighlighting('''
+ int missing() {
+ InputStream i = null
+
+ try {
+ return 1
+ }
+ catch(Exception <error descr="Variable 'i' already defined">i</error>) {
+ return 2
+ }
+ }
+ ''')
+ }
+
+ void testInnerAnnotationType() {
+ testHighlighting('''
+ class A {
+ @interface <error descr="Annotation type cannot be inner">X</error> {}
+ }
+ ''')
+ }
} \ No newline at end of file
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/AnnotationsParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/AnnotationsParsingTest.groovy
index e7771412a0c2..d0fbe70b021b 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/AnnotationsParsingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/AnnotationsParsingTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,4 +33,5 @@ public class AnnotationsParsingTest extends GroovyParsingTestCase {
public void testPackageAnn() { doTest() }
public void testDefAttribute() {doTest()}
public void testLineFeedAfterRef() {doTest()}
-} \ No newline at end of file
+ public void testKeywordsAttributes() {doTest()}
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy
index eb8d50e68739..f875be49b8a5 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -151,6 +151,7 @@ public class ExpressionsParsingTest extends GroovyParsingTestCase {
public void testmapLiteral() throws Throwable { doTest(); }
public void testnew$arr_decl() throws Throwable { doTest(); }
+ public void testnew$emptyTypeArgs() { doTest() }
// public void testnew$new1() throws Throwable { doTest(); }
public void testanonymous$anonymous() throws Throwable { doTest(); }
@@ -245,18 +246,13 @@ public class ExpressionsParsingTest extends GroovyParsingTestCase {
public void testpath$typeVsExpr() { doTest(); }
public void testreferences$ref1() throws Throwable { doTest(); }
-
public void testreferences$ref2() throws Throwable { doTest(); }
-
public void testreferences$ref3() throws Throwable { doTest(); }
-
public void testreferences$ref4() throws Throwable { doTest(); }
-
public void testreferences$ref5() throws Throwable { doTest(); }
-
public void testreferences$ref6() throws Throwable { doTest(); }
-
public void testreferences$ref7() throws Throwable { doTest(); }
+ public void testreferences$emptyTypeArgs() { doTest() }
public void testregex$chen() throws Throwable { doTest(); }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy
index e3f331902f8f..489a2feefbe9 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,4 +49,5 @@ public class TypesParsingTest extends GroovyParsingTestCase {
public void testStaticInitializer() throws Throwable { doTest(); }
public void testInterfaceWithGroovyDoc() throws Throwable { doTest(); }
+ public void testEmptyTypeArgs() {doTest()}
} \ No newline at end of file
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy
index a03a79a3aa92..19a0d96f92a1 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/NavigateDelegatedClsMethodsTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -83,7 +83,7 @@ class A extends Page {
}
''')
def instance = TargetElementUtilBase.getInstance()
- def resolved = instance.findTargetElement(editor, instance.allAccepted, editor.caretModel.offset)
+ def resolved = instance.findTargetElement(editor, instance.allAccepted, editor.caretModel.offset).navigationElement
assertInstanceOf resolved, PsiMethod
assertEquals ('NavigableSupport', (resolved as PsiMethod).containingClass.name)
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy
index f61c59c1df27..f4841dc363d8 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -187,19 +187,6 @@ class X {
doTest()
}
- public void testInnerClassIsNotResolvedInAnonymous() {
- myFixture.addFileToProject "/p/Super.groovy", """
-package p
-
-interface Super {
- class Inner {
- }
-
- def foo(Inner i);
-}"""
- assertNull resolve("A.groovy");
- }
-
public void testInnerClassIsResolvedInAnonymous() {
myFixture.addFileToProject "/p/Super.groovy", """
package p
@@ -288,5 +275,18 @@ class Inheritor {
''', PsiClass)
}
+ void testInterfaceDoesNotResolveWithExpressionQualifier() {
+ def ref = configureByText('''\
+class Foo {
+ interface Inner {
+ }
+}
+
+new Foo().Inn<caret>er
+''')
+
+ assertNull(ref.resolve())
+ }
+
private void doTest(String fileName = getTestName(false) + ".groovy") { resolve(fileName, PsiClass) }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
index 2aed2f157ce9..5ab285189ba9 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
@@ -27,6 +27,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAc
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrMethodImpl
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl
import org.jetbrains.plugins.groovy.util.TestUtils
/**
@@ -1527,4 +1528,39 @@ myEnum = MyEnum.va<caret>lueOf('FOO')
}
+
+ void testContradictingPropertyAccessor() {
+ def method = resolveByText('''\
+class A {
+ def setFoo(Object o) {
+ print 'method'
+ }
+
+ int foo = 5
+}
+
+new A().setF<caret>oo(2)
+''', PsiMethod)
+
+
+ assertInstanceOf(method, GrMethodImpl)
+ }
+
+ void testContradictingPropertyAccessor2() {
+ def method = resolveByText('''\
+class A {
+ def setFoo(Object o) {
+ print 'method'
+ }
+
+ int foo = 5
+}
+
+new A().f<caret>oo = 2
+''', PsiMethod)
+
+
+ assertInstanceOf(method, GrMethodImpl)
+ }
+
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy
index bb482a6506b0..761fa75845ee 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy
@@ -1037,4 +1037,54 @@ print Fie<caret>ld1
assertNotNull(ref.resolve())
}
+
+ void testLocalVarVsClassFieldInAnonymous() {
+ final ref = configureByText('a.groovy', '''\
+ class A {
+ public foo
+ }
+
+ def foo = 4
+
+ new A() {
+ def foo() {
+ print fo<caret>o
+ }
+ }
+''')
+
+ assertFalse( ref.resolve() instanceof PsiField)
+ assertTrue( ref.resolve() instanceof GrVariable)
+ }
+
+ void testInterfaceDoesNotResolveWithExpressionQualifier() {
+ def ref = configureByText('''\
+class Foo {
+ interface Inner {
+ }
+
+ public Inner = 5
+}
+
+new Foo().Inn<caret>er
+''')
+
+ assertInstanceOf(ref.resolve(), PsiField)
+ }
+
+ void testInterfaceDoesNotResolveWithExpressionQualifier2() {
+ def ref = configureByText('''\
+class Foo {
+ interface Inner {
+ }
+
+ public Inner = 5
+}
+
+def foo = new Foo()
+print foo.Inn<caret>er
+''')
+
+ assertInstanceOf(ref.resolve(), PsiField)
+ }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/smartEnter/SmartEnterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/smartEnter/SmartEnterTest.groovy
index 0c368afba27b..4ac199925184 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/smartEnter/SmartEnterTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/smartEnter/SmartEnterTest.groovy
@@ -1,3 +1,18 @@
+/*
+ * 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 org.jetbrains.plugins.groovy.lang.smartEnter
import com.intellij.openapi.actionSystem.IdeActions
@@ -67,6 +82,16 @@ class Foo {
''')
}
+ public void testSynchronizedBraces() {
+ doTextTest('''\
+synchronized(x<caret>)
+''', '''\
+synchronized (x) {
+ <caret>
+}
+''')
+ }
+
private void doTextTest(String before, String after) {
myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, before)
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT)
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/FileGenerationTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/FileGenerationTest.groovy
index faf56cd64cad..e422d76a54ba 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/FileGenerationTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/FileGenerationTest.groovy
@@ -123,4 +123,6 @@ public enum A {
void testGroovyDoc() { doTest() }
void testReflectedMethodWithEllipsis() { doTest() }
+
+ void testMapAccess2() { doTest() }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy
index 780206d95248..a31da7dfa552 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy
@@ -73,13 +73,19 @@ public class ExtractMethodTest extends LightGroovyTestCase {
}
private GroovyExtractMethodHandler configureFromText(String fileText, final String name) {
- int startOffset = fileText.indexOf(TestUtils.BEGIN_MARKER);
- fileText = TestUtils.removeBeginMarker(fileText);
- int endOffset = fileText.indexOf(TestUtils.END_MARKER);
- fileText = TestUtils.removeEndMarker(fileText);
- myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, fileText);
+ final caret = fileText.indexOf(TestUtils.CARET_MARKER)
+ if (caret >= 0) {
+ myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, fileText);
+ }
+ else {
+ int startOffset = fileText.indexOf(TestUtils.BEGIN_MARKER);
+ fileText = TestUtils.removeBeginMarker(fileText);
+ int endOffset = fileText.indexOf(TestUtils.END_MARKER);
+ fileText = TestUtils.removeEndMarker(fileText);
+ myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, fileText);
+ myFixture.editor.selectionModel.setSelection(startOffset, endOffset);
+ }
- myFixture.editor.selectionModel.setSelection(startOffset, endOffset);
return new GroovyExtractMethodHandler() {
@Override
protected ExtractMethodInfoHelper getSettings(@NotNull InitialInfo initialInfo, PsiClass owner) {
@@ -152,4 +158,6 @@ public class ExtractMethodTest extends LightGroovyTestCase {
public void testTupleDeclaration() { doTest() }
public void testNonIdentifierName() {doTest('f*f')}
+
+ public void testAutoSelectExpression() { doTest() }
} \ No newline at end of file
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodTest.groovy
index 1c2d29c5979b..b3153d178b5a 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineMethodTest.groovy
@@ -23,6 +23,7 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil
import com.intellij.psi.impl.source.tree.TreeElement
+import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.refactoring.inline.GenericInlineHandler
import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
@@ -33,6 +34,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil
import org.jetbrains.plugins.groovy.util.TestUtils
/**
@@ -100,25 +102,36 @@ public class InlineMethodTest extends LightCodeInsightFixtureTestCase {
public void testVarargs() {doTest();}
- public void testTypeParameterDeclaredInFile() {
- doTest()
- }
+ public void testTypeParameterDeclaredInFile() { doTest() }
+
+ public void testBadReturns() { doTest() }
public void testInlineAll() {
+ doInlineAllTest()
+ }
+
+ private void doInlineAllTest() {
doTest(new GroovyInlineHandler() {
@Override
public InlineHandler.Settings prepareInlineElement(PsiElement element, Editor editor, boolean invokedOnReference) {
- return new InlineHandler.Settings() {
- @Override
- boolean isOnlyOneReferenceToInline() {false}
- }
+ return { false } as InlineHandler.Settings
}
})
}
-
+
public void testInlineNamedArgs() {doTest(); }
public void testInlineVarargs() {doTest()}
+ public void testCannotInlineMethodRef() {
+ try {
+ doInlineAllTest()
+ assert false
+ }
+ catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
+ assertEquals("Cannot inline reference 'new A().&foo'", e.message)
+ }
+ }
+
protected void doTest() {
doTest(new GroovyInlineHandler());
}
@@ -144,12 +157,19 @@ public class InlineMethodTest extends LightCodeInsightFixtureTestCase {
GroovyPsiElement selectedArea = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrReferenceExpression.class);
if (selectedArea == null) {
- PsiElement identifier = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, PsiElement.class);
- if (identifier != null){
- Assert.assertTrue("Selected area doesn't point to method", identifier.parent instanceof GrVariable);
- selectedArea = (GroovyPsiElement)identifier.parent;
+ PsiElement identifier = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, PsiElement.class);
+ if (identifier != null) {
+ if (identifier.parent instanceof GrVariable) {
+ selectedArea = (GroovyPsiElement)identifier.parent;
+ }
+ else if (identifier instanceof GrMethod) {
+ selectedArea = identifier
+ }
+ else {
+ this.assertTrue("Selected area doesn't point to method or variable", false)
+ }
+ }
}
- }
Assert.assertNotNull("Selected area reference points to nothing", selectedArea);
PsiElement element = selectedArea instanceof GrExpression ? selectedArea.reference.resolve() : selectedArea;
Assert.assertNotNull("Cannot resolve selected reference expression", element);
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
index acdfe52301d3..1fa97d0da58b 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
@@ -233,7 +233,7 @@ public abstract class TestUtils {
String name = nameElement.getText();
- assert name.equals(psiReference.getName());
+ assert name.equals(psiReference.getReferenceName());
int last = lastUnresolvedRef.get();
sb.append(text, last, nameElement.getTextOffset());
diff --git a/plugins/groovy/testdata/groovy/actions/smartEnter/listFixer.test b/plugins/groovy/testdata/groovy/actions/smartEnter/listFixer.test
index 532856ef53d3..429535e3b4e4 100644
--- a/plugins/groovy/testdata/groovy/actions/smartEnter/listFixer.test
+++ b/plugins/groovy/testdata/groovy/actions/smartEnter/listFixer.test
@@ -1,6 +1,4 @@
def foo = ["abc<caret>
-]
-----
-def foo = ["abc",
- <caret>
-] \ No newline at end of file
+def foo = ["abc"]
+<caret> \ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/controlFlow/pendingFromIf.test b/plugins/groovy/testdata/groovy/controlFlow/pendingFromIf.test
new file mode 100644
index 000000000000..54c64e034aca
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/controlFlow/pendingFromIf.test
@@ -0,0 +1,23 @@
+int res
+if (b) {
+ res = 1 // illegall warning here
+ try {} catch (Exception e) {}
+} else {
+ res = 2
+}
+print res
+-----
+0(1) element: null
+1(2) element: IF statement
+2(3,7) READ b
+3(4) WRITE res
+4(9) element: Open block
+5(6) element: Catch clause
+6(8,9) WRITE e
+7(8) WRITE res
+8(9) End element: IF statement
+9(10) READ print
+10(11) READ res
+11(12) ARGUMENT element: Reference expression
+12(13) element: Call expression MAYBE_RETURN
+13() element: null \ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/autoSelectExpression.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/autoSelectExpression.test
new file mode 100644
index 000000000000..31b8ae042a2d
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/autoSelectExpression.test
@@ -0,0 +1,11 @@
+if ('a'.equa<caret>ls('b')) {
+ print 2
+}
+-----
+if (testMethod()) {
+ print 2
+}
+
+private boolean testMethod() {
+ return 'a'.equals('b')
+} \ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/refactoring/inlineMethod/badReturns.test b/plugins/groovy/testdata/groovy/refactoring/inlineMethod/badReturns.test
new file mode 100644
index 000000000000..a7625ab022b4
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/refactoring/inlineMethod/badReturns.test
@@ -0,0 +1,19 @@
+class Cam{}
+
+def loadSettingsForm(Cam cam) {
+ def settings = getSettings(cam);
+ def json = [
+ id: cam.id,
+ name: cam.name,
+ ]
+ return json
+}
+
+<selection>def getSettings(Cam cam) {
+ if (userService.currentUserOwnsCam(cam)) {
+ return gService.getCamSettings(cam)
+ }
+ return null;
+}</selection>
+-----
+FAIL: Refactoring is not supported when return statement interrupts the execution flow \ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/refactoring/inlineMethod/cannotInlineMethodRef.test b/plugins/groovy/testdata/groovy/refactoring/inlineMethod/cannotInlineMethodRef.test
new file mode 100644
index 000000000000..d6469cc188ea
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/refactoring/inlineMethod/cannotInlineMethodRef.test
@@ -0,0 +1,7 @@
+class A {
+ def foo() {}
+}
+
+<selection>new A().foo</selection>()
+new A().&foo
+-----
diff --git a/plugins/groovy/testdata/highlighting/missingReturn/Finally.groovy b/plugins/groovy/testdata/highlighting/missingReturn/Finally.groovy
index ea470aa456ef..35d29d3cd149 100644
--- a/plugins/groovy/testdata/highlighting/missingReturn/Finally.groovy
+++ b/plugins/groovy/testdata/highlighting/missingReturn/Finally.groovy
@@ -4,7 +4,7 @@ int missing() {
try {
return 1;
}
- catch(Exception i) {
+ catch(Exception e) {
}
<warning descr="Not all execution paths return a value">}</warning>
diff --git a/plugins/groovy/testdata/parsing/groovy/annotations/keywordsAttributes.test b/plugins/groovy/testdata/parsing/groovy/annotations/keywordsAttributes.test
new file mode 100644
index 000000000000..fdbb1240a456
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/annotations/keywordsAttributes.test
@@ -0,0 +1,44 @@
+@Foo(as=5, def=4, in=6, foo=4)
+def zx
+-----
+Groovy script
+ Variable definitions
+ Modifiers
+ Annotation
+ PsiElement(@)('@')
+ Reference element
+ PsiElement(identifier)('Foo')
+ Annotation arguments
+ PsiElement(()('(')
+ Annotation member value pair
+ PsiElement(as)('as')
+ PsiElement(=)('=')
+ Literal
+ PsiElement(Integer)('5')
+ PsiElement(,)(',')
+ PsiWhiteSpace(' ')
+ Annotation member value pair
+ PsiElement(def)('def')
+ PsiElement(=)('=')
+ Literal
+ PsiElement(Integer)('4')
+ PsiElement(,)(',')
+ PsiWhiteSpace(' ')
+ Annotation member value pair
+ PsiElement(in)('in')
+ PsiElement(=)('=')
+ Literal
+ PsiElement(Integer)('6')
+ PsiElement(,)(',')
+ PsiWhiteSpace(' ')
+ Annotation member value pair
+ PsiElement(identifier)('foo')
+ PsiElement(=)('=')
+ Literal
+ PsiElement(Integer)('4')
+ PsiElement())(')')
+ PsiElement(new line)('\n')
+ PsiElement(def)('def')
+ PsiWhiteSpace(' ')
+ Variable
+ PsiElement(identifier)('zx') \ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/new/emptyTypeArgs.test b/plugins/groovy/testdata/parsing/groovy/expressions/new/emptyTypeArgs.test
new file mode 100644
index 000000000000..b1087dd46493
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/new/emptyTypeArgs.test
@@ -0,0 +1,14 @@
+new List<>()
+-----
+Groovy script
+ NEW expression
+ PsiElement(new)('new')
+ PsiWhiteSpace(' ')
+ Reference element
+ PsiElement(identifier)('List')
+ Type arguments
+ PsiElement(<)('<')
+ PsiElement(>)('>')
+ Arguments
+ PsiElement(()('(')
+ PsiElement())(')') \ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/references/emptyTypeArgs.test b/plugins/groovy/testdata/parsing/groovy/expressions/references/emptyTypeArgs.test
new file mode 100644
index 000000000000..ac67d64fdc92
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/references/emptyTypeArgs.test
@@ -0,0 +1,17 @@
+foo.<>bar()
+-----
+Groovy script
+ Method call
+ Reference expression
+ Reference expression
+ PsiElement(identifier)('foo')
+ PsiElement(.)('.')
+ Type arguments
+ PsiElement(<)('<')
+ PsiErrorElement:Type argument expected
+ <empty list>
+ PsiElement(>)('>')
+ PsiElement(identifier)('bar')
+ Arguments
+ PsiElement(()('(')
+ PsiElement())(')') \ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/emptyTypeArgs.test b/plugins/groovy/testdata/parsing/groovy/types/emptyTypeArgs.test
new file mode 100644
index 000000000000..7fb7625d2522
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/types/emptyTypeArgs.test
@@ -0,0 +1,29 @@
+List<> l = [1, 2]
+-----
+Groovy script
+ Variable definitions
+ Modifiers
+ <empty list>
+ Type element
+ Reference element
+ PsiElement(identifier)('List')
+ Type arguments
+ PsiElement(<)('<')
+ PsiErrorElement:Type argument expected
+ <empty list>
+ PsiElement(>)('>')
+ PsiWhiteSpace(' ')
+ Variable
+ PsiElement(identifier)('l')
+ PsiWhiteSpace(' ')
+ PsiElement(=)('=')
+ PsiWhiteSpace(' ')
+ Generalized list
+ PsiElement([)('[')
+ Literal
+ PsiElement(Integer)('1')
+ PsiElement(,)(',')
+ PsiWhiteSpace(' ')
+ Literal
+ PsiElement(Integer)('2')
+ PsiElement(])(']') \ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java
index 19dfb233d0c9..49fc47dfd3c5 100644
--- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java
@@ -18,7 +18,7 @@ java.util.HashMap<java.lang.String, java.lang.String> map = new java.util.HashMa
print(putAt0(map, "1", "6"));
print(putAt0(map, 2, "7"));
-org.codehaus.groovy.runtime.DefaultGroovyMethods.putAt(map, "6", 1);
+map.put("6", 1);
print(map.get("1"));
print(map.get(2));
@@ -45,7 +45,7 @@ public arrayAccess() {
super();
}
private static <K, V, Value extends V>Value putAt0(java.util.Map<K, V> propOwner, K key, Value value) {
-org.codehaus.groovy.runtime.DefaultGroovyMethods.putAt(propOwner, key, value);
+propOwner.put(key, value);
return value;
}
private static <Value>Value putAt1(Foo propOwner, java.lang.String s, java.lang.Integer x, Value value) {
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/mapAccess2.groovy b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/mapAccess2.groovy
new file mode 100644
index 000000000000..d706ef720b5a
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/mapAccess2.groovy
@@ -0,0 +1,7 @@
+class G {
+ private Map<String, Map<String, String>> commits = [:]
+
+ int register(String virtualHash, Map<String, String> commitDetails) {
+ commits[virtualHash] = commitDetails
+ }
+} \ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/mapAccess2.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/mapAccess2.java
new file mode 100644
index 000000000000..e27f2f680520
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/mapAccess2.java
@@ -0,0 +1,8 @@
+public class G {
+public int register(java.lang.String virtualHash, java.util.Map<java.lang.String, java.lang.String> commitDetails) {
+commits.put(virtualHash, commitDetails);
+return ((int)(commitDetails));
+}
+
+private java.util.Map<java.lang.String, java.util.Map<java.lang.String, java.lang.String>> commits = new java.util.LinkedHashMap<java.lang.String, java.util.Map<java.lang.String, java.lang.String>>();
+}
diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
index 308d3279e7c6..804bc45776d9 100644
--- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
+++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
@@ -1,6 +1,6 @@
group.MercurialFileGroup.text=Mercurial Init
group.hg4idea.file.menu.text=Mercurial
-action.hg4idea.tag.text=Tag Repository
+action.hg4idea.tag.text=Tag Repository...
action.hg4idea.tag.description=Create a tag for current revision
action.hg4idea.updateTo.text=Update to...
action.hg4idea.updateTo.description=Updating to {0}...
@@ -114,7 +114,9 @@ hg4idea.merge.please-commit=Merged heads, please commit repository \"{0}\"
hg4idea.error.invalidExecutable=\"{0}\" is not a valid mercurial executable
hg4idea.integrate.other.head=Other head: {0}
hg4idea.error.log.command.execution=Error during log command execution
-hg4idea.branches.error.description=Couldn't collect information about branches
+hg4idea.branches.error.description=Couldn't collect information about branches and tags
+hg4idea.error.debugancestor.command.execution=Error during debugancestor command execution
+hg4idea.error.debugancestor.command.description=Couldn't collect information about ancestor
hg4idea.dialog.login.password.required=Login and password required
hg4idea.dialog.login.description=Login to {0}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java
index 04c40795f6d9..6b91e826aff0 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java
@@ -32,7 +32,6 @@ import org.zmlx.hg4idea.command.HgTagBranchCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
import org.zmlx.hg4idea.execution.HgCommandResultHandler;
import org.zmlx.hg4idea.ui.HgPushDialog;
-import org.zmlx.hg4idea.util.HgErrorUtil;
import org.zmlx.hg4idea.util.HgUtil;
import java.util.Collections;
@@ -48,6 +47,10 @@ public class HgPusher {
private static final Logger LOG = Logger.getInstance(HgPusher.class);
private static Pattern PUSH_COMMITS_PATTERN = Pattern.compile(".*added (\\d+) changesets.*");
+ // 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;
@@ -55,7 +58,7 @@ public class HgPusher {
myProject = project;
}
- public void showDialogAndPush() {
+ public void showDialogAndPush(@Nullable final VirtualFile selectedRepo) {
HgUtil.executeOnPooledThreadIfNeeded(new Runnable() {
public void run() {
final List<VirtualFile> repositories = HgUtil.getHgRepositories(myProject);
@@ -72,7 +75,7 @@ public class HgPusher {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
- final HgPushDialog dialog = new HgPushDialog(myProject, repositories, branches);
+ final HgPushDialog dialog = new HgPushDialog(myProject, repositories, branches, selectedRepo);
dialog.show();
if (dialog.isOK()) {
dialog.rememberSettings();
@@ -113,13 +116,13 @@ public class HgPusher {
return;
}
- int commitsNum = getNumberOfPushedCommits(result);
- if (commitsNum > 0 && result.getExitValue() == 0) {
+ if (result.getExitValue() == PUSH_SUCCEEDED_EXIT_VALUE) {
+ int commitsNum = getNumberOfPushedCommits(result);
String successTitle = "Pushed successfully";
String successDescription = String.format("Pushed %d %s [%s]", commitsNum, StringUtil.pluralize("commit", commitsNum),
repo.getPresentableName());
new HgCommandResultNotifier(project).notifySuccess(successTitle, successDescription);
- } else if (commitsNum == 0) {
+ } else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) {
new HgCommandResultNotifier(project).notifySuccess("", "Nothing to push");
} else {
new HgCommandResultNotifier(project).notifyError(result, "Push failed",
@@ -139,24 +142,21 @@ public class HgPusher {
private static int getNumberOfPushedCommits(HgCommandResult result) {
int numberOfCommitsInAllSubrepos = 0;
- if (!HgErrorUtil.isAbort(result)) {
- final List<String> outputLines = result.getOutputLines();
- for (String outputLine : outputLines) {
- outputLine = outputLine.trim();
- final Matcher matcher = PUSH_COMMITS_PATTERN.matcher(outputLine);
- if (matcher.matches()) {
- try {
- numberOfCommitsInAllSubrepos += Integer.parseInt(matcher.group(1));
- }
- catch (NumberFormatException e) {
- LOG.info("getNumberOfPushedCommits ", e);
- return -1;
- }
+ final List<String> outputLines = result.getOutputLines();
+ for (String outputLine : outputLines) {
+ outputLine = outputLine.trim();
+ final Matcher matcher = PUSH_COMMITS_PATTERN.matcher(outputLine);
+ if (matcher.matches()) {
+ try {
+ numberOfCommitsInAllSubrepos += Integer.parseInt(matcher.group(1));
+ }
+ catch (NumberFormatException e) {
+ LOG.error("getNumberOfPushedCommits ", e);
+ return -1;
}
}
- return numberOfCommitsInAllSubrepos;
}
- return -1;
+ return numberOfCommitsInAllSubrepos;
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java
index ede2c660fd8b..27ec978229e8 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java
@@ -99,7 +99,7 @@ public class HgVFSListener extends VcsVFSListener {
pi.setText(repo.getPresentableUrl());
try {
untrackedFiles
- .addAll(new HgStatusCommand.Builder(false).includeUnknown(true).build(myProject)
+ .addAll(new HgStatusCommand.Builder(false).unknown(true).build(myProject)
.getHgUntrackedFiles(repo, new ArrayList<VirtualFile>(files)));
}
catch (final VcsException ex) {
@@ -148,7 +148,7 @@ public class HgVFSListener extends VcsVFSListener {
LOG.assertTrue(myProject != null, "Project is null");
Collection<VirtualFile> unversionedAndIgnoredFiles = new ArrayList<VirtualFile>();
final Map<VirtualFile, Collection<VirtualFile>> sortedSourceFilesByRepos = HgUtil.sortByHgRoots(myProject, copyFromMap.values());
- HgStatusCommand statusCommand = new HgStatusCommand.Builder(false).includeUnknown(true).includeIgnored(true).build(myProject);
+ HgStatusCommand statusCommand = new HgStatusCommand.Builder(false).unknown(true).ignored(true).build(myProject);
for (VirtualFile repo : sortedSourceFilesByRepos.keySet()) {
Set<HgChange> changes = statusCommand.execute(repo);
for (HgChange change : changes) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
index 5d41d7e36026..124ae08e034f 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
@@ -16,6 +16,7 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.util.HgUtil;
import javax.swing.*;
@@ -38,7 +39,9 @@ abstract class HgAbstractGlobalAction extends AnAction {
if (project == null) {
return;
}
- execute(project, HgUtil.getHgRepositories(project));
+ VirtualFile file = event.getData(PlatformDataKeys.VIRTUAL_FILE);
+ VirtualFile repo = file != null ? HgUtil.getHgRootOrNull(project, file) : null;
+ execute(project, HgUtil.getHgRepositories(project), repo);
}
@Override
@@ -54,7 +57,7 @@ abstract class HgAbstractGlobalAction extends AnAction {
}
}
- protected abstract void execute(Project project, Collection<VirtualFile> repositories);
+ protected abstract void execute(Project project, Collection<VirtualFile> repositories, @Nullable VirtualFile selectedRepo);
protected static void handleException(Project project, Exception e) {
LOG.info(e);
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java
index 6ef4a88a02bb..31da4a07e7f9 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java
@@ -17,6 +17,9 @@ package org.zmlx.hg4idea.action;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.util.HgUtil;
import javax.swing.*;
@@ -38,8 +41,9 @@ public abstract class HgAction extends AnAction {
if (project == null) {
return;
}
-
- execute(project);
+ VirtualFile file = event.getData(PlatformDataKeys.VIRTUAL_FILE);
+ VirtualFile repo = file != null ? HgUtil.getHgRootOrNull(project, file) : null;
+ execute(project, repo);
}
@Override
@@ -53,6 +57,6 @@ public abstract class HgAction extends AnAction {
}
}
- public abstract void execute(Project project);
+ public abstract void execute(Project project, @Nullable VirtualFile selectedRepo);
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
index d308813ff04e..ea7f2c5a9f6d 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
@@ -26,9 +26,9 @@ import java.util.Collection;
public class HgCreateTagAction extends HgAbstractGlobalAction {
- protected void execute(final Project project, Collection<VirtualFile> repos) {
+ protected void execute(final Project project, Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
final HgTagDialog dialog = new HgTagDialog(project);
- dialog.setRoots(repos);
+ dialog.setRoots(repos, selectedRepo);
dialog.show();
if (dialog.isOK()) {
try {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
index 8d2f865d077d..04360f15aff1 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgRevisionNumber;
import org.zmlx.hg4idea.HgVcsMessages;
import org.zmlx.hg4idea.command.HgMergeCommand;
@@ -32,11 +33,10 @@ import org.zmlx.hg4idea.execution.HgCommandException;
import org.zmlx.hg4idea.provider.update.HgConflictResolver;
import org.zmlx.hg4idea.provider.update.HgHeadMerger;
import org.zmlx.hg4idea.ui.HgMergeDialog;
+import org.zmlx.hg4idea.util.HgBranchesAndTags;
import org.zmlx.hg4idea.util.HgUiUtil;
import java.util.Collection;
-import java.util.List;
-import java.util.Map;
/**
* @author Nadya Zabrodina
@@ -44,21 +44,20 @@ import java.util.Map;
public class HgMerge extends HgAbstractGlobalAction {
@Override
-
- public void execute(final Project project, final Collection<VirtualFile> repos) {
- HgUiUtil.loadBranchesInBackgroundableAndExecuteAction(project, repos, new Consumer<Map<VirtualFile, List<HgTagBranch>>>() {
+ public void execute(final Project project, final Collection<VirtualFile> repos, @Nullable final VirtualFile selectedRepo) {
+ HgUiUtil.loadBranchesInBackgroundableAndExecuteAction(project, repos, new Consumer<HgBranchesAndTags>() {
@Override
- public void consume(Map<VirtualFile, List<HgTagBranch>> branches) {
- showMergeDialogAndExecute(project, repos, branches);
+ public void consume(HgBranchesAndTags info) {
+ showMergeDialogAndExecute(project, repos, selectedRepo, info);
}
});
}
private void showMergeDialogAndExecute(final Project project,
Collection<VirtualFile> repos,
- Map<VirtualFile, List<HgTagBranch>> branchesForRepos) {
- final HgMergeDialog mergeDialog = new HgMergeDialog(project, repos, branchesForRepos);
+ @Nullable VirtualFile selectedRepo, HgBranchesAndTags branchesAndTags) {
+ final HgMergeDialog mergeDialog = new HgMergeDialog(project, repos, selectedRepo, branchesAndTags);
mergeDialog.show();
if (mergeDialog.isOK()) {
new Task.Backgroundable(project, "Merging changes...") {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
index ea4fba71603f..ab1d5fce992d 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
@@ -18,6 +18,7 @@ import com.intellij.openapi.progress.Task;
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.command.HgPullCommand;
import org.zmlx.hg4idea.ui.HgPullDialog;
@@ -28,9 +29,10 @@ public class HgPullAction extends HgAbstractGlobalAction {
super(AllIcons.Actions.CheckOut);
}
- protected void execute(final Project project, Collection<VirtualFile> repos) {
+ @Override
+ protected void execute(final Project project, Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
final HgPullDialog dialog = new HgPullDialog(project);
- dialog.setRoots(repos);
+ dialog.setRoots(repos, selectedRepo);
dialog.show();
if (dialog.isOK()) {
dialog.rememberSettings();
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
index 1f8e42abfd6f..ae6206c7a253 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
@@ -14,6 +14,8 @@ package org.zmlx.hg4idea.action;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgPusher;
public class HgPushAction extends HgAction {
@@ -22,8 +24,8 @@ public class HgPushAction extends HgAction {
}
@Override
- public void execute(final Project project) {
- new HgPusher(project).showDialogAndPush();
+ public void execute(final Project project, @Nullable final VirtualFile selectedRepo) {
+ new HgPusher(project).showDialogAndPush(selectedRepo);
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
index 81bf6418e098..cce3df45c994 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
@@ -17,6 +17,7 @@ import com.intellij.openapi.progress.Task;
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.HgVcsMessages;
import org.zmlx.hg4idea.provider.update.HgConflictResolver;
import org.zmlx.hg4idea.ui.HgRunConflictResolverDialog;
@@ -25,10 +26,11 @@ import java.util.Collection;
public class HgRunConflictResolverAction extends HgAbstractGlobalAction {
- public void execute(final Project project, Collection<VirtualFile> repos) {
+ @Override
+ public void execute(final Project project, Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
final VirtualFile repository;
if (repos.size() > 1) {
- repository = letUserSelectRepository(repos, project);
+ repository = letUserSelectRepository(repos, project, selectedRepo);
}
else if (repos.size() == 1) {
repository = repos.iterator().next();
@@ -49,9 +51,9 @@ public class HgRunConflictResolverAction extends HgAbstractGlobalAction {
}
- private static VirtualFile letUserSelectRepository(Collection<VirtualFile> repos, Project project) {
+ private static VirtualFile letUserSelectRepository(Collection<VirtualFile> repos, Project project, @Nullable VirtualFile selectedRepo) {
HgRunConflictResolverDialog dialog = new HgRunConflictResolverDialog(project);
- dialog.setRoots(repos);
+ dialog.setRoots(repos, selectedRepo);
dialog.show();
if (dialog.isOK()) {
return dialog.getRepository();
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
index f7951e5b7a28..fcb02bb01854 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
@@ -20,36 +20,34 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgVcs;
import org.zmlx.hg4idea.HgVcsMessages;
-import org.zmlx.hg4idea.command.HgTagBranch;
import org.zmlx.hg4idea.command.HgUpdateCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
import org.zmlx.hg4idea.ui.HgUpdateToDialog;
+import org.zmlx.hg4idea.util.HgBranchesAndTags;
import org.zmlx.hg4idea.util.HgErrorUtil;
import org.zmlx.hg4idea.util.HgUiUtil;
import java.util.Collection;
-import java.util.List;
-import java.util.Map;
public class HgUpdateToAction extends HgAbstractGlobalAction {
- protected void execute(final Project project, final Collection<VirtualFile> repos) {
- HgUiUtil.loadBranchesInBackgroundableAndExecuteAction(project, repos, new Consumer<Map<VirtualFile, List<HgTagBranch>>>() {
-
+ protected void execute(final Project project, final Collection<VirtualFile> repos, @Nullable final VirtualFile selectedRepo) {
+ HgUiUtil.loadBranchesInBackgroundableAndExecuteAction(project, repos, new Consumer<HgBranchesAndTags>() {
@Override
- public void consume(Map<VirtualFile, List<HgTagBranch>> branches) {
- showUpdateDialogAndExecute(project, repos, branches);
+ public void consume(HgBranchesAndTags info) {
+ showUpdateDialogAndExecute(project, repos, selectedRepo, info);
}
});
}
private void showUpdateDialogAndExecute(final Project project,
- Collection<VirtualFile> repos,
- Map<VirtualFile, List<HgTagBranch>> branchesForRepos) {
+ Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo,
+ HgBranchesAndTags branchesAndTags) {
final HgUpdateToDialog dialog = new HgUpdateToDialog(project);
- dialog.setRoots(repos, branchesForRepos);
+ dialog.setRoots(repos, selectedRepo, branchesAndTags);
dialog.show();
if (dialog.isOK()) {
FileDocumentManager.getInstance().saveAllDocuments();
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java
index 098f74ed0f86..7187fc4f512d 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java
@@ -1,6 +1,8 @@
package org.zmlx.hg4idea.command;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.execution.HgCommandExecutor;
import org.zmlx.hg4idea.execution.HgCommandResult;
@@ -26,10 +28,10 @@ public class HgIdentifyCommand {
}
@Nullable
- public HgCommandResult execute() {
+ public HgCommandResult execute(@NotNull ModalityState state) {
final List<String> arguments = new LinkedList<String>();
arguments.add(source);
- final HgCommandExecutor executor = new HgCommandExecutor(project, source);
+ final HgCommandExecutor executor = new HgCommandExecutor(project, source, state);
executor.setSilent(true);
return executor.executeInCurrentThread(null, "identify", arguments);
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java
index 46957961c0cf..eada83d0beda 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java
@@ -39,18 +39,18 @@ public class HgStatusCommand {
private static final int ITEM_COUNT = 3;
private static final int STATUS_INDEX = 0;
- private final Project project;
+ @NotNull private final Project myProject;
- private final boolean includeAdded;
- private final boolean includeModified;
- private final boolean includeRemoved;
- private final boolean includeDeleted;
- private final boolean includeUnknown;
- private final boolean includeIgnored;
- private final boolean includeCopySource;
+ private final boolean myIncludeAdded;
+ private final boolean myIncludeModified;
+ private final boolean myIncludeRemoved;
+ private final boolean myIncludeDeleted;
+ private final boolean myIncludeUnknown;
+ private final boolean myIncludeIgnored;
+ private final boolean myIncludeCopySource;
- @Nullable private HgRevisionNumber baseRevision;
- @Nullable private HgRevisionNumber targetRevision;
+ @Nullable private final HgRevisionNumber myBaseRevision;
+ @Nullable private final HgRevisionNumber myTargetRevision;
public static class Builder {
@@ -62,6 +62,9 @@ public class HgStatusCommand {
private boolean includeIgnored;
private boolean includeCopySource;
+ private HgRevisionNumber baseRevision;
+ private HgRevisionNumber targetRevision;
+
public Builder(boolean initValue) {
includeAdded = initValue;
includeModified = initValue;
@@ -70,46 +73,52 @@ public class HgStatusCommand {
includeUnknown = initValue;
includeIgnored = initValue;
includeCopySource = initValue;
+ baseRevision = null;
+ targetRevision = null;
}
- public Builder includeUnknown(boolean val) {
+ public Builder unknown(boolean val) {
includeUnknown = val;
return this;
}
- public Builder includeIgnored(boolean val) {
+ public Builder ignored(boolean val) {
includeIgnored = val;
return this;
}
- public Builder includeCopySource(boolean val) {
+ public Builder copySource(boolean val) {
includeCopySource = val;
return this;
}
- public HgStatusCommand build(Project project) {
- return new HgStatusCommand(project, this);
+ public Builder baseRevision(HgRevisionNumber val) {
+ baseRevision = val;
+ return this;
}
- }
+ public Builder targetRevision(HgRevisionNumber val) {
+ targetRevision = val;
+ return this;
+ }
- private HgStatusCommand(Project project, Builder builder) {
- this.project = project;
- includeAdded = builder.includeAdded;
- includeModified = builder.includeModified;
- includeRemoved = builder.includeRemoved;
- includeDeleted = builder.includeDeleted;
- includeUnknown = builder.includeUnknown;
- includeIgnored = builder.includeIgnored;
- includeCopySource = builder.includeCopySource;
- }
+ public HgStatusCommand build(@NotNull Project project) {
+ return new HgStatusCommand(project, this);
+ }
- public void setBaseRevision(@Nullable HgRevisionNumber base) {
- baseRevision = base;
}
- public void setTargetRevision(@Nullable HgRevisionNumber target) {
- targetRevision = target;
+ private HgStatusCommand(@NotNull Project project, @NotNull Builder builder) {
+ myProject = project;
+ myIncludeAdded = builder.includeAdded;
+ myIncludeModified = builder.includeModified;
+ myIncludeRemoved = builder.includeRemoved;
+ myIncludeDeleted = builder.includeDeleted;
+ myIncludeUnknown = builder.includeUnknown;
+ myIncludeIgnored = builder.includeIgnored;
+ myIncludeCopySource = builder.includeCopySource;
+ myBaseRevision = builder.baseRevision;
+ myTargetRevision = builder.targetRevision;
}
public Set<HgChange> execute(VirtualFile repo) {
@@ -121,37 +130,37 @@ public class HgStatusCommand {
return Collections.emptySet();
}
- HgCommandExecutor executor = new HgCommandExecutor(project, null);
+ HgCommandExecutor executor = new HgCommandExecutor(myProject, null);
executor.setSilent(true);
List<String> options = new LinkedList<String>();
- if (includeAdded) {
+ if (myIncludeAdded) {
options.add("--added");
}
- if (includeModified) {
+ if (myIncludeModified) {
options.add("--modified");
}
- if (includeRemoved) {
+ if (myIncludeRemoved) {
options.add("--removed");
}
- if (includeDeleted) {
+ if (myIncludeDeleted) {
options.add("--deleted");
}
- if (includeUnknown) {
+ if (myIncludeUnknown) {
options.add("--unknown");
}
- if (includeIgnored) {
+ if (myIncludeIgnored) {
options.add("--ignored");
}
- if (includeCopySource) {
+ if (myIncludeCopySource) {
options.add("--copies");
}
- if (baseRevision != null && !baseRevision.getRevision().isEmpty()) {
+ if (myBaseRevision != null && !myBaseRevision.getRevision().isEmpty()) {
options.add("--rev");
- options.add(baseRevision.getChangeset().isEmpty() ? baseRevision.getRevision() : baseRevision.getChangeset());
- if (targetRevision != null) {
+ options.add(myBaseRevision.getChangeset().isEmpty() ? myBaseRevision.getRevision() : myBaseRevision.getChangeset());
+ if (myTargetRevision != null) {
options.add("--rev");
- options.add(targetRevision.getChangeset());
+ options.add(myTargetRevision.getChangeset());
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
index ca44688c674a..548cdf6000ad 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
@@ -69,9 +69,9 @@ class HgCommandAuthenticator {
}
}
- public boolean promptForAuthentication(Project project, String proposedLogin, String uri, String path) {
+ public boolean promptForAuthentication(Project project, String proposedLogin, String uri, String path, @Nullable ModalityState state) {
GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization);
- ApplicationManager.getApplication().invokeAndWait(runnable, ModalityState.defaultModalityState());
+ ApplicationManager.getApplication().invokeAndWait(runnable, state == null ? ModalityState.defaultModalityState() : state);
myRunnable = runnable;
return runnable.isOk();
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java
index 0b039bd048c2..0cc71dc2d605 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java
@@ -13,6 +13,8 @@
package org.zmlx.hg4idea.execution;
import com.intellij.execution.ui.ConsoleViewContentType;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
@@ -51,6 +53,7 @@ import java.util.List;
* <li>error output is logged to the console and log, if the command is not silent.
* </p>
*/
+@SuppressWarnings("UseOfSystemOutOrSystemErr")
public final class HgCommandExecutor {
private static final Logger LOG = Logger.getInstance(HgCommandExecutor.class.getName());
@@ -64,15 +67,21 @@ public final class HgCommandExecutor {
private boolean myIsSilent = false;
private boolean myShowOutput = false;
private List<String> myOptions = DEFAULT_OPTIONS;
+ @Nullable private ModalityState myState;
public HgCommandExecutor(Project project) {
this(project, null);
}
public HgCommandExecutor(Project project, @Nullable String destination) {
+ this(project, destination, null);
+ }
+
+ public HgCommandExecutor(Project project, @Nullable String destination, @Nullable ModalityState state) {
myProject = project;
myVcs = HgVcs.getInstance(project);
myDestination = destination;
+ myState = state;
}
public void setCharset(Charset charset) {
@@ -145,7 +154,7 @@ public final class HgCommandExecutor {
}
WarningReceiver warningReceiver = new WarningReceiver();
- PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization);
+ PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization, myState);
SocketServer promptServer = new SocketServer(new PromptReceiver(handler));
SocketServer warningServer = new SocketServer(warningReceiver);
@@ -223,7 +232,11 @@ public final class HgCommandExecutor {
final String executable = settings.isRunViaBash() ? "bash -c " + exeName : exeName;
final String cmdString = String.format("%s %s %s", executable, operation, arguments == null ? "" : StringUtil.join(arguments, " "));
+ final boolean isUnitTestMode = ApplicationManager.getApplication().isUnitTestMode();
// log command
+ if (isUnitTestMode) {
+ System.out.print(cmdString + "\n");
+ }
if (!myIsSilent) {
LOG.info(cmdString);
myVcs.showMessageInConsole(cmdString, ConsoleViewContentType.NORMAL_OUTPUT.getAttributes());
@@ -234,6 +247,9 @@ public final class HgCommandExecutor {
// log output if needed
if (!result.getRawOutput().isEmpty()) {
+ if (isUnitTestMode) {
+ System.out.print(result.getRawOutput() + "\n");
+ }
if (!myIsSilent && myShowOutput) {
LOG.info(result.getRawOutput());
myVcs.showMessageInConsole(result.getRawOutput(), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
@@ -245,6 +261,9 @@ public final class HgCommandExecutor {
// log error
if (!result.getRawError().isEmpty()) {
+ if (isUnitTestMode) {
+ System.out.print(result.getRawError() + "\n");
+ }
if (!myIsSilent) {
LOG.info(result.getRawError());
myVcs.showMessageInConsole(result.getRawError(), ConsoleViewContentType.ERROR_OUTPUT.getAttributes());
@@ -359,10 +378,12 @@ public final class HgCommandExecutor {
private final Project myProject;
private HgCommandAuthenticator myAuthenticator;
private boolean myForceAuthorization;
+ @Nullable private ModalityState myState;
- private PassReceiver(Project project, boolean forceAuthorization) {
+ private PassReceiver(Project project, boolean forceAuthorization, @Nullable ModalityState state) {
myProject = project;
myForceAuthorization = forceAuthorization;
+ myState = state;
}
@Override
@@ -377,7 +398,7 @@ public final class HgCommandExecutor {
String proposedLogin = new String(readDataBlock(dataInputStream));
HgCommandAuthenticator authenticator = new HgCommandAuthenticator(myProject, myForceAuthorization);
- boolean ok = authenticator.promptForAuthentication(myProject, proposedLogin, uri, path);
+ boolean ok = authenticator.promptForAuthentication(myProject, proposedLogin, uri, path, myState);
if (ok) {
myAuthenticator = authenticator;
sendDataBlock(out, authenticator.getUserName().getBytes());
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgMergeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgMergeProvider.java
index bbd2df3e4fac..575fbe42b17d 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgMergeProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgMergeProvider.java
@@ -18,6 +18,7 @@ package org.zmlx.hg4idea.provider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.merge.MergeData;
@@ -26,13 +27,16 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcsUtil.VcsRunnable;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
-import org.zmlx.hg4idea.*;
+import org.zmlx.hg4idea.HgContentRevision;
+import org.zmlx.hg4idea.HgFile;
+import org.zmlx.hg4idea.HgRevisionNumber;
+import org.zmlx.hg4idea.HgVcsMessages;
import org.zmlx.hg4idea.action.HgCommandResultNotifier;
-import org.zmlx.hg4idea.command.HgLogCommand;
-import org.zmlx.hg4idea.execution.HgCommandException;
-import org.zmlx.hg4idea.util.HgUtil;
import org.zmlx.hg4idea.command.HgResolveCommand;
import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand;
+import org.zmlx.hg4idea.execution.HgCommandExecutor;
+import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.util.HgUtil;
import java.io.File;
import java.io.IOException;
@@ -81,19 +85,30 @@ public class HgMergeProvider implements MergeProvider {
mergeData.CURRENT = local.getContentAsBytes();
// we are sure that we have a common ancestor, because otherwise we'll get "repository is unrelated" error while pulling,
// due to different root changesets which is prohibited.
- // Find common ancestor of two revisions : hg log -r "ancestor(rev1,ancestor(rev2,rev3))"
+ // Find common ancestor of two revisions : hg debugancestor rev1 rev2
+ // Using quotes may produce wrong escaping errors on Unix-type systems
List<String> arguments = new ArrayList<String>();
- arguments.add("-r");
- arguments.add("\"ancestor(" + localRevisionNumber.getRevision() + ',' + serverRevisionNumber.getRevision() + ")\"");
- final List<HgFileRevision> revisions;
- try {
- revisions = new HgLogCommand(myProject).execute(new HgFile(myProject, file), -1, false, arguments);
- if (revisions != null && !revisions.isEmpty()) {
- baseRevisionNumber = revisions.get(0).getRevisionNumber();
+ arguments.add(localRevisionNumber.getRevision());
+ arguments.add(serverRevisionNumber.getRevision());
+ HgCommandResult result = new HgCommandExecutor(myProject).executeInCurrentThread(repo, "debugancestor", arguments);
+ if (result != null) {
+ String output = result.getRawOutput();
+ final List<String> parts = StringUtil.split(output, ":");
+ if (parts.size() < 2) {
+ LOG.info("Couldn't parse result of debugancestor command execution " + arguments);
+ new HgCommandResultNotifier(myProject)
+ .notifyError(null, HgVcsMessages.message("hg4idea.error.debugancestor.command.execution"),
+ HgVcsMessages.message("hg4idea.error.debugancestor.command.description"));
+ }
+ else {
+ baseRevisionNumber = HgRevisionNumber.getInstance(parts.get(0), parts.get(1));
}
}
- catch (HgCommandException e) {
- throw new VcsException(HgVcsMessages.message("hg4idea.error.log.command.execution"), e);
+ else {
+ LOG.info(HgVcsMessages.message("hg4idea.error.debugancestor.command.execution") + arguments);
+ new HgCommandResultNotifier(myProject)
+ .notifyError(null, HgVcsMessages.message("hg4idea.error.debugancestor.command.execution"),
+ HgVcsMessages.message("hg4idea.error.debugancestor.command.description"));
}
} else {
// 2. local changes are not checked in.
@@ -112,7 +127,8 @@ public class HgMergeProvider implements MergeProvider {
if (baseRevisionNumber != null) {
final HgContentRevision base = new HgContentRevision(myProject, hgFile, baseRevisionNumber);
- mergeData.ORIGINAL = base.getContentAsBytes();
+ //if file doesn't exist in ancestor revision the base revision should be empty
+ mergeData.ORIGINAL = base.getContent() != null ? base.getContentAsBytes() : new byte[0];
} else { // no base revision means that the file was added simultaneously with different content in both repositories
mergeData.ORIGINAL = new byte[0];
}
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 9f04d14e89af..7df032e70309 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
@@ -72,7 +72,8 @@ public class HgCheckinEnvironment implements CheckinEnvironment {
@NotNull NullableFunction<Object, Object> parametersHolder,
Set<String> feedback) {
List<VcsException> exceptions = new LinkedList<VcsException>();
- for (Map.Entry<VirtualFile, Set<HgFile>> entry : getFilesByRepository(changes).entrySet()) {
+ Map<VirtualFile, Set<HgFile>> repositoriesMap = getFilesByRepository(changes);
+ for (Map.Entry<VirtualFile, Set<HgFile>> entry : repositoriesMap.entrySet()) {
VirtualFile repo = entry.getKey();
Set<HgFile> selectedFiles = entry.getValue();
@@ -117,9 +118,10 @@ public class HgCheckinEnvironment implements CheckinEnvironment {
// push if needed
if (myNextCommitIsPushed && exceptions.isEmpty()) {
+ final VirtualFile preselectedRepo = repositoriesMap.size() == 1 ? repositoriesMap.keySet().iterator().next() : null;
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
- new HgPusher(myProject).showDialogAndPush();
+ new HgPusher(myProject).showDialogAndPush(preselectedRepo);
}
});
}
@@ -134,8 +136,7 @@ public class HgCheckinEnvironment implements CheckinEnvironment {
private Set<HgFile> getChangedFilesNotInCommit(VirtualFile repo, Set<HgFile> selectedFiles) {
List<HgRevisionNumber> parents = new HgWorkingCopyRevisionsCommand(myProject).parents(repo);
- HgStatusCommand statusCommand = new HgStatusCommand.Builder(true).includeUnknown(false).includeIgnored(false).build(myProject);
- statusCommand.setBaseRevision(parents.get(0));
+ HgStatusCommand statusCommand = new HgStatusCommand.Builder(true).unknown(false).ignored(false).baseRevision(parents.get(0)).build(myProject);
Set<HgChange> allChangedFilesInRepo = statusCommand.execute(repo);
Set<HgFile> filesNotIncluded = new HashSet<HgFile>();
@@ -209,6 +210,7 @@ public class HgCheckinEnvironment implements CheckinEnvironment {
return false;
}
+ @NotNull
private Map<VirtualFile, Set<HgFile>> getFilesByRepository(List<Change> changes) {
Map<VirtualFile, Set<HgFile>> result = new HashMap<VirtualFile, Set<HgFile>>();
for (Change change : changes) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java
index 2fdc47e4cadb..e44b38859763 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java
@@ -216,7 +216,7 @@ public class HgRegularUpdater implements HgUpdater {
}
private Set<HgChange> getLocalChanges() {
- HgStatusCommand statusCommand = new HgStatusCommand.Builder(true).includeUnknown(false).includeIgnored(false).build(project);
+ HgStatusCommand statusCommand = new HgStatusCommand.Builder(true).unknown(false).ignored(false).build(project);
return statusCommand.execute(repository);
}
@@ -264,9 +264,8 @@ public class HgRegularUpdater implements HgUpdater {
if (parentAfterUpdate.equals(parentBeforeUpdate)) { // nothing to update => returning not to capture local uncommitted changes
return;
}
- HgStatusCommand statusCommand = new HgStatusCommand.Builder(true).build(project);
- statusCommand.setBaseRevision(parentBeforeUpdate);
- statusCommand.setTargetRevision(parentAfterUpdate);
+ HgStatusCommand statusCommand = new HgStatusCommand.Builder(true).baseRevision(parentBeforeUpdate).targetRevision(
+ parentAfterUpdate).build(project);
Set<HgChange> changes = statusCommand.execute(repo);
for (HgChange change : changes) {
HgFileStatusEnum status = change.getStatus();
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
index 11a7a09f5d68..a5724010ba1e 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
@@ -146,7 +146,7 @@ public class HgStatusWidget extends EditorBasedWidget implements StatusBarWidget
int maxLength = MAX_STRING.length();
myText = StringUtil.shortenTextWithEllipsis(myText, maxLength, 5);
- if (!isDisposed()) {
+ if (!isDisposed() && myStatusBar != null) {
myStatusBar.updateWidget(ID());
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java
index b914b706fe68..e5c0d4994450 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java
@@ -15,7 +15,7 @@
*/
package org.zmlx.hg4idea.ui;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -185,22 +185,17 @@ public class HgCloneDialog extends DialogWrapper {
testButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
testURL = repositoryURL.getText();
- ProgressManager.getInstance().run(new Task.Backgroundable(project,HgVcsMessages.message("hg4idea.clone.test.progress", testURL), true) {
+ ProgressManager.getInstance().run(new Task.Modal(project, HgVcsMessages.message("hg4idea.clone.test.progress", testURL), true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
- testResult = testRepository(project, testURL);
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- if (testResult) {
- Messages.showInfoMessage(testButton, HgVcsMessages.message("hg4idea.clone.test.success.message", testURL),
- HgVcsMessages.message("hg4idea.clone.test.success"));
- }
- updateCloneButton();
- }
- });
+ testResult = testRepository(project, testURL, indicator.getModalityState());
}
});
+ if (testResult) {
+ Messages.showInfoMessage(testButton, HgVcsMessages.message("hg4idea.clone.test.success.message", testURL),
+ HgVcsMessages.message("hg4idea.clone.test.success"));
+ }
+ updateCloneButton();
}
});
@@ -346,10 +341,10 @@ public class HgCloneDialog extends DialogWrapper {
return "reference.mercurial.clone.mercurial.repository";
}
- private static boolean testRepository(Project project, final String repositoryUrl) {
+ private static boolean testRepository(Project project, final String repositoryUrl, @NotNull ModalityState state) {
final HgIdentifyCommand identifyCommand = new HgIdentifyCommand(project);
identifyCommand.setSource(repositoryUrl);
- final HgCommandResult result = identifyCommand.execute();
+ final HgCommandResult result = identifyCommand.execute(state);
return result != null && result.getExitValue() == 0;
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
index e2b2a82678a6..52ae3ed6b2e5 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
@@ -22,9 +22,8 @@ import org.zmlx.hg4idea.HgRevisionNumber;
import org.zmlx.hg4idea.HgVcsMessages;
import org.zmlx.hg4idea.command.HgHeadsCommand;
import org.zmlx.hg4idea.command.HgTagBranch;
-import org.zmlx.hg4idea.command.HgTagBranchCommand;
import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand;
-import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.util.HgBranchesAndTags;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
@@ -53,12 +52,16 @@ public class HgMergeDialog extends DialogWrapper {
private HgRevisionNumber otherHead;
private Map<VirtualFile, List<HgTagBranch>> branchesForRepos;
+ private Map<VirtualFile, List<HgTagBranch>> tagsForRepos;
- public HgMergeDialog(Project project, Collection<VirtualFile> roots, Map<VirtualFile, List<HgTagBranch>> branchesForRepos) {
+ public HgMergeDialog(Project project,
+ Collection<VirtualFile> roots,
+ @Nullable VirtualFile selectedRepo, HgBranchesAndTags branchesAndTags) {
super(project, false);
this.project = project;
- this.branchesForRepos = branchesForRepos;
- setRoots(roots);
+ branchesForRepos = branchesAndTags.getBranchesForRepos();
+ tagsForRepos = branchesAndTags.getTagsForRepos();
+ setRoots(roots, selectedRepo);
hgRepositorySelectorComponent.setTitle("Select repository to merge");
hgRepositorySelectorComponent.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -79,8 +82,9 @@ public class HgMergeDialog extends DialogWrapper {
init();
}
- public void setRoots(Collection<VirtualFile> repos) {
+ public void setRoots(Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
hgRepositorySelectorComponent.setRoots(repos);
+ hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
updateRepository();
}
@@ -118,20 +122,13 @@ public class HgMergeDialog extends DialogWrapper {
}
private void loadBranches(VirtualFile root) {
- assert branchesForRepos.get(root) != null;
+ assert branchesForRepos.get(root) != null : "No inforamtion about root " + root;
branchSelector.setModel(new DefaultComboBoxModel(branchesForRepos.get(root).toArray()));
}
private void loadTags(VirtualFile root) {
- HgCommandResult tagsResult = new HgTagBranchCommand(project, root).collectTags();
- assert tagsResult != null;
- final List<HgTagBranch> tags = HgTagBranchCommand.parseResult(tagsResult);
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override
- public void run() {
- tagSelector.setModel(new DefaultComboBoxModel(tags.toArray()));
- }
- });
+ assert tagsForRepos.get(root) != null : "No inforamtion about root " + root;
+ tagSelector.setModel(new DefaultComboBoxModel(tagsForRepos.get(root).toArray()));
}
private void loadHeads(final VirtualFile root) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
index 5b1c97d0e9c0..8d1f2b00df77 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorComboBox;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgRememberedInputs;
import org.zmlx.hg4idea.command.HgShowConfigCommand;
import org.zmlx.hg4idea.util.HgUtil;
@@ -80,8 +81,9 @@ public class HgPullDialog extends DialogWrapper {
return myCurrentRepositoryUrl;
}
- public void setRoots(Collection<VirtualFile> repos) {
+ public void setRoots(Collection<VirtualFile> repos, @Nullable final VirtualFile selectedRepo) {
hgRepositorySelector.setRoots(repos);
+ hgRepositorySelector.setSelectedRoot(selectedRepo);
onChangeRepository();
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
index 158d18c06535..f7ee65c06d52 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
@@ -53,7 +53,7 @@ public class HgPushDialog extends DialogWrapper {
private EditorComboBox myRepositoryURL;
private String myCurrentRepositoryUrl;
- public HgPushDialog(Project project, Collection<VirtualFile> repos, List<HgTagBranch> branches) {
+ public HgPushDialog(Project project, Collection<VirtualFile> repos, List<HgTagBranch> branches, @Nullable VirtualFile selectedRepo) {
super(project, false);
myProject = project;
@@ -74,6 +74,7 @@ public class HgPushDialog extends DialogWrapper {
init();
hgRepositorySelectorComponent.setRoots(repos);
+ hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
updateBranchComboBox(branches);
updateRepository();
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java
index 4952a79cb902..89fc834de60b 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRepositorySelectorComponent.java
@@ -14,6 +14,8 @@ package org.zmlx.hg4idea.ui;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.IdeBorderFactory;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ActionListener;
@@ -32,6 +34,12 @@ public class HgRepositorySelectorComponent {
mainPanel.setVisible(roots.size() > 1);
}
+ public void setSelectedRoot(@Nullable VirtualFile repository) {
+ if (repository != null) {
+ repositorySelector.setSelectedItem(new RepositoryDisplay(repository));
+ }
+ }
+
public void addActionListener(ActionListener actionListener) {
repositorySelector.addActionListener(actionListener);
}
@@ -45,9 +53,9 @@ public class HgRepositorySelectorComponent {
}
private class RepositoryDisplay {
- private final VirtualFile repo;
+ @NotNull private final VirtualFile repo;
- public RepositoryDisplay(VirtualFile repo) {
+ public RepositoryDisplay(@NotNull VirtualFile repo) {
this.repo = repo;
}
@@ -55,6 +63,16 @@ public class HgRepositorySelectorComponent {
public String toString() {
return repo.getPresentableUrl();
}
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof RepositoryDisplay && this.repo.equals(((RepositoryDisplay)obj).repo);
+ }
+
+ @Override
+ public int hashCode() {
+ return repo.hashCode();
+ }
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java
index 94125cfceb67..ca4ab00462f6 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgRunConflictResolverDialog.java
@@ -12,10 +12,13 @@
// limitations under the License.
package org.zmlx.hg4idea.ui;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgFile;
import org.zmlx.hg4idea.command.HgResolveCommand;
import org.zmlx.hg4idea.command.HgResolveStatusEnum;
@@ -50,8 +53,9 @@ public class HgRunConflictResolverDialog extends DialogWrapper {
return repositorySelector.getRepository();
}
- public void setRoots(Collection<VirtualFile> repos) {
+ public void setRoots(Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
repositorySelector.setRoots(repos);
+ repositorySelector.setSelectedRoot(selectedRepo);
onChangeRepository();
}
@@ -62,20 +66,27 @@ public class HgRunConflictResolverDialog extends DialogWrapper {
private void onChangeRepository() {
VirtualFile repo = repositorySelector.getRepository();
HgResolveCommand command = new HgResolveCommand(project);
+ final ModalityState modalityState = ApplicationManager.getApplication().getModalityStateForComponent(getRootPane());
command.list(repo, new Consumer<Map<HgFile, HgResolveStatusEnum>>() {
@Override
public void consume(Map<HgFile, HgResolveStatusEnum> status) {
- DefaultListModel model = new DefaultListModel();
+ final DefaultListModel model = new DefaultListModel();
for (Map.Entry<HgFile, HgResolveStatusEnum> entry : status.entrySet()) {
if (entry.getValue() == HgResolveStatusEnum.UNRESOLVED) {
model.addElement(entry.getKey().getRelativePath());
}
}
- setOKActionEnabled(!model.isEmpty());
- if (model.isEmpty()) {
- model.addElement("No conflicts to resolve");
- }
- conflictsList.setModel(model);
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+ setOKActionEnabled(!model.isEmpty());
+ if (model.isEmpty()) {
+ model.addElement("No conflicts to resolve");
+ }
+ conflictsList.setModel(model);
+ }
+ }, modalityState);
}
});
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java
index a633123b52a0..02e3e8d7a245 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgTagDialog.java
@@ -16,6 +16,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
@@ -59,8 +60,9 @@ public class HgTagDialog extends DialogWrapper {
return hgRepositorySelectorComponent.getRepository();
}
- public void setRoots(Collection<VirtualFile> repos) {
+ public void setRoots(Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
hgRepositorySelectorComponent.setRoots(repos);
+ hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
update();
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java
index e3c03be57a5e..8dd74fe87ac3 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateToDialog.java
@@ -15,10 +15,9 @@ package org.zmlx.hg4idea.ui;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.command.HgTagBranch;
-import org.zmlx.hg4idea.command.HgTagBranchCommand;
-import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.util.HgBranchesAndTags;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
@@ -43,6 +42,7 @@ public class HgUpdateToDialog extends DialogWrapper {
private JComboBox tagSelector;
private HgRepositorySelectorComponent hgRepositorySelectorComponent;
private Map<VirtualFile, List<HgTagBranch>> branchesForRepos;
+ private Map<VirtualFile, List<HgTagBranch>> tagsForRepos;
public HgUpdateToDialog(Project project) {
super(project, false);
@@ -67,9 +67,12 @@ public class HgUpdateToDialog extends DialogWrapper {
init();
}
- public void setRoots(Collection<VirtualFile> repos, Map<VirtualFile, List<HgTagBranch>> branchesForRepos) {
+ public void setRoots(Collection<VirtualFile> repos,
+ @Nullable VirtualFile selectedRepo, HgBranchesAndTags branchesAndTags) {
hgRepositorySelectorComponent.setRoots(repos);
- this.branchesForRepos = branchesForRepos;
+ branchesForRepos = branchesAndTags.getBranchesForRepos();
+ tagsForRepos = branchesAndTags.getTagsForRepos();
+ hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
updateRepository();
}
@@ -119,20 +122,13 @@ public class HgUpdateToDialog extends DialogWrapper {
}
private void loadBranches(VirtualFile root) {
- assert branchesForRepos.get(root) != null;
+ assert branchesForRepos.get(root) != null : "No inforamtion about root " + root;
branchSelector.setModel(new DefaultComboBoxModel(branchesForRepos.get(root).toArray()));
}
private void loadTags(VirtualFile root) {
- HgCommandResult tagsResult = new HgTagBranchCommand(project, root).collectTags();
- assert tagsResult != null;
- final List<HgTagBranch> tags = HgTagBranchCommand.parseResult(tagsResult);
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override
- public void run() {
- tagSelector.setModel(new DefaultComboBoxModel(tags.toArray()));
- }
- });
+ assert tagsForRepos.get(root) != null : "No inforamtion about root " + root;
+ tagSelector.setModel(new DefaultComboBoxModel(tagsForRepos.get(root).toArray()));
}
protected JComponent createCenterPanel() {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgBranchesAndTags.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgBranchesAndTags.java
new file mode 100644
index 000000000000..056d573ec0d2
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgBranchesAndTags.java
@@ -0,0 +1,53 @@
+/*
+ * 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 org.zmlx.hg4idea.util;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.command.HgTagBranch;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Nadya Zabrodina
+ */
+
+public class HgBranchesAndTags {
+
+ @NotNull private final Map<VirtualFile, List<HgTagBranch>> branchesForRepos = new HashMap<VirtualFile, List<HgTagBranch>>();
+ @NotNull private final Map<VirtualFile, List<HgTagBranch>> tagsForRepos = new HashMap<VirtualFile, List<HgTagBranch>>();
+
+
+ @NotNull
+ public Map<VirtualFile, List<HgTagBranch>> getBranchesForRepos() {
+ return branchesForRepos;
+ }
+
+ public void addBranches(@NotNull VirtualFile repo, @NotNull List<HgTagBranch> branches) {
+ branchesForRepos.put(repo, branches);
+ }
+
+ @NotNull
+ public Map<VirtualFile, List<HgTagBranch>> getTagsForRepos() {
+ return tagsForRepos;
+ }
+
+ public void addTags(@NotNull VirtualFile repo, @NotNull List<HgTagBranch> tags) {
+ tagsForRepos.put(repo, tags);
+ }
+} \ No newline at end of file
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java
index cf209ceb3ba3..cf25b716c942 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java
@@ -1,5 +1,6 @@
package org.zmlx.hg4idea.util;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.annotations.NotNull;
@@ -9,32 +10,40 @@ import java.nio.charset.Charset;
* @author Kirill Likhodedov
*/
public class HgEncodingUtil {
-
+
+ private static final Logger LOG = Logger.getInstance(HgEncodingUtil.class);
+
private static final String WINDOWS_DEFAULT_CHARSET = "cp1251";
private static final String UNIX_DEFAULT_CHARSET = "UTF-8";
+ private static final Charset DEFAULT_CHARSET = updateDefaultEncoding();
+
+ public static Charset updateDefaultEncoding() {
+ String name = SystemInfo.isWindows ? WINDOWS_DEFAULT_CHARSET : UNIX_DEFAULT_CHARSET;
+ try {
+ String enc = System.getenv("HGENCODING");
+ if (enc != null && enc.length() > 0 && Charset.isSupported(enc)) {
+ name = enc;
+ }
+ return Charset.forName(name);
+ }
+ catch (Exception e) {
+ LOG.info("Couldn't find encoding " + name, e);
+ }
+ return Charset.defaultCharset();
+ }
+
private HgEncodingUtil() {
}
/**
* Returns the default charset for Mercurial.
- * It is cp1251 for Windows, and UTF-8 for Unix-like systems.
- * The {@code HGENCODING} environment variable is not considered, because being set for IDEA it is inherited by the hg process
- * spawned by IDEA.
- * @return cp1251 for windows / UTF-8 for Unix-like systems.
+ * It is value of{@code HGENCODING} or cp1251 for Windows, and UTF-8 for Unix-like systems.
+ *
+ * @return user encoding/cp1251 for windows/UTF-8 for Unix-like systems.
*/
@NotNull
public static Charset getDefaultCharset() {
- return SystemInfo.isWindows ? getCharsetForNameOrDefault(WINDOWS_DEFAULT_CHARSET) : getCharsetForNameOrDefault(UNIX_DEFAULT_CHARSET);
- }
-
- @NotNull
- private static Charset getCharsetForNameOrDefault(@NotNull String name) {
- try {
- return Charset.forName(name);
- }
- catch (Exception e) {
- return Charset.defaultCharset();
- }
+ return DEFAULT_CHARSET;
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java
index 80acef513f14..4cadfc86a552 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java
@@ -26,8 +26,13 @@ public final class HgErrorUtil {
if (result == null) {
return true;
}
- String line = getLastErrorLine(result);
- return !StringUtil.isEmptyOrSpaces(line) && line.contains("abort:");
+ final List<String> errorLines = result.getErrorLines();
+ for (String line : errorLines) {
+ if (!StringUtil.isEmptyOrSpaces(line) && line.trim().startsWith("abort:")) {
+ return true;
+ }
+ }
+ return false;
}
public static boolean isAuthorizationError(@Nullable HgCommandResult result) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUiUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUiUtil.java
index 090a9f46178f..0fdc7aeb2e33 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUiUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUiUtil.java
@@ -20,17 +20,13 @@ import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
-import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.zmlx.hg4idea.HgVcsMessages;
import org.zmlx.hg4idea.action.HgCommandResultNotifier;
-import org.zmlx.hg4idea.command.HgTagBranch;
import org.zmlx.hg4idea.command.HgTagBranchCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
import java.util.Collection;
-import java.util.List;
-import java.util.Map;
/**
* @author Nadya Zabrodina
@@ -39,18 +35,25 @@ public class HgUiUtil {
public static void loadBranchesInBackgroundableAndExecuteAction(final Project project,
final Collection<VirtualFile> repos,
- final Consumer<Map<VirtualFile, List<HgTagBranch>>> successHandler) {
- final Map<VirtualFile, List<HgTagBranch>> branchesForRepos = new HashMap<VirtualFile, List<HgTagBranch>>();
+ final Consumer<HgBranchesAndTags> successHandler) {
+ final HgBranchesAndTags branchTagInfo = new HgBranchesAndTags();
new Task.Backgroundable(project, "Collecting information...") {
@Override
public void run(@NotNull ProgressIndicator indicator) {
for (final VirtualFile repo : repos) {
- HgCommandResult result = new HgTagBranchCommand(project, repo).collectBranches();
+ HgTagBranchCommand tagBranchCommand = new HgTagBranchCommand(project, repo);
+ HgCommandResult result = tagBranchCommand.collectBranches();
if (result == null) {
indicator.cancel();
return;
}
- branchesForRepos.put(repo, HgTagBranchCommand.parseResult(result));
+ branchTagInfo.addBranches(repo, HgTagBranchCommand.parseResult(result));
+ result = tagBranchCommand.collectTags();
+ if (result == null) {
+ indicator.cancel();
+ return;
+ }
+ branchTagInfo.addTags(repo, HgTagBranchCommand.parseResult(result));
}
}
@@ -62,7 +65,7 @@ public class HgUiUtil {
@Override
public void onSuccess() {
- successHandler.consume(branchesForRepos);
+ successHandler.consume(branchTagInfo);
}
}.queue();
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
index 9747fb45904b..a76e1517ecad 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
@@ -226,7 +226,7 @@ public abstract class HgUtil {
* @see #getHgRootOrNull(com.intellij.openapi.project.Project, com.intellij.openapi.vcs.FilePath)
*/
@Nullable
- public static VirtualFile getHgRootOrNull(Project project, VirtualFile file) {
+ public static VirtualFile getHgRootOrNull(Project project, @NotNull VirtualFile file) {
return getHgRootOrNull(project, VcsUtil.getFilePath(file.getPath()));
}
@@ -285,8 +285,7 @@ public abstract class HgUtil {
public static HgFile getFileNameInTargetRevision(Project project, HgRevisionNumber vcsRevisionNumber, HgFile localHgFile) {
- HgStatusCommand statCommand = new HgStatusCommand.Builder(true).includeUnknown(false).build(project);
- statCommand.setBaseRevision(vcsRevisionNumber);
+ HgStatusCommand statCommand = new HgStatusCommand.Builder(true).unknown(false).baseRevision(vcsRevisionNumber).build(project);
Set<HgChange> changes = statCommand.execute(localHgFile.getRepo());
@@ -400,16 +399,18 @@ public abstract class HgUtil {
@NotNull final FilePath path,
@Nullable final HgFileRevision rev1,
@Nullable final HgFileRevision rev2) {
- HgStatusCommand statusCommand = new HgStatusCommand.Builder(true).includeCopySource(false).build(project);
+ HgStatusCommand statusCommand;
HgRevisionNumber revNumber1 = null;
if (rev1 != null) {
revNumber1 = rev1.getRevisionNumber();
- statusCommand.setBaseRevision(revNumber1);
- statusCommand.setTargetRevision(rev2 != null ? rev2.getRevisionNumber() : null); //rev2==null means "compare with local version"
+ //rev2==null means "compare with local version"
+ statusCommand = new HgStatusCommand.Builder(true).copySource(false).baseRevision(revNumber1)
+ .targetRevision(rev2 != null ? rev2.getRevisionNumber() : null).build(project);
}
else {
LOG.assertTrue(rev2 != null, "revision1 and revision2 can't both be null. Path: " + path); //rev1 and rev2 can't be null both//
- statusCommand.setBaseRevision(rev2.getRevisionNumber()); //get initial changes//
+ //get initial changes//
+ statusCommand = new HgStatusCommand.Builder(true).copySource(false).baseRevision(rev2.getRevisionNumber()).build(project);
}
Collection<HgChange> hgChanges = statusCommand.execute(root, Collections.singleton(path));
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
index 99a90cbd8d78..0544e2ac7976 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
@@ -16,8 +16,11 @@
package hg4idea.test;
import com.intellij.dvcs.test.Executor;
-import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import java.io.File;
import java.util.Arrays;
import java.util.List;
@@ -27,31 +30,44 @@ import java.util.List;
public class HgExecutor extends Executor {
private static final String HG_EXECUTABLE_ENV = "IDEA_TEST_HG_EXECUTABLE";
- //private static final String TEAMCITY_HG_EXECUTABLE_ENV = "TEAMCITY_HG_PATH"; //todo var for server testing
- private static boolean myVersionPrinted;
- private static final String HG_EXECUTABLE = findHgExecutable();
+ private static final String HG_EXECUTABLE = doFindExecutable();
- private static String findHgExecutable() {
- return findExecutable("hg", "hg", "hg.exe", Arrays.asList(HG_EXECUTABLE_ENV));
+ private static String doFindExecutable() {
+ final String programName = "hg";
+ final String unixExec = "hg";
+ final String winExec = "hg.exe";
+ String exec = findInPathEnvs(programName, Arrays.asList(HG_EXECUTABLE_ENV));
+ if (exec != null) {
+ return exec;
+ }
+ exec = findInPath(programName, unixExec, winExec);
+ if (exec != null) {
+ return exec;
+ }
+ exec = findInSources(programName, unixExec, winExec);
+ if (exec != null) {
+ return exec;
+ }
+ throw new IllegalStateException(programName + " executable not found.");
+ }
+
+ private static String findInSources(String programName, String unixExec, String winExec) {
+ File pluginRoot = new File(PluginPathManager.getPluginHomePath("hg4idea"));
+ File bin = new File(pluginRoot, FileUtil.toSystemDependentName("testData/bin"));
+ File exec = new File(bin, SystemInfo.isWindows ? winExec : unixExec);
+ if (exec.exists() && exec.canExecute()) {
+ log("Using " + programName + " from test data");
+ return exec.getPath();
+ }
+ return null;
}
public static String hg(String command) {
- printVersionTheFirstTime();
- List<String> split = StringUtil.split(command, " ");
+ List<String> split = splitCommandInParameters(command);
split.add(0, HG_EXECUTABLE);
log("hg " + command);
- for(int attempt = 0; attempt < 3; attempt++) {
- return run(split);
- }
- throw new RuntimeException("fatal error during execution of Hg command: " + command);
+ return run(split);
}
- private static void printVersionTheFirstTime() {
- if (!myVersionPrinted) {
- myVersionPrinted = true;
- hg("version");
- }
- }
}
-
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
index af5cad92bb72..e7bd4cdedac5 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
@@ -18,8 +18,13 @@ package hg4idea.test;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.merge.MergeProvider;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.testFramework.LightPlatformTestCase;
+import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.UsefulTestCase;
+import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
+import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
+import org.zmlx.hg4idea.HgVcs;
import java.io.File;
import java.io.IOException;
@@ -32,35 +37,62 @@ import static hg4idea.test.HgExecutor.hg;
* The base class for tests of hg4idea plugin.<br/>
* Extend this test to write a test on Mercurial which has the following features/limitations:
* <ul>
- * <li>This is a {@link LightPlatformTestCase}, which means that IDEA [almost] production platform is set up before the test starts.</li>
- * <li>Project base directory is the root of everything. It can contain as much nested repositories as needed,
- * but if you need to test the case when hg repository is <b>above</b> the project dir, you need either to adjust this base class,
- * or create another one.</li>
- * <li>Initially one repository is created with the project dir as its root. I. e. all project is under Mercurial.</li>
+ * <li>This is a "platform test case", which means that IDEA [almost] production platform is set up before the test starts.</li>
+ * <li>Project base directory is the root of everything. It can contain as much nested repositories as needed,
+ * but if you need to test the case when hg repository is <b>above</b> the project dir, you need either to adjust this base class,
+ * or create another one.</li>
+ * <li>Initially one repository is created with the project dir as its root. I. e. all project is under Mercurial.</li>
* </ul>
*
* @author Kirill Likhodedov
*/
-public abstract class HgPlatformTest extends LightPlatformTestCase {
+public abstract class HgPlatformTest extends UsefulTestCase {
protected Project myProject;
protected VirtualFile myProjectRoot;
protected VirtualFile myRepository;
+ protected VirtualFile myChildRepo;
+ protected MergeProvider myMergeProvider;
+
+ protected static final String COMMIT_MESSAGE = "text";
+
+ private IdeaProjectTestFixture myProjectFixture;
+
+ protected static final String AFILE = "A.txt";
+ protected static final String BFILE = "B.txt";
+
+ @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
+ protected HgPlatformTest() {
+ PlatformTestCase.initPlatformLangPrefix();
+ }
@Override
protected void setUp() throws Exception {
super.setUp();
+ myProjectFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getTestName(true)).getFixture();
+ myProjectFixture.setUp();
- myProject = getProject();
+ myProject = myProjectFixture.getProject();
myProjectRoot = myProject.getBaseDir();
+ cd(myProjectRoot);
+ hg("version");
+
createRepository(myProjectRoot);
myRepository = myProjectRoot;
setUpHgrc(myRepository);
+
+ HgVcs vcs = HgVcs.getInstance(myProject);
+ assertNotNull(vcs);
+ myMergeProvider = vcs.getMergeProvider();
+ assertNotNull(myMergeProvider);
+
+ prepareSecondRepository();
}
@Override
protected void tearDown() throws Exception {
+ myProjectFixture.tearDown();
super.tearDown();
}
@@ -92,4 +124,14 @@ public abstract class HgPlatformTest extends LightPlatformTestCase {
hg("commit -m initial");
}
+ private void prepareSecondRepository() throws IOException {
+ cd(myRepository);
+ hg("clone " + myRepository.getCanonicalPath() + " childRepo");
+ myChildRepo = myRepository.findChild("childRepo");
+ cd(myChildRepo);
+ hg("pull");
+ hg("update");
+ HgTestUtil.updateDirectoryMappings(myProject, myRepository);
+ HgTestUtil.updateDirectoryMappings(myProject, myChildRepo);
+ }
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java b/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java
new file mode 100644
index 000000000000..d3644d139b1c
--- /dev/null
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgTestUtil.java
@@ -0,0 +1,89 @@
+/*
+ * 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 hg4idea.test;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
+import com.intellij.openapi.vcs.VcsDirectoryMapping;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.zmlx.hg4idea.HgVcs;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public class HgTestUtil {
+
+ public static void updateDirectoryMappings(Project project, VirtualFile mapRoot) {
+ if (project != null && (!project.isDefault()) && project.getBaseDir() != null && VfsUtil
+ .isAncestor(project.getBaseDir(), mapRoot, false)) {
+ mapRoot.refresh(false, false);
+ final String path = mapRoot.equals(project.getBaseDir()) ? "" : mapRoot.getPath();
+ final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
+ final List<VcsDirectoryMapping> vcsDirectoryMappings = new ArrayList<VcsDirectoryMapping>(vcsManager.getDirectoryMappings());
+ VcsDirectoryMapping mapping = new VcsDirectoryMapping(path, HgVcs.VCS_NAME);
+ for (int i = 0; i < vcsDirectoryMappings.size(); i++) {
+ final VcsDirectoryMapping m = vcsDirectoryMappings.get(i);
+ if (m.getDirectory().equals(path)) {
+ if (m.getVcs().length() == 0) {
+ vcsDirectoryMappings.set(i, mapping);
+ mapping = null;
+ break;
+ }
+ else if (m.getVcs().equals(mapping.getVcs())) {
+ mapping = null;
+ break;
+ }
+ }
+ }
+ if (mapping != null) {
+ vcsDirectoryMappings.add(mapping);
+ }
+ vcsManager.setDirectoryMappings(vcsDirectoryMappings);
+ vcsManager.updateActiveVcss();
+ }
+ }
+
+ private HgTestUtil() {
+ }
+
+ /**
+ * Writes the given content to the file.
+ *
+ * @param file file which content will be substituted by the given one.
+ * @param content new file content
+ */
+ public static void printToFile(VirtualFile file, String content) throws FileNotFoundException {
+ PrintStream centralPrinter = null;
+ try {
+ centralPrinter = new PrintStream(new FileOutputStream(new File(file.getPath())));
+ centralPrinter.print(content);
+ centralPrinter.close();
+ }
+ finally {
+ if (centralPrinter != null) {
+ centralPrinter.close();
+ }
+ }
+ }
+}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java b/plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java
index 19b3b8871477..a17114d8baae 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java
@@ -63,6 +63,6 @@ public class HgGetDiffForDirTest extends HgPlatformTest {
new HgFileRevision(myProject, new HgFile(myRepository, dirFile), r2number, "", null, "", "", null, null, null, null);
FilePath dirPath = new FilePathImpl(dirFile, true);
List<Change> changes = HgUtil.getDiff(myProject, myRepository, dirPath, rev1, rev2);
- assertEquals(changes.size(), 2);
+ assertEquals(2, changes.size());
}
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java b/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java
new file mode 100644
index 000000000000..c084259bac2c
--- /dev/null
+++ b/plugins/hg4idea/testSrc/hg4idea/test/merge/HgMergeProviderTest.java
@@ -0,0 +1,206 @@
+/*
+ * 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 hg4idea.test.merge;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.merge.MergeData;
+import com.intellij.openapi.vfs.VirtualFile;
+import hg4idea.test.HgPlatformTest;
+import hg4idea.test.HgTestUtil;
+import org.testng.Assert;
+
+import java.io.IOException;
+
+import static com.intellij.dvcs.test.Executor.*;
+import static hg4idea.test.HgExecutor.hg;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public class HgMergeProviderTest extends HgPlatformTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testMerge2BranchesIfFileCreatedSeparatelyInBoth() throws VcsException {
+ cd(myRepository);
+ hg("branch branchA");
+ hg("commit -m 'create branchA' ");
+ touch(AFILE, "a");
+ hg("add " + AFILE);
+ hg("commit -m 'create file in branchA' ");
+ hg("up default");
+ touch(AFILE, "default");
+ hg("add " + AFILE);
+ hg("commit -m 'create file in default branch'");
+ hg("merge branchA");
+ verifyMergeData(myRepository.findChild(AFILE), "", "default", "a");
+ }
+
+ public void testMerge2Branches() throws VcsException {
+ cd(myRepository);
+ String FILENAME = "A.txt";
+ touch(FILENAME, "base");
+ hg("add " + FILENAME);
+ hg("commit -m 'create file'");
+ hg("branch branchA");
+ hg("commit -m 'create branchA'");
+ echo(FILENAME, " modify with a");
+ hg("commit -m 'modify file in branchA'");
+ hg("up default");
+ echo(FILENAME, " modify with b");
+ hg("commit -m 'modify file in default'");
+ hg("merge branchA");
+ verifyMergeData(myRepository.findChild(FILENAME), "base", "base modify with b", "base modify with a");
+ }
+
+ /**
+ * Start with a file in both repositories.
+ * 1. Edit the file in parent repository, commit the change.
+ * 2. Edit the file in child repository, commit the change.
+ * 3. Update.
+ * 4. Test the MergeData from the MergeProvider to have correct data.
+ */
+ public void testMergeWithCommittedLocalChange() throws Exception {
+ final Pair<VirtualFile, VirtualFile> files = prepareFileInBothRepositories();
+ final VirtualFile parentFile = files.first;
+ final VirtualFile childFile = files.second;
+ cd(myRepository);
+ HgTestUtil.printToFile(parentFile, "server");
+ hg("commit -m " + COMMIT_MESSAGE);
+ // committing conflicting change
+ cd(myChildRepo);
+ HgTestUtil.printToFile(childFile, "local");
+ hg("commit -m " + COMMIT_MESSAGE);
+ hg("pull");
+ hg("update");
+ hg("merge");
+ verifyMergeData(myChildRepo.findChild(childFile.getName()), "basic", "local", "server");
+ }
+
+ /**
+ * Start with a file in both repositories.
+ * 1. Edit the file in parent repository, commit the change.
+ * 2. Edit the file in child repository, don't commit the change.
+ * 3. Update.
+ * 4. Test the MergeData from the MergeProvider to have correct data.
+ */
+ public void testMergeWithUncommittedLocalChange() throws Exception {
+ final Pair<VirtualFile, VirtualFile> files = prepareFileInBothRepositories();
+ final VirtualFile parentFile = files.first;
+ final VirtualFile childFile = files.second;
+ cd(myRepository);
+ HgTestUtil.printToFile(parentFile, "server");
+ hg("commit -m " + COMMIT_MESSAGE);
+
+ // uncommitted conflicting change
+ cd(myChildRepo);
+ HgTestUtil.printToFile(childFile, "local");
+ hg("pull");
+ hg("update");
+ hg("merge");
+
+ verifyMergeData(myChildRepo.findChild(childFile.getName()), "basic", "local", "server");
+ }
+
+ /**
+ * Start with a non fresh repository.
+ * 1. Add a file in parent repository, commit.
+ * 2. Add a file with the same name, but different content in child repository, commit.
+ * 3. Update.
+ * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty).
+ */
+ public void testFileAddedAndCommitted() throws Exception {
+ // this is needed to have the same root changeset - otherwise conflicting root changeset will cause
+ // an error during 'hg pull': "abort: repository is unrelated"
+ prepareFileInBothRepositories();
+ cd(myRepository);
+ touch(BFILE, "server");
+ hg("add " + BFILE);
+ hg("commit -m " + COMMIT_MESSAGE);
+
+ cd(myChildRepo);
+ touch(BFILE, "local");
+ hg("add " + BFILE);
+ hg("commit -m " + COMMIT_MESSAGE);
+
+ hg("pull");
+ hg("update");
+ hg("merge");
+
+ verifyMergeData(myChildRepo.findChild(BFILE), "", "local", "server");
+ }
+
+ /**
+ * Start with a non fresh repository.
+ * 1. Add a file in parent repository, commit.
+ * 2. Add a file with the same name, but different content in child repository, don't commit.
+ * 3. Update.
+ * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty).
+ */
+ public void testFileAddedNotCommited() throws Exception {
+ // this is needed to have the same root changeset - otherwise conflicting root changeset will cause
+ // an error during 'hg pull': "abort: repository is unrelated"
+ prepareFileInBothRepositories();
+ cd(myRepository);
+ touch(BFILE, "server");
+ hg("add " + BFILE);
+ hg("commit -m " + COMMIT_MESSAGE);
+
+ cd(myChildRepo);
+ touch(BFILE, "local");
+ hg("add " + BFILE);
+
+ hg("pull");
+ hg("update");
+ hg("merge");
+
+ verifyMergeData(myChildRepo.findChild(BFILE), "", "local", "server");
+ }
+
+
+ /**
+ * Creates a file with initial content in the parent repository, pulls & updates it to the child repository.
+ *
+ * @return References to the files in parent and child repositories respectively.
+ */
+ private Pair<VirtualFile, VirtualFile> prepareFileInBothRepositories() throws IOException {
+ cd(myRepository);
+ touch(AFILE, "basic");
+ hg("add " + AFILE);
+ hg("commit -m 'create file' ");
+ cd(myChildRepo);
+ hg("pull");
+ hg("update");
+ final VirtualFile childFile = myChildRepo.findChild(AFILE);
+ return Pair.create(myRepository.findChild(AFILE), childFile);
+ }
+
+ private void verifyMergeData(final VirtualFile file, String expectedBase, String expectedLocal, String expectedServer)
+ throws VcsException {
+ final MergeData mergeData = myMergeProvider.loadRevisions(file);
+ assertEquals(expectedBase, mergeData.ORIGINAL);
+ assertEquals(expectedServer, mergeData.LAST);
+ assertEquals(expectedLocal, mergeData.CURRENT);
+ }
+
+ private static void assertEquals(String s, byte[] bytes) {
+ Assert.assertEquals(s, new String(bytes));
+ }
+}
diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java
deleted file mode 100644
index ca486678b082..000000000000
--- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMergeProviderTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2000-2010 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.zmlx.hg4idea.test;
-
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.merge.MergeData;
-import com.intellij.openapi.vcs.merge.MergeProvider;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ui.UIUtil;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.zmlx.hg4idea.HgVcs;
-
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
-
-/**
- * Tests HgMergeProvider for different merge situations.
- * All Mercurial operations are performed natively to test only HgMergeProvider functionality.
- * @author Kirill Likhodedov
- */
-public class HgMergeProviderTest extends HgCollaborativeTest {
-
- private MergeProvider myMergeProvider;
-
- @BeforeMethod
- @Override
- protected void setUp(Method testMethod) throws Exception {
- super.setUp(testMethod);
- myMergeProvider = HgVcs.getInstance(myProject).getMergeProvider();
- assertNotNull(myMergeProvider);
- }
-
- /**
- * Start with a file in both repositories.
- * 1. Edit the file in parent repository, commit the change.
- * 2. Edit the file in child repository, commit the change.
- * 3. Update.
- * 4. Test the MergeData from the MergeProvider to have correct data.
- */
- @Test
- public void mergeWithCommittedLocalChange() throws Exception {
- final Pair<VirtualFile, VirtualFile> files = prepareFileInBothRepositories();
- final VirtualFile parentFile = files.first;
- final VirtualFile childFile = files.second;
-
- HgTestUtil.printToFile(parentFile, "server");
- myParentRepo.commit();
- // committing conflicting change
- HgTestUtil.printToFile(childFile, "local");
- myRepo.commit();
-
- myRepo.pullUpdateMerge();
-
- verifyMergeData(childFile, "basic", "local", "server");
- }
-
- /**
- * Start with a file in both repositories.
- * 1. Edit the file in parent repository, commit the change.
- * 2. Edit the file in child repository, don't commit the change.
- * 3. Update.
- * 4. Test the MergeData from the MergeProvider to have correct data.
- */
- @Test
- public void mergeWithUncommittedLocalChange() throws Exception {
- final Pair<VirtualFile, VirtualFile> files = prepareFileInBothRepositories();
- final VirtualFile parentFile = files.first;
- final VirtualFile childFile = files.second;
-
- HgTestUtil.printToFile(parentFile, "server");
- myParentRepo.commit();
-
- // uncommitted conflicting change
- HgTestUtil.printToFile(childFile, "local");
-
- myRepo.pullUpdateMerge();
-
- verifyMergeData(childFile, "basic", "local", "server");
- }
-
- /**
- * Start with a non fresh repository.
- * 1. Add a file in parent repository, commit.
- * 2. Add a file with the same name, but different content in child repository, commit.
- * 3. Update.
- * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty).
- */
- @Test
- public void fileAddedAndCommitted() throws Exception {
- // this is needed to have the same root changeset - otherwise conflicting root changeset will cause
- // an error during 'hg pull': "abort: repository is unrelated"
- prepareFileInBothRepositories();
-
- myParentRepo.createFile("b.txt", "server");
- myParentRepo.addCommit();
-
- final VirtualFile childFile = myRepo.createFile("b.txt", "local");
- myRepo.addCommit();
-
- myRepo.pullUpdateMerge();
-
- verifyMergeData(childFile, "", "local", "server");
- }
-
- /**
- * Start with a non fresh repository.
- * 1. Add a file in parent repository, commit.
- * 2. Add a file with the same name, but different content in child repository, don't commit.
- * 3. Update.
- * 4. Test the MergeData from the MergeProvider to have correct data (there is no basic version, but it shouldn't be null - just empty).
- */
- @Test
- public void fileAddedNotCommited() throws Exception {
- // this is needed to have the same root changeset - otherwise conflicting root changeset will cause
- // an error during 'hg pull': "abort: repository is unrelated"
- prepareFileInBothRepositories();
-
- myParentRepo.createFile("b.txt", "server");
- myParentRepo.addCommit();
-
- final VirtualFile childFile = myRepo.createFile("b.txt", "local");
- myRepo.add();
-
- myRepo.pullUpdateMerge();
-
- verifyMergeData(childFile, "", "local", "server");
- }
-
- private void verifyMergeData(final VirtualFile file, String expectedBase, String expectedLocal, String expectedServer) throws Exception {
- final AtomicReference<MergeData> mergeData = new AtomicReference<MergeData>();
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override
- public void run() {
- try {
- mergeData.set(myMergeProvider.loadRevisions(file));
- } catch (VcsException e) {
- fail("Failed to load revisions", e);
- }
- }
- });
-
- assertEquals(mergeData.get().ORIGINAL, expectedBase);
- assertEquals(mergeData.get().CURRENT, expectedLocal);
- assertEquals(mergeData.get().LAST, expectedServer);
- }
-
- private static void assertEquals(byte[] bytes, String s) {
- Assert.assertEquals(new String(bytes), s);
- }
-
- /**
- * Creates a file with initial content in the parent repository, pulls & updates it to the child repository.
- * @return References to the files in parent and child repositories respectively.
- */
- private Pair<VirtualFile, VirtualFile> prepareFileInBothRepositories() throws IOException {
- final VirtualFile parentFile = myParentRepo.createFile("a.txt", "basic");
- myParentRepo.add();
- myParentRepo.commit();
- myRepo.pull();
- myRepo.update();
- final VirtualFile childFile = myRepo.getDir().findChild("a.txt");
- return Pair.create(parentFile, childFile);
- }
-
-}
diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java
deleted file mode 100644
index 875ddfa0081d..000000000000
--- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTestUtil.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2000-2010 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.zmlx.hg4idea.test;
-
-import com.intellij.openapi.vfs.VirtualFile;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
-/**
- * HgTestUtil is a collection of static utility methods for Mercurial tests.
- * @author Kirill Likhodedov
- */
-public class HgTestUtil {
-
- private HgTestUtil() {}
-
- /**
- * Writes the given content to the file.
- * @param file file which content will be substituted by the given one.
- * @param content new file content
- */
- public static void printToFile(VirtualFile file, String content) throws FileNotFoundException {
- PrintStream centralPrinter = null;
- try {
- centralPrinter = new PrintStream(new FileOutputStream(new File(file.getPath())));
- centralPrinter.print(content);
- centralPrinter.close();
- } finally {
- if (centralPrinter != null) {
- centralPrinter.close();
- }
- }
- }
-
-}
diff --git a/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml b/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml
new file mode 100644
index 000000000000..4c9fb28f9e23
--- /dev/null
+++ b/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml
@@ -0,0 +1,13 @@
+<?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" />
+ </component>
+</module>
+
diff --git a/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/AbstractJavaFxPackager.java b/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/AbstractJavaFxPackager.java
new file mode 100644
index 000000000000..a36363116174
--- /dev/null
+++ b/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/AbstractJavaFxPackager.java
@@ -0,0 +1,338 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Base64Converter;
+import com.intellij.util.PathUtilRt;
+import com.intellij.util.io.ZipUtil;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 3/12/13
+ */
+public abstract class AbstractJavaFxPackager {
+ private static final Logger LOG = Logger.getInstance("#" + AbstractJavaFxPackager.class.getName());
+
+ //artifact description
+ protected String getArtifactRootName() {
+ return PathUtilRt.getFileName(getArtifactOutputFilePath());
+ }
+
+ protected abstract String getArtifactOutputPath();
+
+ protected abstract String getArtifactOutputFilePath();
+
+ //artifact properties
+ protected abstract String getAppClass();
+
+ protected abstract String getTitle();
+
+ protected abstract String getVendor();
+
+ protected abstract String getDescription();
+
+ protected abstract String getWidth();
+
+ protected abstract String getHeight();
+
+ protected abstract String getHtmlParamFile();
+
+ protected abstract String getParamFile();
+
+ protected abstract String getUpdateMode();
+
+ protected abstract void registerJavaFxPackagerError(final String message);
+
+
+ public void buildJavaFxArtifact(final String homePath) {
+ if (!checkNotEmpty(getAppClass(), "Application class")) return;
+ if (!checkNotEmpty(getWidth(), "Width")) return;
+ if (!checkNotEmpty(getHeight(), "Height")) return;
+
+ final String zipPath = getArtifactOutputFilePath();
+
+ final File tempUnzippedArtifactOutput;
+ try {
+ tempUnzippedArtifactOutput = FileUtil.createTempDirectory("artifact", "unzipped");
+ ZipUtil.extract(new File(zipPath), tempUnzippedArtifactOutput, null);
+ copyLibraries(zipPath, tempUnzippedArtifactOutput);
+ }
+ catch (IOException e) {
+ registerJavaFxPackagerError(e);
+ return;
+ }
+
+ final File tempDirectory = new File(tempUnzippedArtifactOutput, "deploy");
+ try {
+
+ final StringBuilder buf = new StringBuilder();
+ buf.append("<project default=\"build artifact\">\n");
+ buf.append("<taskdef resource=\"com/sun/javafx/tools/ant/antlib.xml\" uri=\"javafx:com.sun.javafx.tools.ant\" ")
+ .append("classpath=\"").append(homePath).append("/lib/ant-javafx.jar\"/>\n");
+ buf.append("<target name=\"build artifact\" xmlns:fx=\"javafx:com.sun.javafx.tools.ant\">");
+ final String artifactFileName = getArtifactRootName();
+ final String artifactName = FileUtil.getNameWithoutExtension(artifactFileName);
+ final List<JavaFxAntGenerator.SimpleTag> tags =
+ JavaFxAntGenerator.createJarAndDeployTasks(this, artifactFileName, artifactName, tempUnzippedArtifactOutput.getPath());
+ for (JavaFxAntGenerator.SimpleTag tag : tags) {
+ tag.generate(buf);
+ }
+ buf.append("</target>");
+ buf.append("</project>");
+
+ final int result = startAntTarget(buf.toString(), homePath);
+ if (result == 0) {
+ if (isEnabledSigning()) {
+ signApp(homePath + File.separator + "bin", tempDirectory);
+ }
+ }
+ else {
+ registerJavaFxPackagerError("fx:deploy task has failed.");
+ }
+ }
+ finally {
+ copyResultsToArtifactsOutput(tempDirectory);
+ FileUtil.delete(tempUnzippedArtifactOutput);
+ }
+ }
+
+ private void copyLibraries(String zipPath, File tempUnzippedArtifactOutput) throws IOException {
+ final File[] outFiles = new File(getArtifactOutputPath()).listFiles();
+ if (outFiles != null) {
+ for (File file : outFiles) {
+ if (file.isFile()) {
+ final String fileName = file.getName();
+ if (fileName.endsWith(".jar") && !zipPath.equals(fileName)) {
+ FileUtil.copy(file, new File(tempUnzippedArtifactOutput, fileName));
+ }
+ }
+ }
+ }
+ }
+
+ private boolean checkNotEmpty(final String text, final String title) {
+ if (StringUtil.isEmptyOrSpaces(text)) {
+ registerJavaFxPackagerError("Unable to build JavaFX artifact. " + title + " should be specified in artifact's settings.");
+ return false;
+ }
+ return true;
+ }
+
+ private void signApp(String binPath, File tempDirectory) {
+ final boolean selfSigning = isSelfSigning();
+ final int genResult = selfSigning ? genKey(binPath) : 0;
+ if (genResult == 0) {
+ final File[] files = tempDirectory.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isFile() && file.getName().endsWith(".jar")) {
+ sign(binPath, selfSigning, file.getPath());
+ }
+ }
+ }
+ } else {
+ registerJavaFxPackagerError("JavaFX generate certificate task has failed.");
+ }
+ }
+
+ private void sign(String binPath, boolean selfSigning, final String jar2Sign) {
+ final List<String> signCommandLine = new ArrayList<String>();
+ addParameter(signCommandLine, FileUtil.toSystemDependentName(binPath + File.separator + "jarsigner"));
+
+ collectStoreParams(selfSigning, signCommandLine);
+
+ addParameter(signCommandLine, jar2Sign);
+ addParameter(signCommandLine, getAlias(selfSigning));
+
+ final int signedResult = startProcess(signCommandLine);
+ if (signedResult != 0) {
+ registerJavaFxPackagerError("JavaFX sign task has failed for: " + jar2Sign + ".");
+ }
+ }
+
+ private int genKey(String binPath) {
+ final String keyStorePath = getKeystore(true);
+ final File keyStoreFile = new File(keyStorePath);
+ if (keyStoreFile.isFile()) {
+ FileUtil.delete(keyStoreFile);
+ }
+
+ final List<String> genCommandLine = new ArrayList<String>();
+ addParameter(genCommandLine, FileUtil.toSystemDependentName(binPath + File.separator + "keytool"));
+
+ addParameter(genCommandLine, "-genkeypair");
+
+ addParameter(genCommandLine, "-dname");
+ String vendor = getVendor();
+ if (StringUtil.isEmptyOrSpaces(vendor)) {
+ vendor = "jb-fx-build";
+ }
+ addParameter(genCommandLine, "CN=" + vendor.replaceAll(",", "\\\\,"));
+
+ addParameter(genCommandLine, "-alias");
+ addParameter(genCommandLine, getAlias(true));
+
+ collectStoreParams(true, genCommandLine);
+
+ return startProcess(genCommandLine);
+ }
+
+ private void collectStoreParams(boolean selfSigning, List<String> signCommandLine) {
+ addParameter(signCommandLine, "-keyStore");
+ addParameter(signCommandLine, getKeystore(selfSigning));
+
+ addParameter(signCommandLine, "-storepass");
+ addParameter(signCommandLine, getStorepass(selfSigning));
+
+ addParameter(signCommandLine, "-keypass");
+ addParameter(signCommandLine, getKeypass(selfSigning));
+ }
+
+ private void copyResultsToArtifactsOutput(final File tempDirectory) {
+ try {
+ final File resultedJar = new File(getArtifactOutputPath());
+ FileUtil.copyDir(tempDirectory, resultedJar);
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ FileUtil.delete(tempDirectory);
+ }
+
+ private void registerJavaFxPackagerError(Exception ex) {
+ registerJavaFxPackagerError(ex.getMessage());
+ }
+
+ protected abstract String prepareParam(String param);
+ private void addParameter(List<String> commandLine, String param) {
+ if (!StringUtil.isEmptyOrSpaces(param)) {
+ commandLine.add(prepareParam(param));
+ }
+ }
+
+ private int startProcess(List<String> commands) {
+ try {
+ final Process process = new ProcessBuilder(commands).start();
+ final String message = new String(FileUtil.loadBytes(process.getErrorStream()));
+ if (!StringUtil.isEmptyOrSpaces(message)) {
+ registerJavaFxPackagerError(message);
+ }
+ return process.waitFor();
+ }
+ catch (Exception e) {
+ registerJavaFxPackagerError(e);
+ return -1;
+ }
+ }
+
+ private int startAntTarget(String buildText, String javaHome) {
+ final String antHome = getAntHome();
+ if (antHome == null) {
+ registerJavaFxPackagerError("Bundled ant not found.");
+ return -1;
+ }
+ final ArrayList<String> commands = new ArrayList<String>();
+ commands.add(javaHome + File.separator + "bin" + File.separator + "java");
+
+ commands.add("-Dant.home=" + antHome);
+
+ commands.add("-classpath");
+ commands.add(antHome + "/lib/ant.jar" + File.pathSeparator +
+ antHome + "/lib/ant-launcher.jar" + File.pathSeparator +
+ javaHome + "/lib/ant-javafx.jar");
+ commands.add("org.apache.tools.ant.launch.Launcher");
+ commands.add("-f");
+ try {
+ File tempFile = FileUtil.createTempFile("build", ".xml");
+ tempFile.deleteOnExit();
+ OutputStream outputStream = new FileOutputStream(tempFile.getAbsolutePath());
+ try {
+ outputStream.write(buildText.getBytes(Charset.defaultCharset()));
+ }
+ finally {
+ outputStream.close();
+ }
+ commands.add(tempFile.getCanonicalPath());
+ }
+ catch (IOException e) {
+ registerJavaFxPackagerError(e);
+ return -1;
+ }
+ return startProcess(commands);
+ }
+
+ private static String getAntHome() {
+ final String appHome = PathManager.getHomePath();
+ if (appHome == null) {
+ return null;
+ }
+
+ File antHome = new File(appHome, "lib" + File.separator + "ant");
+ if (!antHome.exists()) {
+ File communityAntHome = new File(appHome, "community" + File.separator + "lib" + File.separator + "ant");
+ if (communityAntHome.exists()) {
+ antHome = communityAntHome;
+ }
+ }
+
+ if (!antHome.exists()) {
+ return null;
+ }
+
+ return antHome.getPath();
+ }
+
+ private String getAlias(boolean selfSigning) {
+ return selfSigning ? "jb" : getAlias();
+ }
+
+ private String getKeypass(boolean selfSigning) {
+ return selfSigning ? "keypass" : Base64Converter.decode(getKeypass());
+ }
+
+ private String getKeystore(boolean selfSigning) {
+ return selfSigning ? getArtifactOutputPath() + File.separator + "jb-jfx.jks" : getKeystore();
+ }
+
+ private String getStorepass(boolean selfSigning) {
+ return selfSigning ? "storepass" : Base64Converter.decode(getStorepass());
+ }
+
+ public abstract String getKeypass();
+
+ public abstract String getStorepass();
+
+ public abstract String getKeystore();
+
+ public abstract String getAlias();
+
+ public abstract boolean isSelfSigning();
+
+ public abstract boolean isEnabledSigning();
+
+ public abstract String getPreloaderClass();
+
+ public abstract String getPreloaderJar();
+}
diff --git a/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxAntGenerator.java b/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxAntGenerator.java
new file mode 100644
index 000000000000..883dd8dba8ec
--- /dev/null
+++ b/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxAntGenerator.java
@@ -0,0 +1,219 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ArrayUtil;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * User: anna
+ * Date: 3/28/13
+ */
+public class JavaFxAntGenerator {
+ public static List<SimpleTag> createJarAndDeployTasks(AbstractJavaFxPackager packager,
+ String artifactFileName,
+ String artifactName,
+ String tempDirPath) {
+ final List<SimpleTag> topLevelTagsCollector = new ArrayList<SimpleTag>();
+ final String preloaderJar = packager.getPreloaderJar();
+ final String preloaderClass = packager.getPreloaderClass();
+ String preloaderFiles = null;
+ if (!StringUtil.isEmptyOrSpaces(preloaderJar) && !StringUtil.isEmptyOrSpaces(preloaderClass)) {
+ preloaderFiles = artifactName + "_preloader_files";
+ topLevelTagsCollector.add(new SimpleTag("fx:fileset",
+ new Pair<String, String>("id", preloaderFiles),
+ new Pair<String, String>("requiredFor", "preloader"),
+ new Pair<String, String>("dir", tempDirPath),
+ new Pair<String, String>("includes", preloaderJar)));
+ }
+
+ //register application
+ final String appId = artifactName + "_id";
+ Pair[] applicationParams = {
+ new Pair<String, String>("id", appId),
+ new Pair<String, String>("name", artifactName),
+ new Pair<String, String>("mainClass", packager.getAppClass())
+ };
+ if (preloaderFiles != null) {
+ applicationParams = ArrayUtil.append(applicationParams, new Pair<String, String>("preloaderClass", preloaderClass));
+ }
+
+ final SimpleTag applicationTag = new SimpleTag("fx:application", applicationParams);
+
+ appendValuesFromPropertiesFile(applicationTag, packager.getHtmlParamFile(), "fx:htmlParam", false);
+ //also loads fx:argument values
+ appendValuesFromPropertiesFile(applicationTag, packager.getParamFile(), "fx:param", true);
+
+ topLevelTagsCollector.add(applicationTag);
+
+ //create jar task
+ final SimpleTag createJarTag = new SimpleTag("fx:jar",
+ new Pair<String, String>("destfile", tempDirPath + File.separator + artifactFileName));
+ createJarTag.add(new SimpleTag("fx:application", new Pair<String, String>("refid", appId)));
+
+ final List<Pair> fileset2Jar = new ArrayList<Pair>();
+ fileset2Jar.add(new Pair<String, String>("dir", tempDirPath));
+ fileset2Jar.add(new Pair<String, String>("excludes", "*.jar"));
+ createJarTag.add(new SimpleTag("fileset", fileset2Jar.toArray(new Pair[fileset2Jar.size()])));
+
+ createJarTag.add(createResourcesTag(tempDirPath, preloaderFiles, artifactFileName, preloaderJar, false));
+
+ topLevelTagsCollector.add(createJarTag);
+
+ //deploy task
+ final SimpleTag deployTag = new SimpleTag("fx:deploy",
+ new Pair<String, String>("width", packager.getWidth()),
+ new Pair<String, String>("height", packager.getHeight()),
+ new Pair<String, String>("updatemode", packager.getUpdateMode()),
+ new Pair<String, String>("outdir", tempDirPath + File.separator + "deploy"),
+ new Pair<String, String>("outfile", artifactName));
+ deployTag.add(new SimpleTag("fx:application", new Pair<String, String>("refid", appId)));
+
+ final List<Pair> infoPairs = new ArrayList<Pair>();
+ appendIfNotEmpty(infoPairs, "title", packager.getTitle());
+ appendIfNotEmpty(infoPairs, "vendor", packager.getVendor());
+ appendIfNotEmpty(infoPairs, "description", packager.getDescription());
+ if (!infoPairs.isEmpty()) {
+ deployTag.add(new SimpleTag("fx:info", infoPairs.toArray(new Pair[infoPairs.size()])));
+ }
+ deployTag.add(createResourcesTag(tempDirPath, preloaderFiles, artifactFileName, preloaderJar, true));
+
+ topLevelTagsCollector.add(deployTag);
+ return topLevelTagsCollector;
+ }
+
+ private static SimpleTag createResourcesTag(String tempDirPath, String preloaderFiles,
+ String artifactFileName,
+ String preloaderJar,
+ boolean includeSelf) {
+ final SimpleTag resourcesTag = new SimpleTag("fx:resources");
+ if (preloaderFiles != null) {
+ resourcesTag.add(new SimpleTag("fx:fileset", new Pair<String, String>("refid", preloaderFiles)));
+ }
+ final File[] files = new File(tempDirPath).listFiles();
+ if (files != null) {
+ for (File file : files) {
+ final String fileName = file.getName();
+ if (!fileName.equals(preloaderJar) && (includeSelf || !fileName.equals(artifactFileName))) {
+ resourcesTag.add(new SimpleTag("fx:fileset", new Pair<String, String>("dir", tempDirPath), new Pair<String, String>("includes", fileName)));
+ }
+
+ }
+ }
+ return resourcesTag;
+ }
+
+ private static void appendIfNotEmpty(final List<Pair> pairs, final String propertyName, final String propValue) {
+ if (!StringUtil.isEmptyOrSpaces(propValue)) {
+ pairs.add(Pair.create(propertyName, propValue));
+ }
+ }
+
+ private static void appendValuesFromPropertiesFile(final SimpleTag applicationTag,
+ final String paramFile,
+ final String paramTagName,
+ final boolean allowNoNamed) {
+ if (!StringUtil.isEmptyOrSpaces(paramFile)) {
+ final Properties properties = new Properties();
+ try {
+ final FileInputStream paramsInputStream = new FileInputStream(new File(paramFile));
+ try {
+ properties.load(paramsInputStream);
+ for (Object o : properties.keySet()) {
+ final String propName = (String)o;
+ final String propValue = properties.getProperty(propName);
+ if (!StringUtil.isEmptyOrSpaces(propValue)) {
+ applicationTag
+ .add(new SimpleTag(paramTagName, new Pair<String, String>("name", propName), new Pair<String, String>("value", propValue)));
+ }
+ else if (allowNoNamed) {
+ applicationTag.add(new SimpleTag("fx:argument", propName) {
+ @Override
+ public void generate(StringBuilder buf) {
+ buf.append("<").append(getName()).append(">").append(propName).append("</").append(getName()).append(">");
+ }
+ });
+ }
+ }
+ }
+ finally {
+ paramsInputStream.close();
+ }
+ }
+ catch (IOException ignore) {
+ }
+ }
+ }
+
+ public static class SimpleTag {
+ private final String myName;
+ private final Pair[] myPairs;
+ private final List<SimpleTag> mySubTags = new ArrayList<SimpleTag>();
+ private final String myValue;
+
+ public SimpleTag(String name, Pair... pairs) {
+ myName = name;
+ myPairs = pairs;
+ myValue = null;
+ }
+
+ public SimpleTag(String name, String value) {
+ myName = name;
+ myPairs = new Pair[0];
+ myValue = value;
+ }
+
+ public void add(SimpleTag tag) {
+ mySubTags.add(tag);
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public Pair[] getPairs() {
+ return myPairs;
+ }
+
+ public String getValue() {
+ return myValue;
+ }
+
+ public List<SimpleTag> getSubTags() {
+ return mySubTags;
+ }
+
+ public void generate(StringBuilder buf) {
+ buf.append("<").append(getName());
+ for (Pair pair : getPairs()) {
+ buf.append(" ").append(pair.first).append("=\"").append(pair.second).append("\"");
+ }
+ buf.append(">\n");
+ for (SimpleTag tag : getSubTags()) {
+ tag.generate(buf);
+ }
+ buf.append("</").append(getName()).append(">\n");
+ }
+ }
+}
diff --git a/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxPackagerConstants.java b/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxPackagerConstants.java
new file mode 100644
index 000000000000..d53bdd2eb431
--- /dev/null
+++ b/plugins/javaFX/common-javaFX-plugin/src/org/jetbrains/plugins/javaFX/packaging/JavaFxPackagerConstants.java
@@ -0,0 +1,29 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JavaFxPackagerConstants {
+ @NonNls public static final String UPDATE_MODE_BACKGROUND = "background";
+ @NonNls public static final String UPDATE_MODE_ALWAYS = "always";
+ @NonNls public static final String DEFAULT_HEIGHT = "400";
+ @NonNls public static final String DEFAULT_WEIGHT = "600";
+}
diff --git a/plugins/javaFX/javaFX-CE/javaFX-CE.iml b/plugins/javaFX/javaFX-CE/javaFX-CE.iml
index 358c313c2ca3..29658e539dad 100644
--- a/plugins/javaFX/javaFX-CE/javaFX-CE.iml
+++ b/plugins/javaFX/javaFX-CE/javaFX-CE.iml
@@ -12,6 +12,9 @@
<orderEntry type="module" module-name="platform-impl" scope="TEST" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
<orderEntry type="module" module-name="xml" scope="TEST" />
+ <orderEntry type="module" module-name="jetgroovy" scope="TEST" />
+ <orderEntry type="module" module-name="java-tests" scope="TEST" />
+ <orderEntry type="module" module-name="common-javaFX-plugin" scope="TEST" />
</component>
</module>
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/GenerateGetterSetterTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/GenerateGetterSetterTest.java
new file mode 100644
index 000000000000..2761011c1e61
--- /dev/null
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/GenerateGetterSetterTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX;
+
+import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
+import com.intellij.codeInsight.generation.ClassMember;
+import com.intellij.codeInsight.generation.GenerateGetterAndSetterHandler;
+import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.testFramework.PsiTestUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class GenerateGetterSetterTest extends DaemonAnalyzerTestCase {
+ public void testDouble() throws Exception {
+ doTest();
+ }
+
+ @Override
+ protected void setUpModule() {
+ super.setUpModule();
+ PsiTestUtil.addLibrary(getModule(), "javafx", PluginPathManager.getPluginHomePath("javaFX") + "/testData", "jfxrt.jar");
+ }
+
+ protected void doTest() throws Exception {
+ configureByFile("/generateGetterSetter/before" + getTestName(false) + ".java");
+ new GenerateGetterAndSetterHandler() {
+ @Nullable
+ @Override
+ protected ClassMember[] chooseMembers(ClassMember[] members,
+ boolean allowEmptySelection,
+ boolean copyJavadocCheckbox,
+ Project project,
+ @Nullable Editor editor) {
+ return members;
+ }
+ }.invoke(getProject(), getEditor(), getFile());
+ checkResultByFile("/generateGetterSetter/after" + getTestName(false) + ".java");
+ }
+
+ @NotNull
+ @Override
+ protected String getTestDataPath() {
+ return PluginPathManager.getPluginHomePath("javaFX") + "/testData";
+ }
+}
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/AbstractJavaFXQuickFixTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/AbstractJavaFXQuickFixTest.java
new file mode 100644
index 000000000000..feaaf1ec1336
--- /dev/null
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/AbstractJavaFXQuickFixTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+
+/**
+ * User: anna
+ * Date: 3/20/13
+ */
+public abstract class AbstractJavaFXQuickFixTest extends AbstractJavaFXTestCase {
+ protected abstract String getHint(String tagName);
+
+ protected void doLaunchQuickfixTest(final String tagName) throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ final IntentionAction singleIntention = myFixture.findSingleIntention(getHint(tagName));
+ assertNotNull(singleIntention);
+ myFixture.launchAction(singleIntention);
+ myFixture.checkResultByFile(getTestName(true) + "_after.fxml");
+ }
+
+ protected void checkQuickFixNotAvailable(String tagName) throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ final IntentionAction intention = myFixture.getAvailableIntention(getHint(tagName));
+ assertNull(intention);
+ }
+}
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/AbstractJavaFXTestCase.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/AbstractJavaFXTestCase.java
new file mode 100644
index 000000000000..795e923ed080
--- /dev/null
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/AbstractJavaFXTestCase.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml;
+
+import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.testFramework.LightProjectDescriptor;
+import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: anna
+ * Date: 3/20/13
+ */
+public abstract class AbstractJavaFXTestCase extends LightCodeInsightFixtureTestCase {
+ public static final DefaultLightProjectDescriptor JAVA_FX_DESCRIPTOR = new DefaultLightProjectDescriptor() {
+ @Override
+ public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
+ PsiTestUtil.addLibrary(module, model, "javafx", PluginPathManager.getPluginHomePath("javaFX") + "/testData", "jfxrt.jar");
+ super.configureModule(module, model, contentEntry);
+ }
+ };
+
+ @NotNull
+ @Override
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return JAVA_FX_DESCRIPTOR;
+ }
+
+ protected void enableInspections() {}
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ enableInspections();
+ }
+
+
+}
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXCollapseSubtagToAttributeTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXCollapseSubtagToAttributeTest.java
index d27cd08ce0e9..9839bef63707 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXCollapseSubtagToAttributeTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXCollapseSubtagToAttributeTest.java
@@ -46,6 +46,10 @@ public class JavaFXCollapseSubtagToAttributeTest extends DaemonAnalyzerTestCase
doTest(true, "GridPane.rowIndex");
}
+ public void testStyleclass() throws Exception {
+ doTest(true, "styleClass");
+ }
+
private void doTest(boolean available) throws Exception {
doTest(available, "text");
}
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXDefaultTagInspectionTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXDefaultTagInspectionTest.java
index e8aa2a4349e3..62f9c3f2190b 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXDefaultTagInspectionTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXDefaultTagInspectionTest.java
@@ -15,56 +15,37 @@
*/
package org.jetbrains.plugins.javaFX.fxml;
-import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
-import com.intellij.codeInsight.daemon.impl.HighlightInfo;
-import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.openapi.application.PluginPathManager;
-import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections.JavaFxDefaultTagInspection;
-import java.util.List;
-
/**
* User: anna
* Date: 1/10/13
*/
-public class JavaFXDefaultTagInspectionTest extends DaemonAnalyzerTestCase {
- @Override
- protected void setUpModule() {
- super.setUpModule();
- PsiTestUtil.addLibrary(getModule(), "javafx", PluginPathManager.getPluginHomePath("javaFX") + "/testData", "jfxrt.jar");
- }
+public class JavaFXDefaultTagInspectionTest extends AbstractJavaFXQuickFixTest {
@Override
- protected LocalInspectionTool[] configureLocalInspectionTools() {
- return new LocalInspectionTool[]{new JavaFxDefaultTagInspection()};
+ protected void enableInspections() {
+ myFixture.enableInspections(new JavaFxDefaultTagInspection());
}
public void testChildren() throws Exception {
- doTest("children");
+ doLaunchQuickfixTest("children");
}
public void testEmptyChildren() throws Exception {
- doTest("children");
+ doLaunchQuickfixTest("children");
}
public void testStylesheets() throws Exception {
- checkNotAvailable("stylesheets");
+ checkQuickFixNotAvailable("stylesheets");
}
- private void doTest(String tagName) throws Exception {
- configureByFiles(null, getTestName(true) + ".fxml");
- final List<HighlightInfo> infos = doHighlighting();
- findAndInvokeIntentionAction(infos, "Unwrap '" + tagName + "'", getEditor(), getFile());
- checkResultByFile(getTestName(true) + "_after.fxml");
- }
-
- private void checkNotAvailable(String tagName) throws Exception {
- configureByFiles(null, getTestName(true) + ".fxml");
- final List<HighlightInfo> infos = doHighlighting();
- assertNull(findIntentionAction(infos, "Unwrap '" + tagName + "'", getEditor(), getFile()));
+ @Override
+ protected String getHint(String tagName) {
+ return "Unwrap '" + tagName + "'";
}
@NotNull
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java
index f66c68429f01..971f3a9b4c3b 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java
@@ -15,14 +15,13 @@
*/
package org.jetbrains.plugins.javaFX.fxml;
-import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
import com.intellij.codeInsight.daemon.impl.analysis.XmlPathReferenceInspection;
-import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection;
+import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.psi.*;
-import com.intellij.psi.search.ProjectScope;
-import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -30,18 +29,7 @@ import org.jetbrains.annotations.NotNull;
* @author anna
* @since 10.01.2013
*/
-public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
- @Override
- protected void setUpModule() {
- super.setUpModule();
- //noinspection SpellCheckingInspection
- PsiTestUtil.addLibrary(getModule(), "javafx", PluginPathManager.getPluginHomePath("javaFX") + "/testData", "jfxrt.jar");
- }
-
- @Override
- protected LocalInspectionTool[] configureLocalInspectionTools() {
- return new LocalInspectionTool[] {new XmlPathReferenceInspection(), new RequiredAttributesInspection() };
- }
+public class JavaFXHighlightingTest extends AbstractJavaFXTestCase {
public void testLoginForm() throws Exception {
doTest();
@@ -59,10 +47,20 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
doTest();
}
+ public void testRootTagCoercedUnchecked() throws Exception {
+ doTest();
+ }
+
public void testStaticProperties() throws Exception {
doTest();
}
+ public void testStaticPropertiesCustomLayout() throws Exception {
+ myFixture.addClass("import javafx.scene.layout.GridPane;\n" +
+ "public class MyGridPane extends GridPane {}\n");
+ myFixture.testHighlighting(false, false, false, getTestName(true) + ".fxml");
+ }
+
public void testEnumValues() throws Exception {
doTest();
}
@@ -80,8 +78,9 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
}
public void testImageIcon() throws Exception {
- configureByFiles(null, getTestName(true) + ".fxml", "appIcon.png");
- doDoTest(false, false);
+ myFixture.copyFileToProject("appIcon.png");
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ myFixture.testHighlighting(false, false, false, getTestName(true) + ".fxml");
}
public void testControllerIdRef() throws Exception {
@@ -89,18 +88,21 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
}
public void testPackageLocalController() throws Exception {
- configureByFiles(null, getTestName(true) + ".fxml", getTestName(false) + ".java");
- doDoTest(false, false);
+ doTest(getTestName(false) + ".java");
+ }
+
+ public void testNoParamsHandler() throws Exception {
+ doTest(getTestName(false) + ".java");
}
private void doTestIdController() throws Exception {
final String controllerClassName = getTestName(false) + "Controller";
- configureByFiles(null, getTestName(true) + ".fxml", controllerClassName + ".java");
- final PsiClass controllerClass = findClass(controllerClassName);
+ myFixture.configureByFiles(getTestName(true) + ".fxml", controllerClassName + ".java");
+ final PsiClass controllerClass = myFixture.findClass(controllerClassName);
assertNotNull(controllerClass);
assertTrue(controllerClass.getFields().length > 0);
- final int offset = myEditor.getCaretModel().getOffset();
- final PsiReference reference = myFile.findReferenceAt(offset);
+ final int offset = myFixture.getCaretOffset();
+ final PsiReference reference = myFixture.getFile().findReferenceAt(offset);
assertNotNull(reference);
assertEquals(controllerClass.getFields()[0], reference.resolve());
}
@@ -117,9 +119,22 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
doTestNavigation("CustomVBox", "tf", "custom/" + getTestName(true) + ".fxml", "custom/CustomVBox.java");
}
+ public void testCustomComponentFieldsWithSameProperties() throws Exception {
+ doTest("custom/" + getTestName(true) + ".fxml", "custom/" + getTestName(false) + ".java");
+ }
+
public void testCustomComponent_Fields() throws Exception {
- configureByFiles(null, "custom/" + getTestName(true) + ".fxml", "custom/_CustomVBox.java");
- doDoTest(false, false);
+ doTest("custom/" + getTestName(true) + ".fxml", "custom/_CustomVBox.java");
+ }
+
+ public void testInjectedController() throws Exception {
+ myFixture.copyFileToProject("injected/MyController.java");
+ myFixture.copyFileToProject("injected/FooVBox.java");
+ doTestNavigation("injected.MyController", "label", "injected/" + getTestName(true) + ".fxml");
+ }
+
+ public void testNamedColor() throws Exception {
+ doTestNavigation(JavaFxCommonClassNames.JAVAFX_SCENE_COLOR, "ORANGE");
}
private void doTestNavigation(String resultClassName, String resultFieldName) throws Exception {
@@ -128,14 +143,14 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
private void doTestNavigation(String resultClassName, String resultFieldName, String... additionalPaths) throws Exception {
if (additionalPaths.length == 0) {
- configureByFiles(null, getTestName(true) + ".fxml");
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
} else {
- configureByFiles(null, additionalPaths);
+ myFixture.configureByFiles(additionalPaths);
}
- final int offset = myEditor.getCaretModel().getOffset();
- final PsiReference reference = myFile.findReferenceAt(offset);
+ final int offset = myFixture.getCaretOffset();
+ final PsiReference reference = myFixture.getFile().findReferenceAt(offset);
assertNotNull(reference);
- final PsiClass resultClass = myJavaFacade.findClass(resultClassName, ProjectScope.getAllScope(getProject()));
+ final PsiClass resultClass = myFixture.getJavaFacade().findClass(resultClassName, GlobalSearchScope.allScope(getProject()));
assertNotNull("Class " + resultClassName + " not found", resultClass);
final PsiField resultField = resultClass.findFieldByName(resultFieldName, false);
assertNotNull(resultField);
@@ -143,9 +158,9 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
}
public void testNavigationFromMainToFxml() throws Exception {
- configureByFiles(null, getTestName(false) + ".java", getTestName(true) + ".fxml");
- final int offset = myEditor.getCaretModel().getOffset();
- final PsiReference reference = myFile.findReferenceAt(offset);
+ myFixture.configureByFiles(getTestName(false) + ".java", getTestName(true) + ".fxml");
+ final int offset = myFixture.getCaretOffset();
+ final PsiReference reference = myFixture.getFile().findReferenceAt(offset);
assertNotNull(reference);
final PsiElement resolve = reference.resolve();
assertNotNull(resolve);
@@ -186,9 +201,20 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
doTest();
}
+ public void testIdOutOfHierarchy() throws Exception {
+ doTest("btn.fxml", "MyController.java");
+ }
+
public void testIncludeBtn() throws Exception {
- configureByFiles(null, getTestName(true) + ".fxml", "btn.fxml");
- doDoTest(false, false);
+ doTest("btn.fxml");
+ }
+
+ public void testWrongBindingType() throws Exception {
+ doTest(getTestName(false) + ".java");
+ }
+
+ public void testAllowIncludeTagInsideDefine() throws Exception {
+ doTest("btn.fxml");
}
public void testValueOfAcceptance() throws Exception {
@@ -220,8 +246,17 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
}
public void testScriptSource() throws Exception {
- configureByFiles(null, getTestName(true) + ".fxml", "s1.js");
- doDoTest(false, false);
+ doTest("s1.js");
+ }
+
+ private void doTest(String additionalPath) {
+ myFixture.configureByFiles(getTestName(true) + ".fxml", additionalPath);
+ myFixture.testHighlighting(false, false, false, getTestName(true) + ".fxml");
+ }
+
+ private void doTest(String... paths) {
+ myFixture.configureByFiles(paths);
+ myFixture.testHighlighting(false, false, false, paths[0]);
}
public void testExpressionBinding() throws Exception {
@@ -240,8 +275,74 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
doTest();
}
+ public void testLineChartInstantiation() throws Exception {
+ doTest();
+ }
+
+ public void testUnexpectedNode() throws Exception {
+ doTest();
+ }
+
+ public void testDefaultPropertyField() throws Exception {
+ doTest();
+ }
+
+ public void testPrimitiveSubtags() throws Exception {
+ doTest();
+ }
+
+ public void testReferencePosition() throws Exception {
+ doTest();
+ }
+
+ public void testAcceptReferenceInsideDefine() throws Exception {
+ doTest();
+ }
+
+ public void testRootTagOnDifferentLevels() throws Exception {
+ doTest();
+ }
+
+ public void testAbsenceOfDefineAttributes() throws Exception {
+ doTest();
+ }
+
+ public void testCopyReference() throws Exception {
+ doTest();
+ }
+
+ public void testCharsetInInclude() throws Exception {
+ myFixture.addFileToProject("sample.fxml", "<?import javafx.scene.layout.GridPane?>\n" +
+ "<fx:root type=\"javafx.scene.layout.GridPane\" xmlns:fx=\"http://javafx.com/fxml\"/>\n");
+ myFixture.testHighlighting(true, false, false, getTestName(true) + ".fxml");
+ }
+
+ public void testIncludedForm() throws Exception {
+ myFixture.addFileToProject("sample.fxml", "<?import javafx.scene.layout.GridPane?>\n" +
+ "<fx:root type=\"javafx.scene.layout.GridPane\" xmlns:fx=\"http://javafx.com/fxml\"/>\n");
+ myFixture.testHighlighting(true, false, false, getTestName(true) + ".fxml");
+ }
+
+ public void testInjectedControllerFields() throws Exception {
+ myFixture.addFileToProject("sample.fxml", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<?import javafx.scene.control.*?>\n" +
+ "<?import javafx.scene.layout.*?>\n" +
+ "<AnchorPane id=\"AnchorPane\" xmlns:fx=\"http://javafx.com/fxml\" fx:controller=\"" + getTestName(false)+ "\">\n" +
+ " <Button fx:id=\"id1\" />\n" +
+ "</AnchorPane>\n");
+ myFixture.testHighlighting(true, false, false, getTestName(false) + ".java");
+ }
+
private void doTest() throws Exception {
- doTest(false, false, getTestName(true) + ".fxml");
+ myFixture.testHighlighting(false, false, false, getTestName(true) + ".fxml");
+ }
+
+ @Override
+ protected void enableInspections() {
+ myFixture.enableInspections(new XmlPathReferenceInspection(),
+ new RequiredAttributesInspection(),
+ new UnusedSymbolLocalInspection(),
+ new UnusedDeclarationInspection());
}
@NotNull
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXImportTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXImportTest.java
index a6537061b0df..45a3f04c73e9 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXImportTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXImportTest.java
@@ -33,7 +33,20 @@ public class JavaFXImportTest extends DaemonAnalyzerTestCase {
public void testSimpleImport() throws Exception {
doTest();
}
-
+
+ public void testTextField() throws Exception {
+ configureByFiles(null, getTestName(true) + ".fxml", getTestName(false) + ".java");
+ final List<HighlightInfo> infos = doHighlighting();
+ findAndInvokeIntentionAction(infos, "Import Class", getEditor(), getFile());
+ checkResultByFile(getTestName(true) + "_after.fxml");
+ }
+
+ public void testInsets() throws Exception {
+ configureByFiles(null, getTestName(true) + ".fxml", getTestName(false) + ".java");
+ final List<HighlightInfo> infos = doHighlighting();
+ findAndInvokeIntentionAction(infos, "Import Class", getEditor(), getFile());
+ checkResultByFile(getTestName(true) + "_after.fxml");
+ }
private void doTest() throws Exception {
configureByFiles(null, getTestName(true) + ".fxml");
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXOptimizeImportsTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXOptimizeImportsTest.java
index b3726abc3a14..9db7f2f3e319 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXOptimizeImportsTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXOptimizeImportsTest.java
@@ -16,18 +16,10 @@
package org.jetbrains.plugins.javaFX.fxml;
import com.intellij.codeInsight.actions.OptimizeImportsProcessor;
-import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
import com.intellij.openapi.application.PluginPathManager;
-import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NotNull;
-public class JavaFXOptimizeImportsTest extends DaemonAnalyzerTestCase {
- @Override
- protected void setUpModule() {
- super.setUpModule();
- PsiTestUtil.addLibrary(getModule(), "javafx", PluginPathManager.getPluginHomePath("javaFX") + "/testData", "jfxrt.jar");
- }
-
+public class JavaFXOptimizeImportsTest extends AbstractJavaFXTestCase {
public void testCollapseOnDemand() throws Exception {
doTest();
}
@@ -36,10 +28,26 @@ public class JavaFXOptimizeImportsTest extends DaemonAnalyzerTestCase {
doTest();
}
+ public void testDblImports() throws Exception {
+ doTest();
+ }
+
+ public void testStaticPropertiesAttrAndCustomComponents() throws Exception {
+ myFixture.addClass("import javafx.scene.layout.GridPane;\n" +
+ "public class MyGridPane extends GridPane {}\n");
+ doTest();
+ }
+
+ public void testStaticPropertiesTagAndCustomComponents() throws Exception {
+ myFixture.addClass("import javafx.scene.layout.GridPane;\n" +
+ "public class MyGridPane extends GridPane {}\n");
+ doTest();
+ }
+
private void doTest() throws Exception {
- configureByFile(getTestName(true) + ".fxml");
- new OptimizeImportsProcessor(getProject(), getFile()).run();
- checkResultByFile(getTestName(true) + "_after.fxml");
+ myFixture.configureByFile(getTestName(true) + ".fxml");
+ new OptimizeImportsProcessor(getProject(), myFixture.getFile()).run();
+ myFixture.checkResultByFile(getTestName(true) + "_after.fxml");
}
@NotNull
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java
index e7b7135d929b..f9e9fe78247a 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java
@@ -15,49 +15,67 @@
*/
package org.jetbrains.plugins.javaFX.fxml;
-import com.intellij.codeInsight.TargetElementUtilBase;
-import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
-import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.application.PluginPathManager;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.fileEditor.OpenFileDescriptor;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiElement;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections.JavaFxUnresolvedFxIdReferenceInspection;
-import java.util.List;
+public class JavaFXQuickfixTest extends LightCodeInsightFixtureTestCase {
+ public static final DefaultLightProjectDescriptor JAVA_FX_WITH_GROOVY_DESCRIPTOR = new DefaultLightProjectDescriptor() {
+ @Override
+ public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
+ PsiTestUtil.addLibrary(module, model, "javafx", PluginPathManager.getPluginHomePath("javaFX") + "/testData", "jfxrt.jar");
+ PsiTestUtil.addLibrary(module, model, "groovy", PluginPathManager.getPluginHomePath("groovy") + "/testdata/mockGroovyLib1.8", "groovy-1.8.0-beta-2.jar");
+ super.configureModule(module, model, contentEntry);
+ }
+ };
-public class JavaFXQuickfixTest extends DaemonAnalyzerTestCase {
+ @NotNull
@Override
- protected void setUpModule() {
- super.setUpModule();
- PsiTestUtil.addLibrary(getModule(), "javafx", PluginPathManager.getPluginHomePath("javaFX") + "/testData", "jfxrt.jar");
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return JAVA_FX_WITH_GROOVY_DESCRIPTOR;
}
public void testCreateControllerMethod() throws Exception {
- doTest("Create Method 'void bar(ActionEvent)'", true);
+ doTest("Create Method 'void bar(ActionEvent)'", ".java");
+ }
+
+ public void testCreateControllerMethodInGroovy() throws Exception {
+ doTest("Create Method 'void bar(ActionEvent)'", ".groovy");
+ }
+
+ public void testCreateField() throws Exception {
+ doTest("Create Field 'btn'", ".java");
+ }
+
+ public void testWrapWithDefine() throws Exception {
+ final IntentionAction intention =
+ myFixture.getAvailableIntention("Wrap \"lb\" with fx:define", getTestName(true) + ".fxml");
+ assertNotNull(intention);
+ myFixture.launchAction(intention);
+ myFixture.checkResultByFile(getTestName(true) + "_after.fxml");
}
- private void doTest(final String actionName) throws Exception {
- doTest(actionName, false);
+ private void doTest(final String actionName, final String extension) throws Exception {
+ String path = getTestName(true) + ".fxml";
+ final IntentionAction intention =
+ myFixture.getAvailableIntention(actionName, path, getTestName(false) + extension);
+ assertNotNull(intention);
+ myFixture.launchAction(intention);
+ myFixture.checkResultByFile(getTestName(false) + extension, getTestName(false) + "_after" + extension, true);
}
- private void doTest(final String actionName, boolean changeEditor) throws Exception {
- configureByFiles(null, getTestName(true) + ".fxml", getTestName(false) + ".java");
- final List<HighlightInfo> infos = doHighlighting();
- findAndInvokeIntentionAction(infos, actionName, getEditor(), getFile());
- if (changeEditor) {
- final PsiElement targetMethod = TargetElementUtilBase.findTargetElement(getEditor(), TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
- assertNotNull(targetMethod);
- final VirtualFile file = targetMethod.getContainingFile().getVirtualFile();
- assertNotNull(file);
- final Editor editor = FileEditorManager.getInstance(getProject()).openTextEditor(new OpenFileDescriptor(getProject(), file), true);
- assertNotNull(editor);
- setActiveEditor(editor);
- }
- checkResultByFile(getTestName(false) + "_after.java");
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.enableInspections(new JavaFxUnresolvedFxIdReferenceInspection());
}
@NotNull
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java
index e84c06dcff60..7b5893da6b90 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java
@@ -20,7 +20,9 @@ import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.rename.RenameProcessor;
+import com.intellij.refactoring.rename.inplace.MemberInplaceRenameHandler;
import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.testFramework.fixtures.CodeInsightTestUtil;
import org.jetbrains.annotations.NotNull;
public class JavaFXRenameTest extends DaemonAnalyzerTestCase {
@@ -38,16 +40,41 @@ public class JavaFXRenameTest extends DaemonAnalyzerTestCase {
doTest("newFieldName");
}
+ public void testControllerFieldWithRefs() throws Exception {
+ doTest("newFieldName");
+ }
+
+ public void testHandler() throws Exception {
+ doTest("newHandlerName");
+ }
+
public void testCustomComponentTag() throws Exception {
- doTest("Foo");
+ doTest("Foo", true);
+ }
+
+ public void testIdWithRefs() throws Exception {
+ configureByFiles(null, getTestName(true) + ".fxml");
+ PsiElement element = TargetElementUtilBase
+ .findTargetElement(myEditor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
+ assertNotNull(element);
+ new RenameProcessor(getProject(), element, "lb1", true, true).run();
+ checkResultByFile(getTestName(true) + "_after.fxml");
}
private void doTest(final String newName) throws Exception {
+ doTest(newName, false);
+ }
+
+ private void doTest(final String newName, boolean inline) throws Exception {
configureByFiles(null, getTestName(true) + ".fxml", getTestName(false) + ".java");
PsiElement element = TargetElementUtilBase
.findTargetElement(myEditor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
assertNotNull(element);
- new RenameProcessor(getProject(), element, newName, true, true).run();
+ if (inline) {
+ CodeInsightTestUtil.doInlineRename(new MemberInplaceRenameHandler(), newName, getEditor(), element);
+ } else {
+ new RenameProcessor(getProject(), element, newName, true, true).run();
+ }
checkResultByFile(getTestName(true) + "_after.fxml");
}
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXUnresolvedFxIdReferenceInspectionTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXUnresolvedFxIdReferenceInspectionTest.java
new file mode 100644
index 000000000000..ca9c80166995
--- /dev/null
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXUnresolvedFxIdReferenceInspectionTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.openapi.application.PluginPathManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections.JavaFxUnresolvedFxIdReferenceInspection;
+
+/**
+ * User: anna
+ * Date: 1/10/13
+ */
+public class JavaFXUnresolvedFxIdReferenceInspectionTest extends AbstractJavaFXQuickFixTest {
+
+ @Override
+ protected void enableInspections() {
+ myFixture.enableInspections(new JavaFxUnresolvedFxIdReferenceInspection());
+ }
+
+ public void testUnknownRef() throws Exception {
+ doTest("Controller");
+ }
+
+ private void doTest(final String controllerName) {
+ myFixture.configureByFiles(getTestName(true) + ".fxml", controllerName + ".java");
+ final IntentionAction singleIntention = myFixture.findSingleIntention(getHint("unknown"));
+ assertNotNull(singleIntention);
+ myFixture.launchAction(singleIntention);
+ myFixture.checkResultByFile(controllerName + ".java", controllerName + "_after.java", true);
+ }
+
+ @Override
+ protected String getHint(String tagName) {
+ return "Create Field '" + tagName + "'";
+ }
+
+ @NotNull
+ @Override
+ protected String getTestDataPath() {
+ return PluginPathManager.getPluginHomePath("javaFX") + "/testData/inspections/unresolvedFxId/";
+ }
+}
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCoercingTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCoercingTest.java
new file mode 100644
index 000000000000..48ffb35544dd
--- /dev/null
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCoercingTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml;
+
+import com.intellij.codeInsight.daemon.impl.analysis.XmlPathReferenceInspection;
+import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
+import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection;
+import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
+import com.intellij.openapi.application.PluginPathManager;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author anna
+ * @since 10.01.2013
+ */
+public class JavaFxCoercingTest extends AbstractJavaFXTestCase {
+
+ public void testReferencedTag() throws Exception {
+ doTest();
+ }
+
+ public void testInvalidInteger() throws Exception {
+ doTest();
+ }
+
+ public void testInvalidDouble() throws Exception {
+ doTest();
+ }
+
+ public void testRootTagSubtagsCoercing() throws Exception {
+ doTest();
+ }
+
+ private void doTest() throws Exception {
+ myFixture.testHighlighting(false, false, false, getTestName(true) + ".fxml");
+ }
+
+ @Override
+ protected void enableInspections() {
+ myFixture.enableInspections(new XmlPathReferenceInspection(),
+ new RequiredAttributesInspection(),
+ new UnusedSymbolLocalInspection(),
+ new UnusedDeclarationInspection());
+ }
+
+ @NotNull
+ @Override
+ protected String getTestDataPath() {
+ return PluginPathManager.getPluginHomePath("javaFX") + "/testData/coercing/";
+ }
+}
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java
index 296b93dd2ee7..fc96388464da 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java
@@ -15,22 +15,22 @@
*/
package org.jetbrains.plugins.javaFX.fxml;
-import com.intellij.codeInsight.completion.CompletionTestCase;
+import com.intellij.codeInsight.completion.LightFixtureCompletionTestCase;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.application.PluginPathManager;
-import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
/**
* User: anna
* Date: 1/17/13
*/
-public class JavaFxCompletionTest extends CompletionTestCase {
+public class JavaFxCompletionTest extends LightFixtureCompletionTestCase {
+ @NotNull
@Override
- protected void setUpModule() {
- super.setUpModule();
- PsiTestUtil.addLibrary(getModule(), "javafx", PluginPathManager.getPluginHomePath("javaFX") + "/testData", "jfxrt.jar");
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return AbstractJavaFXTestCase.JAVA_FX_DESCRIPTOR;
}
public void testAvailablePositions() throws Exception {
@@ -109,6 +109,86 @@ public class JavaFxCompletionTest extends CompletionTestCase {
doTest("stylesheets");
}
+ public void testNamedColors() throws Exception {
+ doTest("blue");
+ }
+
+ public void testRootTagNameLayout() throws Exception {
+ doTest("GridPane");
+ }
+
+ public void testChildrenInsideGridPaneRoot() throws Exception {
+ doTest("children");
+ }
+
+ public void testClassInsideObjectProperty() throws Exception {
+ doTest("Insets");
+ }
+
+ public void testPrimitiveProperties() throws Exception {
+ doTest("top");
+ }
+
+ public void testPrimitiveSubtags() throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ complete();
+ assertDoesntContain(myFixture.getLookupElementStrings(), "geomBoundsInvalid");
+ }
+
+ public void testDefaultPropertyWrappedField() throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ complete();
+ assertContainsElements(myFixture.getLookupElementStrings(), "image", "Image");
+ }
+
+ public void testInfinity() throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ complete();
+ assertContainsElements(myFixture.getLookupElementStrings(), "Infinity", "-Infinity", "NaN", "-NaN");
+ }
+
+ public void testNoInfinity() throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ complete();
+ assertDoesntContain(myFixture.getLookupElementStrings(), "Infinity");
+ }
+
+ public void testBooleanValues() throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ complete();
+ assertContainsElements(myFixture.getLookupElementStrings(), "true", "false");
+ }
+
+ public void testDefaultPropertyIncludeOnce() throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ myItems = myFixture.completeBasic();
+ assertContainsElements(myFixture.getLookupElementStrings(), "fx:reference");
+ assertEquals(5, myItems.length);
+ }
+
+ public void testAcceptableSourceOnly() throws Exception {
+ myFixture.configureByFiles(getTestName(true) + ".fxml");
+ myItems = myFixture.completeBasic();
+ assertEmpty(myItems);
+ }
+
+ public void testIncludedRootAttributes() throws Exception {
+ myFixture.addFileToProject("foo.fxml", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<?import javafx.scene.layout.*?>\n" +
+ "<VBox xmlns:fx=\"http://javafx.com/fxml\"/>");
+ doTest("layoutY");
+ }
+
+ public void testIncludedRootRootAttributes() throws Exception {
+ myFixture.addFileToProject("sample.fxml", "?import javafx.scene.layout.GridPane?>\n" +
+ "<fx:root type=\"javafx.scene.layout.GridPane\" xmlns:fx=\"http://javafx.com/fxml\" />");
+ doTest("blendMode");
+ }
+
+ public void testAllowPropertyTypeClass() throws Exception {
+ doTest("ColumnConstraints");
+ }
+
public void testReadOnly() throws Exception {
configureByFile(getTestName(true) + ".fxml");
assertTrue(myItems.length > 0);
@@ -135,7 +215,7 @@ public class JavaFxCompletionTest extends CompletionTestCase {
private void doTest(final String selection, String additionalPath) throws Exception {
final String mainFxml = getTestName(true) + ".fxml";
if (additionalPath != null) {
- configureByFiles(null, mainFxml, additionalPath);
+ myFixture.configureByFiles(mainFxml, additionalPath);
complete();
} else {
configureByFile(mainFxml);
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/packaging/JavaFxAntTaskTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/packaging/JavaFxAntTaskTest.java
new file mode 100644
index 000000000000..c70899c98bdd
--- /dev/null
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/packaging/JavaFxAntTaskTest.java
@@ -0,0 +1,283 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.testFramework.UsefulTestCase;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * User: anna
+ * Date: 3/28/13
+ */
+public class JavaFxAntTaskTest extends UsefulTestCase{
+
+ private static final String PRELOADER_CLASS = "preloaderClass";
+ private static final String TITLE = "title";
+ private static final String PRELOADER_JAR = "preloaderJar";
+
+ public void testJarDeployNoInfo() throws Exception {
+ doTest("<fx:application id=\"jarDeployNoInfo_id\" name=\"jarDeployNoInfo\" mainClass=\"Main\">\n" +
+ "</fx:application>\n" +
+ "<fx:jar destfile=\"temp\\jarDeployNoInfo.jar\">\n" +
+ "<fx:application refid=\"jarDeployNoInfo_id\">\n" +
+ "</fx:application>\n" +
+ "<fileset dir=\"temp\" excludes=\"*.jar\">\n" +
+ "</fileset>\n" +
+ "<fx:resources>\n" +
+ "</fx:resources>\n" +
+ "</fx:jar>\n" +
+ "<fx:deploy width=\"800\" height=\"400\" updatemode=\"background\" outdir=\"temp\\deploy\" outfile=\"jarDeployNoInfo\">\n" +
+ "<fx:application refid=\"jarDeployNoInfo_id\">\n" +
+ "</fx:application>\n" +
+ "<fx:resources>\n" +
+ "</fx:resources>\n" +
+ "</fx:deploy>\n", Collections.<String, String>emptyMap());
+ }
+
+ public void testJarDeployTitle() throws Exception {
+ doTest("<fx:application id=\"jarDeployTitle_id\" name=\"jarDeployTitle\" mainClass=\"Main\">\n" +
+ "</fx:application>\n" +
+ "<fx:jar destfile=\"temp/jarDeployTitle.jar\">\n" +
+ "<fx:application refid=\"jarDeployTitle_id\">\n" +
+ "</fx:application>\n" +
+ "<fileset dir=\"temp\" excludes=\"*.jar\">\n" +
+ "</fileset>\n" +
+ "<fx:resources>\n" +
+ "</fx:resources>\n" +
+ "</fx:jar>\n" +
+ "<fx:deploy width=\"800\" height=\"400\" updatemode=\"background\" outdir=\"temp/deploy\" outfile=\"jarDeployTitle\">\n" +
+ "<fx:application refid=\"jarDeployTitle_id\">\n" +
+ "</fx:application>\n" +
+ "<fx:info title=\"My App\">\n" +
+ "</fx:info>\n" +
+ "<fx:resources>\n" +
+ "</fx:resources>\n" +
+ "</fx:deploy>\n", Collections.singletonMap(TITLE, "My App"));
+ }
+
+ public void testJarDeployPreloader() throws Exception {
+ final HashMap<String, String> options = new HashMap<String, String>();
+ options.put(PRELOADER_CLASS, "MyPreloader");
+ options.put(PRELOADER_JAR, "preloader.jar");
+ doTest("<fx:fileset id=\"jarDeployPreloader_preloader_files\" requiredFor=\"preloader\" dir=\"temp\" includes=\"preloader.jar\">\n" +
+ "</fx:fileset>\n" +
+ "<fx:application id=\"jarDeployPreloader_id\" name=\"jarDeployPreloader\" mainClass=\"Main\" preloaderClass=\"MyPreloader\">\n" +
+ "</fx:application>\n" +
+ "<fx:jar destfile=\"temp\\jarDeployPreloader.jar\">\n" +
+ "<fx:application refid=\"jarDeployPreloader_id\">\n" +
+ "</fx:application>\n" +
+ "<fileset dir=\"temp\" excludes=\"*.jar\">\n" +
+ "</fileset>\n" +
+ "<fx:resources>\n" +
+ "<fx:fileset refid=\"jarDeployPreloader_preloader_files\">\n" +
+ "</fx:fileset>\n" +
+ "</fx:resources>\n" +
+ "</fx:jar>\n" +
+ "<fx:deploy width=\"800\" height=\"400\" updatemode=\"background\" outdir=\"temp\\deploy\" outfile=\"jarDeployPreloader\">\n" +
+ "<fx:application refid=\"jarDeployPreloader_id\">\n" +
+ "</fx:application>\n" +
+ "<fx:resources>\n" +
+ "<fx:fileset refid=\"jarDeployPreloader_preloader_files\">\n" +
+ "</fx:fileset>\n" +
+ "</fx:resources>\n" +
+ "</fx:deploy>\n", options);
+ }
+
+ private void doTest(final String expected, Map<String, String> options) {
+ final String artifactName = getTestName(true);
+ final String artifactFileName = artifactName + ".jar";
+ final MockJavaFxPackager packager = new MockJavaFxPackager(artifactName + File.separator + artifactFileName);
+
+ final String title = options.get(TITLE);
+ if (title != null) {
+ packager.setTitle(title);
+ }
+
+ final String preloaderClass = options.get(PRELOADER_CLASS);
+ if (preloaderClass != null) {
+ packager.setPreloaderClass(preloaderClass);
+ }
+
+ final String preloaderJar = options.get(PRELOADER_JAR);
+ if (preloaderJar != null) {
+ packager.setPreloaderJar(preloaderJar);
+ }
+
+ final List<JavaFxAntGenerator.SimpleTag> temp = JavaFxAntGenerator
+ .createJarAndDeployTasks(packager, artifactFileName, artifactName, "temp");
+ final StringBuilder buf = new StringBuilder();
+ for (JavaFxAntGenerator.SimpleTag tag : temp) {
+ tag.generate(buf);
+ }
+ assertEquals(expected
+ .replaceAll("temp/deploy", "temp\\" + File.separator + "deploy")
+ .replaceAll("temp/" + artifactFileName, "temp\\" + File.separator + artifactFileName),
+ buf.toString());
+ }
+
+ private static class MockJavaFxPackager extends AbstractJavaFxPackager {
+
+ private String myOutputPath;
+ private String myTitle;
+ private String myVendor;
+ private String myDescription;
+ private String myHtmlParams;
+ private String myParams;
+ private String myPreloaderClass;
+ private String myPreloaderJar;
+
+ private MockJavaFxPackager(String outputPath) {
+ myOutputPath = outputPath;
+ }
+
+ private void setTitle(String title) {
+ myTitle = title;
+ }
+
+ private void setVendor(String vendor) {
+ myVendor = vendor;
+ }
+
+ private void setDescription(String description) {
+ myDescription = description;
+ }
+
+ private void setHtmlParams(String htmlParams) {
+ myHtmlParams = htmlParams;
+ }
+
+ private void setParams(String params) {
+ myParams = params;
+ }
+
+ private void setPreloaderClass(String preloaderClass) {
+ myPreloaderClass = preloaderClass;
+ }
+
+ private void setPreloaderJar(String preloaderJar) {
+ myPreloaderJar = preloaderJar;
+ }
+
+ @Override
+ protected String getArtifactOutputPath() {
+ return new File(myOutputPath).getParent();
+ }
+
+ @Override
+ protected String getArtifactOutputFilePath() {
+ return myOutputPath;
+ }
+
+ @Override
+ protected String getAppClass() {
+ return "Main";
+ }
+
+ @Override
+ protected String getTitle() {
+ return myTitle;
+ }
+
+ @Override
+ protected String getVendor() {
+ return myVendor;
+ }
+
+ @Override
+ protected String getDescription() {
+ return myDescription;
+ }
+
+ @Override
+ protected String getWidth() {
+ return "800";
+ }
+
+ @Override
+ protected String getHeight() {
+ return "400";
+ }
+
+ @Override
+ protected String getHtmlParamFile() {
+ return myHtmlParams;
+ }
+
+ @Override
+ protected String getParamFile() {
+ return myParams;
+ }
+
+ @Override
+ protected String getUpdateMode() {
+ return JavaFxPackagerConstants.UPDATE_MODE_BACKGROUND;
+ }
+
+ @Override
+ protected void registerJavaFxPackagerError(String message) {
+ }
+
+ @Override
+ protected String prepareParam(String param) {
+ return param;
+ }
+
+ @Override
+ public String getKeypass() {
+ return null;
+ }
+
+ @Override
+ public String getStorepass() {
+ return null;
+ }
+
+ @Override
+ public String getKeystore() {
+ return null;
+ }
+
+ @Override
+ public String getAlias() {
+ return null;
+ }
+
+ @Override
+ public boolean isSelfSigning() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabledSigning() {
+ return false;
+ }
+
+ @Override
+ public String getPreloaderClass() {
+ return myPreloaderClass;
+ }
+
+ @Override
+ public String getPreloaderJar() {
+ return myPreloaderJar;
+ }
+ }
+}
diff --git a/plugins/javaFX/javaFX-jps-plugin/javaFX-jps-plugin.iml b/plugins/javaFX/javaFX-jps-plugin/javaFX-jps-plugin.iml
new file mode 100644
index 000000000000..67e665a727a8
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/javaFX-jps-plugin.iml
@@ -0,0 +1,17 @@
+<?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="jps-builders" />
+ <orderEntry type="module" module-name="jps-model-api" />
+ <orderEntry type="module" module-name="jps-model-serialization" />
+ <orderEntry type="module" module-name="common-javaFX-plugin" />
+ <orderEntry type="module" module-name="jps-model-impl" />
+ </component>
+</module>
+
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/META-INF/services/org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider b/plugins/javaFX/javaFX-jps-plugin/src/META-INF/services/org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider
new file mode 100644
index 000000000000..82018bd5a3f0
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/META-INF/services/org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider
@@ -0,0 +1 @@
+org.jetbrains.plugins.javaFX.JpsJavaFxArtifactBuildTaskProvider \ No newline at end of file
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension b/plugins/javaFX/javaFX-jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
new file mode 100644
index 000000000000..3677d6ce9d0e
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
@@ -0,0 +1,2 @@
+org.jetbrains.plugins.javaFX.JpsJavaFxModelSerializerExtension
+org.jetbrains.plugins.javaFX.preloader.JpsJavaFxPreloaderModelSerializerExtension \ No newline at end of file
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxApplicationArtifactType.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxApplicationArtifactType.java
new file mode 100644
index 000000000000..3d1df6e092f2
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxApplicationArtifactType.java
@@ -0,0 +1,11 @@
+package org.jetbrains.plugins.javaFX;
+
+import org.jetbrains.jps.model.artifact.JpsArtifactType;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxApplicationArtifactType extends JpsArtifactType<JpsJavaFxArtifactProperties> {
+ public static final JpsJavaFxApplicationArtifactType INSTANCE = new JpsJavaFxApplicationArtifactType();
+}
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactBuildTaskProvider.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactBuildTaskProvider.java
new file mode 100644
index 000000000000..f26dcac10632
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactBuildTaskProvider.java
@@ -0,0 +1,229 @@
+package org.jetbrains.plugins.javaFX;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider;
+import org.jetbrains.jps.incremental.BuildTask;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.ExternalProcessUtil;
+import org.jetbrains.jps.incremental.ProjectBuildException;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.model.JpsElement;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.elements.JpsArchivePackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
+import org.jetbrains.plugins.javaFX.packaging.AbstractJavaFxPackager;
+import org.jetbrains.plugins.javaFX.preloader.JpsJavaFxPreloaderArtifactProperties;
+import org.jetbrains.plugins.javaFX.preloader.JpsJavaFxPreloaderArtifactType;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxArtifactBuildTaskProvider extends ArtifactBuildTaskProvider {
+
+ public static final String COMPILER_NAME = "Java FX Packager";
+
+ @NotNull
+ @Override
+ public List<? extends BuildTask> createArtifactBuildTasks(@NotNull JpsArtifact artifact,
+ @NotNull ArtifactBuildPhase buildPhase) {
+ if (buildPhase != ArtifactBuildPhase.POST_PROCESSING) {
+ return Collections.emptyList();
+ }
+
+ if (!(artifact.getArtifactType() instanceof JpsJavaFxApplicationArtifactType)) {
+ return Collections.emptyList();
+ }
+ final JpsElement props = artifact.getProperties();
+
+ if (!(props instanceof JpsJavaFxArtifactProperties)) {
+ return Collections.emptyList();
+ }
+
+ return Collections.singletonList(new JavaFxJarDeployTask((JpsJavaFxArtifactProperties)props, artifact));
+ }
+
+ private static class JavaFxJarDeployTask extends BuildTask {
+
+ private final JpsJavaFxArtifactProperties myProps;
+ private final JpsArtifact myArtifact;
+
+ public JavaFxJarDeployTask(JpsJavaFxArtifactProperties props, JpsArtifact artifact) {
+ myProps = props;
+ myArtifact = artifact;
+ }
+
+ @Override
+ public void build(CompileContext context) throws ProjectBuildException {
+ final Set<JpsSdk<?>> sdks = context.getProjectDescriptor().getProjectJavaSdks();
+ JpsSdk javaSdk = null;
+ for (JpsSdk<?> sdk : sdks) {
+ final JpsSdkType<? extends JpsElement> sdkType = sdk.getSdkType();
+ if (sdkType instanceof JpsJavaSdkType) {
+ javaSdk = sdk;
+ break;
+ }
+ }
+ if (javaSdk == null) {
+ context.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, "Java version 7 or higher is required to build JavaFX package"));
+ return;
+ }
+ new JpsJavaFxPackager(myProps, context, myArtifact).buildJavaFxArtifact(javaSdk.getHomePath());
+ }
+ }
+
+ private static class JpsJavaFxPackager extends AbstractJavaFxPackager {
+ private final JpsJavaFxArtifactProperties myProperties;
+ private final CompileContext myCompileContext;
+ private final JpsArtifact myArtifact;
+
+ public JpsJavaFxPackager(JpsJavaFxArtifactProperties properties, CompileContext compileContext, JpsArtifact artifact) {
+ myArtifact = artifact;
+ myProperties = properties;
+ myCompileContext = compileContext;
+ }
+
+ @Override
+ protected String getArtifactOutputPath() {
+ return myArtifact.getOutputPath();
+ }
+
+ @Override
+ protected String getArtifactOutputFilePath() {
+ for (JpsPackagingElement element : myArtifact.getRootElement().getChildren()) {
+ if (element instanceof JpsArchivePackagingElement) {
+ return myArtifact.getOutputFilePath() + File.separator + ((JpsArchivePackagingElement)element).getArchiveName();
+ }
+ }
+ return myArtifact.getOutputFilePath();
+ }
+
+ @Override
+ protected String getAppClass() {
+ return myProperties.myState.getAppClass();
+ }
+
+ @Override
+ protected String getTitle() {
+ return myProperties.myState.getTitle();
+ }
+
+ @Override
+ protected String getVendor() {
+ return myProperties.myState.getVendor();
+ }
+
+ @Override
+ protected String getDescription() {
+ return myProperties.myState.getDescription();
+ }
+
+ @Override
+ protected String getWidth() {
+ return myProperties.myState.getWidth();
+ }
+
+ @Override
+ protected String getHeight() {
+ return myProperties.myState.getHeight();
+ }
+
+ @Override
+ protected void registerJavaFxPackagerError(String message) {
+ myCompileContext.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, message));
+ }
+
+ @Override
+ protected String prepareParam(String param) {
+ return ExternalProcessUtil.prepareCommand(param);
+ }
+
+ @Override
+ protected String getHtmlParamFile() {
+ return myProperties.myState.getHtmlParamFile();
+ }
+
+ @Override
+ protected String getParamFile() {
+ return myProperties.myState.getParamFile();
+ }
+
+ @Override
+ protected String getUpdateMode() {
+ return myProperties.myState.getUpdateMode();
+ }
+
+ @Override
+ public String getKeypass() {
+ return myProperties.myState.getKeypass();
+ }
+
+ @Override
+ public String getStorepass() {
+ return myProperties.myState.getStorepass();
+ }
+
+ @Override
+ public String getKeystore() {
+ return myProperties.myState.getKeystore();
+ }
+
+ @Override
+ public String getAlias() {
+ return myProperties.myState.getAlias();
+ }
+
+ @Override
+ public boolean isSelfSigning() {
+ return myProperties.myState.isSelfSigning();
+ }
+
+ @Override
+ public boolean isEnabledSigning() {
+ return myProperties.myState.isEnabledSigning();
+ }
+
+ @Override
+ public String getPreloaderClass() {
+ final JpsArtifact artifact = getPreloaderArtifact();
+ if (artifact != null) {
+ final JpsJavaFxPreloaderArtifactProperties artifactProperties = (JpsJavaFxPreloaderArtifactProperties)artifact.getProperties();
+ return artifactProperties.getPreloaderClass();
+ }
+ return null;
+ }
+
+ @Override
+ public String getPreloaderJar() {
+ final JpsArtifact artifact = getPreloaderArtifact();
+ if (artifact != null) {
+ return ((JpsArchivePackagingElement)artifact.getRootElement()).getArchiveName();
+ }
+ return null;
+ }
+
+ private JpsArtifact getPreloaderArtifact() {
+ for (JpsPackagingElement element : myArtifact.getRootElement().getChildren()) {
+ if (element instanceof JpsArtifactOutputPackagingElement) {
+ final JpsArtifact artifact = ((JpsArtifactOutputPackagingElement)element).getArtifactReference().resolve();
+ if (artifact != null && artifact.getArtifactType() instanceof JpsJavaFxPreloaderArtifactType) {
+ return artifact;
+ }
+ }
+ }
+ return null;
+ }
+ }
+}
+
+
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactProperties.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactProperties.java
new file mode 100644
index 000000000000..fcb5ae582383
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactProperties.java
@@ -0,0 +1,187 @@
+package org.jetbrains.plugins.javaFX;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.plugins.javaFX.packaging.JavaFxPackagerConstants;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxArtifactProperties extends JpsElementBase<JpsJavaFxArtifactProperties> {
+ protected MyState myState = new MyState();
+
+ public JpsJavaFxArtifactProperties() {
+ }
+
+ public JpsJavaFxArtifactProperties(MyState state) {
+ copyState(state);
+ }
+
+ private void copyState(MyState state) {
+ myState.setAppClass(state.myAppClass);
+ myState.setTitle(state.myTitle);
+ myState.setVendor(state.myVendor);
+ myState.setDescription(state.myDescription);
+ myState.setWidth(state.myWidth);
+ myState.setHeight(state.myHeight);
+ myState.setHtmlParamFile(state.myHtmlParamFile);
+ myState.setParamFile(state.myParamFile);
+ myState.setUpdateMode(state.myUpdateMode);
+ myState.setEnabledSigning(state.myEnabledSigning);
+ myState.setSelfSigning(state.mySelfSigning);
+ myState.setKeystore(state.myKeystore);
+ myState.setKeypass(state.myKeypass);
+ myState.setStorepass(state.myStorepass);
+ myState.setAlias(state.myAlias);
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaFxArtifactProperties createCopy() {
+ return new JpsJavaFxArtifactProperties(myState);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsJavaFxArtifactProperties modified) {
+ copyState(modified.myState);
+ }
+
+ public static class MyState {
+ private String myTitle;
+ private String myVendor;
+ private String myDescription;
+ private String myAppClass;
+ private String myWidth = JavaFxPackagerConstants.DEFAULT_WEIGHT;
+ private String myHeight = JavaFxPackagerConstants.DEFAULT_HEIGHT;
+ private String myHtmlParamFile;
+ private String myParamFile;
+ private String myUpdateMode = JavaFxPackagerConstants.UPDATE_MODE_BACKGROUND;
+ private boolean myEnabledSigning = false;
+ private boolean mySelfSigning = true;
+ private String myAlias;
+ private String myKeystore;
+ private String myStorepass;
+ private String myKeypass;
+
+ public String getTitle() {
+ return myTitle;
+ }
+
+ public void setTitle(String title) {
+ myTitle = title;
+ }
+
+ public String getVendor() {
+ return myVendor;
+ }
+
+ public void setVendor(String vendor) {
+ myVendor = vendor;
+ }
+
+ public String getDescription() {
+ return myDescription;
+ }
+
+ public void setDescription(String description) {
+ myDescription = description;
+ }
+
+ public String getAppClass() {
+ return myAppClass;
+ }
+
+ public void setAppClass(String appClass) {
+ myAppClass = appClass;
+ }
+
+ public String getWidth() {
+ return myWidth;
+ }
+
+ public String getHeight() {
+ return myHeight;
+ }
+
+ public void setWidth(String width) {
+ myWidth = width;
+ }
+
+ public void setHeight(String height) {
+ myHeight = height;
+ }
+
+ public String getHtmlParamFile() {
+ return myHtmlParamFile;
+ }
+
+ public String getParamFile() {
+ return myParamFile;
+ }
+
+ public void setHtmlParamFile(String htmlParamFile) {
+ myHtmlParamFile = htmlParamFile;
+ }
+
+ public void setParamFile(String paramFile) {
+ myParamFile = paramFile;
+ }
+
+ public String getUpdateMode() {
+ return myUpdateMode;
+ }
+
+ public void setUpdateMode(String updateMode) {
+ myUpdateMode = updateMode;
+ }
+
+ public boolean isEnabledSigning() {
+ return myEnabledSigning;
+ }
+
+ public void setEnabledSigning(boolean enabledSigning) {
+ myEnabledSigning = enabledSigning;
+ }
+
+ public boolean isSelfSigning() {
+ return mySelfSigning;
+ }
+
+ public void setSelfSigning(boolean selfSigning) {
+ mySelfSigning = selfSigning;
+ }
+
+ public String getAlias() {
+ return myAlias;
+ }
+
+ public void setAlias(String alias) {
+ myAlias = alias;
+ }
+
+ public String getKeystore() {
+ return myKeystore;
+ }
+
+ public void setKeystore(String keystore) {
+ myKeystore = keystore;
+ }
+
+ public String getStorepass() {
+ return myStorepass;
+ }
+
+ public void setStorepass(String storepass) {
+ myStorepass = storepass;
+ }
+
+ public String getKeypass() {
+ return myKeypass;
+ }
+
+ public void setKeypass(String keypass) {
+ myKeypass = keypass;
+ }
+ }
+}
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactPropertiesSerializer.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactPropertiesSerializer.java
new file mode 100644
index 000000000000..b2a392568953
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxArtifactPropertiesSerializer.java
@@ -0,0 +1,62 @@
+package org.jetbrains.plugins.javaFX;
+
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.jps.model.serialization.artifact.ArtifactPropertiesState;
+import org.jetbrains.jps.model.serialization.artifact.JpsArtifactPropertiesSerializer;
+
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxArtifactPropertiesSerializer extends JpsArtifactPropertiesSerializer<JpsJavaFxArtifactProperties> {
+ public JpsJavaFxArtifactPropertiesSerializer() {
+ super("javafx", JpsJavaFxApplicationArtifactType.INSTANCE);
+ }
+
+ @Override
+ public JpsJavaFxArtifactProperties loadProperties(List<ArtifactPropertiesState> stateList) {
+ final JpsJavaFxArtifactProperties.MyState properties = doLoadProperties(stateList);
+ return properties != null ? new JpsJavaFxArtifactProperties(properties) : new JpsJavaFxArtifactProperties();
+ }
+
+ private static JpsJavaFxArtifactProperties.MyState doLoadProperties(List<ArtifactPropertiesState> stateList) {
+ final ArtifactPropertiesState state = findApplicationProperties(stateList);
+
+ if (state == null) {
+ return null;
+ }
+ final Element options = state.getOptions();
+
+ if (options == null) {
+ return null;
+ }
+ return XmlSerializer.deserialize(options, JpsJavaFxArtifactProperties.MyState.class);
+ }
+
+ @Override
+ public void saveProperties(JpsJavaFxArtifactProperties properties, List<ArtifactPropertiesState> stateList) {
+ final ArtifactPropertiesState state = findApplicationProperties(stateList);
+
+ if (state == null) {
+ return;
+ }
+ final Element element = XmlSerializer.serialize(properties);
+
+ if (element == null) {
+ return;
+ }
+ state.setOptions(element);
+ }
+
+ private static ArtifactPropertiesState findApplicationProperties(List<ArtifactPropertiesState> stateList) {
+ for (ArtifactPropertiesState state : stateList) {
+ if ("javafx-properties".equals(state.getId())) {
+ return state;
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxModelSerializerExtension.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxModelSerializerExtension.java
new file mode 100644
index 000000000000..6998e32a9b38
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/JpsJavaFxModelSerializerExtension.java
@@ -0,0 +1,18 @@
+package org.jetbrains.plugins.javaFX;
+
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+import org.jetbrains.jps.model.serialization.artifact.JpsArtifactPropertiesSerializer;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxModelSerializerExtension extends JpsModelSerializerExtension {
+ @Override
+ public List<? extends JpsArtifactPropertiesSerializer<?>> getArtifactTypePropertiesSerializers() {
+ return Collections.singletonList(new JpsJavaFxArtifactPropertiesSerializer());
+ }
+}
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactProperties.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactProperties.java
new file mode 100644
index 000000000000..94176241b502
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactProperties.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.preloader;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxPreloaderArtifactProperties extends JpsElementBase<JpsJavaFxPreloaderArtifactProperties> {
+ protected MyState myState = new MyState();
+
+ public JpsJavaFxPreloaderArtifactProperties() {
+ }
+
+ public JpsJavaFxPreloaderArtifactProperties(MyState state) {
+ copyState(state);
+ }
+
+ private void copyState(MyState state) {
+ myState.setPreloaderClass(state.myPreloaderClass);
+ }
+
+ @NotNull
+ @Override
+ public JpsJavaFxPreloaderArtifactProperties createCopy() {
+ return new JpsJavaFxPreloaderArtifactProperties(myState);
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsJavaFxPreloaderArtifactProperties modified) {
+ copyState(modified.myState);
+ }
+
+ public String getPreloaderClass() {
+ return myState.getPreloaderClass();
+ }
+
+ public static class MyState {
+ private String myPreloaderClass;
+
+ public String getPreloaderClass() {
+ return myPreloaderClass;
+ }
+
+ public void setPreloaderClass(String preloaderClass) {
+ myPreloaderClass = preloaderClass;
+ }
+ }
+}
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactPropertiesSerializer.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactPropertiesSerializer.java
new file mode 100644
index 000000000000..4e99fe1287dc
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactPropertiesSerializer.java
@@ -0,0 +1,77 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.preloader;
+
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.jps.model.serialization.artifact.ArtifactPropertiesState;
+import org.jetbrains.jps.model.serialization.artifact.JpsArtifactPropertiesSerializer;
+
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxPreloaderArtifactPropertiesSerializer extends JpsArtifactPropertiesSerializer<JpsJavaFxPreloaderArtifactProperties> {
+ public JpsJavaFxPreloaderArtifactPropertiesSerializer() {
+ super("javafx-preloader", JpsJavaFxPreloaderArtifactType.INSTANCE);
+ }
+
+ @Override
+ public JpsJavaFxPreloaderArtifactProperties loadProperties(List<ArtifactPropertiesState> stateList) {
+ final JpsJavaFxPreloaderArtifactProperties.MyState properties = doLoadProperties(stateList);
+ return properties != null ? new JpsJavaFxPreloaderArtifactProperties(properties) : new JpsJavaFxPreloaderArtifactProperties();
+ }
+
+ private static JpsJavaFxPreloaderArtifactProperties.MyState doLoadProperties(List<ArtifactPropertiesState> stateList) {
+ final ArtifactPropertiesState state = findApplicationProperties(stateList);
+
+ if (state == null) {
+ return null;
+ }
+ final Element options = state.getOptions();
+
+ if (options == null) {
+ return null;
+ }
+ return XmlSerializer.deserialize(options, JpsJavaFxPreloaderArtifactProperties.MyState.class);
+ }
+
+ @Override
+ public void saveProperties(JpsJavaFxPreloaderArtifactProperties properties, List<ArtifactPropertiesState> stateList) {
+ final ArtifactPropertiesState state = findApplicationProperties(stateList);
+
+ if (state == null) {
+ return;
+ }
+ final Element element = XmlSerializer.serialize(properties);
+
+ if (element == null) {
+ return;
+ }
+ state.setOptions(element);
+ }
+
+ private static ArtifactPropertiesState findApplicationProperties(List<ArtifactPropertiesState> stateList) {
+ for (ArtifactPropertiesState state : stateList) {
+ if ("javafx-preloader-properties".equals(state.getId())) {
+ return state;
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactType.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactType.java
new file mode 100644
index 000000000000..ab0440dc9195
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderArtifactType.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.preloader;
+
+import org.jetbrains.jps.model.artifact.JpsArtifactType;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxPreloaderArtifactType extends JpsArtifactType<JpsJavaFxPreloaderArtifactProperties> {
+ public static final JpsJavaFxPreloaderArtifactType INSTANCE = new JpsJavaFxPreloaderArtifactType();
+}
diff --git a/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderModelSerializerExtension.java b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderModelSerializerExtension.java
new file mode 100644
index 000000000000..94da690d3473
--- /dev/null
+++ b/plugins/javaFX/javaFX-jps-plugin/src/org/jetbrains/plugins/javaFX/preloader/JpsJavaFxPreloaderModelSerializerExtension.java
@@ -0,0 +1,33 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.preloader;
+
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+import org.jetbrains.jps.model.serialization.artifact.JpsArtifactPropertiesSerializer;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 3/13/13
+ */
+public class JpsJavaFxPreloaderModelSerializerExtension extends JpsModelSerializerExtension {
+ @Override
+ public List<? extends JpsArtifactPropertiesSerializer<?>> getArtifactTypePropertiesSerializers() {
+ return Collections.singletonList(new JpsJavaFxPreloaderArtifactPropertiesSerializer());
+ }
+}
diff --git a/plugins/javaFX/javaFX.iml b/plugins/javaFX/javaFX.iml
index 2a8f125eb754..b56fab016ed8 100644
--- a/plugins/javaFX/javaFX.iml
+++ b/plugins/javaFX/javaFX.iml
@@ -18,6 +18,9 @@
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="java-indexing-api" />
<orderEntry type="module" module-name="openapi" />
+ <orderEntry type="module" module-name="compiler-openapi" />
+ <orderEntry type="module" module-name="compiler-impl" />
+ <orderEntry type="module" module-name="common-javaFX-plugin" />
</component>
</module>
diff --git a/plugins/javaFX/resources/inspectionDescriptions/JavaFxUnresolvedFxIdReference.html b/plugins/javaFX/resources/inspectionDescriptions/JavaFxUnresolvedFxIdReference.html
new file mode 100644
index 000000000000..8dd4bc8c403d
--- /dev/null
+++ b/plugins/javaFX/resources/inspectionDescriptions/JavaFxUnresolvedFxIdReference.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+This inspection reports unresolved fx:id references. Quickfix to create corresponding field is provided.
+</body>
+</html>
diff --git a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
index 82c06995b4fe..ce37e7bf9534 100644
--- a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
+++ b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
@@ -13,13 +13,16 @@
<multiHostInjector implementation="org.jetbrains.plugins.javaFX.fxml.ScriptLanguageInjector"/>
<annotator language="XML" implementationClass="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxAnnotator"/>
<codeInsight.lineMarkerProvider language="JAVA" implementationClass="org.jetbrains.plugins.javaFX.fxml.codeInsight.JavaFxRelatedItemLineMarkerProvider"/>
- <useScopeEnlarger implementation="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxScopeEnlager"/>
+ <useScopeEnlarger implementation="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxScopeEnlarger"/>
<localInspection language="XML" shortName="JavaFxDefaultTag" displayName="Unnecessary default tag" groupName="JavaFX"
enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections.JavaFxDefaultTagInspection"/>
+ <localInspection language="XML" implementationClass="org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections.JavaFxUnresolvedFxIdReferenceInspection" displayName="Unresolved fx:id attribute reference"
+ enabledByDefault="true" level="WARNING" groupName="JavaFX"/>
<applicationService serviceInterface="org.jetbrains.plugins.javaFX.JavaFxSettings" serviceImplementation="org.jetbrains.plugins.javaFX.JavaFxSettings"/>
<applicationConfigurable instance="org.jetbrains.plugins.javaFX.JavaFxSettingsConfigurable"/>
<fileBasedIndex implementation="org.jetbrains.plugins.javaFX.JavaFxControllerClassIndex"/>
+ <fileBasedIndex implementation="org.jetbrains.plugins.javaFX.JavaFxIdsIndex"/>
<intentionAction>
<className>org.jetbrains.plugins.javaFX.fxml.codeInsight.intentions.JavaFxCollapseSubTagToAttributeIntention</className>
<category>JavaFX</category>
@@ -30,11 +33,21 @@
</intentionAction>
<lang.importOptimizer language="XML" implementationClass="org.jetbrains.plugins.javaFX.fxml.codeInsight.JavaFxImportsOptimizer" order="before XML"/>
<psi.referenceContributor implementation="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxReferencesContributor"/>
+ <getterSetterProvider implementation="org.jetbrains.plugins.javaFX.codeInsight.JavaFxGetterSetterPrototypeProvider"/>
+ <packaging.artifactPropertiesProvider implementation="org.jetbrains.plugins.javaFX.packaging.JavaFxArtifactPropertiesProvider"/>
+ <packaging.artifactType implementation="org.jetbrains.plugins.javaFX.packaging.JavaFxApplicationArtifactType"/>
+ <compileServer.plugin classpath="javaFX-jps-plugin.jar;common-javaFX-plugin.jar"/>
+ <antBuildGen implementation="org.jetbrains.plugins.javaFX.packaging.ant.JavaFxChunkBuildExtension"/>
+ <packaging.artifactType implementation="org.jetbrains.plugins.javaFX.packaging.preloader.JavaFxPreloaderArtifactType"/>
+ <packaging.artifactPropertiesProvider implementation="org.jetbrains.plugins.javaFX.packaging.preloader.JavaFxPreloaderArtifactPropertiesProvider"/>
+ <implicitUsageProvider implementation="org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections.JavaFxImplicitUsageProvider"/>
+ <referencesSearch implementation="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxControllerFieldSearcher"/>
</extensions>
<actions>
<action class="org.jetbrains.plugins.javaFX.actions.OpenInSceneBuilderAction" id="OpenInSceneBuilder" text="Open In SceneBuilder">
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
+ <add-to-group group-id="ProjectViewPopupMenu" anchor="last"/>
</action>
</actions>
</idea-plugin>
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataExternalizer.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataExternalizer.java
new file mode 100644
index 000000000000..2de1bc61d599
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataExternalizer.java
@@ -0,0 +1,50 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX;
+
+import com.intellij.util.io.DataExternalizer;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+* User: anna
+* Date: 3/14/13
+*/
+public class FxmlDataExternalizer implements DataExternalizer<Set<String>> {
+ @Override
+ public void save(DataOutput out, Set<String> value) throws IOException {
+ out.writeInt(value.size());
+ for (String s : value) {
+ out.writeUTF(s);
+ }
+ }
+
+ @Override
+ public Set<String> read(DataInput in) throws IOException {
+ final int size = in.readInt();
+ final Set<String> result = new HashSet<String>(size);
+
+ for (int i = 0; i < size; i++) {
+ final String s = in.readUTF();
+ result.add(s);
+ }
+ return result;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataIndexer.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataIndexer.java
new file mode 100644
index 000000000000..bd5dfe863f24
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/FxmlDataIndexer.java
@@ -0,0 +1,92 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX;
+
+import com.intellij.util.indexing.DataIndexer;
+import com.intellij.util.indexing.FileContent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
+import org.jetbrains.plugins.javaFX.fxml.JavaFXNamespaceProvider;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.StringReader;
+import java.util.*;
+
+/**
+* User: anna
+* Date: 3/14/13
+*/
+public class FxmlDataIndexer implements DataIndexer<String, Set<String>, FileContent> {
+ private static final SAXParser SAX_PARSER = createParser();
+
+ private static SAXParser createParser() {
+ try {
+ return SAXParserFactory.newInstance().newSAXParser();
+ }
+ catch (Exception e) {
+ return null;
+ }
+ }
+
+ @Override
+ @NotNull
+ public Map<String, Set<String>> map(final FileContent inputData) {
+ final Map<String, Set<String>> map = getIds(inputData.getContentAsText().toString(), inputData.getFile().getPath());
+ if (map != null) {
+ return map;
+ }
+ return Collections.emptyMap();
+ }
+
+ @Nullable
+ protected Map<String, Set<String>> getIds(String content, final String path) {
+ if (!content.contains(JavaFXNamespaceProvider.JAVAFX_NAMESPACE)) {
+ return null;
+ }
+
+ final Map<String, Set<String>> map = new HashMap<String, Set<String>>();
+ try {
+ SAX_PARSER.parse(new InputSource(new StringReader(content)), createParseHandler(path, map));
+ }
+ catch (Exception e) {
+ // Do nothing.
+ }
+
+ return map;
+ }
+
+ protected DefaultHandler createParseHandler(final String path, final Map<String, Set<String>> map) {
+ return new DefaultHandler() {
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ final String attributesValue = attributes.getValue(FxmlConstants.FX_ID);
+ if (attributesValue != null) {
+ Set<String> paths = map.get(attributesValue);
+ if (paths == null) {
+ paths = new HashSet<String>();
+ map.put(attributesValue, paths);
+ }
+ paths.add(path);
+ }
+ }
+ };
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java
index 6d9d01562b08..f1d5cac979d0 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxControllerClassIndex.java
@@ -115,6 +115,11 @@ public class JavaFxControllerClassIndex extends ScalarIndexExtension<String> {
SAX_PARSER.parse(new InputSource(new StringReader(content)), new DefaultHandler() {
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
className[0] = attributes.getValue("", FxmlConstants.FX_CONTROLLER);
+ if (className[0] == null) {
+ if (FxmlConstants.FX_ROOT.equals(qName)) {
+ className[0] = attributes.getValue("", FxmlConstants.TYPE);
+ }
+ }
throw new SAXException("controllers are accepted on top level only");
}
});
@@ -127,14 +132,14 @@ public class JavaFxControllerClassIndex extends ScalarIndexExtension<String> {
}
}
- private static class MyInputFilter implements FileBasedIndex.InputFilter {
+ static class MyInputFilter implements FileBasedIndex.InputFilter {
@Override
public boolean acceptInput(final VirtualFile file) {
return JavaFxFileTypeFactory.isFxml(file);
}
}
- public static List<PsiFile> findFxmlWithController(final Project project, String className) {
+ public static List<PsiFile> findFxmlWithController(final Project project, @NotNull String className) {
return findFxmlWithController(project, className, new Function<VirtualFile, PsiFile>() {
@Override
public PsiFile fun(VirtualFile file) {
@@ -148,7 +153,7 @@ public class JavaFxControllerClassIndex extends ScalarIndexExtension<String> {
}
public static <T> List<T> findFxmlWithController(final Project project,
- final String className,
+ @NotNull final String className,
final Function<VirtualFile, T> f,
final GlobalSearchScope scope) {
return ApplicationManager.getApplication().runReadAction(new Computable<List<T>>() {
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxIdsIndex.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxIdsIndex.java
new file mode 100644
index 000000000000..ce51e924b6a6
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxIdsIndex.java
@@ -0,0 +1,88 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.CommonProcessors;
+import com.intellij.util.indexing.*;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+public class JavaFxIdsIndex extends FileBasedIndexExtension<String, Set<String>> {
+
+ @NonNls public static final ID<String, Set<String>> KEY = ID.create("javafx.id.name");
+
+ private final KeyDescriptor<String> myKeyDescriptor = new EnumeratorStringDescriptor();
+ private final FileBasedIndex.InputFilter myInputFilter = new JavaFxControllerClassIndex.MyInputFilter();
+ private final FxmlDataIndexer myDataIndexer = new FxmlDataIndexer();
+ private final FxmlDataExternalizer myDataExternalizer = new FxmlDataExternalizer();
+
+ @NotNull
+ @Override
+ public DataIndexer<String, Set<String>, FileContent> getIndexer() {
+ return myDataIndexer;
+ }
+
+ @Override
+ public DataExternalizer<Set<String>> getValueExternalizer() {
+ return myDataExternalizer;
+ }
+
+ @Override
+ public FileBasedIndex.InputFilter getInputFilter() {
+ return myInputFilter;
+ }
+
+ @NotNull
+ @Override
+ public ID<String, Set<String>> getName() {
+ return KEY;
+ }
+
+ @Override
+ public KeyDescriptor<String> getKeyDescriptor() {
+ return myKeyDescriptor;
+ }
+
+ @Override
+ public boolean dependsOnFileContent() {
+ return true;
+ }
+
+ @Override
+ public int getVersion() {
+ return 0;
+ }
+
+ @NotNull
+ public static Collection<String> getAllRegisteredIds(Project project) {
+ CommonProcessors.CollectUniquesProcessor<String> processor = new CommonProcessors.CollectUniquesProcessor<String>();
+ FileBasedIndex.getInstance().processAllKeys(KEY, processor, project);
+ return processor.getResults();
+ }
+
+ @NotNull
+ public static Collection<String> getFilePaths(Project project, String id) {
+ final List<Set<String>> values = FileBasedIndex.getInstance().getValues(KEY, id, GlobalSearchScope.projectScope(project));
+ return (Collection<String>)(values.isEmpty() ? Collections.emptySet() : values.get(0));
+ }
+} \ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxSettingsConfigurable.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxSettingsConfigurable.java
index 8ad083de7820..8a83fee0f8e4 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxSettingsConfigurable.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxSettingsConfigurable.java
@@ -95,7 +95,7 @@ public class JavaFxSettingsConfigurable implements SearchableConfigurable, Confi
}
public static FileChooserDescriptor createSceneBuilderDescriptor() {
- final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor();
+ final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileOrExecutableAppDescriptor();
descriptor.setTitle("SceneBuilder Configuration");
descriptor.setDescription("Select path to SceneBuilder executable");
return descriptor;
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java
index c342891ae51b..f809cc9402e9 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java
@@ -18,27 +18,42 @@ package org.jetbrains.plugins.javaFX.actions;
import com.intellij.CommonBundle;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.configurations.JavaParameters;
+import com.intellij.execution.configurations.PathEnvironmentVariableUtil;
+import com.intellij.execution.process.OSProcessHandler;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.JavaFxSettings;
import org.jetbrains.plugins.javaFX.JavaFxSettingsConfigurable;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* User: anna
* Date: 2/14/13
*/
public class OpenInSceneBuilderAction extends AnAction {
private static final Logger LOG = Logger.getInstance("#" + OpenInSceneBuilderAction.class.getName());
+ public static final String ORACLE = "Oracle";
@Override
public void actionPerformed(AnActionEvent e) {
@@ -49,15 +64,75 @@ public class OpenInSceneBuilderAction extends AnAction {
final JavaFxSettings settings = JavaFxSettings.getInstance();
String pathToSceneBuilder = settings.getPathToSceneBuilder();
if (StringUtil.isEmptyOrSpaces(settings.getPathToSceneBuilder())){
- final VirtualFile sceneBuilderFile = FileChooser.chooseFile(JavaFxSettingsConfigurable.createSceneBuilderDescriptor(), e.getProject(), null);
+ final VirtualFile sceneBuilderFile = FileChooser.chooseFile(JavaFxSettingsConfigurable.createSceneBuilderDescriptor(), e.getProject(), getPredefinedPath());
if (sceneBuilderFile == null) return;
pathToSceneBuilder = sceneBuilderFile.getPath();
settings.setPathToSceneBuilder(FileUtil.toSystemIndependentName(pathToSceneBuilder));
}
+ final Project project = getEventProject(e);
+ if (project != null && !Registry.is("scene.builder.start.executable", true)) {
+ final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project);
+ if (module != null) {
+ try {
+ final JavaParameters javaParameters = new JavaParameters();
+ javaParameters.configureByModule(module, JavaParameters.JDK_AND_CLASSES);
+
+ final File sceneBuilderLibsFile;
+ if (SystemInfo.isMac) {
+ sceneBuilderLibsFile = new File(new File(pathToSceneBuilder, "Contents"), "Java");
+ } else if (SystemInfo.isWindows) {
+ File sceneBuilderRoot = new File(pathToSceneBuilder);
+ File sceneBuilderRootDir = sceneBuilderRoot.getParentFile();
+ if (sceneBuilderRootDir == null) {
+ final File foundInPath = PathEnvironmentVariableUtil.findInPath(pathToSceneBuilder);
+ if (foundInPath != null) {
+ sceneBuilderRootDir = foundInPath.getParentFile();
+ }
+ }
+ sceneBuilderRoot = sceneBuilderRootDir != null ? sceneBuilderRootDir.getParentFile() : null;
+ if (sceneBuilderRoot != null) {
+ final File libFile = new File(sceneBuilderRoot, "lib");
+ if (libFile.isDirectory()) {
+ sceneBuilderLibsFile = libFile;
+ }
+ else {
+ final File appFile = new File(sceneBuilderRootDir, "app");
+ sceneBuilderLibsFile = appFile.isDirectory() ? appFile : null;
+ }
+ }
+ else {
+ sceneBuilderLibsFile = null;
+ }
+ } else {
+ sceneBuilderLibsFile = new File(new File(pathToSceneBuilder).getParent(), "app");
+ }
+ if (sceneBuilderLibsFile != null) {
+ final File[] sceneBuilderLibs = sceneBuilderLibsFile.listFiles();
+ if (sceneBuilderLibs != null) {
+ for (File jarFile : sceneBuilderLibs) {
+ javaParameters.getClassPath().add(jarFile.getPath());
+ }
+ javaParameters.setMainClass("com.oracle.javafx.authoring.Main");
+ javaParameters.getProgramParametersList().add(path);
+
+ final OSProcessHandler processHandler = javaParameters.createOSProcessHandler();
+ final String commandLine = processHandler.getCommandLine();
+ LOG.info("scene builder command line: " + commandLine);
+ processHandler.startNotify();
+ return;
+ }
+ }
+ }
+ catch (Throwable ex) {
+ LOG.info(ex);
+ }
+ }
+ }
+
if (SystemInfo.isMac) {
- pathToSceneBuilder += "/Contents/MacOS/JavaAppLauncher";
+ pathToSceneBuilder += "/Contents/MacOS/scenebuilder-launcher.sh";
}
final GeneralCommandLine commandLine = new GeneralCommandLine();
@@ -84,4 +159,57 @@ public class OpenInSceneBuilderAction extends AnAction {
presentation.setVisible(true);
}
}
+
+ @Nullable
+ private static VirtualFile getPredefinedPath() {
+ String path = null;
+ if (SystemInfo.isWindows) {
+ String programFilesPath = null;
+ final String property = System.getProperty("java.home");
+ if (property != null) {
+ final File jdkDir = new File(property).getParentFile();
+ if (jdkDir != null) {
+ final File javaDir = jdkDir.getParentFile();
+ if (javaDir != null) {
+ final File programFilesDir = javaDir.getParentFile();
+ if (programFilesDir != null) {
+ programFilesPath = programFilesDir.getPath();
+ }
+ }
+ }
+ }
+
+ final String sb11 = File.separator + "JavaFX Scene Builder 1.1" + File.separator + "JavaFX Scene Builder 1.1.exe";
+ final String sb10 = File.separator + "JavaFX Scene Builder 1.0" + File.separator + "JavaFX Scene Builder 1.0.exe";
+ final List<String> suspiciousPaths = new ArrayList<String>();
+ if (programFilesPath != null && new File(programFilesPath, ORACLE).isDirectory()) {
+ fillPaths(programFilesPath, sb11, sb10, suspiciousPaths);
+ } else {
+ final String programFiles = "C:\\Program Files";
+ fillPaths(programFiles, sb11, sb10, suspiciousPaths);
+ fillPaths(programFiles + " (x86)", sb11, sb10, suspiciousPaths);
+ }
+ final File sb = FileUtil.findFirstThatExist(ArrayUtil.toStringArray(suspiciousPaths));
+ if (sb != null) {
+ path = sb.getPath();
+ }
+ }
+ else if (SystemInfo.isMac) {
+ final File sb = FileUtil.findFirstThatExist("/Applications/JavaFX Scene Builder 1.1.app",
+ "/Applications/JavaFX Scene Builder 1.0.app");
+ if (sb != null) {
+ path = sb.getPath();
+ }
+ }
+ else if (SystemInfo.isUnix) {
+ path = "/opt/JavaFXSceneBuilder1.1/JavaFXSceneBuilder1.1";
+ }
+
+ return path != null ? LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(path)) : null;
+ }
+
+ private static void fillPaths(String programFilesPath, String sb11, String sb10, List<String> suspiciousPaths) {
+ suspiciousPaths.add(new File(programFilesPath, ORACLE).getPath() + sb11);
+ suspiciousPaths.add(new File(programFilesPath, ORACLE).getPath() + sb10);
+ }
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/codeInsight/JavaFxGetterSetterPrototypeProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/codeInsight/JavaFxGetterSetterPrototypeProvider.java
new file mode 100644
index 000000000000..2c3ae170919d
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/codeInsight/JavaFxGetterSetterPrototypeProvider.java
@@ -0,0 +1,88 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.codeInsight;
+
+import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import com.intellij.psi.codeStyle.VariableKind;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PropertyUtil;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
+
+/**
+ * User: anna
+ * Date: 3/4/13
+ */
+public class JavaFxGetterSetterPrototypeProvider extends GetterSetterPrototypeProvider {
+ private static final Logger LOG = Logger.getInstance("#" + JavaFxGetterSetterPrototypeProvider.class.getName());
+
+ @Override
+ public boolean canGeneratePrototypeFor(PsiField field) {
+ return InheritanceUtil.isInheritor(field.getType(), JavaFxCommonClassNames.JAVAFX_BEANS_VALUE_OBSERVABLE_VALUE);
+ }
+
+ @Override
+ public PsiMethod[] generateGetters(PsiField field) {
+ final Project project = field.getProject();
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
+ final PsiMethod getter = PropertyUtil.generateGetterPrototype(field);
+
+ final PsiType wrappedType = JavaFxPsiUtil.getWrappedPropertyType(field, project, JavaFxCommonClassNames.ourReadOnlyMap);
+
+ final PsiTypeElement returnTypeElement = getter.getReturnTypeElement();
+ LOG.assertTrue(returnTypeElement != null);
+ returnTypeElement.replace(factory.createTypeElement(wrappedType));
+
+ final PsiCodeBlock getterBody = getter.getBody();
+ LOG.assertTrue(getterBody != null);
+ getterBody.getStatements()[0].replace(factory.createStatementFromText("return " + field.getName() + ".get();", field));
+
+ final PsiMethod propertyGetter = PropertyUtil.generateGetterPrototype(field);
+ propertyGetter.setName(JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD) + "Property");
+ return new PsiMethod[] {getter, propertyGetter};
+ }
+
+ @Override
+ public PsiMethod[] generateSetters(PsiField field) {
+ final PsiMethod setter = PropertyUtil.generateSetterPrototype(field);
+ final Project project = field.getProject();
+
+ final PsiType wrappedType = JavaFxPsiUtil.getWrappedPropertyType(field, project, JavaFxCommonClassNames.ourWritableMap);
+
+ final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
+ final PsiTypeElement newTypeElement = elementFactory.createTypeElement(wrappedType);
+ final PsiParameter[] parameters = setter.getParameterList().getParameters();
+ LOG.assertTrue(parameters.length == 1);
+ final PsiParameter parameter = parameters[0];
+ final PsiTypeElement typeElement = parameter.getTypeElement();
+ LOG.assertTrue(typeElement != null);
+ typeElement.replace(newTypeElement);
+ final PsiCodeBlock body = setter.getBody();
+ LOG.assertTrue(body != null);
+ body.getStatements()[0].replace(elementFactory.createStatementFromText("this." + field.getName() + ".set(" + parameter.getName() + ");", field));
+
+ return new PsiMethod[] {setter};
+ }
+
+ @Override
+ public boolean isReadOnly(PsiField field) {
+ return !InheritanceUtil.isInheritor(field.getType(), JavaFxCommonClassNames.JAVAFX_BEANS_VALUE_WRITABLE_VALUE);
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java
index a901380717ee..429cfc978ad8 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java
@@ -41,19 +41,22 @@ public class FxmlConstants {
@NonNls public static final String FX_INCLUDE = "fx:include";
@NonNls public static final String FX_ROOT = "fx:root";
@NonNls public static final String TYPE = "type";
-
+ @NonNls public static final String RESOURCES = "resources";
+ @NonNls public static final String CHARSET = "charset";
+
@NonNls public static final String STYLE_CLASS = "styleClass";
@NonNls public static final String STYLESHEETS = "stylesheets";
public static final List<String> FX_DEFAULT_PROPERTIES = Arrays.asList(FX_ID, FX_CONTROLLER, VALUE, FX_VALUE, FX_FACTORY, FX_CONSTANT);
- public static final List<String> FX_DEFAULT_ELEMENTS = Arrays.asList(FX_INCLUDE, FX_REFERENCE, FX_COPY, FX_DEFINE, FX_SCRIPT);
+ public static final List<String> FX_DEFAULT_ELEMENTS = Arrays.asList(FX_INCLUDE, FX_REFERENCE, FX_COPY, FX_DEFINE, FX_SCRIPT, FX_ROOT);
public static final String FX_ELEMENT_SOURCE = "source";
public static final Map<String, List<String>> FX_ELEMENT_ATTRIBUTES = new HashMap<String, List<String>>();
static {
- FX_ELEMENT_ATTRIBUTES.put(FX_INCLUDE, Arrays.asList(FX_ELEMENT_SOURCE, FX_ID));
+ FX_ELEMENT_ATTRIBUTES.put(FX_INCLUDE, Arrays.asList(FX_ELEMENT_SOURCE, FX_ID, RESOURCES, CHARSET));
FX_ELEMENT_ATTRIBUTES.put(FX_REFERENCE, Arrays.asList(FX_ELEMENT_SOURCE));
+ FX_ELEMENT_ATTRIBUTES.put(FX_COPY, Arrays.asList(FX_ELEMENT_SOURCE));
FX_ELEMENT_ATTRIBUTES.put(FX_SCRIPT, Arrays.asList(FX_ELEMENT_SOURCE));
FX_ELEMENT_ATTRIBUTES.put(FX_ROOT, Arrays.asList(TYPE));
}
@@ -63,6 +66,7 @@ public class FxmlConstants {
static {
FX_REQUIRED_ELEMENT_ATTRIBUTES.put(FX_INCLUDE, Arrays.asList(FX_ELEMENT_SOURCE));
FX_REQUIRED_ELEMENT_ATTRIBUTES.put(FX_REFERENCE, Arrays.asList(FX_ELEMENT_SOURCE));
+ FX_REQUIRED_ELEMENT_ATTRIBUTES.put(FX_COPY, Arrays.asList(FX_ELEMENT_SOURCE));
FX_REQUIRED_ELEMENT_ATTRIBUTES.put(FX_ROOT, Arrays.asList(TYPE));
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
index 7044f922600d..28c99b0ff067 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
@@ -1,11 +1,17 @@
package org.jetbrains.plugins.javaFX.fxml;
import com.intellij.codeInsight.daemon.Validator;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.Processor;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlNSDescriptor;
import org.jetbrains.annotations.NotNull;
@@ -13,6 +19,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassBackedElementDescriptor;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxDefaultPropertyElementDescriptor;
+import java.util.ArrayList;
+
/**
* User: anna
* Date: 1/9/13
@@ -41,7 +49,21 @@ public class JavaFXNSDescriptor implements XmlNSDescriptor, Validator<XmlDocumen
@NotNull
@Override
public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable XmlDocument document) {
- //todo
+ if (document != null) {
+ final Project project = document.getProject();
+ final PsiClass paneClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_SCENE_LAYOUT_PANE, GlobalSearchScope.allScope(project));
+ if (paneClass != null) {
+ final ArrayList<XmlElementDescriptor> result = new ArrayList<XmlElementDescriptor>();
+ ClassInheritorsSearch.search(paneClass).forEach(new Processor<PsiClass>() {
+ @Override
+ public boolean process(PsiClass psiClass) {
+ result.add(new JavaFxClassBackedElementDescriptor(psiClass.getName(), psiClass));
+ return true;
+ }
+ });
+ return result.toArray(new XmlElementDescriptor[result.size()]);
+ }
+ }
return new XmlElementDescriptor[0];
}
@@ -80,7 +102,5 @@ public class JavaFXNSDescriptor implements XmlNSDescriptor, Validator<XmlDocumen
}
@Override
- public void validate(@NotNull XmlDocument context, @NotNull ValidationHost host) {
- //todo check that node has correct type
- }
+ public void validate(@NotNull XmlDocument context, @NotNull ValidationHost host) {}
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java
index 73e2d9af1850..b6fea16ad785 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java
@@ -15,8 +15,12 @@
*/
package org.jetbrains.plugins.javaFX.fxml;
+import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NonNls;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* User: anna
* Date: 1/16/13
@@ -31,8 +35,32 @@ public class JavaFxCommonClassNames {
@NonNls public static final String JAVAFX_EVENT_EVENT_HANDLER = "javafx.event.EventHandler";
@NonNls public static final String JAVAFX_SCENE_NODE = "javafx.scene.Node";
@NonNls public static final String JAVAFX_SCENE_PAINT = "javafx.scene.paint.Paint";
+ @NonNls public static final String JAVAFX_SCENE_COLOR = "javafx.scene.paint.Color";
@NonNls public static final String JAVAFX_FXML_BUILDER = "javafx.util.Builder";
@NonNls public static final String JAVAFX_BEANS_OBSERVABLE = "javafx.beans.Observable";
@NonNls public static final String VALUE_OF = "valueOf";
@NonNls public static final String JAVAFX_FXML_FXMLLOADER = "javafx.fxml.FXMLLoader";
+ @NonNls public static final String JAVAFX_BEANS_VALUE_OBSERVABLE_VALUE = "javafx.beans.value.ObservableValue";
+ @NonNls public static final String JAVAFX_BEANS_VALUE_WRITABLE_VALUE = "javafx.beans.value.WritableValue";
+ @NonNls public static final String JAVAFX_SCENE_LAYOUT_PANE = "javafx.scene.layout.Pane";
+
+ public static final Map<String, PsiType> ourWritableMap = new HashMap<String, PsiType>();
+ static {
+ ourWritableMap.put("javafx.beans.value.WritableBooleanValue", PsiType.BOOLEAN);
+ ourWritableMap.put("javafx.beans.value.WritableIntegerValue", PsiType.INT);
+ ourWritableMap.put("javafx.beans.value.WritableFloatValue", PsiType.FLOAT);
+ ourWritableMap.put("javafx.beans.value.WritableLongValue", PsiType.LONG);
+ ourWritableMap.put("javafx.beans.value.WritableDoubleValue", PsiType.DOUBLE);
+ }
+
+ public static final Map<String, PsiType> ourReadOnlyMap = new HashMap<String, PsiType>();
+ static {
+ ourReadOnlyMap.put("javafx.beans.property.ReadOnlyBooleanProperty", PsiType.BOOLEAN);
+ ourReadOnlyMap.put("javafx.beans.property.ReadOnlyIntegerProperty", PsiType.INT);
+ ourReadOnlyMap.put("javafx.beans.property.ReadOnlyFloatProperty", PsiType.FLOAT);
+ ourReadOnlyMap.put("javafx.beans.property.ReadOnlyLongProperty", PsiType.LONG);
+ ourReadOnlyMap.put("javafx.beans.property.ReadOnlyDoubleProperty", PsiType.DOUBLE);
+ }
+
+ @NonNls public static final String JAVA_FX_PARENT = "javafx.scene.Parent";
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java
index c381600a8a7b..e551345cfad1 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java
@@ -16,12 +16,14 @@
package org.jetbrains.plugins.javaFX.fxml;
import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil;
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.lang.ASTNode;
import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
@@ -34,17 +36,19 @@ import com.intellij.util.Processor;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassBackedElementDescriptor;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxDefaultPropertyElementDescriptor;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyElementDescriptor;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
/**
* User: anna
*/
public class JavaFxPsiUtil {
+ private static final Logger LOG = Logger.getInstance("#" + JavaFxPsiUtil.class.getName());
+
public static XmlProcessingInstruction createSingleImportInstruction(String qualifiedName, Project project) {
final String importText = "<?import " + qualifiedName + "?>";
final PsiElement child =
@@ -141,6 +145,10 @@ public class JavaFxPsiUtil {
}
public static PsiClassType getPropertyClassType(PsiElement field) {
+ return getPropertyClassType(field, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY_OBJECT_PROPERTY);
+ }
+
+ public static PsiClassType getPropertyClassType(PsiElement field, final String superTypeFQN) {
if (field instanceof PsiField) {
final PsiType type = ((PsiField)field).getType();
if (type instanceof PsiClassType) {
@@ -148,7 +156,7 @@ public class JavaFxPsiUtil {
final PsiClass attributeClass = resolveResult.getElement();
if (attributeClass != null) {
final PsiClass objectProperty = JavaPsiFacade.getInstance(attributeClass.getProject())
- .findClass(JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY_OBJECT_PROPERTY, attributeClass.getResolveScope());
+ .findClass(superTypeFQN, attributeClass.getResolveScope());
if (objectProperty != null) {
final PsiSubstitutor superClassSubstitutor = TypeConversionUtil
.getClassSubstitutor(objectProperty, attributeClass, resolveResult.getSubstitutor());
@@ -205,25 +213,46 @@ public class JavaFxPsiUtil {
}
private static final Key<CachedValue<PsiClass>> INJECTED_CONTROLLER = Key.create("javafx.injected.controller");
+ private static final RecursionGuard ourGuard = RecursionManager.createGuard("javafx.controller");
public static PsiClass getControllerClass(final PsiFile containingFile) {
if (containingFile instanceof XmlFile) {
final XmlTag rootTag = ((XmlFile)containingFile).getRootTag();
final Project project = containingFile.getProject();
if (rootTag != null) {
XmlAttribute attribute = rootTag.getAttribute(FxmlConstants.FX_CONTROLLER);
- if (attribute == null && FxmlConstants.FX_ROOT.equals(rootTag.getName())) {
- attribute = rootTag.getAttribute(FxmlConstants.TYPE);
- }
if (attribute != null) {
- final String attributeValue = attribute.getValue();
- if (!StringUtil.isEmptyOrSpaces(attributeValue)) {
- return JavaPsiFacade.getInstance(project).findClass(attributeValue, containingFile.getResolveScope());
+ final PsiClass controllerClass = findControllerClass(containingFile, project, attribute);
+ if (controllerClass != null) {
+ return controllerClass;
}
}
}
- CachedValuesManager manager = CachedValuesManager.getManager(containingFile.getProject());
- return manager.getCachedValue(containingFile, INJECTED_CONTROLLER,
- new JavaFxControllerCachedValueProvider(containingFile.getProject(), containingFile), true);
+ final CachedValuesManager manager = CachedValuesManager.getManager(containingFile.getProject());
+ final PsiClass injectedControllerClass = ourGuard.doPreventingRecursion(containingFile, true, new Computable<PsiClass>() {
+ @Override
+ public PsiClass compute() {
+ return manager.getCachedValue(containingFile, INJECTED_CONTROLLER,
+ new JavaFxControllerCachedValueProvider(containingFile.getProject(), containingFile), true);
+ }
+ });
+ if (injectedControllerClass != null) {
+ return injectedControllerClass;
+ }
+
+ if (rootTag != null && FxmlConstants.FX_ROOT.equals(rootTag.getName())) {
+ final XmlAttribute rootTypeAttr = rootTag.getAttribute(FxmlConstants.TYPE);
+ if (rootTypeAttr != null) {
+ return findControllerClass(containingFile, project, rootTypeAttr);
+ }
+ }
+ }
+ return null;
+ }
+
+ private static PsiClass findControllerClass(PsiFile containingFile, Project project, XmlAttribute attribute) {
+ final String attributeValue = attribute.getValue();
+ if (!StringUtil.isEmptyOrSpaces(attributeValue)) {
+ return JavaPsiFacade.getInstance(project).findClass(attributeValue, containingFile.getResolveScope());
}
return null;
}
@@ -299,20 +328,7 @@ public class JavaFxPsiUtil {
final PsiClass psiClass = (PsiClass)declaration;
final PsiField psiField = psiClass.findFieldByName(attributeName, true);
if (psiField != null) {
- if (findPropertySetter(attributeName, (PsiClass)declaration) == null &&
- findPropertySetter(attributeName, tag) == null &&
- !InheritanceUtil.isInheritor(psiField.getType(), "javafx.collections.ObservableList")) {
- //todo read only condition?
- final PsiMethod[] constructors = psiClass.getConstructors();
- for (PsiMethod constructor : constructors) {
- for (PsiParameter parameter : constructor.getParameterList().getParameters()) {
- if (psiField.getType().equals(parameter.getType())) {
- return false;
- }
- }
- }
- return true;
- }
+ return isReadOnly(psiClass, psiField);
}
}
}
@@ -320,6 +336,24 @@ public class JavaFxPsiUtil {
}
+ public static boolean isReadOnly(PsiClass psiClass, PsiField psiField) {
+ final String name = psiField.getName();
+ if (findPropertySetter(name, psiClass) == null &&
+ !InheritanceUtil.isInheritor(psiField.getType(), "javafx.collections.ObservableList")) {
+ //todo read only condition?
+ final PsiMethod[] constructors = psiClass.getConstructors();
+ for (PsiMethod constructor : constructors) {
+ for (PsiParameter parameter : constructor.getParameterList().getParameters()) {
+ if (psiField.getType().equals(parameter.getType())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
public static boolean isExpressionBinding(String value) {
if (!value.startsWith("$")) return false;
value = value.substring(1);
@@ -328,13 +362,14 @@ public class JavaFxPsiUtil {
@Nullable
public static PsiType getPropertyType(final PsiType type, final Project project) {
- final PsiClass psiClass = PsiUtil.resolveClassInType(type);
+ final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type);
+ final PsiClass psiClass = resolveResult.getElement();
if (psiClass != null) {
final PsiClass propertyClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY,
GlobalSearchScope.allScope(project));
if (propertyClass != null) {
final PsiSubstitutor substitutor =
- TypeConversionUtil.getClassSubstitutor(propertyClass, psiClass, PsiSubstitutor.EMPTY);
+ TypeConversionUtil.getClassSubstitutor(propertyClass, psiClass, resolveResult.getSubstitutor());
if (substitutor != null) {
return substitutor.substitute(propertyClass.getTypeParameters()[0]);
}
@@ -372,35 +407,145 @@ public class JavaFxPsiUtil {
public static String isAbleToInstantiate(final PsiClass psiClass) {
if(psiClass.getConstructors().length > 0) {
- final Project project = psiClass.getProject();
- final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
- final PsiMethod noArgConstructor = psiClass
- .findMethodBySignature(factory.createConstructor(psiClass.getName()), false);
- if (noArgConstructor == null) {
- final PsiMethod valueOf = findValueOfMethod(psiClass);
- if (valueOf == null) {
- final PsiClass builderClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_FXML_BUILDER,
- GlobalSearchScope.allScope(project));
- if (builderClass != null) {
- //todo cache this info
- final PsiTypeParameter typeParameter = builderClass.getTypeParameters()[0];
+ for (PsiMethod constr : psiClass.getConstructors()) {
+ if (constr.getParameterList().getParametersCount() == 0) return null;
+ }
+ final PsiMethod valueOf = findValueOfMethod(psiClass);
+ if (valueOf == null) {
+ if (!hasBuilder(psiClass)) return "Unable to instantiate";
+ }
+ }
+ return null;
+ }
+
+ public static boolean hasBuilder(@NotNull final PsiClass psiClass) {
+ final Project project = psiClass.getProject();
+ return CachedValuesManager.getManager(project).getCachedValue(psiClass, new CachedValueProvider<Boolean>() {
+ @Nullable
+ @Override
+ public Result<Boolean> compute() {
+ final PsiClass builderClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_FXML_BUILDER,
+ GlobalSearchScope.allScope(project));
+ if (builderClass != null) {
+ final PsiMethod[] buildMethods = builderClass.findMethodsByName("build", false);
+ if (buildMethods.length == 1 && buildMethods[0].getParameterList().getParametersCount() == 0) {
if (ClassInheritorsSearch.search(builderClass).forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass aClass) {
- final PsiType initType =
- TypeConversionUtil.getSuperClassSubstitutor(builderClass, aClass, PsiSubstitutor.EMPTY).substitute(typeParameter);
- return !Comparing.equal(psiClass, PsiUtil.resolveClassInClassTypeOnly(initType));
+ PsiType returnType = null;
+ final PsiMethod method = MethodSignatureUtil.findMethodBySuperMethod(aClass, buildMethods[0], false);
+ if (method != null) {
+ returnType = method.getReturnType();
+ }
+ return !Comparing.equal(psiClass, PsiUtil.resolveClassInClassTypeOnly(returnType));
}
})) {
- return "Unable to instantiate";
+ return Result.create(false, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
}
}
+ return Result.create(true, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
+ }
+ });
+ }
+
+ public static String isClassAcceptable(@Nullable XmlTag parentTag, final PsiClass aClass) {
+ if (parentTag == null) {
+ return null;
+ }
+ if (aClass != null && aClass.isValid()) {
+ XmlElementDescriptor descriptor = parentTag.getDescriptor();
+ if (descriptor instanceof JavaFxDefaultPropertyElementDescriptor) {
+ descriptor = ((JavaFxDefaultPropertyElementDescriptor)descriptor).getRootTagDescriptor(parentTag);
+ }
+
+ if (descriptor instanceof JavaFxPropertyElementDescriptor) {
+ final PsiElement declaration = descriptor.getDeclaration();
+ if (declaration instanceof PsiField) {
+ return canCoerce(aClass, ((PsiField)declaration).getType());
+ }
+ }
+ else if (descriptor instanceof JavaFxClassBackedElementDescriptor) {
+ final PsiElement declaration = descriptor.getDeclaration();
+ if (declaration instanceof PsiClass) {
+ final PsiType type = getDefaultPropertyExpectedType((PsiClass)declaration);
+ if (type != null) {
+ return canCoerce(aClass, type);
+ }
+ }
}
}
return null;
}
+ private static String canCoerce(PsiClass aClass, PsiType type) {
+ PsiType collectionItemType = GenericsHighlightUtil.getCollectionItemType(type, aClass.getResolveScope());
+ if (collectionItemType == null && InheritanceUtil.isInheritor(type, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY)) {
+ collectionItemType = getPropertyType(type, aClass.getProject());
+ }
+ if (collectionItemType != null && PsiPrimitiveType.getUnboxedType(collectionItemType) == null) {
+ final PsiClass baseClass = PsiUtil.resolveClassInType(collectionItemType);
+ if (baseClass != null) {
+ final String qualifiedName = baseClass.getQualifiedName();
+ if (qualifiedName != null && !Comparing.strEqual(qualifiedName, CommonClassNames.JAVA_LANG_STRING)) {
+ if (!InheritanceUtil.isInheritor(aClass, qualifiedName)) {
+ return unableToCoerceMessage(aClass, qualifiedName);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private static String unableToCoerceMessage(PsiClass aClass, String qualifiedName) {
+ return "Unable to coerce " + HighlightUtil.formatClass(aClass)+ " to " + qualifiedName;
+ }
+
+ public static boolean isOutOfHierarchy(final XmlAttributeValue element) {
+ XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
+ while (tag != null) {
+ if (FxmlConstants.FX_DEFINE.equals(tag.getName())) {
+ return true;
+ }
+ tag = tag.getParentTag();
+ }
+ return false;
+ }
+
+ public static PsiType getWrappedPropertyType(PsiField field, final Project project, final Map<String, PsiType> typeMap) {
+ final PsiType fieldType = field.getType();
+ final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(fieldType);
+ final PsiClass fieldClass = resolveResult.getElement();
+ if (fieldClass == null) return fieldType;
+ return CachedValuesManager.getManager(project).getCachedValue(fieldClass, new CachedValueProvider<PsiType>() {
+ @Nullable
+ @Override
+ public Result<PsiType> compute() {
+ PsiType substitute = null;
+ for (String typeName : typeMap.keySet()) {
+ if (InheritanceUtil.isInheritor(fieldType, typeName)) {
+ substitute = typeMap.get(typeName);
+ break;
+ }
+ }
+ if (substitute == null) {
+ if (!InheritanceUtil.isInheritor(fieldType, JavaFxCommonClassNames.JAVAFX_BEANS_VALUE_OBSERVABLE_VALUE)) {
+ return Result.create(fieldType, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
+ }
+ final PsiClass aClass = JavaPsiFacade.getInstance(project)
+ .findClass(JavaFxCommonClassNames.JAVAFX_BEANS_VALUE_OBSERVABLE_VALUE, GlobalSearchScope.allScope(project));
+ LOG.assertTrue(aClass != null);
+ final PsiSubstitutor substitutor =
+ TypeConversionUtil.getSuperClassSubstitutor(aClass, fieldClass, resolveResult.getSubstitutor());
+ final PsiMethod[] values = aClass.findMethodsByName("getValue", false);
+ substitute = substitutor.substitute(values[0].getReturnType());
+ }
+
+ return Result.create(substitute, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
+ }
+ });
+ }
+
private static class JavaFxControllerCachedValueProvider implements CachedValueProvider<PsiClass> {
private final Project myProject;
private final PsiFile myContainingFile;
@@ -426,7 +571,9 @@ public class JavaFxPsiUtil {
return methodCallExpression.resolveMethod() == injectControllerMethods[0];
}
};
- ReferencesSearch.search(myContainingFile).forEach(new Processor<PsiReference>() {
+ final GlobalSearchScope globalSearchScope = GlobalSearchScope
+ .notScope(GlobalSearchScope.getScopeRestrictedByFileTypes(myContainingFile.getResolveScope(), StdFileTypes.XML));
+ ReferencesSearch.search(myContainingFile, globalSearchScope).forEach(new Processor<PsiReference>() {
@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
@@ -436,7 +583,7 @@ public class JavaFxPsiUtil {
final PsiType type = expression.getType();
if (type != null && type.equalsToText(JavaFxCommonClassNames.JAVAFX_FXML_FXMLLOADER)) {
final PsiElement parent = expression.getParent();
- if (parent instanceof PsiVariable) {
+ if (parent instanceof PsiLocalVariable) {
ReferencesSearch.search(parent).forEach(processor);
final PsiClass controller = processor.getInjectedController();
if (controller != null) {
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxImportsOptimizer.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxImportsOptimizer.java
index fcffd00395d0..a88c7762e811 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxImportsOptimizer.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxImportsOptimizer.java
@@ -32,10 +32,13 @@ import com.intellij.psi.impl.source.codeStyle.ImportHelper;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.containers.HashSet;
+import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassBackedElementDescriptor;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyElementDescriptor;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxStaticPropertyAttributeDescriptor;
import java.util.*;
@@ -70,18 +73,19 @@ public class JavaFxImportsOptimizer implements ImportOptimizer {
final List<Pair<String, Boolean>> sortedNames = ImportHelper.sortItemsAccordingToSettings(names, settings);
final HashSet<String> onDemand = new HashSet<String>();
ImportHelper.collectOnDemandImports(sortedNames, onDemand, settings);
- final Set<String> importedOnDemand = new HashSet<String>();
+ final Set<String> imported = new HashSet<String>();
final List<String> imports = new ArrayList<String>();
for (Pair<String, Boolean> pair : sortedNames) {
final String qName = pair.first;
final String packageName = StringUtil.getPackageName(qName);
- if (importedOnDemand.contains(packageName)) {
+ if (imported.contains(packageName) || imported.contains(qName)) {
continue;
}
if (onDemand.contains(packageName)) {
- importedOnDemand.add(packageName);
+ imported.add(packageName);
imports.add("<?import " + packageName + ".*?>");
} else {
+ imported.add(qName);
imports.add("<?import " + qName + "?>");
}
}
@@ -122,21 +126,35 @@ public class JavaFxImportsOptimizer implements ImportOptimizer {
public void visitXmlProcessingInstruction(XmlProcessingInstruction processingInstruction) {}
@Override
- public void visitXmlAttribute(XmlAttribute attribute) {}
+ public void visitXmlAttribute(XmlAttribute attribute) {
+ final XmlAttributeDescriptor descriptor = attribute.getDescriptor();
+ if (descriptor instanceof JavaFxStaticPropertyAttributeDescriptor) {
+ final PsiElement declaration = descriptor.getDeclaration();
+ if (declaration instanceof PsiMember) {
+ appendClassName(((PsiMember)declaration).getContainingClass());
+ }
+ }
+ }
@Override
public void visitXmlTag(XmlTag tag) {
super.visitXmlTag(tag);
final XmlElementDescriptor descriptor = tag.getDescriptor();
if (descriptor instanceof JavaFxClassBackedElementDescriptor) {
+ appendClassName(descriptor.getDeclaration());
+ } else if (descriptor instanceof JavaFxPropertyElementDescriptor && ((JavaFxPropertyElementDescriptor)descriptor).isStatic()) {
final PsiElement declaration = descriptor.getDeclaration();
- if (declaration instanceof PsiClass) {
- names.add(Pair.create(((PsiClass)declaration).getQualifiedName(), false));
+ if (declaration instanceof PsiMember) {
+ appendClassName(((PsiMember)declaration).getContainingClass());
}
}
}
-
+ private void appendClassName(PsiElement declaration) {
+ if (declaration instanceof PsiClass) {
+ names.add(Pair.create(((PsiClass)declaration).getQualifiedName(), false));
+ }
+ }
});
}
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java
index 7ce757f8b0cf..432891d9f4de 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java
@@ -36,6 +36,7 @@ import com.intellij.util.Function;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.JavaFxControllerClassIndex;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
@@ -104,6 +105,7 @@ public class JavaFxRelatedItemLineMarkerProvider extends RelatedItemLineMarkerPr
final XmlAttributeValue attributeValue = (XmlAttributeValue)referenceElement;
final PsiElement parent = attributeValue.getParent();
if (!(parent instanceof XmlAttribute)) return true;
+ if (!FxmlConstants.FX_ID.equals(((XmlAttribute)parent).getName())) return true;
targets.add(fun.fun(parent));
return !stopAtFirst;
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxImplicitUsageProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxImplicitUsageProvider.java
new file mode 100644
index 000000000000..0bcfa1999aa8
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxImplicitUsageProvider.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections;
+
+import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import org.jetbrains.plugins.javaFX.JavaFxControllerClassIndex;
+import org.jetbrains.plugins.javaFX.JavaFxIdsIndex;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 3/22/13
+ */
+public class JavaFxImplicitUsageProvider implements ImplicitUsageProvider {
+
+ @Override
+ public boolean isImplicitUsage(PsiElement element) {
+ return isImplicitWrite(element);
+ }
+
+ @Override
+ public boolean isImplicitRead(PsiElement element) {
+ return false;
+ }
+
+ @Override
+ public boolean isImplicitWrite(PsiElement element) {
+ if (element instanceof PsiField) {
+ final String name = ((PsiField)element).getName();
+ final PsiClass containingClass = ((PsiField)element).getContainingClass();
+ if (containingClass != null) {
+ final String qualifiedName = containingClass.getQualifiedName();
+ if (qualifiedName != null) {
+ final Project project = element.getProject();
+ final List<VirtualFile> fxmls = JavaFxControllerClassIndex.findFxmlsWithController(project, qualifiedName);
+ if (!fxmls.isEmpty()) {
+ final Collection<String> filePaths = JavaFxIdsIndex.getFilePaths(project, name);
+ for (VirtualFile fxml : fxmls) {
+ if (filePaths.contains(fxml.getPath())) return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxUnresolvedFxIdReferenceInspection.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxUnresolvedFxIdReferenceInspection.java
new file mode 100644
index 000000000000..9c9e256f5286
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxUnresolvedFxIdReferenceInspection.java
@@ -0,0 +1,143 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections;
+
+import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.ExpectedTypeInfo;
+import com.intellij.codeInsight.ExpectedTypeInfoImpl;
+import com.intellij.codeInsight.TailType;
+import com.intellij.codeInsight.daemon.QuickFixBundle;
+import com.intellij.codeInsight.daemon.impl.quickfix.CreateFieldFromUsageFix;
+import com.intellij.codeInsight.daemon.impl.quickfix.CreateFieldFromUsageHelper;
+import com.intellij.codeInspection.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.VisibilityUtil;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassBackedElementDescriptor;
+import org.jetbrains.plugins.javaFX.fxml.refs.JavaFxFieldIdReferenceProvider;
+
+/**
+ * User: anna
+ */
+public class JavaFxUnresolvedFxIdReferenceInspection extends XmlSuppressableInspectionTool {
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder,
+ final boolean isOnTheFly,
+ @NotNull LocalInspectionToolSession session) {
+ return new XmlElementVisitor() {
+ @Override
+ public void visitXmlFile(XmlFile file) {
+ if (!JavaFxFileTypeFactory.isFxml(file)) return;
+ super.visitXmlFile(file);
+ }
+
+ @Override
+ public void visitXmlAttribute(XmlAttribute attribute) {
+ if (FxmlConstants.FX_ID.equals(attribute.getName())) {
+ final XmlAttributeValue valueElement = attribute.getValueElement();
+ if (valueElement != null && valueElement.getTextLength() > 0) {
+ final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(attribute.getContainingFile());
+ if (controllerClass != null) {
+ final PsiReference reference = valueElement.getReference();
+ if (reference instanceof JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef && reference.resolve() == null) {
+ final PsiClass fieldClass =
+ checkContext(((JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef)reference).getXmlAttributeValue());
+ if (fieldClass != null) {
+ holder.registerProblem(reference.getElement(), reference.getRangeInElement(), "Unresolved fx:id reference",
+ isOnTheFly ? new LocalQuickFix[]{new CreateFieldFromUsageQuickFix(reference.getCanonicalText())} : LocalQuickFix.EMPTY_ARRAY);
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+
+ protected static PsiClass checkContext(final XmlAttributeValue attributeValue) {
+ if (attributeValue == null) return null;
+ final PsiElement parent = attributeValue.getParent();
+ if (parent instanceof XmlAttribute) {
+ final XmlTag tag = ((XmlAttribute)parent).getParent();
+ if (tag != null) {
+ final XmlElementDescriptor descriptor = tag.getDescriptor();
+ if (descriptor instanceof JavaFxClassBackedElementDescriptor) {
+ final PsiElement declaration = descriptor.getDeclaration();
+ if (declaration instanceof PsiClass) {
+ return (PsiClass)declaration;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private static class CreateFieldFromUsageQuickFix implements LocalQuickFix {
+ private final String myCanonicalName;
+
+ private CreateFieldFromUsageQuickFix(String canonicalName) {
+ myCanonicalName = canonicalName;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return QuickFixBundle.message("create.field.from.usage.text", myCanonicalName);
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return QuickFixBundle.message("create.field.from.usage.family");
+ }
+
+ @Override
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ final PsiElement psiElement = descriptor.getPsiElement();
+ final XmlAttributeValue attrValue = PsiTreeUtil.getParentOfType(psiElement, XmlAttributeValue.class, false);
+ assert attrValue != null;
+
+ final JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef reference =
+ (JavaFxFieldIdReferenceProvider.JavaFxControllerFieldRef)attrValue.getReference();
+ assert reference != null;
+
+ final PsiClass targetClass = reference.getAClass();
+ if (!CodeInsightUtilBase.prepareFileForWrite(targetClass.getContainingFile())) {
+ return;
+ }
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
+ PsiField field = factory.createField(reference.getCanonicalText(), PsiType.INT);
+ VisibilityUtil.setVisibility(field.getModifierList(), PsiModifier.PUBLIC);
+
+ field = CreateFieldFromUsageHelper.insertField(targetClass, field, psiElement);
+
+ final PsiClassType fieldType = factory.createType(checkContext(reference.getXmlAttributeValue()));
+ final ExpectedTypeInfo[] types = {new ExpectedTypeInfoImpl(fieldType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, 0, fieldType, TailType.NONE)};
+ CreateFieldFromUsageFix.createFieldFromUsageTemplate(targetClass, project, types, field, false, psiElement);
+ }
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/UnwrapTagFix.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/UnwrapTagFix.java
index 1723db0a79fd..2e20e6f720c8 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/UnwrapTagFix.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/UnwrapTagFix.java
@@ -17,18 +17,22 @@ package org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlTagChild;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
/**
* User: anna
*/
public class UnwrapTagFix implements LocalQuickFix {
+ private static final Logger LOG = Logger.getInstance("#" + UnwrapTagFix.class.getName());
private final String myTagName;
public UnwrapTagFix(String tagName) {
@@ -51,6 +55,8 @@ public class UnwrapTagFix implements LocalQuickFix {
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (element != null) {
+ final PsiFile containingFile = element.getContainingFile();
+ LOG.assertTrue(containingFile != null && JavaFxFileTypeFactory.isFxml(containingFile), containingFile == null ? "no containing file found" : "containing file: " + containingFile.getName());
final XmlTag xmlTag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
if (xmlTag != null) {
final XmlTag parentTag = xmlTag.getParentTag();
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxCollapseSubTagToAttributeIntention.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxCollapseSubTagToAttributeIntention.java
index 1f772ba4765b..abf7ed5c2c36 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxCollapseSubTagToAttributeIntention.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxCollapseSubTagToAttributeIntention.java
@@ -19,11 +19,17 @@ import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.XmlElementFactory;
-import com.intellij.psi.xml.*;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassBackedElementDescriptor;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyElementDescriptor;
@@ -36,7 +42,23 @@ public class JavaFxCollapseSubTagToAttributeIntention extends PsiElementBaseInte
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
if (!CodeInsightUtilBase.preparePsiElementsForWrite(element)) return;
final XmlTag tag = (XmlTag)element.getParent();
- final XmlAttribute attribute = XmlElementFactory.getInstance(project).createXmlAttribute(tag.getName(), tag.getValue().getText().trim());
+ final String value;
+ if (tag.getSubTags().length == 0) {
+ value = tag.getValue().getText().trim();
+ }
+ else {
+ value = StringUtil.join(tag.getSubTags(), new Function<XmlTag, String>() {
+ @Override
+ public String fun(XmlTag childTag) {
+ final XmlAttribute valueAttr = childTag.getAttribute(FxmlConstants.FX_VALUE);
+ if (valueAttr != null) {
+ return valueAttr.getValue();
+ }
+ return "";
+ }
+ }, ", ");
+ }
+ final XmlAttribute attribute = XmlElementFactory.getInstance(project).createXmlAttribute(tag.getName(), value);
final XmlTag parentTag = tag.getParentTag();
parentTag.add(attribute);
tag.delete();
@@ -46,15 +68,16 @@ public class JavaFxCollapseSubTagToAttributeIntention extends PsiElementBaseInte
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_NAME && element.getParent() instanceof XmlTag) {
final XmlTag tag = (XmlTag)element.getParent();
- if (tag.getSubTags().length == 0) {
- final XmlTag parentTag = tag.getParentTag();
- if (parentTag != null &&
- tag.getDescriptor() instanceof JavaFxPropertyElementDescriptor &&
- parentTag.getDescriptor() instanceof JavaFxClassBackedElementDescriptor) {
-
- setText("Collapse tag '" + tag.getName() + "' to attribute");
- return true;
- }
+ for (XmlTag xmlTag : tag.getSubTags()) {
+ if (xmlTag.getAttribute(FxmlConstants.FX_VALUE) == null) return false;
+ }
+ final XmlTag parentTag = tag.getParentTag();
+ if (parentTag != null &&
+ tag.getDescriptor() instanceof JavaFxPropertyElementDescriptor &&
+ parentTag.getDescriptor() instanceof JavaFxClassBackedElementDescriptor) {
+
+ setText("Collapse tag '" + tag.getName() + "' to attribute");
+ return true;
}
}
return false;
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxWrapWithDefineIntention.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxWrapWithDefineIntention.java
new file mode 100644
index 000000000000..fe2c6821d885
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxWrapWithDefineIntention.java
@@ -0,0 +1,64 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml.codeInsight.intentions;
+
+import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
+
+/**
+ * User: anna
+ * Date: 4/1/13
+ */
+public class JavaFxWrapWithDefineIntention extends PsiElementBaseIntentionAction {
+ private final XmlTag myTag;
+ private final String myId;
+
+ public JavaFxWrapWithDefineIntention(@NotNull XmlTag tag, @NotNull String id) {
+ myTag = tag;
+ myId = id;
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Wrap with fx:define";
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
+ setText("Wrap \"" + myId + "\" with fx:define");
+ return myTag.isValid();
+ }
+
+ @Override
+ public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
+ final XmlTag tagFromText = XmlElementFactory.getInstance(project).createTagFromText("<" + FxmlConstants.FX_DEFINE + "/>");
+ tagFromText.addSubTag(myTag, true);
+ myTag.replace(tagFromText);
+ }
+
+ @Override
+ public boolean startInWriteAction() {
+ return true;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java
index 1c7bf1b57305..582882b74639 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java
@@ -1,17 +1,15 @@
package org.jetbrains.plugins.javaFX.fxml.descriptors;
+import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.Validator;
import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.xml.XmlAttributeImpl;
import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.PropertyUtil;
-import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.*;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
@@ -28,6 +26,7 @@ import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -62,22 +61,27 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
if (context != null) {
if (myPsiClass != null) {
final List<XmlElementDescriptor> children = new ArrayList<XmlElementDescriptor>();
- collectProperties(children, context, new Function<PsiField, XmlElementDescriptor>() {
+ collectProperties(children, new Function<PsiField, XmlElementDescriptor>() {
@Override
public XmlElementDescriptor fun(PsiField field) {
return new JavaFxPropertyElementDescriptor(myPsiClass, field.getName(), false);
}
- });
+ }, false);
+
+ final JavaFxPropertyElementDescriptor defaultPropertyDescriptor = getDefaultPropertyDescriptor();
+ if (defaultPropertyDescriptor != null) {
+ Collections.addAll(children, defaultPropertyDescriptor.getElementsDescriptors(context));
+ } else {
+ for (String name : FxmlConstants.FX_DEFAULT_ELEMENTS) {
+ children.add(new JavaFxDefaultPropertyElementDescriptor(name, null));
+ }
+ }
collectStaticElementDescriptors(context, children);
final PsiType returnType = JavaFxPsiUtil.getDefaultPropertyExpectedType(myPsiClass);
if (returnType != null) {
- JavaFxPropertyElementDescriptor.collectDescriptorsByCollection(returnType, myPsiClass.getResolveScope(), children);
- }
-
- for (String name : FxmlConstants.FX_DEFAULT_ELEMENTS) {
- children.add(new JavaFxDefaultPropertyElementDescriptor(name, null));
+ JavaFxPropertyElementDescriptor.collectDescriptorsByCollection(returnType, myPsiClass.getResolveScope(), children, myPsiClass.getProject());
}
if (!children.isEmpty()) {
@@ -88,6 +92,21 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
return XmlElementDescriptor.EMPTY_ARRAY;
}
+ private JavaFxPropertyElementDescriptor getDefaultPropertyDescriptor() {
+ final PsiAnnotation defaultProperty = AnnotationUtil
+ .findAnnotationInHierarchy(myPsiClass, Collections.singleton(JavaFxCommonClassNames.JAVAFX_BEANS_DEFAULT_PROPERTY));
+ if (defaultProperty != null) {
+ final PsiAnnotationMemberValue defaultPropertyAttributeValue = defaultProperty.findAttributeValue("value");
+ if (defaultPropertyAttributeValue instanceof PsiLiteralExpression) {
+ final Object value = ((PsiLiteralExpression)defaultPropertyAttributeValue).getValue();
+ if (value instanceof String) {
+ return new JavaFxPropertyElementDescriptor(myPsiClass, (String)value, false);
+ }
+ }
+ }
+ return null;
+ }
+
static void collectStaticAttributesDescriptors(@Nullable XmlTag context, List<XmlAttributeDescriptor> simpleAttrs) {
if (context == null) return;
collectParentStaticProperties(context.getParentTag(), simpleAttrs, new Function<PsiMethod, XmlAttributeDescriptor>() {
@@ -109,19 +128,32 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
}
private static <T> void collectParentStaticProperties(XmlTag context, List<T> children, Function<PsiMethod, T> factory) {
+ final CachedValuesManager manager = context != null ? CachedValuesManager.getManager(context.getProject()) : null;
XmlTag tag = context;
while (tag != null) {
final XmlElementDescriptor descr = tag.getDescriptor();
if (descr instanceof JavaFxClassBackedElementDescriptor) {
final PsiElement element = descr.getDeclaration();
if (element instanceof PsiClass) {
- for (PsiMethod method : ((PsiClass)element).getMethods()) {
- if (method.hasModifierProperty(PsiModifier.STATIC) && method.getName().startsWith("set")) {
- final PsiParameter[] parameters = method.getParameterList().getParameters();
- if (parameters.length == 2 && InheritanceUtil.isInheritor(parameters[0].getType(), JavaFxCommonClassNames.JAVAFX_SCENE_NODE)) {
- children.add(factory.fun(method));
+ final List<PsiMethod> setters = manager.getCachedValue(element, new CachedValueProvider<List<PsiMethod>>() {
+ @Nullable
+ @Override
+ public Result<List<PsiMethod>> compute() {
+ final List<PsiMethod> meths = new ArrayList<PsiMethod>();
+ for (PsiMethod method : ((PsiClass)element).getAllMethods()) {
+ if (method.hasModifierProperty(PsiModifier.STATIC) && method.getName().startsWith("set")) {
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ if (parameters.length == 2 &&
+ InheritanceUtil.isInheritor(parameters[0].getType(), JavaFxCommonClassNames.JAVAFX_SCENE_NODE)) {
+ meths.add(method);
+ }
+ }
}
+ return Result.create(meths, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
+ });
+ for (PsiMethod setter : setters) {
+ children.add(factory.fun(setter));
}
}
}
@@ -149,26 +181,46 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
}
}
- final JavaFxPropertyElementDescriptor elementDescriptor = new JavaFxPropertyElementDescriptor(myPsiClass, name, false);
- if (myPsiClass != null && elementDescriptor.getDeclaration() != null) {
- return elementDescriptor;
+ final String parentTagName = contextTag.getName();
+ if (myPsiClass != null) {
+ if (!FxmlConstants.FX_DEFINE.equals(parentTagName)) {
+ JavaFxPropertyElementDescriptor elementDescriptor = new JavaFxPropertyElementDescriptor(myPsiClass, name, false);
+ if (FxmlConstants.FX_ROOT.equals(parentTagName)) {
+ final PsiField fieldByName = myPsiClass.findFieldByName(name, true);
+ if (fieldByName != null) {
+ return elementDescriptor;
+ }
+ } else {
+ final JavaFxPropertyElementDescriptor defaultPropertyDescriptor = getDefaultPropertyDescriptor();
+ if (defaultPropertyDescriptor != null) {
+ final String defaultPropertyName = defaultPropertyDescriptor.getName();
+ if (StringUtil.equalsIgnoreCase(defaultPropertyName, name) && !StringUtil.equals(defaultPropertyName, name)) {
+ final XmlElementDescriptor childDescriptor = defaultPropertyDescriptor.getElementDescriptor(childTag, contextTag);
+ if (childDescriptor != null) {
+ return childDescriptor;
+ }
+ }
+ }
+ final PsiElement declaration = elementDescriptor.getDeclaration();
+ if (declaration != null) {
+ if (declaration instanceof PsiField && ((PsiField)declaration).getType() instanceof PsiPrimitiveType) {
+ return null;
+ }
+ return elementDescriptor;
+ }
+ }
+ }
}
return new JavaFxClassBackedElementDescriptor(name, childTag);
}
@Override
public XmlAttributeDescriptor[] getAttributesDescriptors(@Nullable XmlTag context) {
- //todo filter
if (context != null) {
final String name = context.getName();
if (Comparing.equal(name, getName()) && myPsiClass != null) {
final List<XmlAttributeDescriptor> simpleAttrs = new ArrayList<XmlAttributeDescriptor>();
- collectProperties(simpleAttrs, context, new Function<PsiField, XmlAttributeDescriptor>() {
- @Override
- public XmlAttributeDescriptor fun(PsiField field) {
- return new JavaFxPropertyAttributeDescriptor(field.getName(), myPsiClass);
- }
- });
+ collectInstanceProperties(simpleAttrs);
collectStaticAttributesDescriptors(context, simpleAttrs);
for (String defaultProperty : FxmlConstants.FX_DEFAULT_PROPERTIES) {
simpleAttrs.add(new JavaFxDefaultAttributeDescriptor(defaultProperty, myPsiClass));
@@ -179,18 +231,42 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
return XmlAttributeDescriptor.EMPTY;
}
- private <T> void collectProperties(List<T> children, XmlTag context, Function<PsiField, T> factory) {
- final PsiField[] fields = myPsiClass.getAllFields();
- if (fields.length > 0) {
- for (PsiField field : fields) {
- if (field.hasModifierProperty(PsiModifier.STATIC)) continue;
- final PsiType fieldType = field.getType();
- if (!JavaFxPsiUtil.isReadOnly(field.getName(), context) &&
- InheritanceUtil.isInheritor(fieldType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY) ||
- fieldType.equalsToText(CommonClassNames.JAVA_LANG_STRING) ||
- GenericsHighlightUtil.getCollectionItemType(field.getType(), myPsiClass.getResolveScope()) != null) {
- children.add(factory.fun(field));
+ protected void collectInstanceProperties(List<XmlAttributeDescriptor> simpleAttrs) {
+ collectProperties(simpleAttrs, new Function<PsiField, XmlAttributeDescriptor>() {
+ @Override
+ public XmlAttributeDescriptor fun(PsiField field) {
+ return new JavaFxPropertyAttributeDescriptor(field.getName(), myPsiClass);
+ }
+ }, true);
+ }
+
+ private <T> void collectProperties(final List<T> children, final Function<PsiField, T> factory, final boolean acceptPrimitive) {
+ final List<PsiField> fieldList =
+ CachedValuesManager.getManager(myPsiClass.getProject()).getCachedValue(myPsiClass, new CachedValueProvider<List<PsiField>>() {
+ @Nullable
+ @Override
+ public Result<List<PsiField>> compute() {
+ List<PsiField> acceptableFields = new ArrayList<PsiField>();
+ final PsiField[] fields = myPsiClass.getAllFields();
+ if (fields.length > 0) {
+ for (PsiField field : fields) {
+ if (field.hasModifierProperty(PsiModifier.STATIC)) continue;
+ final PsiType fieldType = field.getType();
+ if (!JavaFxPsiUtil.isReadOnly(myPsiClass, field) &&
+ InheritanceUtil.isInheritor(fieldType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY) ||
+ fieldType.equalsToText(CommonClassNames.JAVA_LANG_STRING) ||
+ (acceptPrimitive && fieldType instanceof PsiPrimitiveType) ||
+ GenericsHighlightUtil.getCollectionItemType(field.getType(), myPsiClass.getResolveScope()) != null) {
+ acceptableFields.add(field);
+ }
+ }
+ }
+ return Result.create(acceptableFields, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
+ });
+ if (fieldList != null) {
+ for (PsiField field : fieldList) {
+ children.add(factory.fun(field));
}
}
}
@@ -278,7 +354,10 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
host.addMessage(((XmlAttributeImpl)attribute).getNameElement(), "fx:controller can only be applied to root element", ValidationHost.ErrorType.ERROR); //todo add delete/move to upper tag fix
}
}
- validateTagAccordingToFieldType(context, parentTag, host);
+ final String canCoerceError = JavaFxPsiUtil.isClassAcceptable(parentTag, myPsiClass);
+ if (canCoerceError != null) {
+ host.addMessage(context.getNavigationElement(), canCoerceError, ValidationHost.ErrorType.ERROR);
+ }
if (myPsiClass != null && myPsiClass.isValid()) {
final String message = JavaFxPsiUtil.isAbleToInstantiate(myPsiClass);
if (message != null) {
@@ -286,29 +365,4 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
}
}
}
-
- private void validateTagAccordingToFieldType(XmlTag context, XmlTag parentTag, ValidationHost host) {
- if (myPsiClass != null && myPsiClass.isValid()) {
- final XmlElementDescriptor descriptor = parentTag != null ? parentTag.getDescriptor() : null;
- if (descriptor instanceof JavaFxPropertyElementDescriptor) {
- final PsiElement declaration = descriptor.getDeclaration();
- if (declaration instanceof PsiField) {
- final PsiType type = ((PsiField)declaration).getType();
- final PsiType collectionItemType = GenericsHighlightUtil.getCollectionItemType(type, myPsiClass.getResolveScope());
- if (collectionItemType != null && PsiPrimitiveType.getUnboxedType(collectionItemType) == null) {
- final PsiClass baseClass = PsiUtil.resolveClassInType(collectionItemType);
- if (baseClass != null) {
- final String qualifiedName = baseClass.getQualifiedName();
- if (qualifiedName != null && !Comparing.strEqual(qualifiedName, CommonClassNames.JAVA_LANG_STRING)) {
- if (!InheritanceUtil.isInheritor(myPsiClass, qualifiedName)) {
- host.addMessage(context.getNavigationElement(),
- "Unable to coerce " + HighlightUtil.formatClass(myPsiClass)+ " to " + qualifiedName, ValidationHost.ErrorType.ERROR);
- }
- }
- }
- }
- }
- }
- }
- }
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java
index cef24e3229c0..0d92f4712359 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java
@@ -78,7 +78,8 @@ public class JavaFxDefaultAttributeDescriptor extends JavaFxPropertyAttributeDes
final PsiElement parent = context.getParent();
if (parent instanceof XmlAttribute) {
final XmlAttribute attribute = (XmlAttribute)parent;
- if (FxmlConstants.FX_VALUE.equals(attribute.getName())) {
+ final String attributeName = attribute.getName();
+ if (FxmlConstants.FX_VALUE.equals(attributeName)) {
final PsiClass tagClass = JavaFxPsiUtil.getTagClass((XmlAttributeValue)context);
if (tagClass != null) {
final PsiMethod method = JavaFxPsiUtil.findValueOfMethod(tagClass);
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java
index e025f13a90c3..ec4a6bfbb499 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java
@@ -15,12 +15,15 @@
*/
package org.jetbrains.plugins.javaFX.fxml.descriptors;
+import com.intellij.codeInsight.daemon.Validator;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.xml.XmlAttributeDescriptor;
@@ -28,6 +31,7 @@ import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlElementsGroup;
import com.intellij.xml.XmlNSDescriptor;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
@@ -39,7 +43,7 @@ import java.util.List;
/**
* User: anna
*/
-public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescriptor{
+public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescriptor, Validator<XmlTag>{
private final String myName;
private final XmlTag myXmlTag;
@@ -60,6 +64,12 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
@Override
public XmlElementDescriptor[] getElementsDescriptors(XmlTag context) {
+ if (myName.equals(FxmlConstants.FX_ROOT)) {
+ final JavaFxClassBackedElementDescriptor tagDescriptor = getRootTagDescriptor(context);
+ if (tagDescriptor != null) {
+ return tagDescriptor.getElementsDescriptors(context);
+ }
+ }
return XmlElementDescriptor.EMPTY_ARRAY;
}
@@ -67,11 +77,14 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
@Override
public XmlElementDescriptor getElementDescriptor(XmlTag childTag, XmlTag contextTag) {
final String name = childTag.getName();
- if (myName.equals(FxmlConstants.FX_DEFINE)) {
+ if (FxmlConstants.FX_DEFINE.equals(myName)) {
+ if (FxmlConstants.FX_DEFAULT_ELEMENTS.contains(name)) {
+ return new JavaFxDefaultPropertyElementDescriptor(name, childTag);
+ }
return new JavaFxClassBackedElementDescriptor(name, childTag);
}
- if (myName.equals(FxmlConstants.FX_ROOT)) {
+ if (FxmlConstants.FX_ROOT.equals(myName)) {
final JavaFxClassBackedElementDescriptor tagDescriptor = getRootTagDescriptor(contextTag);
if (tagDescriptor != null) {
return tagDescriptor.getElementDescriptor(childTag, contextTag);
@@ -90,7 +103,7 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
descriptors.add(new JavaFxDefaultAttributeDescriptor(defaultAttrName, getName()));
}
JavaFxClassBackedElementDescriptor.collectStaticAttributesDescriptors(context, descriptors);
- final XmlTag referencedTag = getReferencedTag(getName(), myXmlTag);
+ final XmlTag referencedTag = getReferencedTag(myXmlTag);
if (referencedTag != null) {
final XmlElementDescriptor referencedDescriptor = referencedTag.getDescriptor();
if (referencedDescriptor != null) {
@@ -104,6 +117,19 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
if (rootTagDescriptor != null) {
Collections.addAll(descriptors, rootTagDescriptor.getAttributesDescriptors(context));
}
+ final XmlTag includedRoot = getIncludedRoot(context);
+ if (includedRoot != null) {
+ final XmlElementDescriptor includedRootDescriptor = includedRoot.getDescriptor();
+ if (includedRootDescriptor instanceof JavaFxClassBackedElementDescriptor) {
+ ((JavaFxClassBackedElementDescriptor)includedRootDescriptor).collectInstanceProperties(descriptors);
+ }
+ else if (includedRootDescriptor instanceof JavaFxDefaultPropertyElementDescriptor) {
+ final JavaFxClassBackedElementDescriptor includedRootTagDescriptor = ((JavaFxDefaultPropertyElementDescriptor)includedRootDescriptor).getRootTagDescriptor(includedRoot);
+ if (includedRootTagDescriptor != null) {
+ includedRootTagDescriptor.collectInstanceProperties(descriptors);
+ }
+ }
+ }
}
return descriptors.toArray(new XmlAttributeDescriptor[descriptors.size()]);
}
@@ -111,8 +137,9 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
}
@Nullable
- private static XmlTag getReferencedTag(String name, XmlTag tag) {
- if (name.equals(FxmlConstants.FX_REFERENCE)) {
+ public static XmlTag getReferencedTag(XmlTag tag) {
+ final String tagName = tag.getName();
+ if (FxmlConstants.FX_REFERENCE.equals(tagName) || FxmlConstants.FX_COPY.equals(tagName)) {
final XmlAttribute attribute = tag.getAttribute(FxmlConstants.FX_ELEMENT_SOURCE);
if (attribute != null) {
final XmlAttributeValue valueElement = attribute.getValueElement();
@@ -142,7 +169,7 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
if (propertySetter != null) {
return new JavaFxStaticPropertyAttributeDescriptor(propertySetter, attributeName);
}
- final XmlTag referencedTag = getReferencedTag(getName(), myXmlTag);
+ final XmlTag referencedTag = getReferencedTag(myXmlTag);
if (referencedTag != null) {
final XmlElementDescriptor referencedDescriptor = referencedTag.getDescriptor();
if (referencedDescriptor != null) {
@@ -153,17 +180,47 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
if (rootTagDescriptor != null) {
return rootTagDescriptor.getAttributeDescriptor(attributeName, context);
}
+ if (context != null && FxmlConstants.FX_INCLUDE.equals(getName())) {
+ final XmlTag includedRoot = getIncludedRoot(context);
+ if (includedRoot != null) {
+ final XmlElementDescriptor includedRootDescriptor = includedRoot.getDescriptor();
+ if (includedRootDescriptor != null) {
+ return includedRootDescriptor.getAttributeDescriptor(attributeName, includedRoot);
+ }
+ }
+ }
}
return null;
}
- private JavaFxClassBackedElementDescriptor getRootTagDescriptor(XmlTag context) {
+ private static XmlTag getIncludedRoot(XmlTag context) {
+ if (context == null) return null;
+ final XmlAttribute xmlAttribute = context.getAttribute(FxmlConstants.FX_ELEMENT_SOURCE);
+ if (xmlAttribute != null) {
+ final XmlAttributeValue valueElement = xmlAttribute.getValueElement();
+ if (valueElement != null) {
+ final PsiReference reference = valueElement.getReference();
+ if (reference != null) {
+ final PsiElement resolve = reference.resolve();
+ if (resolve instanceof XmlFile) {
+ final XmlTag rootTag = ((XmlFile)resolve).getRootTag();
+ if (rootTag != null) {
+ return rootTag;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public JavaFxClassBackedElementDescriptor getRootTagDescriptor(XmlTag context) {
if (context != null && FxmlConstants.FX_ROOT.equals(getName())) {
final XmlAttribute typeAttr = context.getAttribute(FxmlConstants.TYPE);
if (typeAttr != null) {
final String rootClassName = typeAttr.getValue();
final Project project = context.getProject();
- final PsiClass rootClass = JavaPsiFacade.getInstance(project).findClass(rootClassName, GlobalSearchScope.allScope(project));
+ final PsiClass rootClass = rootClassName != null ? JavaPsiFacade.getInstance(project).findClass(rootClassName, GlobalSearchScope.allScope(project)) : null;
if (rootClass != null) {
return new JavaFxClassBackedElementDescriptor(getName(), rootClass);
}
@@ -223,4 +280,42 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
public Object[] getDependences() {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
+
+ @Override
+ public void validate(@NotNull XmlTag context, @NotNull ValidationHost host) {
+ final String contextName = context.getName();
+ if (FxmlConstants.FX_ROOT.equals(contextName)) {
+ if (context.getParentTag() != null) {
+ host.addMessage(context.getNavigationElement(), "<fx:root> is valid only as the root node of an FXML document", ValidationHost.ERROR);
+ }
+ } else {
+ final XmlTag referencedTag = getReferencedTag(context);
+ if (referencedTag != null) {
+ final XmlElementDescriptor descriptor = referencedTag.getDescriptor();
+ if (descriptor != null) {
+ final PsiElement declaration = descriptor.getDeclaration();
+ if (declaration instanceof PsiClass) {
+ final PsiClass psiClass = (PsiClass)declaration;
+ final String canCoerceError = JavaFxPsiUtil.isClassAcceptable(context.getParentTag(), psiClass);
+ if (canCoerceError != null) {
+ host.addMessage(context.getNavigationElement(), canCoerceError, ValidationHost.ErrorType.ERROR);
+ }
+ if (FxmlConstants.FX_COPY.equals(contextName)) {
+ boolean copyConstructorFound = false;
+ for (PsiMethod constructor : psiClass.getConstructors()) {
+ final PsiParameter[] parameters = constructor.getParameterList().getParameters();
+ if (parameters.length == 1 && psiClass == PsiUtil.resolveClassInType(parameters[0].getType())) {
+ copyConstructorFound = true;
+ break;
+ }
+ }
+ if (!copyConstructorFound) {
+ host.addMessage(context.getNavigationElement(), "Copy constructor not found for \'" + psiClass.getName() + "\'", ValidationHost.ERROR);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java
index 2e3180da7b53..8c0ff3d847b3 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java
@@ -1,18 +1,19 @@
package org.jetbrains.plugins.javaFX.fxml.descriptors;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiEnumConstant;
-import com.intellij.psi.PsiField;
-import com.intellij.psi.xml.XmlAttribute;
-import com.intellij.psi.xml.XmlAttributeValue;
-import com.intellij.psi.xml.XmlElement;
-import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.xml.*;
import com.intellij.util.ArrayUtil;
import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -78,7 +79,15 @@ public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor
}
return ArrayUtil.toStringArray(enumConstants);
}
- return null;
+
+ final String propertyQName = getBoxedPropertyType(getDeclaration());
+ if (CommonClassNames.JAVA_LANG_FLOAT.equals(propertyQName) || CommonClassNames.JAVA_LANG_DOUBLE.equals(propertyQName)) {
+ return new String[] {"Infinity", "-Infinity", "NaN", "-NaN"};
+ } else if (CommonClassNames.JAVA_LANG_BOOLEAN.equals(propertyQName)) {
+ return new String[] {"true", "false"};
+ }
+
+ return ArrayUtil.EMPTY_STRING_ARRAY;
}
protected boolean isConstant(PsiField enumField) {
@@ -105,15 +114,56 @@ public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor
if (context instanceof XmlAttributeValue) {
final XmlAttributeValue xmlAttributeValue = (XmlAttributeValue)context;
final PsiElement parent = xmlAttributeValue.getParent();
- if (parent instanceof XmlAttribute && JavaFxPsiUtil.checkIfAttributeHandler((XmlAttribute)parent)) {
- if (value.startsWith("#")) {
- if (JavaFxPsiUtil.getControllerClass(context.getContainingFile()) == null) {
- return "No controller specified for top level element";
+ if (parent instanceof XmlAttribute) {
+ if (JavaFxPsiUtil.checkIfAttributeHandler((XmlAttribute)parent)) {
+ if (value.startsWith("#")) {
+ if (JavaFxPsiUtil.getControllerClass(context.getContainingFile()) == null) {
+ return "No controller specified for top level element";
+ }
+ }
+ else {
+ if (JavaFxPsiUtil.parseInjectedLanguages((XmlFile)context.getContainingFile()).isEmpty()) {
+ return "Page language not specified.";
+ }
+ }
+ } else if (FxmlConstants.FX_ID.equals(((XmlAttribute)parent).getName())) {
+ final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(context.getContainingFile());
+ if (controllerClass != null) {
+ final XmlTag xmlTag = ((XmlAttribute)parent).getParent();
+ if (xmlTag != null) {
+ final XmlElementDescriptor descriptor = xmlTag.getDescriptor();
+ if (descriptor instanceof JavaFxClassBackedElementDescriptor) {
+ final PsiElement declaration = descriptor.getDeclaration();
+ if (declaration instanceof PsiClass) {
+ final PsiField fieldByName = controllerClass.findFieldByName(xmlAttributeValue.getValue(), false);
+ if (fieldByName != null && !InheritanceUtil.isInheritorOrSelf((PsiClass)declaration, PsiUtil.resolveClassInType(fieldByName.getType()), true)) {
+ return "Cannot set " + ((PsiClass)declaration).getQualifiedName() + " to field \'" + fieldByName.getName() + "\'";
+ }
+ }
+ }
+ }
}
}
else {
- if (JavaFxPsiUtil.parseInjectedLanguages((XmlFile)context.getContainingFile()).isEmpty()) {
- return "Page language not specified.";
+ final XmlAttributeDescriptor attributeDescriptor = ((XmlAttribute)parent).getDescriptor();
+ if (attributeDescriptor != null) {
+ final PsiElement declaration = attributeDescriptor.getDeclaration();
+ final String boxedQName = getBoxedPropertyType(declaration);
+ if (boxedQName != null) {
+ try {
+ final Class<?> aClass = Class.forName(boxedQName);
+ final Method method = aClass.getMethod(JavaFxCommonClassNames.VALUE_OF, String.class);
+ method.invoke(aClass, ((XmlAttributeValue)context).getValue());
+ }
+ catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof NumberFormatException) {
+ return "Invalid value: unable to coerce to " + boxedQName;
+ }
+ }
+ catch (Exception ignore) {
+ }
+ }
}
}
}
@@ -121,6 +171,28 @@ public class JavaFxPropertyAttributeDescriptor implements XmlAttributeDescriptor
return null;
}
+ @Nullable
+ private static String getBoxedPropertyType(PsiElement declaration) {
+ PsiType attrType = null;
+ if (declaration instanceof PsiField) {
+ attrType = JavaFxPsiUtil.getWrappedPropertyType((PsiField)declaration, declaration.getProject(), JavaFxCommonClassNames.ourWritableMap);
+ } else if (declaration instanceof PsiMethod) {
+ final PsiParameter[] parameters = ((PsiMethod)declaration).getParameterList().getParameters();
+ if (parameters.length == 2) {
+ attrType = parameters[1].getType();
+ }
+ }
+
+ String boxedQName = null;
+ if (attrType instanceof PsiPrimitiveType) {
+ boxedQName = ((PsiPrimitiveType)attrType).getBoxedTypeName();
+ } else if (PsiPrimitiveType.getUnboxedType(attrType) != null) {
+ final PsiClass attrClass = PsiUtil.resolveClassInType(attrType);
+ boxedQName = attrClass != null ? attrClass.getQualifiedName() : null;
+ }
+ return boxedQName;
+ }
+
@Override
public PsiElement getDeclaration() {
if (myPsiClass != null) {
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
index 7cd6dff8942e..abae636d8bc3 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
@@ -1,6 +1,7 @@
package org.jetbrains.plugins.javaFX.fxml.descriptors;
import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -19,6 +20,7 @@ import com.intellij.xml.impl.schema.AnyXmlAttributeDescriptor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
import java.util.ArrayList;
@@ -39,6 +41,10 @@ public class JavaFxPropertyElementDescriptor implements XmlElementDescriptor {
myStatic = isStatic;
}
+ public boolean isStatic() {
+ return myStatic;
+ }
+
@Override
public String getQualifiedName() {
return getName();
@@ -55,7 +61,7 @@ public class JavaFxPropertyElementDescriptor implements XmlElementDescriptor {
if (declaration instanceof PsiField) {
final PsiType psiType = ((PsiField)declaration).getType();
final ArrayList<XmlElementDescriptor> descriptors = new ArrayList<XmlElementDescriptor>();
- collectDescriptorsByCollection(psiType, declaration.getResolveScope(), descriptors);
+ collectDescriptorsByCollection(psiType, declaration.getResolveScope(), descriptors, declaration.getProject());
for (String name : FxmlConstants.FX_DEFAULT_ELEMENTS) {
descriptors.add(new JavaFxDefaultPropertyElementDescriptor(name, null));
}
@@ -66,7 +72,8 @@ public class JavaFxPropertyElementDescriptor implements XmlElementDescriptor {
public static void collectDescriptorsByCollection(PsiType psiType,
GlobalSearchScope resolveScope,
- final List<XmlElementDescriptor> descriptors) {
+ final List<XmlElementDescriptor> descriptors,
+ final Project project) {
final PsiType collectionItemType = GenericsHighlightUtil.getCollectionItemType(psiType, resolveScope);
if (collectionItemType != null) {
final PsiClass aClass = PsiUtil.resolveClassInType(collectionItemType);
@@ -78,6 +85,13 @@ public class JavaFxPropertyElementDescriptor implements XmlElementDescriptor {
return true;
}
});
+ descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass));
+ }
+ } else if (InheritanceUtil.isInheritor(psiType, JavaFxCommonClassNames.JAVAFX_BEANS_PROPERTY)) {
+ final PsiType propertyType = JavaFxPsiUtil.getPropertyType(psiType, project);
+ final PsiClass aClass = PsiUtil.resolveClassInType(propertyType);
+ if (aClass != null) {
+ descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass));
}
}
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
index febd08f873ab..8463225e7643 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
@@ -16,19 +16,20 @@
package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.openapi.util.TextRange;
-import com.intellij.patterns.*;
+import com.intellij.patterns.PlatformPatterns;
+import com.intellij.patterns.XmlAttributeValuePattern;
+import com.intellij.patterns.XmlPatterns;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
-import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlProcessingInstruction;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
+import static com.intellij.patterns.PlatformPatterns.virtualFile;
import static com.intellij.patterns.StandardPatterns.string;
/**
@@ -40,7 +41,8 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
- final XmlAttributeValuePattern attributeValueInFxml = XmlPatterns.xmlAttributeValue().with(inFxmlCondition());
+ final XmlAttributeValuePattern attributeValueInFxml = XmlPatterns.xmlAttributeValue().inVirtualFile(
+ virtualFile().withExtension(JavaFxFileTypeFactory.FXML_EXTENSION));
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_CONTROLLER))
.and(attributeValueInFxml),
CLASS_REFERENCE_PROVIDER);
@@ -51,7 +53,7 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
.and(attributeValueInFxml),
CLASS_REFERENCE_PROVIDER);
- registrar.registerReferenceProvider(XmlPatterns.xmlTag().with(inFxmlCondition()),
+ registrar.registerReferenceProvider(XmlPatterns.xmlTag().inVirtualFile(virtualFile().withExtension(JavaFxFileTypeFactory.FXML_EXTENSION)),
new MyJavaClassReferenceProvider());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_ID))
@@ -72,7 +74,7 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_ELEMENT_SOURCE)
.withParent(XmlPatterns.xmlTag()
- .withName(FxmlConstants.FX_REFERENCE)))
+ .withName(string().oneOf(FxmlConstants.FX_REFERENCE, FxmlConstants.FX_COPY))))
.and(attributeValueInFxml),
new JavaFxComponentIdReferenceProvider());
@@ -95,11 +97,15 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.STYLESHEETS)).and(attributeValueInFxml),
new JavaFxLocationReferenceProvider(true));
- registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlProcessingInstruction.class).inFile(inFxmlElementPattern()), new ImportReferenceProvider());
+ registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlProcessingInstruction.class).inVirtualFile(virtualFile().withExtension(JavaFxFileTypeFactory.FXML_EXTENSION)),
+ new ImportReferenceProvider());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().and(attributeValueInFxml),
new EnumeratedAttributeReferenceProvider());
+ registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().and(attributeValueInFxml),
+ new JavaFxColorReferenceProvider());
+
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue()
.withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_VALUE)
.withParent(XmlPatterns.xmlTag().withParent(XmlPatterns.xmlTag().withName(FxmlConstants.STYLESHEETS))))
@@ -107,24 +113,6 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
new JavaFxLocationReferenceProvider(true));
}
- public static PsiFilePattern.Capture<PsiFile> inFxmlElementPattern() {
- return new PsiFilePattern.Capture<PsiFile>(new InitialPatternCondition<PsiFile>(PsiFile.class) {
- @Override
- public boolean accepts(@Nullable Object o, ProcessingContext context) {
- return o instanceof PsiFile && JavaFxFileTypeFactory.isFxml((PsiFile)o);
- }
- });
- }
-
- public static <T extends XmlElement> PatternCondition<T> inFxmlCondition() {
- return new PatternCondition<T>("inFxmlFile") {
- @Override
- public boolean accepts(@NotNull T value, ProcessingContext context) {
- return JavaFxFileTypeFactory.isFxml(value.getContainingFile());
- }
- };
- }
-
private static class MyJavaClassReferenceProvider extends JavaClassReferenceProvider {
@NotNull
@Override
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
index 9da83e9eee7a..bcfb4dc897e4 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
@@ -28,19 +28,20 @@ import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.presentation.java.SymbolPresentationUtil;
-import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlTag;
import com.intellij.ui.ColorUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.ColorIcon;
-import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.util.ColorSampleLookupValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
-import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyAttributeDescriptor;
+import org.jetbrains.plugins.javaFX.fxml.codeInsight.intentions.JavaFxWrapWithDefineIntention;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxDefaultPropertyElementDescriptor;
import javax.swing.*;
import java.awt.*;
@@ -70,45 +71,55 @@ public class JavaFxAnnotator implements Annotator {
}
}
}
- if (references.length == 0) {
- final String attributeValueText = StringUtil.stripQuotesAroundValue(element.getText());
- if (attributeValueText.startsWith("#")) {
- attachColorIcon(element, holder, attributeValueText);
- }
+ if (references.length == 1 && references[0] instanceof JavaFxColorReference) {
+ attachColorIcon(element, holder, StringUtil.stripQuotesAroundValue(element.getText()));
}
} else if (element instanceof XmlAttribute) {
- final String attributeName = ((XmlAttribute)element).getName();
- if (!FxmlConstants.FX_DEFAULT_PROPERTIES.contains(attributeName) &&
- !((XmlAttribute)element).isNamespaceDeclaration() &&
- JavaFxPsiUtil.isReadOnly(attributeName, ((XmlAttribute)element).getParent())) {
+ final XmlAttribute attribute = (XmlAttribute)element;
+ final String attributeName = attribute.getName();
+ if (!FxmlConstants.FX_DEFAULT_PROPERTIES.contains(attributeName) &&
+ !attribute.isNamespaceDeclaration() &&
+ JavaFxPsiUtil.isReadOnly(attributeName, attribute.getParent())) {
holder.createErrorAnnotation(element.getNavigationElement(), "Property '" + attributeName + "' is read-only");
}
+ if (FxmlConstants.FX_ELEMENT_SOURCE.equals(attributeName)) {
+ final XmlAttributeValue valueElement = attribute.getValueElement();
+ if (valueElement != null) {
+ final XmlTag xmlTag = attribute.getParent();
+ if (xmlTag != null) {
+ final XmlTag referencedTag = JavaFxDefaultPropertyElementDescriptor.getReferencedTag(xmlTag);
+ if (referencedTag != null) {
+ if (referencedTag.getTextOffset() > xmlTag.getTextOffset()) {
+ holder.createErrorAnnotation(valueElement.getValueTextRange(), valueElement.getValue() + " not found");
+ } else if (xmlTag.getParentTag() == referencedTag.getParentTag()) {
+ final Annotation annotation = holder.createErrorAnnotation(valueElement.getValueTextRange(), "Duplicate child added");
+ annotation.registerFix(new JavaFxWrapWithDefineIntention(referencedTag, valueElement.getValue()));
+ }
+ }
+ }
+ }
+ }
}
}
private static void attachColorIcon(final PsiElement element, AnnotationHolder holder, String attributeValueText) {
- final PsiElement parent = element.getParent();
- if (parent instanceof XmlAttribute) {
- final XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
- if (descriptor instanceof JavaFxPropertyAttributeDescriptor) {
- final PsiElement declaration = descriptor.getDeclaration();
- if (declaration instanceof PsiField) {
- final PsiField field = (PsiField)declaration;
- final PsiClassType propertyClassType = JavaFxPsiUtil.getPropertyClassType(field);
- if (propertyClassType != null && InheritanceUtil.isInheritor(propertyClassType, JavaFxCommonClassNames.JAVAFX_SCENE_PAINT)) {
- try {
- final Color color = ColorUtil.fromHex(attributeValueText.substring(1));
- if (color != null) {
- final ColorIcon icon = new ColorIcon(8, color);
- final Annotation annotation = holder.createInfoAnnotation(element, null);
- annotation.setGutterIconRenderer(new ColorIconRenderer(icon, element));
- }
- }
- catch (Exception ignored) {
- }
- }
+ try {
+ Color color = null;
+ if (attributeValueText.startsWith("#")) {
+ color = ColorUtil.fromHex(attributeValueText.substring(1));
+ } else {
+ final String hexCode = ColorSampleLookupValue.getHexCodeForColorName(StringUtil.toLowerCase(attributeValueText));
+ if (hexCode != null) {
+ color = ColorUtil.fromHex(hexCode);
}
}
+ if (color != null) {
+ final ColorIcon icon = new ColorIcon(8, color);
+ final Annotation annotation = holder.createInfoAnnotation(element, null);
+ annotation.setGutterIconRenderer(new ColorIconRenderer(icon, element));
+ }
+ }
+ catch (Exception ignored) {
}
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxColorReference.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxColorReference.java
new file mode 100644
index 000000000000..e3ac22476a13
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxColorReference.java
@@ -0,0 +1,69 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml.refs;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReferenceBase;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.xml.util.ColorSampleLookupValue;
+import com.intellij.xml.util.UserColorLookup;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
+
+/**
+ * User: anna
+ * Date: 3/7/13
+ */
+public class JavaFxColorReference extends PsiReferenceBase<XmlAttributeValue> {
+ public JavaFxColorReference(XmlAttributeValue value) {
+ super(value);
+ }
+
+ @Nullable
+ @Override
+ public PsiElement resolve() {
+ final Project project = getElement().getProject();
+ final PsiClass psiClass =
+ JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_SCENE_COLOR, GlobalSearchScope.allScope(project));
+ if (psiClass != null) {
+ return psiClass.findFieldByName(getCanonicalText().toUpperCase(), false);
+ }
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public Object[] getVariants() {
+ final ColorSampleLookupValue[] lookupValues = ColorSampleLookupValue.getColors();
+ final Object[] vars = new Object[lookupValues.length + 1];
+ for (int i = 0; i < lookupValues.length; i++) {
+ final ColorSampleLookupValue value = lookupValues[i];
+ vars[i] = new ColorSampleLookupValue(value.getName(), value.getValue(), true);
+ }
+ vars[lookupValues.length] = new UserColorLookup();
+ return vars;
+ }
+
+ @Override
+ public boolean isSoft() {
+ return true;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxColorReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxColorReferenceProvider.java
new file mode 100644
index 000000000000..d53f8752ec90
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxColorReferenceProvider.java
@@ -0,0 +1,55 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml.refs;
+
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ProcessingContext;
+import com.intellij.xml.XmlAttributeDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyAttributeDescriptor;
+
+/**
+* User: anna
+* Date: 3/7/13
+*/
+class JavaFxColorReferenceProvider extends PsiReferenceProvider {
+ @NotNull
+ @Override
+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element,
+ @NotNull ProcessingContext context) {
+ final XmlAttributeValue attributeValue = (XmlAttributeValue)element;
+ final PsiElement parent = attributeValue.getParent();
+ if (parent instanceof XmlAttribute) {
+ final XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
+ if (descriptor instanceof JavaFxPropertyAttributeDescriptor) {
+ final PsiElement declaration = descriptor.getDeclaration();
+ if (declaration instanceof PsiField) {
+ final PsiField field = (PsiField)declaration;
+ final PsiClassType propertyClassType = JavaFxPsiUtil.getPropertyClassType(field);
+ if (propertyClassType != null && InheritanceUtil.isInheritor(propertyClassType, JavaFxCommonClassNames.JAVAFX_SCENE_PAINT)) {
+ return new PsiReference[] {new JavaFxColorReference(attributeValue)};
+ }
+ }
+ }
+ }
+ return PsiReference.EMPTY_ARRAY;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java
index 3f344c1572f9..20b7fad50d55 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxComponentIdReferenceProvider.java
@@ -31,10 +31,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* User: anna
@@ -94,24 +91,49 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
}
return new PsiReference[] {idReferenceBase};
}
- final JavaFxIdReferenceBase idReferenceBase = new JavaFxIdReferenceBase(xmlAttributeValue, fileIds, referencesId);
if (startsWithDollar) {
+ final JavaFxIdReferenceBase idReferenceBase = new JavaFxIdReferenceBase(xmlAttributeValue, fileIds, referencesId);
final TextRange rangeInElement = idReferenceBase.getRangeInElement();
idReferenceBase.setRangeInElement(new TextRange(rangeInElement.getStartOffset() + 1, rangeInElement.getEndOffset()));
+ return new PsiReference[]{idReferenceBase};
+ } else {
+ final Set<String> acceptableIds = new HashSet<String>();
+ if (currentTag != null) {
+ final XmlTag parentTag = currentTag.getParentTag();
+ for (final String id : fileIds.keySet()) {
+ final XmlAttributeValue resolvedAttrValue = fileIds.get(id);
+ if (JavaFxPsiUtil.isClassAcceptable(parentTag, JavaFxPsiUtil.getTagClass(resolvedAttrValue)) == null) {
+ acceptableIds.add(id);
+ }
+ }
+ }
+ JavaFxIdReferenceBase idReferenceBase = new JavaFxIdReferenceBase(xmlAttributeValue, fileIds, acceptableIds, referencesId);
+ return new PsiReference[]{idReferenceBase};
}
- return new PsiReference[]{idReferenceBase};
}
private static class JavaFxIdReferenceBase extends PsiReferenceBase<XmlAttributeValue> {
private final Map<String, XmlAttributeValue> myFileIds;
+ private final Set<String> myAcceptableIds;
private final String myReferencesId;
+ private JavaFxIdReferenceBase(XmlAttributeValue element,
+ Map<String, XmlAttributeValue> fileIds,
+ Set<String> acceptableIds,
+ String referencesId) {
+ super(element);
+ myFileIds = fileIds;
+ myAcceptableIds = acceptableIds;
+ myReferencesId = referencesId;
+ }
+
public JavaFxIdReferenceBase(XmlAttributeValue xmlAttributeValue,
Map<String, XmlAttributeValue> fileIds,
String referencesId) {
super(xmlAttributeValue);
myFileIds = fileIds;
myReferencesId = referencesId;
+ myAcceptableIds = myFileIds.keySet();
}
@Nullable
@@ -123,7 +145,7 @@ class JavaFxComponentIdReferenceProvider extends PsiReferenceProvider {
@NotNull
@Override
public Object[] getVariants() {
- return ArrayUtil.toStringArray(myFileIds.keySet());
+ return ArrayUtil.toStringArray(myAcceptableIds);
}
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java
index a200fad4aaba..e4eef13f5281 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java
@@ -35,7 +35,8 @@ public abstract class JavaFxControllerBasedReferenceProvider extends PsiReferenc
if (!JavaFxFileTypeFactory.isFxml(containingFile)) return PsiReference.EMPTY_ARRAY;
final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(containingFile);
- return controllerClass != null ? getReferencesByElement(controllerClass, xmlAttrVal, context) : PsiReference.EMPTY_ARRAY;
+ return controllerClass != null ? getReferencesByElement(controllerClass, xmlAttrVal, context)
+ : new PsiReference[] {new PsiReferenceBase.Immediate<XmlAttributeValue>(xmlAttrVal, xmlAttrVal)};
}
protected abstract PsiReference[] getReferencesByElement(@NotNull PsiClass controllerClass, XmlAttributeValue element, ProcessingContext context);
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerFieldSearcher.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerFieldSearcher.java
new file mode 100644
index 000000000000..ffbfd9f68ab9
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerFieldSearcher.java
@@ -0,0 +1,95 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml.refs;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.Processor;
+import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.JavaFxControllerClassIndex;
+import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
+
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 3/29/13
+ */
+public class JavaFxControllerFieldSearcher implements QueryExecutor<PsiReference, ReferencesSearch.SearchParameters>{
+ @Override
+ public boolean execute(@NotNull ReferencesSearch.SearchParameters queryParameters, @NotNull final Processor<PsiReference> consumer) {
+ final PsiElement elementToSearch = queryParameters.getElementToSearch();
+ if (elementToSearch instanceof PsiField) {
+ final PsiField field = (PsiField)elementToSearch;
+ final PsiClass containingClass = field.getContainingClass();
+ if (containingClass != null) {
+ final String qualifiedName = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ return containingClass.getQualifiedName();
+ }
+ });
+ if (qualifiedName != null) {
+ final List<PsiFile> fxmlWithController =
+ JavaFxControllerClassIndex.findFxmlWithController(containingClass.getProject(), qualifiedName);
+ final String fieldName = field.getName();
+ for (PsiFile file : fxmlWithController) {
+ final VirtualFile virtualFile = file.getViewProvider().getVirtualFile();
+ final SearchScope searchScope = queryParameters.getEffectiveSearchScope();
+ if (searchScope instanceof LocalSearchScope) {
+ if (!((LocalSearchScope)searchScope).isInScope(virtualFile)) continue;
+ } else if (searchScope instanceof GlobalSearchScope) {
+ if (!((GlobalSearchScope)searchScope).contains(virtualFile)) continue;
+ }
+ file.accept(new XmlRecursiveElementVisitor() {
+ @Override
+ public void visitXmlAttributeValue(XmlAttributeValue value) {
+ final PsiReference reference = value.getReference();
+ if (reference != null) {
+ Runnable runnable = new Runnable() {
+ public void run() {
+ final PsiElement resolve = reference.resolve();
+ if (resolve instanceof XmlAttributeValue) {
+ final PsiElement parent = resolve.getParent();
+ if (parent instanceof XmlAttribute) {
+ final XmlAttribute attribute = (XmlAttribute)parent;
+ if (FxmlConstants.FX_ID.equals(attribute.getName()) && fieldName.equals(attribute.getValue())) {
+ consumer.process(reference);
+ }
+ }
+ }
+ }
+ };
+ ApplicationManager.getApplication().runReadAction(runnable);
+ }
+ }
+ });
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java
index ed34c51a9cb5..432e3eeabe25 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java
@@ -79,6 +79,7 @@ public class JavaFxEventHandlerReference extends PsiReferenceBase<XmlAttributeVa
return true;
}
}
+ return parameters.length == 0;
}
return false;
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java
index c649a37f8639..a6d9ccda005c 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java
@@ -17,6 +17,8 @@ package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.psi.*;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
@@ -27,16 +29,16 @@ import java.util.ArrayList;
import java.util.List;
/**
-* User: anna
-* Date: 1/17/13
-*/
-class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferenceProvider {
+ * User: anna
+ * Date: 1/17/13
+ */
+public class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferenceProvider {
@Override
protected PsiReference[] getReferencesByElement(@NotNull final PsiClass aClass,
final XmlAttributeValue xmlAttributeValue,
ProcessingContext context) {
final PsiField field = aClass.findFieldByName(xmlAttributeValue.getValue(), false);
- return new PsiReference[] {new JavaFxControllerFieldRef(xmlAttributeValue, field, aClass)};
+ return new PsiReference[]{new JavaFxControllerFieldRef(xmlAttributeValue, field, aClass)};
}
public static class JavaFxControllerFieldRef extends PsiReferenceBase<XmlAttributeValue> {
@@ -45,16 +47,38 @@ class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferenceProvi
private final PsiClass myAClass;
public JavaFxControllerFieldRef(XmlAttributeValue xmlAttributeValue, PsiField field, PsiClass aClass) {
- super(xmlAttributeValue);
+ super(xmlAttributeValue, true);
myXmlAttributeValue = xmlAttributeValue;
myField = field;
myAClass = aClass;
}
+ public XmlAttributeValue getXmlAttributeValue() {
+ return myXmlAttributeValue;
+ }
+
+ public PsiClass getAClass() {
+ return myAClass;
+ }
+
@Nullable
@Override
public PsiElement resolve() {
- return myField != null ? myField : myXmlAttributeValue;
+ if (myField != null) {
+ return myField;
+ }
+ else {
+ if (myAClass != null) {
+ final XmlFile xmlFile = (XmlFile)myXmlAttributeValue.getContainingFile();
+ final XmlTag rootTag = xmlFile.getRootTag();
+ if (rootTag != null) {
+ if (!JavaFxPsiUtil.isOutOfHierarchy(myXmlAttributeValue)) {
+ return null;
+ }
+ }
+ }
+ return myXmlAttributeValue;
+ }
}
@NotNull
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxImportClassFix.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxImportClassFix.java
index f2ef0a51237b..04abf3baa07f 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxImportClassFix.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxImportClassFix.java
@@ -66,7 +66,7 @@ abstract class JavaFxImportClassFix extends ImportClassFixBase<XmlTag, JavaFxTag
@Override
protected boolean isAccessible(PsiMember member, XmlTag reference) {
- return true;
+ return member instanceof PsiClass && JavaFxPsiUtil.isClassAcceptable(reference.getParentTag(), (PsiClass)member) == null;
}
@Override
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxScopeEnlager.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxScopeEnlager.java
deleted file mode 100644
index c3a3589a5f38..000000000000
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxScopeEnlager.java
+++ /dev/null
@@ -1,51 +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 org.jetbrains.plugins.javaFX.fxml.refs;
-
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiField;
-import com.intellij.psi.PsiModifier;
-import com.intellij.psi.search.DelegatingGlobalSearchScope;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.SearchScope;
-import com.intellij.psi.search.UseScopeEnlarger;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
-
-/**
- * User: anna
- */
-public class JavaFxScopeEnlager extends UseScopeEnlarger {
- @Nullable
- @Override
- public SearchScope getAdditionalUseScope(@NotNull PsiElement element) {
- if (element instanceof PsiField) {
- final PsiField field = (PsiField)element;
- if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
- final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(field.getProject());
- return new DelegatingGlobalSearchScope(projectScope){
- @Override
- public boolean contains(VirtualFile file) {
- return super.contains(file) && JavaFxFileTypeFactory.isFxml(file);
- }
- };
- }
- }
- return null;
- }
-}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxScopeEnlarger.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxScopeEnlarger.java
new file mode 100644
index 000000000000..13f3efcdf967
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxScopeEnlarger.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.fxml.refs;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.search.DelegatingGlobalSearchScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.UseScopeEnlarger;
+import com.intellij.psi.util.PropertyUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.JavaFxControllerClassIndex;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
+
+/**
+ * User: anna
+ */
+public class JavaFxScopeEnlarger extends UseScopeEnlarger {
+ @Nullable
+ @Override
+ public SearchScope getAdditionalUseScope(@NotNull PsiElement element) {
+ PsiClass containingClass = null;
+ if (element instanceof PsiField) {
+ containingClass = ((PsiField)element).getContainingClass();
+ }
+ else if (element instanceof PsiParameter) {
+ final PsiElement declarationScope = ((PsiParameter)element).getDeclarationScope();
+ if (declarationScope instanceof PsiMethod && PropertyUtil.isSimplePropertySetter((PsiMethod)declarationScope)) {
+ containingClass = ((PsiMethod)declarationScope).getContainingClass();
+ }
+ }
+
+ if (containingClass != null) {
+ if (element instanceof PsiField && ((PsiField)element).hasModifierProperty(PsiModifier.PRIVATE) || element instanceof PsiParameter) {
+ final Project project = element.getProject();
+ final String qualifiedName = containingClass.getQualifiedName();
+ if (qualifiedName != null && !JavaFxControllerClassIndex.findFxmlWithController(project, qualifiedName).isEmpty()) {
+ final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(project);
+ return new DelegatingGlobalSearchScope(projectScope){
+ @Override
+ public boolean contains(VirtualFile file) {
+ return super.contains(file) && JavaFxFileTypeFactory.isFxml(file);
+ }
+ };
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java
index 0fcaabc29bb0..ad8a88441e30 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxTagNameReference.java
@@ -8,6 +8,7 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
@@ -36,6 +37,20 @@ public class JavaFxTagNameReference extends TagNameReference{
}
@Override
+ public TextRange getRangeInElement() {
+ final TextRange rangeInElement = super.getRangeInElement();
+ final XmlTag tagElement = getTagElement();
+ if (tagElement != null) {
+ final String tagElementName = tagElement.getName();
+ final int dotIdx = tagElementName.indexOf(".");
+ if (dotIdx > -1 && dotIdx + 2 < rangeInElement.getEndOffset()) {
+ return new TextRange(rangeInElement.getStartOffset() + dotIdx + 1, rangeInElement.getEndOffset());
+ }
+ }
+ return rangeInElement;
+ }
+
+ @Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
if (element instanceof PsiClass) {
final String qualifiedName = ((PsiClass)element).getQualifiedName();
@@ -69,9 +84,10 @@ public class JavaFxTagNameReference extends TagNameReference{
final List<LookupElement> elements = new ArrayList<LookupElement>(variants.size());
for (XmlElementDescriptor descriptor : variants) {
final String descriptorName = descriptor.getName(element);
- LOGGER.assertTrue(descriptorName != null, "Descriptor: " + descriptor + "; tag: " + xmlTag.getName());
- LookupElementBuilder lookupElement = LookupElementBuilder.create(descriptor, descriptorName);
- elements.add(lookupElement.withInsertHandler(JavaFxTagInsertHandler.INSTANCE));
+ if (descriptorName != null) {
+ LookupElementBuilder lookupElement = LookupElementBuilder.create(descriptor, descriptorName);
+ elements.add(lookupElement.withInsertHandler(JavaFxTagInsertHandler.INSTANCE));
+ }
}
return elements.toArray(new LookupElement[elements.size()]);
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxApplicationArtifactType.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxApplicationArtifactType.java
new file mode 100644
index 000000000000..dffbbc8be6a0
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxApplicationArtifactType.java
@@ -0,0 +1,125 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.module.JavaModuleType;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleType;
+import com.intellij.openapi.roots.ui.configuration.ChooseModulesDialog;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.packaging.artifacts.ArtifactTemplate;
+import com.intellij.packaging.artifacts.ArtifactType;
+import com.intellij.packaging.elements.*;
+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;
+
+/**
+ * User: anna
+ * Date: 3/12/13
+ */
+public class JavaFxApplicationArtifactType extends ArtifactType {
+ public static JavaFxApplicationArtifactType getInstance() {
+ return EP_NAME.findExtension(JavaFxApplicationArtifactType.class);
+ }
+
+ protected JavaFxApplicationArtifactType() {
+ super("javafx", "JavaFx Application");
+ }
+
+ @NotNull
+ @Override
+ public Icon getIcon() {
+ return AllIcons.Nodes.Artifact;
+ }
+
+ @Nullable
+ @Override
+ public String getDefaultPathFor(@NotNull PackagingElementOutputKind kind) {
+ return "/";
+ }
+
+ @NotNull
+ @Override
+ public CompositePackagingElement<?> createRootElement(@NotNull String artifactName) {
+ return PackagingElementFactory.getInstance().createArtifactRootElement();
+ }
+
+ @NotNull
+ @Override
+ public List<? extends ArtifactTemplate> getNewArtifactTemplates(@NotNull PackagingElementResolvingContext context) {
+ final List<Module> modules = new ArrayList<Module>();
+ for (Module module : context.getModulesProvider().getModules()) {
+ if (ModuleType.get(module) instanceof JavaModuleType) {
+ modules.add(module);
+ }
+ }
+ if (modules.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return Collections.singletonList(new JavaFxArtifactTemplate(modules));
+ }
+
+ private class JavaFxArtifactTemplate extends ArtifactTemplate {
+ private final List<Module> myModules;
+
+ public JavaFxArtifactTemplate(List<Module> modules) {
+ myModules = modules;
+ }
+
+ @Override
+ public String getPresentableName() {
+ if (myModules.size() == 1) {
+ return "From module '" + myModules.get(0).getName() + "'";
+ }
+ return "From module...";
+ }
+
+ @Override
+ public NewArtifactConfiguration createArtifact() {
+ Module module = null;
+ if (myModules.size() == 1) {
+ module = myModules.get(0);
+ } else {
+ final ChooseModulesDialog dialog = new ChooseModulesDialog(myModules.get(0).getProject(), myModules,
+ "Select Module",
+ "Selected module output would to be included in the artifact");
+ dialog.setSingleSelectionMode();
+ dialog.show();
+ if (dialog.isOK()) {
+ final List<Module> elements = dialog.getChosenElements();
+ if (elements.isEmpty()) {
+ return null;
+ }
+ module = elements.get(0);
+ }
+ }
+ if (module == null) return null;
+ final CompositePackagingElement<?> rootElement = JavaFxApplicationArtifactType.this.createRootElement(module.getName());
+ final CompositePackagingElement<?>
+ subElement = PackagingElementFactory.getInstance().createArchive(FileUtil.sanitizeFileName(module.getName()) + ".jar");
+ final PackagingElement<?> moduleOutputElement = PackagingElementFactory.getInstance().createModuleOutput(module);
+ subElement.addFirstChild(moduleOutputElement);
+ rootElement.addFirstChild(subElement);
+ return new NewArtifactConfiguration(rootElement, module.getName(), JavaFxApplicationArtifactType.this);
+ }
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxApplicationClassBrowser.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxApplicationClassBrowser.java
new file mode 100644
index 000000000000..16c19918874e
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxApplicationClassBrowser.java
@@ -0,0 +1,88 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.execution.JavaExecutionUtil;
+import com.intellij.execution.ui.ClassBrowser;
+import com.intellij.ide.util.ClassFilter;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.impl.artifacts.ArtifactUtil;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.InheritanceUtil;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+* User: anna
+* Date: 3/19/13
+*/
+public class JavaFxApplicationClassBrowser extends ClassBrowser {
+
+ private final Artifact myArtifact;
+
+ public JavaFxApplicationClassBrowser(Project project, Artifact artifact) {
+ this(project, artifact, "Choose Application Class");
+ }
+
+ public JavaFxApplicationClassBrowser(final Project project,
+ final Artifact artifact,
+ final String title) {
+ super(project, title);
+ myArtifact = artifact;
+ }
+
+ @Override
+ protected ClassFilter.ClassFilterWithScope getFilter() throws NoFilterException {
+ return new ClassFilter.ClassFilterWithScope() {
+ @Override
+ public GlobalSearchScope getScope() {
+ return GlobalSearchScope.projectScope(getProject());
+ }
+
+ @Override
+ public boolean isAccepted(PsiClass aClass) {
+ return InheritanceUtil.isInheritor(aClass, getApplicationClass());
+ }
+ };
+ }
+
+ protected String getApplicationClass() {
+ return "javafx.application.Application";
+ }
+
+ @Override
+ protected PsiClass findClass(String className) {
+ final Set<Module> modules = ApplicationManager.getApplication().runReadAction(new Computable<Set<Module>>() {
+ @Override
+ public Set<Module> compute() {
+ return ArtifactUtil.getModulesIncludedInArtifacts(Collections.singletonList(myArtifact), getProject());
+ }
+ });
+ for (Module module : modules) {
+ final PsiClass aClass = JavaExecutionUtil.findMainClass(getProject(), className, GlobalSearchScope.moduleScope(module));
+ if (aClass != null) {
+ return aClass;
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactProperties.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactProperties.java
new file mode 100644
index 000000000000..67e295fbafb1
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactProperties.java
@@ -0,0 +1,400 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompilerMessageCategory;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.JavaSdk;
+import com.intellij.openapi.projectRoots.JavaSdkVersion;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.util.Computable;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactManager;
+import com.intellij.packaging.artifacts.ArtifactProperties;
+import com.intellij.packaging.elements.PackagingElement;
+import com.intellij.packaging.impl.artifacts.ArtifactUtil;
+import com.intellij.packaging.impl.elements.ArchivePackagingElement;
+import com.intellij.packaging.impl.elements.ArtifactPackagingElement;
+import com.intellij.packaging.ui.ArtifactEditorContext;
+import com.intellij.packaging.ui.ArtifactPropertiesEditor;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.packaging.preloader.JavaFxPreloaderArtifactProperties;
+import org.jetbrains.plugins.javaFX.packaging.preloader.JavaFxPreloaderArtifactPropertiesProvider;
+import org.jetbrains.plugins.javaFX.packaging.preloader.JavaFxPreloaderArtifactType;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * User: anna
+ * Date: 3/12/13
+ */
+public class JavaFxArtifactProperties extends ArtifactProperties<JavaFxArtifactProperties> {
+
+ private String myTitle;
+ private String myVendor;
+ private String myDescription;
+ private String myAppClass;
+ private String myWidth = JavaFxPackagerConstants.DEFAULT_WEIGHT;
+ private String myHeight = JavaFxPackagerConstants.DEFAULT_HEIGHT;
+ private String myHtmlParamFile;
+ private String myParamFile;
+ private String myUpdateMode = JavaFxPackagerConstants.UPDATE_MODE_BACKGROUND;
+
+ private boolean myEnabledSigning = false;
+ private boolean mySelfSigning = true;
+ private String myAlias;
+ private String myKeystore;
+ private String myStorepass;
+ private String myKeypass;
+
+ @Override
+ public void onBuildFinished(@NotNull final Artifact artifact, @NotNull final CompileContext compileContext) {
+ if (!(artifact.getArtifactType() instanceof JavaFxApplicationArtifactType)) {
+ return;
+ }
+ final Project project = compileContext.getProject();
+ final Set<Module> modules = ApplicationManager.getApplication().runReadAction(new Computable<Set<Module>>() {
+ @Override
+ public Set<Module> compute() {
+ return ArtifactUtil.getModulesIncludedInArtifacts(Collections.singletonList(artifact), project);
+ }
+ });
+ if (modules.isEmpty()) {
+ return;
+ }
+
+ Sdk fxCompatibleSdk = null;
+ for (Module module : modules) {
+ final Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
+ if (sdk != null && sdk.getSdkType() instanceof JavaSdk) {
+ if (((JavaSdk)sdk.getSdkType()).isOfVersionOrHigher(sdk, JavaSdkVersion.JDK_1_7)) {
+ fxCompatibleSdk = sdk;
+ break;
+ }
+ }
+ }
+
+ if (fxCompatibleSdk == null) {
+ compileContext.addMessage(CompilerMessageCategory.ERROR, "Java version 7 or higher is required to build JavaFX package", null, -1, -1);
+ return;
+ }
+
+ final JavaFxArtifactProperties properties =
+ (JavaFxArtifactProperties)artifact.getProperties(JavaFxArtifactPropertiesProvider.getInstance());
+
+ final JavaFxPackager javaFxPackager = new JavaFxPackager(artifact, properties, project) {
+ @Override
+ protected void registerJavaFxPackagerError(String message) {
+ compileContext.addMessage(CompilerMessageCategory.ERROR, message, null, -1, -1);
+ }
+ };
+ javaFxPackager.buildJavaFxArtifact(fxCompatibleSdk.getHomePath());
+ }
+
+ @Override
+ public ArtifactPropertiesEditor createEditor(@NotNull ArtifactEditorContext context) {
+ return new JavaFxArtifactPropertiesEditor(this, context.getProject(), context.getArtifact());
+ }
+
+ @Nullable
+ @Override
+ public JavaFxArtifactProperties getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(JavaFxArtifactProperties state) {
+ XmlSerializerUtil.copyBean(state, this);
+ }
+
+ public String getTitle() {
+ return myTitle;
+ }
+
+ public void setTitle(String title) {
+ myTitle = title;
+ }
+
+ public String getVendor() {
+ return myVendor;
+ }
+
+ public void setVendor(String vendor) {
+ myVendor = vendor;
+ }
+
+ public String getDescription() {
+ return myDescription;
+ }
+
+ public void setDescription(String description) {
+ myDescription = description;
+ }
+
+ public String getAppClass() {
+ return myAppClass;
+ }
+
+ public void setAppClass(String appClass) {
+ myAppClass = appClass;
+ }
+
+ public String getWidth() {
+ return myWidth;
+ }
+
+ public String getHeight() {
+ return myHeight;
+ }
+
+ public void setWidth(String width) {
+ myWidth = width;
+ }
+
+ public void setHeight(String height) {
+ myHeight = height;
+ }
+
+ public String getHtmlParamFile() {
+ return myHtmlParamFile;
+ }
+
+ public void setHtmlParamFile(String htmlParamFile) {
+ myHtmlParamFile = htmlParamFile;
+ }
+
+ public String getParamFile() {
+ return myParamFile;
+ }
+
+ public void setParamFile(String paramFile) {
+ myParamFile = paramFile;
+ }
+
+ public String getUpdateMode() {
+ return myUpdateMode;
+ }
+
+ public void setUpdateMode(String updateMode) {
+ myUpdateMode = updateMode;
+ }
+
+ public boolean isEnabledSigning() {
+ return myEnabledSigning;
+ }
+
+ public void setEnabledSigning(boolean enabledSigning) {
+ myEnabledSigning = enabledSigning;
+ }
+
+ public boolean isSelfSigning() {
+ return mySelfSigning;
+ }
+
+ public void setSelfSigning(boolean selfSigning) {
+ mySelfSigning = selfSigning;
+ }
+
+ public String getAlias() {
+ return myAlias;
+ }
+
+ public void setAlias(String alias) {
+ myAlias = alias;
+ }
+
+ public String getKeystore() {
+ return myKeystore;
+ }
+
+ public void setKeystore(String keystore) {
+ myKeystore = keystore;
+ }
+
+ public String getStorepass() {
+ return myStorepass;
+ }
+
+ public void setStorepass(String storepass) {
+ myStorepass = storepass;
+ }
+
+ public String getKeypass() {
+ return myKeypass;
+ }
+
+ public void setKeypass(String keypass) {
+ myKeypass = keypass;
+ }
+
+ public String getPreloaderClass(Artifact rootArtifact, Project project) {
+ final Artifact artifact = getPreloaderArtifact(rootArtifact, project);
+ if (artifact != null) {
+ final JavaFxPreloaderArtifactProperties properties =
+ (JavaFxPreloaderArtifactProperties)artifact.getProperties(JavaFxPreloaderArtifactPropertiesProvider.getInstance());
+ return properties.getPreloaderClass();
+ }
+ return null;
+ }
+
+ public String getPreloaderJar(Artifact rootArtifact, Project project) {
+ final Artifact artifact = getPreloaderArtifact(rootArtifact, project);
+ if (artifact != null) {
+ return ((ArchivePackagingElement)artifact.getRootElement()).getArchiveFileName();
+ }
+ return null;
+ }
+
+
+ private static Artifact getPreloaderArtifact(Artifact rootArtifact, Project project) {
+ for (PackagingElement<?> element : rootArtifact.getRootElement().getChildren()) {
+ if (element instanceof ArtifactPackagingElement) {
+ final Artifact artifact = ((ArtifactPackagingElement)element)
+ .findArtifact(ArtifactManager.getInstance(project).getResolvingContext());
+ if (artifact != null && artifact.getArtifactType() instanceof JavaFxPreloaderArtifactType) {
+ return artifact;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static abstract class JavaFxPackager extends AbstractJavaFxPackager {
+ private final Artifact myArtifact;
+ private final JavaFxArtifactProperties myProperties;
+ private final Project myProject;
+
+ public JavaFxPackager(Artifact artifact, JavaFxArtifactProperties properties, Project project) {
+ myArtifact = artifact;
+ myProperties = properties;
+ myProject = project;
+ }
+
+ @Override
+ protected String getArtifactOutputPath() {
+ return myArtifact.getOutputPath();
+ }
+
+ @Override
+ protected String getArtifactOutputFilePath() {
+ for (PackagingElement<?> element : myArtifact.getRootElement().getChildren()) {
+ if (element instanceof ArchivePackagingElement) {
+ return myArtifact.getOutputFilePath() + File.separator + ((ArchivePackagingElement)element).getArchiveFileName();
+ }
+ }
+ return myArtifact.getOutputFilePath();
+ }
+
+ @Override
+ protected String getAppClass() {
+ return myProperties.getAppClass();
+ }
+
+ @Override
+ protected String getTitle() {
+ return myProperties.getTitle();
+ }
+
+ @Override
+ protected String getVendor() {
+ return myProperties.getVendor();
+ }
+
+ @Override
+ protected String getDescription() {
+ return myProperties.getDescription();
+ }
+
+ @Override
+ protected String getWidth() {
+ return myProperties.getWidth();
+ }
+
+ @Override
+ protected String getHeight() {
+ return myProperties.getHeight();
+ }
+
+ @Override
+ public String getPreloaderClass() {
+ return myProperties.getPreloaderClass(myArtifact, myProject);
+ }
+
+ @Override
+ public String getPreloaderJar() {
+ return myProperties.getPreloaderJar(myArtifact, myProject);
+ }
+
+ @Override
+ protected String prepareParam(String param) {
+ return GeneralCommandLine.prepareCommand(param);
+ }
+
+ @Override
+ protected String getHtmlParamFile() {
+ return myProperties.getHtmlParamFile();
+ }
+
+ @Override
+ protected String getParamFile() {
+ return myProperties.getParamFile();
+ }
+
+ @Override
+ protected String getUpdateMode() {
+ return myProperties.getUpdateMode();
+ }
+
+ @Override
+ public String getKeypass() {
+ return myProperties.getKeypass();
+ }
+
+ @Override
+ public String getStorepass() {
+ return myProperties.getStorepass();
+ }
+
+ @Override
+ public String getKeystore() {
+ return myProperties.getKeystore();
+ }
+
+ @Override
+ public String getAlias() {
+ return myProperties.getAlias();
+ }
+
+ @Override
+ public boolean isSelfSigning() {
+ return myProperties.isSelfSigning();
+ }
+
+ @Override
+ public boolean isEnabledSigning() {
+ return myProperties.isEnabledSigning();
+ }
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.form b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.form
new file mode 100644
index 000000000000..65c36ea983ec
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.form
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.javaFX.packaging.JavaFxArtifactPropertiesEditor">
+ <grid id="27dc6" binding="myWholePanel" 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>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="ca833" layout-manager="GridLayoutManager" row-count="10" 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"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="e6b9f" class="javax.swing.JLabel">
+ <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>
+ <labelFor value="7bfab"/>
+ <text value="&amp;Title:"/>
+ </properties>
+ </component>
+ <component id="7bfab" class="javax.swing.JTextField" binding="myTitleTF">
+ <constraints>
+ <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="b0dab" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <labelFor value="ad1f3"/>
+ <text value="&amp;Vendor:"/>
+ </properties>
+ </component>
+ <component id="ad1f3" class="javax.swing.JTextField" binding="myVendorTF">
+ <constraints>
+ <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <scrollpane id="c7b69" class="com.intellij.ui.components.JBScrollPane">
+ <constraints>
+ <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="-1" height="100"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="a51e8" class="javax.swing.JEditorPane" binding="myDescriptionEditorPane" default-binding="true">
+ <constraints/>
+ <properties/>
+ </component>
+ </children>
+ </scrollpane>
+ <component id="3ada" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="3" 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="a51e8"/>
+ <text value="&amp;Description:"/>
+ </properties>
+ </component>
+ <component id="a1cdd" 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>
+ <labelFor value="e5f9c"/>
+ <text value="A&amp;pplication class:"/>
+ </properties>
+ </component>
+ <component id="e5f9c" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myAppClass">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="5a049" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <labelFor value="fde94"/>
+ <text value="&amp;Width:"/>
+ </properties>
+ </component>
+ <component id="fde94" class="javax.swing.JTextField" binding="myWidthTF">
+ <constraints>
+ <grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="fcef9" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <labelFor value="2a255"/>
+ <text value="&amp;Height:"/>
+ </properties>
+ </component>
+ <component id="2a255" class="javax.swing.JTextField" binding="myHeightTF">
+ <constraints>
+ <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="d5f8c" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <labelFor value="b2b7a"/>
+ <text value="HTM&amp;L Parameters:"/>
+ </properties>
+ </component>
+ <component id="b2b7a" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myHtmlParams">
+ <constraints>
+ <grid row="6" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="db3d4" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <labelFor value="be63e"/>
+ <text value="Application Pa&amp;rameters:"/>
+ </properties>
+ </component>
+ <component id="be63e" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myParams">
+ <constraints>
+ <grid row="7" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="4a8b2" class="javax.swing.JCheckBox" binding="myUpdateInBackgroundCB">
+ <constraints>
+ <grid row="8" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Update in &amp;background"/>
+ </properties>
+ </component>
+ <component id="b03bd" class="javax.swing.JCheckBox" binding="myEnableSigningCB">
+ <constraints>
+ <grid row="9" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Enable &amp;signing"/>
+ </properties>
+ </component>
+ <grid id="506ce" 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="9" column="1" 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="1123f" class="javax.swing.JButton" binding="myEditSignCertificateButton" default-binding="true">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Edit &amp;Cerificates"/>
+ </properties>
+ </component>
+ <hspacer id="d47d8">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ <vspacer id="1a12e">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ </children>
+ </grid>
+</form>
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.java
new file mode 100644
index 000000000000..feaee5b4e41f
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesEditor.java
@@ -0,0 +1,179 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.ui.ArtifactPropertiesEditor;
+import com.intellij.util.Base64Converter;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.text.JTextComponent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * User: anna
+ * Date: 3/12/13
+ */
+public class JavaFxArtifactPropertiesEditor extends ArtifactPropertiesEditor {
+ private final JavaFxArtifactProperties myProperties;
+
+ private JPanel myWholePanel;
+ private JTextField myTitleTF;
+ private JTextField myVendorTF;
+ private JEditorPane myDescriptionEditorPane;
+ private TextFieldWithBrowseButton myAppClass;
+ private JTextField myWidthTF;
+ private JTextField myHeightTF;
+ private TextFieldWithBrowseButton myHtmlParams;
+ private TextFieldWithBrowseButton myParams;
+ private JCheckBox myUpdateInBackgroundCB;
+ private JCheckBox myEnableSigningCB;
+ private JButton myEditSignCertificateButton;
+ private JavaFxEditCertificatesDialog myDialog;
+
+ public JavaFxArtifactPropertiesEditor(JavaFxArtifactProperties properties, final Project project, Artifact artifact) {
+ super();
+ myProperties = properties;
+ new JavaFxApplicationClassBrowser(project, artifact).setField(myAppClass);
+ final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileDescriptor(StdFileTypes.PROPERTIES);
+ myHtmlParams.addBrowseFolderListener("Choose Properties File", "Parameters for the resulting application to run standalone.", project, descriptor);
+ myParams.addBrowseFolderListener("Choose Properties File", "Parameters for the resulting application to run in the browser.", project, descriptor);
+ myEditSignCertificateButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myDialog = new JavaFxEditCertificatesDialog(myWholePanel, myProperties, project);
+ myDialog.show();
+ }
+ });
+ myEnableSigningCB.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myEditSignCertificateButton.setEnabled(myEnableSigningCB.isSelected());
+ }
+ });
+ }
+
+ @Override
+ public String getTabName() {
+ return "Java FX";
+ }
+
+ @Nullable
+ @Override
+ public JComponent createComponent() {
+ return myWholePanel;
+ }
+
+ @Override
+ public boolean isModified() {
+ if (isModified(myProperties.getTitle(), myTitleTF)) return true;
+ if (isModified(myProperties.getVendor(), myVendorTF)) return true;
+ if (isModified(myProperties.getDescription(), myDescriptionEditorPane)) return true;
+ if (isModified(myProperties.getWidth(), myWidthTF)) return true;
+ if (isModified(myProperties.getHeight(), myHeightTF)) return true;
+ if (isModified(myProperties.getAppClass(), myAppClass)) return true;
+ if (isModified(myProperties.getHtmlParamFile(), myHtmlParams)) return true;
+ if (isModified(myProperties.getParamFile(), myParams)) return true;
+ final boolean inBackground = Comparing.strEqual(myProperties.getUpdateMode(), JavaFxPackagerConstants.UPDATE_MODE_BACKGROUND);
+ if (inBackground != myUpdateInBackgroundCB.isSelected()) return true;
+ if (myProperties.isEnabledSigning() != myEnableSigningCB.isSelected()) return true;
+ if (myDialog != null) {
+ if (isModified(myProperties.getAlias(), myDialog.myPanel.myAliasTF)) return true;
+ if (isModified(myProperties.getKeystore(), myDialog.myPanel.myKeystore)) return true;
+ final String keypass = myProperties.getKeypass();
+ if (isModified(keypass != null ? Base64Converter.decode(keypass) : "", myDialog.myPanel.myKeypassTF)) return true;
+ final String storepass = myProperties.getStorepass();
+ if (isModified(storepass != null ? Base64Converter.decode(storepass) : "", myDialog.myPanel.myStorePassTF)) return true;
+ if (myProperties.isSelfSigning() != myDialog.myPanel.mySelfSignedRadioButton.isSelected()) return true;
+ }
+ return false;
+ }
+
+ private static boolean isModified(final String title, JTextComponent tf) {
+ return !Comparing.strEqual(title, tf.getText().trim());
+ }
+
+ private static boolean isModified(final String title, TextFieldWithBrowseButton tf) {
+ return !Comparing.strEqual(title, tf.getText().trim());
+ }
+
+ @Override
+ public void apply() {
+ myProperties.setTitle(myTitleTF.getText());
+ myProperties.setVendor(myVendorTF.getText());
+ myProperties.setDescription(myDescriptionEditorPane.getText());
+ myProperties.setAppClass(myAppClass.getText());
+ myProperties.setWidth(myWidthTF.getText());
+ myProperties.setHeight(myHeightTF.getText());
+ myProperties.setHtmlParamFile(myHtmlParams.getText());
+ myProperties.setParamFile(myParams.getText());
+ myProperties.setUpdateMode(myUpdateInBackgroundCB.isSelected() ? JavaFxPackagerConstants.UPDATE_MODE_BACKGROUND
+ : JavaFxPackagerConstants.UPDATE_MODE_ALWAYS);
+ myProperties.setEnabledSigning(myEnableSigningCB.isSelected());
+ if (myDialog != null) {
+ myProperties.setSelfSigning(myDialog.myPanel.mySelfSignedRadioButton.isSelected());
+ myProperties.setAlias(myDialog.myPanel.myAliasTF.getText());
+ myProperties.setKeystore(myDialog.myPanel.myKeystore.getText());
+ final String keyPass = String.valueOf((myDialog.myPanel.myKeypassTF.getPassword()));
+ myProperties.setKeypass(!StringUtil.isEmptyOrSpaces(keyPass) ? Base64Converter.encode(keyPass) : null);
+ final String storePass = String.valueOf(myDialog.myPanel.myStorePassTF.getPassword());
+ myProperties.setStorepass(!StringUtil.isEmptyOrSpaces(storePass) ? Base64Converter.encode(storePass) : null);
+ }
+ }
+
+ @Override
+ public void reset() {
+ setText(myTitleTF, myProperties.getTitle());
+ setText(myVendorTF, myProperties.getVendor());
+ setText(myDescriptionEditorPane, myProperties.getDescription());
+ setText(myWidthTF, myProperties.getWidth());
+ setText(myHeightTF, myProperties.getHeight());
+ setText(myAppClass, myProperties.getAppClass());
+ setText(myHtmlParams, myProperties.getHtmlParamFile());
+ setText(myParams, myProperties.getParamFile());
+ myUpdateInBackgroundCB.setSelected(Comparing.strEqual(myProperties.getUpdateMode(), JavaFxPackagerConstants.UPDATE_MODE_BACKGROUND));
+ myEnableSigningCB.setSelected(myProperties.isEnabledSigning());
+ myEditSignCertificateButton.setEnabled(myProperties.isEnabledSigning());
+ }
+
+ private static void setText(TextFieldWithBrowseButton tf, final String title) {
+ if (title != null) {
+ tf.setText(title.trim());
+ }
+ }
+
+ private static void setText(JTextComponent tf, final String title) {
+ if (title != null) {
+ tf.setText(title.trim());
+ }
+ }
+
+ @Override
+ public void disposeUIResources() {
+ if (myDialog != null) {
+ myDialog.myPanel = null;
+ }
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesProvider.java
new file mode 100644
index 000000000000..5a9f5d681720
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxArtifactPropertiesProvider.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.packaging.artifacts.ArtifactProperties;
+import com.intellij.packaging.artifacts.ArtifactPropertiesProvider;
+import com.intellij.packaging.artifacts.ArtifactType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: anna
+ * Date: 3/12/13
+ */
+public class JavaFxArtifactPropertiesProvider extends ArtifactPropertiesProvider {
+ protected JavaFxArtifactPropertiesProvider() {
+ super("javafx-properties");
+ }
+
+ @Override
+ public boolean isAvailableFor(@NotNull ArtifactType type) {
+ return type instanceof JavaFxApplicationArtifactType;
+ }
+
+ @NotNull
+ @Override
+ public ArtifactProperties<?> createProperties(@NotNull ArtifactType artifactType) {
+ return new JavaFxArtifactProperties();
+ }
+
+ public static JavaFxArtifactPropertiesProvider getInstance() {
+ return EP_NAME.findExtension(JavaFxArtifactPropertiesProvider.class);
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxEditCertificatesDialog.form b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxEditCertificatesDialog.form
new file mode 100644
index 000000000000..f38dc6be6552
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxEditCertificatesDialog.form
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.javaFX.packaging.JavaFxEditCertificatesDialog.Panel">
+ <grid id="27dc6" binding="myWholePanel" 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="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="3116a" class="javax.swing.JRadioButton" binding="mySelfSignedRadioButton" default-binding="true">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <selected value="true"/>
+ <text value="&amp;Self signed"/>
+ </properties>
+ </component>
+ <hspacer id="20d2b">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ <component id="96e7d" class="javax.swing.JRadioButton" binding="mySignedByKeyRadioButton" default-binding="true">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Signed by &amp;key"/>
+ </properties>
+ </component>
+ <grid id="69a6a" binding="myKeysPanel" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="36" bottom="0" right="0"/>
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="cb253" class="javax.swing.JLabel">
+ <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>
+ <labelFor value="5411"/>
+ <text value="Ke&amp;ystore:"/>
+ </properties>
+ </component>
+ <vspacer id="c35e">
+ <constraints>
+ <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="5411" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myKeystore">
+ <constraints>
+ <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="f5f44" 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>
+ <labelFor value="e86df"/>
+ <text value="&amp;Alias:"/>
+ </properties>
+ </component>
+ <component id="3b7cc" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="2" 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="Store&amp;pass:"/>
+ </properties>
+ </component>
+ <component id="e22e" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="3" 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="K&amp;eypass:"/>
+ </properties>
+ </component>
+ <component id="e86df" class="javax.swing.JTextField" binding="myAliasTF">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="f1b80" class="javax.swing.JPasswordField" binding="myStorePassTF">
+ <constraints>
+ <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="4cb86" class="javax.swing.JPasswordField" binding="myKeypassTF">
+ <constraints>
+ <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ <buttonGroups>
+ <group name="myGroup1">
+ <member id="3116a"/>
+ <member id="96e7d"/>
+ </group>
+ </buttonGroups>
+</form>
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxEditCertificatesDialog.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxEditCertificatesDialog.java
new file mode 100644
index 000000000000..b085f53895ad
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/JavaFxEditCertificatesDialog.java
@@ -0,0 +1,114 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging;
+
+import com.intellij.ide.util.BrowseFilesListener;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Base64Converter;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+/**
+ * User: anna
+ * Date: 3/15/13
+ */
+public class JavaFxEditCertificatesDialog extends DialogWrapper {
+
+ Panel myPanel;
+
+ protected JavaFxEditCertificatesDialog(JComponent parent, JavaFxArtifactProperties properties, Project project) {
+ super(parent, true);
+ setTitle("Choose Certificate");
+ init();
+ final ActionListener actionListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ UIUtil.setEnabled(myPanel.myKeysPanel, !myPanel.mySelfSignedRadioButton.isSelected(), true);
+ }
+ };
+ myPanel.mySelfSignedRadioButton.addActionListener(actionListener);
+ myPanel.mySignedByKeyRadioButton.addActionListener(actionListener);
+ final boolean selfSigning = properties.isSelfSigning();
+ UIUtil.setEnabled(myPanel.myKeysPanel, !selfSigning, true);
+ myPanel.mySelfSignedRadioButton.setSelected(selfSigning);
+ myPanel.mySignedByKeyRadioButton.setSelected(!selfSigning);
+
+ myPanel.myAliasTF.setText(properties.getAlias());
+ myPanel.myKeystore.setText(properties.getKeystore());
+ final String keypass = properties.getKeypass();
+ myPanel.myKeypassTF.setText(keypass != null ? Base64Converter.decode(keypass) : "");
+ final String storepass = properties.getStorepass();
+ myPanel.myStorePassTF.setText(storepass != null ? Base64Converter.decode(storepass) : "");
+ myPanel.myKeystore.addBrowseFolderListener("Choose Keystore File", "Select file containing generated keys", project, BrowseFilesListener.SINGLE_FILE_DESCRIPTOR);
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (myPanel.mySignedByKeyRadioButton.isSelected()) {
+ if (StringUtil.isEmptyOrSpaces(myPanel.myAliasTF.getText())) {
+ Messages.showErrorDialog(myPanel.myWholePanel, "Alias should be non-empty");
+ return;
+ }
+ final String keystore = myPanel.myKeystore.getText();
+ if (StringUtil.isEmptyOrSpaces(keystore)) {
+ Messages.showErrorDialog(myPanel.myWholePanel, "Path to the keystore file should be set");
+ return;
+ }
+ if (!new File(keystore).isFile()) {
+ Messages.showErrorDialog(myPanel.myWholePanel, "Keystore file should exist");
+ return;
+ }
+ if (StringUtil.isEmptyOrSpaces(String.valueOf(myPanel.myKeypassTF.getPassword())) ||
+ StringUtil.isEmptyOrSpaces(String.valueOf(myPanel.myStorePassTF.getPassword()))) {
+ Messages.showErrorDialog(myPanel.myWholePanel, "Passwords should be set");
+ return;
+ }
+ }
+ super.doOKAction();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ myPanel = new Panel();
+ return myPanel.myWholePanel;
+ }
+
+ @Override
+ protected void dispose() {
+ super.dispose();
+ }
+
+ protected static class Panel {
+ JRadioButton mySelfSignedRadioButton;
+ JRadioButton mySignedByKeyRadioButton;
+ JPasswordField myStorePassTF;
+ JPasswordField myKeypassTF;
+ JTextField myAliasTF;
+ TextFieldWithBrowseButton myKeystore;
+ JPanel myWholePanel;
+ JPanel myKeysPanel;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/ant/JavaFxChunkBuildExtension.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/ant/JavaFxChunkBuildExtension.java
new file mode 100644
index 000000000000..17565840f111
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/ant/JavaFxChunkBuildExtension.java
@@ -0,0 +1,239 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging.ant;
+
+import com.intellij.compiler.ant.*;
+import com.intellij.compiler.ant.artifacts.DirectoryAntCopyInstructionCreator;
+import com.intellij.compiler.ant.taskdefs.Property;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.JavaSdkType;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactManager;
+import com.intellij.packaging.artifacts.ArtifactType;
+import com.intellij.packaging.elements.*;
+import com.intellij.packaging.impl.elements.ArchivePackagingElement;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Base64Converter;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.packaging.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * User: anna
+ * Date: 3/14/13
+ */
+public class JavaFxChunkBuildExtension extends ChunkBuildExtension {
+
+ @NonNls public static final String ARTIFACT_VENDOR_SIGN_PROPERTY = "artifact.sign.vendor";
+ @NonNls public static final String ARTIFACT_ALIAS_SIGN_PROPERTY = "artifact.sign.alias";
+ @NonNls public static final String ARTIFACT_KEYSTORE_SIGN_PROPERTY = "artifact.sign.keystore";
+ @NonNls public static final String ARTIFACT_STOREPASS_SIGN_PROPERTY = "artifact.sign.storepass";
+ @NonNls public static final String ARTIFACTKEYPASS_SIGN_PROPERTY = "artifact.sign.keypass";
+
+ @NotNull
+ @Override
+ public String[] getTargets(ModuleChunk chunk) {
+ return ArrayUtil.EMPTY_STRING_ARRAY;
+ }
+
+ @Override
+ public void process(Project project, ModuleChunk chunk, GenerationOptions genOptions, CompositeGenerator generator) {}
+
+ @Override
+ public void initArtifacts(Project project, GenerationOptions genOptions, CompositeGenerator generator) {
+ final Collection<? extends Artifact> artifacts =
+ ArtifactManager.getInstance(project).getArtifactsByType(JavaFxApplicationArtifactType.getInstance());
+ if (artifacts.isEmpty()) return;
+ final Sdk[] jdks = BuildProperties.getUsedJdks(project);
+ Sdk javaSdk = null;
+ for (Sdk jdk : jdks) {
+ if (jdk.getSdkType() instanceof JavaSdkType) {
+ javaSdk = jdk;
+ break;
+ }
+ }
+ if (javaSdk != null) {
+ final Tag taskdef = new Tag("taskdef",
+ new Pair<String, String>("resource", "com/sun/javafx/tools/ant/antlib.xml"),
+ new Pair<String, String>("uri", "javafx:com.sun.javafx.tools.ant"),
+ new Pair<String, String>("classpath",
+ BuildProperties
+ .propertyRef(BuildProperties.getJdkHomeProperty(javaSdk.getName())) +
+ "/lib/ant-javafx.jar"));
+ generator.add(taskdef);
+ }
+ }
+
+ protected List<? extends Generator> computeChildrenGenerators(PackagingElementResolvingContext resolvingContext,
+ final AntCopyInstructionCreator copyInstructionCreator,
+ final ArtifactAntGenerationContext generationContext,
+ ArtifactType artifactType,
+ List<PackagingElement<?>> children) {
+ final List<Generator> generators = new ArrayList<Generator>();
+ for (PackagingElement<?> child : children) {
+ generators.addAll(child.computeAntInstructions(resolvingContext, copyInstructionCreator, generationContext, artifactType));
+ }
+ return generators;
+ }
+
+ @Override
+ public void generateTasksForArtifact(Artifact artifact,
+ boolean preprocessing,
+ ArtifactAntGenerationContext context,
+ CompositeGenerator generator) {
+ if (preprocessing) return;
+ if (!(artifact.getArtifactType() instanceof JavaFxApplicationArtifactType)) return;
+
+ final CompositePackagingElement<?> rootElement = artifact.getRootElement();
+
+ final List<PackagingElement<?>> children = new ArrayList<PackagingElement<?>>();
+ String artifactFileName = rootElement.getName();
+ for (PackagingElement<?> child : rootElement.getChildren()) {
+ if (child instanceof ArchivePackagingElement) {
+ artifactFileName = ((ArchivePackagingElement)child).getArchiveFileName();
+ children.addAll(((ArchivePackagingElement)child).getChildren());
+ } else {
+ children.add(child);
+ }
+ }
+
+ final String artifactName = FileUtil.getNameWithoutExtension(artifactFileName);
+
+ final String tempDirPath = BuildProperties.propertyRef(
+ context.createNewTempFileProperty("artifact.temp.output." + artifactName, artifactFileName));
+
+ final PackagingElementResolvingContext resolvingContext = ArtifactManager.getInstance(context.getProject()).getResolvingContext();
+ for (Generator childGenerator : computeChildrenGenerators(resolvingContext,
+ new DirectoryAntCopyInstructionCreator(tempDirPath),
+ context, artifact.getArtifactType(), children)) {
+ generator.add(childGenerator);
+ }
+
+ final JavaFxArtifactProperties properties =
+ (JavaFxArtifactProperties)artifact.getProperties(JavaFxArtifactPropertiesProvider.getInstance());
+
+ final JavaFxArtifactProperties.JavaFxPackager javaFxPackager =
+ new JavaFxArtifactProperties.JavaFxPackager(artifact, properties, context.getProject()) {
+ @Override
+ protected void registerJavaFxPackagerError(String message) {}
+ };
+ final List<JavaFxAntGenerator.SimpleTag> tags =
+ JavaFxAntGenerator.createJarAndDeployTasks(javaFxPackager, artifactFileName, artifactName, tempDirPath);
+ for (JavaFxAntGenerator.SimpleTag tag : tags) {
+ buildTags(generator, tag);
+ }
+
+ if (properties.isEnabledSigning()) {
+
+ final boolean selfSigning = properties.isSelfSigning();
+ String vendor = properties.getVendor();
+ if (vendor != null) {
+ vendor = vendor.replaceAll(",", "\\\\,") ;
+ }
+ generator.add(new Property(artifactBasedProperty(ARTIFACT_VENDOR_SIGN_PROPERTY, artifactName), "CN=" + vendor));
+
+ final String alias = selfSigning ? "jb" : properties.getAlias();
+ generator.add(new Property(artifactBasedProperty(ARTIFACT_ALIAS_SIGN_PROPERTY, artifactName), alias));
+
+ final String keystore = selfSigning ? tempDirPath + File.separator + "jb-key.jks" : properties.getKeystore();
+ generator.add(new Property(artifactBasedProperty(ARTIFACT_KEYSTORE_SIGN_PROPERTY, artifactName), keystore));
+
+ final String storepass = selfSigning ? "storepass" : Base64Converter.decode(properties.getStorepass());
+ generator.add(new Property(artifactBasedProperty(ARTIFACT_STOREPASS_SIGN_PROPERTY, artifactName), storepass));
+
+ final String keypass = selfSigning ? "keypass" : Base64Converter.decode(properties.getKeypass());
+ generator.add(new Property(artifactBasedProperty(ARTIFACTKEYPASS_SIGN_PROPERTY, artifactName), keypass));
+
+ final Pair[] keysDescriptions = createKeysDescriptions(artifactName);
+ if (selfSigning) {
+ generator.add(new Tag("genkey",
+ ArrayUtil.prepend(new Pair<String, String>("dname", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_VENDOR_SIGN_PROPERTY, artifactName))),
+ keysDescriptions)));
+ }
+
+ final Tag signjar = new Tag("signjar", keysDescriptions);
+ final Tag fileset = new Tag("fileset", new Pair<String, String>("dir", tempDirPath + "/deploy"));
+ fileset.add(new Tag("include", new Pair<String, String>("name", "*.jar")));
+ signjar.add(fileset);
+ generator.add(signjar);
+ }
+
+ final DirectoryAntCopyInstructionCreator creator = new DirectoryAntCopyInstructionCreator(BuildProperties.propertyRef(context.getConfiguredArtifactOutputProperty(artifact)));
+ generator.add(creator.createDirectoryContentCopyInstruction(tempDirPath + "/deploy"));
+ final Tag deleteTag = new Tag("delete", new Pair<String, String>("includeemptydirs", "true"));
+ deleteTag.add(new Tag("fileset", new Pair<String, String>("dir", tempDirPath)));
+ generator.add(deleteTag);
+ }
+
+ private static void buildTags(CompositeGenerator generator, final JavaFxAntGenerator.SimpleTag tag) {
+ final Tag newTag = new Tag(tag.getName(), tag.getPairs()){
+ @Override
+ public void generate(PrintWriter out) throws IOException {
+ final String value = tag.getValue();
+ if (value == null) {
+ super.generate(out);
+ } else {
+ out.print("<" + tag.getName() + ">" + value + "</" + tag.getName() + ">");
+ }
+ }
+ };
+
+ for (JavaFxAntGenerator.SimpleTag simpleTag : tag.getSubTags()) {
+ buildTags(newTag, simpleTag);
+ }
+ generator.add(newTag);
+ }
+
+ private static String artifactBasedProperty(final String property, String artifactName) {
+ return property + "." + artifactName;
+ }
+
+ private static Pair[] createKeysDescriptions(String artifactName) {
+ return new Pair[]{
+ new Pair<String, String>("alias", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_ALIAS_SIGN_PROPERTY, artifactName))),
+ new Pair<String, String>("keystore", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_KEYSTORE_SIGN_PROPERTY, artifactName))),
+ new Pair<String, String>("storepass", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACT_STOREPASS_SIGN_PROPERTY, artifactName))),
+ new Pair<String, String>("keypass", BuildProperties.propertyRef(artifactBasedProperty(ARTIFACTKEYPASS_SIGN_PROPERTY, artifactName)))};
+ }
+
+ @Nullable
+ @Override
+ public Pair<String, String> getArtifactXmlNs(ArtifactType artifactType) {
+ if (artifactType instanceof JavaFxApplicationArtifactType) {
+ return Pair.create("xmlns:fx", "javafx:com.sun.javafx.tools.ant");
+ }
+ return null;
+ }
+
+ @Override
+ public boolean needAntArtifactInstructions(ArtifactType type) {
+ if (type instanceof JavaFxApplicationArtifactType) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactProperties.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactProperties.java
new file mode 100644
index 000000000000..a7b65b0d72ca
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactProperties.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging.preloader;
+
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactProperties;
+import com.intellij.packaging.ui.ArtifactEditorContext;
+import com.intellij.packaging.ui.ArtifactPropertiesEditor;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * User: anna
+ * Date: 3/12/13
+ */
+public class JavaFxPreloaderArtifactProperties extends ArtifactProperties<JavaFxPreloaderArtifactProperties> {
+
+ private String myPreloaderClass;
+
+ @Override
+ public void onBuildFinished(@NotNull final Artifact artifact, @NotNull final CompileContext compileContext) {
+ }
+
+ @Override
+ public ArtifactPropertiesEditor createEditor(@NotNull ArtifactEditorContext context) {
+ return new JavaFxPreloaderArtifactPropertiesEditor(this, context.getProject(), context.getArtifact());
+ }
+
+ @Nullable
+ @Override
+ public JavaFxPreloaderArtifactProperties getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(JavaFxPreloaderArtifactProperties state) {
+ XmlSerializerUtil.copyBean(state, this);
+ }
+
+ public String getPreloaderClass() {
+ return myPreloaderClass;
+ }
+
+ public void setPreloaderClass(String preloaderClass) {
+ myPreloaderClass = preloaderClass;
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesEditor.form b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesEditor.form
new file mode 100644
index 000000000000..63d81cc566e9
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesEditor.form
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.javaFX.packaging.preloader.JavaFxPreloaderArtifactPropertiesEditor">
+ <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="92dfb" 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 value="&amp;Preloader class:"/>
+ </properties>
+ </component>
+ <hspacer id="45097">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ <vspacer id="88af">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="4b1e7" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myPreloaderTf">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesEditor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesEditor.java
new file mode 100644
index 000000000000..cdb0f21667c3
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesEditor.java
@@ -0,0 +1,77 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging.preloader;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.ui.ArtifactPropertiesEditor;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.packaging.JavaFxApplicationClassBrowser;
+
+import javax.swing.*;
+
+/**
+ * User: anna
+ * Date: 3/19/13
+ */
+public class JavaFxPreloaderArtifactPropertiesEditor extends ArtifactPropertiesEditor {
+ private final JavaFxPreloaderArtifactProperties myProperties;
+ private JPanel myPanel;
+ private TextFieldWithBrowseButton myPreloaderTf;
+
+ public JavaFxPreloaderArtifactPropertiesEditor(JavaFxPreloaderArtifactProperties properties, Project project, Artifact artifact) {
+ super();
+ myProperties = properties;
+ new JavaFxApplicationClassBrowser(project, artifact, "Choose Preloader Class") {
+ @Override
+ protected String getApplicationClass() {
+ return "javafx.application.Preloader";
+ }
+ }.setField(myPreloaderTf);
+ }
+
+ @Override
+ public String getTabName() {
+ return "JavaFX Preloader";
+ }
+
+ @Nullable
+ @Override
+ public JComponent createComponent() {
+ return myPanel;
+ }
+
+ @Override
+ public boolean isModified() {
+ return !Comparing.strEqual(myPreloaderTf.getText(), myProperties.getPreloaderClass());
+ }
+
+ @Override
+ public void apply() {
+ myProperties.setPreloaderClass(myPreloaderTf.getText());
+ }
+
+ @Override
+ public void reset() {
+ myPreloaderTf.setText(myProperties.getPreloaderClass());
+ }
+
+ @Override
+ public void disposeUIResources() {
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesProvider.java
new file mode 100644
index 000000000000..6790ff127d6d
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactPropertiesProvider.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.jetbrains.plugins.javaFX.packaging.preloader;
+
+import com.intellij.packaging.artifacts.ArtifactProperties;
+import com.intellij.packaging.artifacts.ArtifactPropertiesProvider;
+import com.intellij.packaging.artifacts.ArtifactType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: anna
+ * Date: 3/12/13
+ */
+public class JavaFxPreloaderArtifactPropertiesProvider extends ArtifactPropertiesProvider {
+ protected JavaFxPreloaderArtifactPropertiesProvider() {
+ super("javafx-preloader-properties");
+ }
+
+ @Override
+ public boolean isAvailableFor(@NotNull ArtifactType type) {
+ return type instanceof JavaFxPreloaderArtifactType;
+ }
+
+ @NotNull
+ @Override
+ public ArtifactProperties<?> createProperties(@NotNull ArtifactType artifactType) {
+ return new JavaFxPreloaderArtifactProperties();
+ }
+
+ public static JavaFxPreloaderArtifactPropertiesProvider getInstance() {
+ return EP_NAME.findExtension(JavaFxPreloaderArtifactPropertiesProvider.class);
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactType.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactType.java
new file mode 100644
index 000000000000..6163bd33a6ef
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/packaging/preloader/JavaFxPreloaderArtifactType.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 org.jetbrains.plugins.javaFX.packaging.preloader;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.packaging.artifacts.ArtifactType;
+import com.intellij.packaging.elements.CompositePackagingElement;
+import com.intellij.packaging.elements.PackagingElementFactory;
+import com.intellij.packaging.elements.PackagingElementOutputKind;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * User: anna
+ * Date: 3/12/13
+ */
+public class JavaFxPreloaderArtifactType extends ArtifactType {
+ public static JavaFxPreloaderArtifactType getInstance() {
+ return EP_NAME.findExtension(JavaFxPreloaderArtifactType.class);
+ }
+
+ protected JavaFxPreloaderArtifactType() {
+ super("javafx-preloader", "JavaFx Preloader");
+ }
+
+ @NotNull
+ @Override
+ public Icon getIcon() {
+ return AllIcons.Nodes.Artifact;
+ }
+
+ @Nullable
+ @Override
+ public String getDefaultPathFor(@NotNull PackagingElementOutputKind kind) {
+ return "/";
+ }
+
+ @NotNull
+ @Override
+ public CompositePackagingElement<?> createRootElement(@NotNull String artifactName) {
+ return PackagingElementFactory.getInstance().createArchive(artifactName + ".jar");
+ }
+}
diff --git a/plugins/javaFX/src/resources/projectTemplates/Java/JavaFX Application.zip b/plugins/javaFX/src/resources/projectTemplates/Java/JavaFX Application.zip
index 8a6023da00ac..de787de45029 100644
--- a/plugins/javaFX/src/resources/projectTemplates/Java/JavaFX Application.zip
+++ b/plugins/javaFX/src/resources/projectTemplates/Java/JavaFX Application.zip
Binary files differ
diff --git a/plugins/javaFX/testData/coercing/invalidDouble.fxml b/plugins/javaFX/testData/coercing/invalidDouble.fxml
new file mode 100644
index 000000000000..0ef82552a346
--- /dev/null
+++ b/plugins/javaFX/testData/coercing/invalidDouble.fxml
@@ -0,0 +1,7 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Button prefHeight="-Infinity"/>
+ <Button prefHeight=<error descr="Invalid value: unable to coerce to java.lang.Double">"xxx"</error>/>
+</GridPane>
+ \ No newline at end of file
diff --git a/plugins/javaFX/testData/coercing/invalidInteger.fxml b/plugins/javaFX/testData/coercing/invalidInteger.fxml
new file mode 100644
index 000000000000..1ee14a4c1180
--- /dev/null
+++ b/plugins/javaFX/testData/coercing/invalidInteger.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Button GridPane.columnIndex=<error descr="Invalid value: unable to coerce to java.lang.Integer">"1.7"</error>/>
+</GridPane>
diff --git a/plugins/javaFX/testData/coercing/referencedTag.fxml b/plugins/javaFX/testData/coercing/referencedTag.fxml
new file mode 100644
index 000000000000..fcb45b0d09ee
--- /dev/null
+++ b/plugins/javaFX/testData/coercing/referencedTag.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:id="foo">
+ <columnConstraints>
+ <<error descr="Unable to coerce javafx.scene.layout.GridPane to javafx.scene.layout.ColumnConstraints">fx:reference</error> source="foo"/>
+ </columnConstraints>
+</GridPane>
diff --git a/plugins/javaFX/testData/coercing/rootTagSubtagsCoercing.fxml b/plugins/javaFX/testData/coercing/rootTagSubtagsCoercing.fxml
new file mode 100644
index 000000000000..d44cb8ddd612
--- /dev/null
+++ b/plugins/javaFX/testData/coercing/rootTagSubtagsCoercing.fxml
@@ -0,0 +1,18 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<?import java.lang.String?>
+<?import javafx.collections.FXCollections?>
+<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml">
+ <fx:define>
+ <FXCollections fx:factory="observableArrayList">
+ <String fx:value="A"/>
+ <String fx:value="B"/>
+ <String fx:value="C"/>
+ </FXCollections>
+ </fx:define>
+ <<error descr="Unable to coerce javafx.collections.FXCollections to javafx.scene.Node">FXCollections</error> fx:factory="observableArrayList">
+ <String fx:value="A"/>
+ <String fx:value="B"/>
+ <String fx:value="C"/>
+ </<error descr="Unable to coerce javafx.collections.FXCollections to javafx.scene.Node">FXCollections</error>>
+</fx:root> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/acceptableSourceOnly.fxml b/plugins/javaFX/testData/completion/acceptableSourceOnly.fxml
new file mode 100644
index 000000000000..350e929d2a08
--- /dev/null
+++ b/plugins/javaFX/testData/completion/acceptableSourceOnly.fxml
@@ -0,0 +1,7 @@
+<?import javafx.scene.layout.GridPane?>
+
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:id="foo">
+ <rowConstraints>
+ <fx:reference source="<caret>"/>
+ </rowConstraints>
+</GridPane>
diff --git a/plugins/javaFX/testData/completion/allowPropertyTypeClass.fxml b/plugins/javaFX/testData/completion/allowPropertyTypeClass.fxml
new file mode 100644
index 000000000000..4a8aa968f84e
--- /dev/null
+++ b/plugins/javaFX/testData/completion/allowPropertyTypeClass.fxml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml" >
+ <columnConstraints>
+ <<caret>
+ </columnConstraints>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/allowPropertyTypeClass_after.fxml b/plugins/javaFX/testData/completion/allowPropertyTypeClass_after.fxml
new file mode 100644
index 000000000000..ee4d67f86282
--- /dev/null
+++ b/plugins/javaFX/testData/completion/allowPropertyTypeClass_after.fxml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml" >
+ <columnConstraints>
+ <ColumnConstraints
+ </columnConstraints>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/booleanValues.fxml b/plugins/javaFX/testData/completion/booleanValues.fxml
new file mode 100644
index 000000000000..39a9a8ed62ca
--- /dev/null
+++ b/plugins/javaFX/testData/completion/booleanValues.fxml
@@ -0,0 +1,2 @@
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml" focusTraversable="<caret>"/> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/childrenInsideGridPaneRoot.fxml b/plugins/javaFX/testData/completion/childrenInsideGridPaneRoot.fxml
new file mode 100644
index 000000000000..31a14d1825bd
--- /dev/null
+++ b/plugins/javaFX/testData/completion/childrenInsideGridPaneRoot.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Label?>
+<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml">
+ <<caret>
+</fx:root>
diff --git a/plugins/javaFX/testData/completion/childrenInsideGridPaneRoot_after.fxml b/plugins/javaFX/testData/completion/childrenInsideGridPaneRoot_after.fxml
new file mode 100644
index 000000000000..139056bcaf8f
--- /dev/null
+++ b/plugins/javaFX/testData/completion/childrenInsideGridPaneRoot_after.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Label?>
+<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml">
+ <children
+</fx:root>
diff --git a/plugins/javaFX/testData/completion/classInsideObjectProperty.fxml b/plugins/javaFX/testData/completion/classInsideObjectProperty.fxml
new file mode 100644
index 000000000000..78c935734fbb
--- /dev/null
+++ b/plugins/javaFX/testData/completion/classInsideObjectProperty.fxml
@@ -0,0 +1,7 @@
+<?import javafx.scene.layout.GridPane?>
+
+<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <padding>
+ <<caret>
+ </padding>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/classInsideObjectProperty_after.fxml b/plugins/javaFX/testData/completion/classInsideObjectProperty_after.fxml
new file mode 100644
index 000000000000..3d2afaddcfb1
--- /dev/null
+++ b/plugins/javaFX/testData/completion/classInsideObjectProperty_after.fxml
@@ -0,0 +1,8 @@
+<?import javafx.scene.layout.GridPane?>
+
+<?import javafx.geometry.Insets?>
+<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <padding>
+ <Insets
+ </padding>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/defaultPropertyIncludeOnce.fxml b/plugins/javaFX/testData/completion/defaultPropertyIncludeOnce.fxml
new file mode 100644
index 000000000000..d7dd03be80af
--- /dev/null
+++ b/plugins/javaFX/testData/completion/defaultPropertyIncludeOnce.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:id="foo">
+ <fx:ref<caret>
+</GridPane>
diff --git a/plugins/javaFX/testData/completion/defaultPropertyWrappedField.fxml b/plugins/javaFX/testData/completion/defaultPropertyWrappedField.fxml
new file mode 100644
index 000000000000..1670c52bd515
--- /dev/null
+++ b/plugins/javaFX/testData/completion/defaultPropertyWrappedField.fxml
@@ -0,0 +1,4 @@
+<?import javafx.scene.image.*?>
+<ImageView id="lock" pickOnBounds="true">
+ <<caret>
+</ImageView> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/includedRootAttributes.fxml b/plugins/javaFX/testData/completion/includedRootAttributes.fxml
new file mode 100644
index 000000000000..27fe29024865
--- /dev/null
+++ b/plugins/javaFX/testData/completion/includedRootAttributes.fxml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:include source="foo.fxml" <caret> />
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/includedRootAttributes_after.fxml b/plugins/javaFX/testData/completion/includedRootAttributes_after.fxml
new file mode 100644
index 000000000000..5dd1813f52bc
--- /dev/null
+++ b/plugins/javaFX/testData/completion/includedRootAttributes_after.fxml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:include source="foo.fxml" layoutY="" />
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/includedRootRootAttributes.fxml b/plugins/javaFX/testData/completion/includedRootRootAttributes.fxml
new file mode 100644
index 000000000000..72bdcbb9b71b
--- /dev/null
+++ b/plugins/javaFX/testData/completion/includedRootRootAttributes.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:define>
+ <fx:include source="sample.fxml" <caret>/>
+ </fx:define>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/includedRootRootAttributes_after.fxml b/plugins/javaFX/testData/completion/includedRootRootAttributes_after.fxml
new file mode 100644
index 000000000000..88771dbb5f51
--- /dev/null
+++ b/plugins/javaFX/testData/completion/includedRootRootAttributes_after.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:define>
+ <fx:include source="sample.fxml" blendMode=""/>
+ </fx:define>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/infinity.fxml b/plugins/javaFX/testData/completion/infinity.fxml
new file mode 100644
index 000000000000..f964ef327687
--- /dev/null
+++ b/plugins/javaFX/testData/completion/infinity.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Button prefHeight="<caret>"/>
+</GridPane>
diff --git a/plugins/javaFX/testData/completion/namedColors.fxml b/plugins/javaFX/testData/completion/namedColors.fxml
new file mode 100644
index 000000000000..dda432697fcb
--- /dev/null
+++ b/plugins/javaFX/testData/completion/namedColors.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Label text="foo" textFill="<caret>"/>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/namedColors_after.fxml b/plugins/javaFX/testData/completion/namedColors_after.fxml
new file mode 100644
index 000000000000..e1b752eca61d
--- /dev/null
+++ b/plugins/javaFX/testData/completion/namedColors_after.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Label text="foo" textFill="blue"/>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/noInfinity.fxml b/plugins/javaFX/testData/completion/noInfinity.fxml
new file mode 100644
index 000000000000..189d04b5d6fd
--- /dev/null
+++ b/plugins/javaFX/testData/completion/noInfinity.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Button GridPane.columnIndex="<caret>"/>
+</GridPane>
diff --git a/plugins/javaFX/testData/completion/primitiveProperties.fxml b/plugins/javaFX/testData/completion/primitiveProperties.fxml
new file mode 100644
index 000000000000..d5f3e0177a4f
--- /dev/null
+++ b/plugins/javaFX/testData/completion/primitiveProperties.fxml
@@ -0,0 +1,8 @@
+<?import javafx.scene.layout.GridPane?>
+
+<?import javafx.geometry.Insets?>
+<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <padding>
+ <Insets <caret>/>
+ </padding>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/primitiveProperties_after.fxml b/plugins/javaFX/testData/completion/primitiveProperties_after.fxml
new file mode 100644
index 000000000000..762a394a4af0
--- /dev/null
+++ b/plugins/javaFX/testData/completion/primitiveProperties_after.fxml
@@ -0,0 +1,8 @@
+<?import javafx.scene.layout.GridPane?>
+
+<?import javafx.geometry.Insets?>
+<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <padding>
+ <Insets top=""/>
+ </padding>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/primitiveSubtags.fxml b/plugins/javaFX/testData/completion/primitiveSubtags.fxml
new file mode 100644
index 000000000000..1670c52bd515
--- /dev/null
+++ b/plugins/javaFX/testData/completion/primitiveSubtags.fxml
@@ -0,0 +1,4 @@
+<?import javafx.scene.image.*?>
+<ImageView id="lock" pickOnBounds="true">
+ <<caret>
+</ImageView> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/rootTagNameLayout.fxml b/plugins/javaFX/testData/completion/rootTagNameLayout.fxml
new file mode 100644
index 000000000000..b21e7544ac82
--- /dev/null
+++ b/plugins/javaFX/testData/completion/rootTagNameLayout.fxml
@@ -0,0 +1 @@
+<G<caret> \ No newline at end of file
diff --git a/plugins/javaFX/testData/completion/rootTagNameLayout_after.fxml b/plugins/javaFX/testData/completion/rootTagNameLayout_after.fxml
new file mode 100644
index 000000000000..250f4bf9d379
--- /dev/null
+++ b/plugins/javaFX/testData/completion/rootTagNameLayout_after.fxml
@@ -0,0 +1,2 @@
+<?import javafx.scene.layout.GridPane?>
+<GridPane \ No newline at end of file
diff --git a/plugins/javaFX/testData/generateGetterSetter/afterDouble.java b/plugins/javaFX/testData/generateGetterSetter/afterDouble.java
new file mode 100644
index 000000000000..3fadfcb8cc5e
--- /dev/null
+++ b/plugins/javaFX/testData/generateGetterSetter/afterDouble.java
@@ -0,0 +1,17 @@
+import javafx.beans.property.DoubleProperty;
+import javafx.beans.property.SimpleDoubleProperty;
+public class Test {
+ public double getField() {
+ return field.get();
+ }
+
+ public DoubleProperty fieldProperty() {
+ return field;
+ }
+
+ public void setField(double field) {
+ this.field.set(field);
+ }
+
+ private DoubleProperty field = new SimpleDoubleProperty();
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/generateGetterSetter/afterString.java b/plugins/javaFX/testData/generateGetterSetter/afterString.java
new file mode 100644
index 000000000000..a2d3d41392b4
--- /dev/null
+++ b/plugins/javaFX/testData/generateGetterSetter/afterString.java
@@ -0,0 +1,5 @@
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+public class Test {
+ private ObjectProperty<String> ob<caret>j = new SimpleObjectProperty<String>();
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/generateGetterSetter/beforeDouble.java b/plugins/javaFX/testData/generateGetterSetter/beforeDouble.java
new file mode 100644
index 000000000000..a0c16d3b2646
--- /dev/null
+++ b/plugins/javaFX/testData/generateGetterSetter/beforeDouble.java
@@ -0,0 +1,5 @@
+import javafx.beans.property.DoubleProperty;
+import javafx.beans.property.SimpleDoubleProperty;
+public class Test {
+ private DoubleProperty fie<caret>ld = new SimpleDoubleProperty();
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/generateGetterSetter/beforeString.java b/plugins/javaFX/testData/generateGetterSetter/beforeString.java
new file mode 100644
index 000000000000..a2d3d41392b4
--- /dev/null
+++ b/plugins/javaFX/testData/generateGetterSetter/beforeString.java
@@ -0,0 +1,5 @@
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+public class Test {
+ private ObjectProperty<String> ob<caret>j = new SimpleObjectProperty<String>();
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/InjectedControllerFields.java b/plugins/javaFX/testData/highlighting/InjectedControllerFields.java
new file mode 100644
index 000000000000..2e61c3cbca81
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/InjectedControllerFields.java
@@ -0,0 +1,16 @@
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+
+public class InjectedControllerFields {
+ @FXML
+ private Button id1;
+
+ @FXML
+ private Button <warning descr="Private field 'idUnmapped' is never assigned">idUnmapped</warning>;
+
+ {
+ System.out.println(id1);
+ System.out.println(idUnmapped);
+ }
+
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/MyController.java b/plugins/javaFX/testData/highlighting/MyController.java
new file mode 100644
index 000000000000..2603234ac39e
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/MyController.java
@@ -0,0 +1 @@
+public class MyController {} \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/NoParamsHandler.java b/plugins/javaFX/testData/highlighting/NoParamsHandler.java
new file mode 100644
index 000000000000..c96768e76861
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/NoParamsHandler.java
@@ -0,0 +1,4 @@
+public class Controller {
+ public void sayHelloWorld() {
+ }
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/WrongBindingType.java b/plugins/javaFX/testData/highlighting/WrongBindingType.java
new file mode 100644
index 000000000000..9b6e00533328
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/WrongBindingType.java
@@ -0,0 +1,4 @@
+import javafx.scene.control.Label;
+public class WrongBindingType {
+ public Label label;
+}
diff --git a/plugins/javaFX/testData/highlighting/absenceOfDefineAttributes.fxml b/plugins/javaFX/testData/highlighting/absenceOfDefineAttributes.fxml
new file mode 100644
index 000000000000..1d336191b51c
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/absenceOfDefineAttributes.fxml
@@ -0,0 +1,3 @@
+<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml">
+ <fx:define <error descr="Attribute source is not allowed here">source</error>=""/>
+</fx:root> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/acceptReferenceInsideDefine.fxml b/plugins/javaFX/testData/highlighting/acceptReferenceInsideDefine.fxml
new file mode 100644
index 000000000000..e57bf587ea56
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/acceptReferenceInsideDefine.fxml
@@ -0,0 +1,8 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Button fx:id="btn1"/>
+ <fx:define>
+ <fx:reference source="btn1"/>
+ </fx:define>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/allowIncludeTagInsideDefine.fxml b/plugins/javaFX/testData/highlighting/allowIncludeTagInsideDefine.fxml
new file mode 100644
index 000000000000..f085057ef20f
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/allowIncludeTagInsideDefine.fxml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.image.*?>
+
+<AnchorPane xmlns:fx="http://javafx.com/fxml">
+ <fx:define>
+ <fx:include source="btn.fxml"/>
+ <fx:include source="<error descr="Cannot resolve file 'btn1.fxml'">btn1.fxml</error>"/>
+ </fx:define>
+</AnchorPane>
diff --git a/plugins/javaFX/testData/highlighting/btn.fxml b/plugins/javaFX/testData/highlighting/btn.fxml
index 6444aa8b4cda..9b51f22e4142 100644
--- a/plugins/javaFX/testData/highlighting/btn.fxml
+++ b/plugins/javaFX/testData/highlighting/btn.fxml
@@ -1,2 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
+<?import javafx.scene.control.*?>
<Button/> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/charsetInInclude.fxml b/plugins/javaFX/testData/highlighting/charsetInInclude.fxml
new file mode 100644
index 000000000000..9a8ae0edb713
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/charsetInInclude.fxml
@@ -0,0 +1,3 @@
+<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml">
+ <fx:include source="sample.fxml" charset="UTF-8"/>
+</fx:root> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/copyReference.fxml b/plugins/javaFX/testData/highlighting/copyReference.fxml
new file mode 100644
index 000000000000..bf05131ffe81
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/copyReference.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.control.Button?>
+<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml">
+ <<error descr="Copy constructor not found for 'Button'">fx:copy</error> source="<error descr="btn not found">btn</error>"/>
+ <Button fx:id="btn"/>
+</fx:root> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/custom/CustomComponentFieldsWithSameProperties.java b/plugins/javaFX/testData/highlighting/custom/CustomComponentFieldsWithSameProperties.java
new file mode 100644
index 000000000000..6ef68ccdc357
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/custom/CustomComponentFieldsWithSameProperties.java
@@ -0,0 +1,30 @@
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.VBox;
+
+
+public class CustomVBox extends VBox {
+ @FXML
+ Label label;
+
+ @FXML
+ Button button;
+
+ public Button getButton() {
+ return button;
+ }
+
+ public void setButton(Button button) {
+ this.button = button;
+ }
+
+ public Label getLabel() {
+ return label;
+ }
+
+ public void setLabel(Label label) {
+ this.label = label;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/custom/customComponentFieldsWithSameProperties.fxml b/plugins/javaFX/testData/highlighting/custom/customComponentFieldsWithSameProperties.fxml
new file mode 100644
index 000000000000..6df0c6e88f6b
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/custom/customComponentFieldsWithSameProperties.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.control.Button?>
+<fx:root type="CustomVBox" xmlns:fx="http://javafx.com/fxml" >
+ <Label fx:id="label"/>
+</fx:root> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/defaultPropertyField.fxml b/plugins/javaFX/testData/highlighting/defaultPropertyField.fxml
new file mode 100644
index 000000000000..df6b79c789e6
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/defaultPropertyField.fxml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.image.*?>
+<AnchorPane xmlns:fx="http://javafx.com/fxml">
+ <ImageView id="lock" pickOnBounds="true">
+ <Image url="" preserveRatio="true" smooth="true"/>
+ </ImageView>
+</AnchorPane>
diff --git a/plugins/javaFX/testData/highlighting/idOutOfHierarchy.fxml b/plugins/javaFX/testData/highlighting/idOutOfHierarchy.fxml
new file mode 100644
index 000000000000..293910b9b238
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/idOutOfHierarchy.fxml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.image.*?>
+
+<AnchorPane xmlns:fx="http://javafx.com/fxml" fx:controller="MyController">
+ <fx:define>
+ <fx:include fx:id="foo" source="btn.fxml"/>
+ </fx:define>
+</AnchorPane>
diff --git a/plugins/javaFX/testData/highlighting/includedForm.fxml b/plugins/javaFX/testData/highlighting/includedForm.fxml
new file mode 100644
index 000000000000..e0fea5e56d28
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/includedForm.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:define>
+ <fx:include source="sample.fxml"/>
+ </fx:define>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/injected/FooVBox.java b/plugins/javaFX/testData/highlighting/injected/FooVBox.java
new file mode 100644
index 000000000000..25e802bd649a
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/injected/FooVBox.java
@@ -0,0 +1,25 @@
+package injected;
+
+import javafx.fxml.FXMLLoader;
+import javafx.scene.layout.VBox;
+
+import java.io.IOException;
+
+
+public class FooVBox extends VBox{
+ private void loaderCreation() {
+ MyController controller = new MyController();
+ FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("injectedController.fxml"));
+ fxmlLoader.setRoot(this);
+ fxmlLoader.setController(controller);
+
+ try {
+ fxmlLoader.load();
+ } catch (IOException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+ public FooVBox() {
+ loaderCreation();
+ }
+}
diff --git a/plugins/javaFX/testData/highlighting/injected/MyController.java b/plugins/javaFX/testData/highlighting/injected/MyController.java
new file mode 100644
index 000000000000..d175ae2cf290
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/injected/MyController.java
@@ -0,0 +1,7 @@
+package injected;
+
+import javafx.scene.control.Label;
+
+public class MyController {
+ public Label label;
+}
diff --git a/plugins/javaFX/testData/highlighting/injected/injectedController.fxml b/plugins/javaFX/testData/highlighting/injected/injectedController.fxml
new file mode 100644
index 000000000000..524575935010
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/injected/injectedController.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.Button?>
+<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
+ <Label fx:id="la<caret>bel" />
+</fx:root> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/lineChartInstantiation.fxml b/plugins/javaFX/testData/highlighting/lineChartInstantiation.fxml
new file mode 100644
index 000000000000..51fb18a92880
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/lineChartInstantiation.fxml
@@ -0,0 +1,9 @@
+<?import javafx.scene.chart.LineChart?>
+<?import javafx.scene.layout.BorderPane?>
+<BorderPane prefHeight="-1.0" prefWidth="-1.0" xmlns:fx="http://javafx.com/fxml">
+ <center>
+ <LineChart fx:id="chart" alternativeColumnFillVisible="false" alternativeRowFillVisible="false" animated="true"
+ horizontalGridLinesVisible="true" legendVisible="false">
+ </LineChart>
+ </center>
+</BorderPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/namedColor.fxml b/plugins/javaFX/testData/highlighting/namedColor.fxml
new file mode 100644
index 000000000000..7322af9e0fb9
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/namedColor.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Label text="foo" textFill="oran<caret>ge"/>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/noParamsHandler.fxml b/plugins/javaFX/testData/highlighting/noParamsHandler.fxml
new file mode 100644
index 000000000000..a4fc85b8606b
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/noParamsHandler.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="Controller">
+ <Button onAction="#sayHelloWorld"/>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/primitiveSubtags.fxml b/plugins/javaFX/testData/highlighting/primitiveSubtags.fxml
new file mode 100644
index 000000000000..4174f625297c
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/primitiveSubtags.fxml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.image.*?>
+<ImageView id="lock" pickOnBounds="true">
+ <<error descr="Element geomBoundsInvalid is not allowed here">geomBoundsInvalid</error>/>
+</ImageView>
diff --git a/plugins/javaFX/testData/highlighting/referencePosition.fxml b/plugins/javaFX/testData/highlighting/referencePosition.fxml
new file mode 100644
index 000000000000..e30b164dabc5
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/referencePosition.fxml
@@ -0,0 +1,12 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:reference source="<error descr="btn not found">btn</error>"/>
+ <GridPane>
+ <Button fx:id="btn"/>
+ <Button fx:id="btn1"/>
+ </GridPane>
+ <fx:reference source="btn1"/>
+ <Button fx:id="btn2"/>
+ <fx:reference source="<error descr="Duplicate child added">btn2</error>"/>
+</GridPane>
diff --git a/plugins/javaFX/testData/highlighting/rootTagCoercedUnchecked.fxml b/plugins/javaFX/testData/highlighting/rootTagCoercedUnchecked.fxml
new file mode 100644
index 000000000000..03a9f9383a7b
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/rootTagCoercedUnchecked.fxml
@@ -0,0 +1,3 @@
+<?import javafx.scene.control.*?>
+
+<Tab text="Tab Title" xmlns:fx="http://javafx.com/fxml"/>
diff --git a/plugins/javaFX/testData/highlighting/rootTagOnDifferentLevels.fxml b/plugins/javaFX/testData/highlighting/rootTagOnDifferentLevels.fxml
new file mode 100644
index 000000000000..6429fc06ee4f
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/rootTagOnDifferentLevels.fxml
@@ -0,0 +1,10 @@
+<?import javafx.scene.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <<error descr="<fx:root> is valid only as the root node of an FXML document">fx:root</error> type="javafx.scene.layout.AnchorPane"/>
+ <fx:define>
+ <<error descr="<fx:root> is valid only as the root node of an FXML document">fx:root</error> type="javafx.scene.layout.AnchorPane"/>
+ </fx:define>
+ <GridPane>
+ <<error descr="<fx:root> is valid only as the root node of an FXML document">fx:root</error> type="javafx.scene.layout.AnchorPane"/>
+ </GridPane>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/staticPropertiesCustomLayout.fxml b/plugins/javaFX/testData/highlighting/staticPropertiesCustomLayout.fxml
new file mode 100644
index 000000000000..6b3f50f8b3cf
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/staticPropertiesCustomLayout.fxml
@@ -0,0 +1,7 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<?import MyGridPane?>
+<MyGridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <GridPane.columnIndex>1</GridPane.columnIndex>
+ <Button GridPane.columnIndex="0"/>
+</MyGridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/unexpectedNode.fxml b/plugins/javaFX/testData/highlighting/unexpectedNode.fxml
new file mode 100644
index 000000000000..a5a6998f4bfe
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/unexpectedNode.fxml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<?import java.lang.Double?>
+
+<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center">
+ <<error descr="Unable to coerce java.lang.Double to javafx.scene.Node">Double</error> />
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/wrongBindingType.fxml b/plugins/javaFX/testData/highlighting/wrongBindingType.fxml
new file mode 100644
index 000000000000..72d5ad071a19
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/wrongBindingType.fxml
@@ -0,0 +1,7 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Label?>
+
+<?import javafx.scene.control.TextField?>
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="WrongBindingType">
+ <TextField fx:id=<error descr="Cannot set javafx.scene.control.TextField to field 'label'">"label"</error>/>
+</GridPane>
diff --git a/plugins/javaFX/testData/importing/Insets.java b/plugins/javaFX/testData/importing/Insets.java
new file mode 100644
index 000000000000..a2b88dadd303
--- /dev/null
+++ b/plugins/javaFX/testData/importing/Insets.java
@@ -0,0 +1 @@
+public class Insets {} \ No newline at end of file
diff --git a/plugins/javaFX/testData/importing/TextField.java b/plugins/javaFX/testData/importing/TextField.java
new file mode 100644
index 000000000000..4165dc7e7127
--- /dev/null
+++ b/plugins/javaFX/testData/importing/TextField.java
@@ -0,0 +1,2 @@
+package foo;
+public class TextField {} \ No newline at end of file
diff --git a/plugins/javaFX/testData/importing/insets.fxml b/plugins/javaFX/testData/importing/insets.fxml
new file mode 100644
index 000000000000..02f0fee3a104
--- /dev/null
+++ b/plugins/javaFX/testData/importing/insets.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.layout.GridPane?>
+<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <padding>
+ <In<caret>sets/>
+ </padding>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/importing/insets_after.fxml b/plugins/javaFX/testData/importing/insets_after.fxml
new file mode 100644
index 000000000000..53d5f7173544
--- /dev/null
+++ b/plugins/javaFX/testData/importing/insets_after.fxml
@@ -0,0 +1,7 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.geometry.Insets?>
+<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <padding>
+ <Insets/>
+ </padding>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/importing/textField.fxml b/plugins/javaFX/testData/importing/textField.fxml
new file mode 100644
index 000000000000..287a3de9e50c
--- /dev/null
+++ b/plugins/javaFX/testData/importing/textField.fxml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <children>
+ <Text<caret>Field/>
+ </children>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/importing/textField_after.fxml b/plugins/javaFX/testData/importing/textField_after.fxml
new file mode 100644
index 000000000000..33fc9150b877
--- /dev/null
+++ b/plugins/javaFX/testData/importing/textField_after.fxml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.control.TextField?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <children>
+ <TextField/>
+ </children>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/inspections/unresolvedFxId/Controller.java b/plugins/javaFX/testData/inspections/unresolvedFxId/Controller.java
new file mode 100644
index 000000000000..df5fbfcbfd00
--- /dev/null
+++ b/plugins/javaFX/testData/inspections/unresolvedFxId/Controller.java
@@ -0,0 +1 @@
+public class Controller {} \ No newline at end of file
diff --git a/plugins/javaFX/testData/inspections/unresolvedFxId/Controller_after.java b/plugins/javaFX/testData/inspections/unresolvedFxId/Controller_after.java
new file mode 100644
index 000000000000..17cf32880e93
--- /dev/null
+++ b/plugins/javaFX/testData/inspections/unresolvedFxId/Controller_after.java
@@ -0,0 +1,5 @@
+import javafx.scene.control.TextField;
+
+public class Controller {
+ public TextField unknown;
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/inspections/unresolvedFxId/unknownRef.fxml b/plugins/javaFX/testData/inspections/unresolvedFxId/unknownRef.fxml
new file mode 100644
index 000000000000..f6269415a2e1
--- /dev/null
+++ b/plugins/javaFX/testData/inspections/unresolvedFxId/unknownRef.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.TextField?>
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="Controller">
+ <TextField fx:id="unk<caret>nown"/>
+</GridPane>
diff --git a/plugins/javaFX/testData/intentions/collapseToAttr/styleclass.fxml b/plugins/javaFX/testData/intentions/collapseToAttr/styleclass.fxml
new file mode 100644
index 000000000000..fa6206448c57
--- /dev/null
+++ b/plugins/javaFX/testData/intentions/collapseToAttr/styleclass.fxml
@@ -0,0 +1,9 @@
+<?import javafx.scene.layout.GridPane?>
+
+<?import java.lang.String?>
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:id="foo">
+ <style<caret>Class>
+ <String fx:value="foo"/>
+ <String fx:value="foo1"/>
+ </styleClass>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/intentions/collapseToAttr/styleclass_after.fxml b/plugins/javaFX/testData/intentions/collapseToAttr/styleclass_after.fxml
new file mode 100644
index 000000000000..4bcd223a6f63
--- /dev/null
+++ b/plugins/javaFX/testData/intentions/collapseToAttr/styleclass_after.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+
+<?import java.lang.String?>
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:id="foo" styleClass="foo, foo1">
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/optimizeImports/dblImports.fxml b/plugins/javaFX/testData/optimizeImports/dblImports.fxml
new file mode 100644
index 000000000000..c62c5daa662e
--- /dev/null
+++ b/plugins/javaFX/testData/optimizeImports/dblImports.fxml
@@ -0,0 +1,7 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.layout.*?>
+<BorderPane xmlns:fx="http://javafx.com/fxml">
+ <Label/>
+ <Label/>
+</BorderPane>
diff --git a/plugins/javaFX/testData/optimizeImports/dblImports_after.fxml b/plugins/javaFX/testData/optimizeImports/dblImports_after.fxml
new file mode 100644
index 000000000000..4a1f763fb1f2
--- /dev/null
+++ b/plugins/javaFX/testData/optimizeImports/dblImports_after.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.BorderPane?>
+<BorderPane xmlns:fx="http://javafx.com/fxml">
+ <Label/>
+ <Label/>
+</BorderPane>
diff --git a/plugins/javaFX/testData/optimizeImports/staticPropertiesAttrAndCustomComponents.fxml b/plugins/javaFX/testData/optimizeImports/staticPropertiesAttrAndCustomComponents.fxml
new file mode 100644
index 000000000000..68fdd3467344
--- /dev/null
+++ b/plugins/javaFX/testData/optimizeImports/staticPropertiesAttrAndCustomComponents.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.layout.GridPane?>
+<?import MyGridPane?>
+<MyGridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <Button GridPane.columnIndex="0"/>
+</MyGridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/optimizeImports/staticPropertiesAttrAndCustomComponents_after.fxml b/plugins/javaFX/testData/optimizeImports/staticPropertiesAttrAndCustomComponents_after.fxml
new file mode 100644
index 000000000000..68fdd3467344
--- /dev/null
+++ b/plugins/javaFX/testData/optimizeImports/staticPropertiesAttrAndCustomComponents_after.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.layout.GridPane?>
+<?import MyGridPane?>
+<MyGridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <Button GridPane.columnIndex="0"/>
+</MyGridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/optimizeImports/staticPropertiesTagAndCustomComponents.fxml b/plugins/javaFX/testData/optimizeImports/staticPropertiesTagAndCustomComponents.fxml
new file mode 100644
index 000000000000..4e26323a0b83
--- /dev/null
+++ b/plugins/javaFX/testData/optimizeImports/staticPropertiesTagAndCustomComponents.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import MyGridPane?>
+<MyGridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <GridPane.columnIndex>1</GridPane.columnIndex>
+</MyGridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/optimizeImports/staticPropertiesTagAndCustomComponents_after.fxml b/plugins/javaFX/testData/optimizeImports/staticPropertiesTagAndCustomComponents_after.fxml
new file mode 100644
index 000000000000..4e26323a0b83
--- /dev/null
+++ b/plugins/javaFX/testData/optimizeImports/staticPropertiesTagAndCustomComponents_after.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import MyGridPane?>
+<MyGridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
+ <GridPane.columnIndex>1</GridPane.columnIndex>
+</MyGridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/quickfix/CreateControllerMethodInGroovy.groovy b/plugins/javaFX/testData/quickfix/CreateControllerMethodInGroovy.groovy
new file mode 100644
index 000000000000..2ad9064e8815
--- /dev/null
+++ b/plugins/javaFX/testData/quickfix/CreateControllerMethodInGroovy.groovy
@@ -0,0 +1 @@
+public class CreateControllerMethodInGroovy {} \ No newline at end of file
diff --git a/plugins/javaFX/testData/quickfix/CreateControllerMethodInGroovy_after.groovy b/plugins/javaFX/testData/quickfix/CreateControllerMethodInGroovy_after.groovy
new file mode 100644
index 000000000000..0d4740e36633
--- /dev/null
+++ b/plugins/javaFX/testData/quickfix/CreateControllerMethodInGroovy_after.groovy
@@ -0,0 +1,5 @@
+public class CreateControllerMethodInGroovy {
+ public void bar(ActionEvent actionEvent) {
+ //To change body of created methods use File | Settings | File Templates.
+ }
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/quickfix/CreateField.java b/plugins/javaFX/testData/quickfix/CreateField.java
new file mode 100644
index 000000000000..e72dc651892b
--- /dev/null
+++ b/plugins/javaFX/testData/quickfix/CreateField.java
@@ -0,0 +1 @@
+public class CreateControllerMethod {} \ No newline at end of file
diff --git a/plugins/javaFX/testData/quickfix/CreateField_after.java b/plugins/javaFX/testData/quickfix/CreateField_after.java
new file mode 100644
index 000000000000..a247a27be877
--- /dev/null
+++ b/plugins/javaFX/testData/quickfix/CreateField_after.java
@@ -0,0 +1,5 @@
+import javafx.scene.control.Button;
+
+public class CreateControllerMethod {
+ public Button btn;
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/quickfix/createControllerMethodInGroovy.fxml b/plugins/javaFX/testData/quickfix/createControllerMethodInGroovy.fxml
new file mode 100644
index 000000000000..bba29102be8f
--- /dev/null
+++ b/plugins/javaFX/testData/quickfix/createControllerMethodInGroovy.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="CreateControllerMethodInGroovy">
+ <Button onAction="#b<caret>ar"/>
+</GridPane>
diff --git a/plugins/javaFX/testData/quickfix/createField.fxml b/plugins/javaFX/testData/quickfix/createField.fxml
new file mode 100644
index 000000000000..a4f21c4d63a5
--- /dev/null
+++ b/plugins/javaFX/testData/quickfix/createField.fxml
@@ -0,0 +1,5 @@
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.control.Button?>
+<GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="CreateControllerMethod">
+ <Button fx:id="b<caret>tn"/>
+</GridPane>
diff --git a/plugins/javaFX/testData/quickfix/wrapWithDefine.fxml b/plugins/javaFX/testData/quickfix/wrapWithDefine.fxml
new file mode 100644
index 000000000000..f15416e294a7
--- /dev/null
+++ b/plugins/javaFX/testData/quickfix/wrapWithDefine.fxml
@@ -0,0 +1,6 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <Label fx:id="lb"/>
+ <fx:reference source="l<caret>b"/>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/quickfix/wrapWithDefine_after.fxml b/plugins/javaFX/testData/quickfix/wrapWithDefine_after.fxml
new file mode 100644
index 000000000000..485e32ae68ce
--- /dev/null
+++ b/plugins/javaFX/testData/quickfix/wrapWithDefine_after.fxml
@@ -0,0 +1,8 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:define>
+ <Label fx:id="lb"/>
+ </fx:define>
+ <fx:reference source="lb"/>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/ControllerFieldWithRefs.java b/plugins/javaFX/testData/rename/ControllerFieldWithRefs.java
new file mode 100644
index 000000000000..641873be25d9
--- /dev/null
+++ b/plugins/javaFX/testData/rename/ControllerFieldWithRefs.java
@@ -0,0 +1,3 @@
+class ExampleController {
+ public PasswordField passwordField;
+}
diff --git a/plugins/javaFX/testData/rename/Handler.java b/plugins/javaFX/testData/rename/Handler.java
new file mode 100644
index 000000000000..f93ecf87ea3f
--- /dev/null
+++ b/plugins/javaFX/testData/rename/Handler.java
@@ -0,0 +1,3 @@
+public class Handler {
+ public void foo() {}
+} \ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/controllerFieldWithRefs.fxml b/plugins/javaFX/testData/rename/controllerFieldWithRefs.fxml
new file mode 100644
index 000000000000..7983ff985c05
--- /dev/null
+++ b/plugins/javaFX/testData/rename/controllerFieldWithRefs.fxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml"
+ fx:controller="ExampleController">
+ <fx:define>
+ <PasswordField fx:id="pass<caret>wordField"/>
+ </fx:define>
+
+ <fx:reference source="passwordField" GridPane.rowIndex="3"/>
+
+</AnchorPane>
diff --git a/plugins/javaFX/testData/rename/controllerFieldWithRefs_after.fxml b/plugins/javaFX/testData/rename/controllerFieldWithRefs_after.fxml
new file mode 100644
index 000000000000..7f98ed60036d
--- /dev/null
+++ b/plugins/javaFX/testData/rename/controllerFieldWithRefs_after.fxml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml"
+ fx:controller="ExampleController">
+ <fx:define>
+ <PasswordField fx:id="newFieldName"/>
+ </fx:define>
+
+ <fx:reference source="newFieldName" GridPane.rowIndex="3"/>
+
+</AnchorPane>
diff --git a/plugins/javaFX/testData/rename/handler.fxml b/plugins/javaFX/testData/rename/handler.fxml
new file mode 100644
index 000000000000..a6afa36149c1
--- /dev/null
+++ b/plugins/javaFX/testData/rename/handler.fxml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml"
+ fx:controller="Handler">
+ <Button onAction="#fo<caret>o"
+</AnchorPane>
diff --git a/plugins/javaFX/testData/rename/handler_after.fxml b/plugins/javaFX/testData/rename/handler_after.fxml
new file mode 100644
index 000000000000..8930de398f00
--- /dev/null
+++ b/plugins/javaFX/testData/rename/handler_after.fxml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<AnchorPane id="AnchorPane" xmlns:fx="http://javafx.com/fxml"
+ fx:controller="Handler">
+ <Button onAction="#newHandlerName"
+</AnchorPane>
diff --git a/plugins/javaFX/testData/rename/idWithRefs.fxml b/plugins/javaFX/testData/rename/idWithRefs.fxml
new file mode 100644
index 000000000000..47f96d147dd8
--- /dev/null
+++ b/plugins/javaFX/testData/rename/idWithRefs.fxml
@@ -0,0 +1,8 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:define>
+ <Label fx:id="l<caret>b"/>
+ </fx:define>
+ <fx:reference source= "lb"/>
+</GridPane> \ No newline at end of file
diff --git a/plugins/javaFX/testData/rename/idWithRefs_after.fxml b/plugins/javaFX/testData/rename/idWithRefs_after.fxml
new file mode 100644
index 000000000000..5b4aa115e98f
--- /dev/null
+++ b/plugins/javaFX/testData/rename/idWithRefs_after.fxml
@@ -0,0 +1,8 @@
+<?import javafx.scene.control.Label?>
+<?import javafx.layout.*?>
+<GridPane xmlns:fx="http://javafx.com/fxml">
+ <fx:define>
+ <Label fx:id="lb1"/>
+ </fx:define>
+ <fx:reference source= "lb1"/>
+</GridPane> \ No newline at end of file
diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
index 7a838b355e42..2a1f1e98e11f 100644
--- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
+++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
@@ -32,10 +32,7 @@ import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.options.SettingsEditorGroup;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.DefaultJDOMExternalizer;
-import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -376,6 +373,13 @@ public class JUnitConfiguration extends ModuleBasedConfiguration<JavaRunConfigur
patterns.add(JavaExecutionUtil.getRuntimeQualifiedName(pattern) + methodSufiix);
}
myData.setPatterns(patterns);
+ final Module module = PatternConfigurationProducer.findModule(this, getConfigurationModule().getModule(), patterns);
+ if (module == null) {
+ myData.setScope(TestSearchScope.WHOLE_PROJECT);
+ setModule(null);
+ } else {
+ setModule(module);
+ }
setGeneratedName();
}
diff --git a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java
index 808f7158772d..1f0bb80fb4e3 100644
--- a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java
+++ b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java
@@ -16,15 +16,19 @@
package com.intellij.execution.junit;
+import com.intellij.execution.JavaExecutionUtil;
import com.intellij.execution.JavaRunConfigurationExtensionManager;
import com.intellij.execution.Location;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ConfigurationContext;
+import com.intellij.execution.configurations.ModuleBasedConfiguration;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
@@ -55,6 +59,21 @@ public class PatternConfigurationProducer extends JUnitConfigurationProducer {
return settings;
}
+ @Override
+ protected Module findModule(ModuleBasedConfiguration configuration, Module contextModule) {
+ final Set<String> patterns = ((JUnitConfiguration)configuration).getPersistentData().getPatterns();
+ return findModule(configuration, contextModule, patterns);
+ }
+
+ public static Module findModule(ModuleBasedConfiguration configuration, Module contextModule, Set<String> patterns) {
+ return JavaExecutionUtil.findModule(contextModule, patterns, configuration.getProject(), new Condition<PsiClass>() {
+ @Override
+ public boolean value(PsiClass psiClass) {
+ return JUnitUtil.isTestClass(psiClass);
+ }
+ });
+ }
+
static Set<PsiMember> collectTestMembers(PsiElement[] psiElements) {
final Set<PsiMember> foundMembers = new LinkedHashSet<PsiMember>();
for (PsiElement psiElement : psiElements) {
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestObject.java b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
index e59369b8b5e3..04f2dfcc0579 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestObject.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
@@ -39,7 +39,6 @@ import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.util.JavaParametersUtil;
import com.intellij.execution.util.ProgramParametersUtil;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
@@ -62,7 +61,6 @@ import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.rt.execution.junit.IDEAJUnitListener;
import com.intellij.rt.execution.junit.JUnitStarter;
import com.intellij.util.Function;
-import com.intellij.util.IJSwingUtilities;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NotNull;
@@ -303,22 +301,16 @@ public abstract class TestObject implements JavaCommandLine {
if (myListenersFile != null) {
FileUtil.delete(myListenersFile);
}
- IJSwingUtilities.invoke(new Runnable() {
+ final Runnable runnable = new Runnable() {
@Override
public void run() {
- try {
- unboundOutputRoot.flush();
- packetsReceiver.checkTerminated();
- final JUnitRunningModel model = packetsReceiver.getModel();
- notifyByBalloon(model, myStarted, consoleProperties);
- }
- finally {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- Disposer.dispose(consoleView);
- }
- }
+ unboundOutputRoot.flush();
+ packetsReceiver.checkTerminated();
+ final JUnitRunningModel model = packetsReceiver.getModel();
+ notifyByBalloon(model, myStarted, consoleProperties);
}
- });
+ };
+ handler.getOut().addRequest(runnable, queue);
}
@Override
@@ -343,10 +335,6 @@ public abstract class TestObject implements JavaCommandLine {
}
});
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- return new DefaultExecutionResult(null, handler);
- }
-
final RerunFailedTestsAction rerunFailedTestsAction = new RerunFailedTestsAction(consoleView);
rerunFailedTestsAction.init(consoleProperties, myEnvironment);
rerunFailedTestsAction.setModelProvider(new Getter<TestFrameworkRunningModel>() {
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java
index fe6f255cde35..d5f48ed5b629 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java
@@ -28,7 +28,6 @@ import com.intellij.execution.configurations.RuntimeConfigurationWarning;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.util.JavaParametersUtil;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
@@ -121,29 +120,9 @@ public class TestsPattern extends TestPackage {
}
protected void configureClasspath() throws CantRunException {
- final JUnitConfiguration.Data data = myConfiguration.getPersistentData();
- final Project project = myConfiguration.getProject();
- final Set<Module> modules = new HashSet<Module>();
- for (String className : data.getPatterns()) {
- final PsiClass psiClass = JavaExecutionUtil.findMainClass(project,
- className.contains(",")
- ? className.substring(0, className.indexOf(','))
- : className,
- GlobalSearchScope.allScope(project));
- if (psiClass != null && JUnitUtil.isTestClass(psiClass)) {
- modules.add(ModuleUtil.findModuleForPsiElement(psiClass));
- }
- }
-
final String jreHome = myConfiguration.isAlternativeJrePathEnabled() ? myConfiguration.getAlternativeJrePath() : null;
- Module module = myConfiguration.getConfigurationModule().getModule();
- if (module == null && modules.size() == 1) {
- final Module nextModule = modules.iterator().next();
- if (nextModule != null) {
- module = nextModule;
- }
- }
+ final Module module = myConfiguration.getConfigurationModule().getModule();
if (module != null) {
JavaParametersUtil.configureModule(module, myJavaParameters, JavaParameters.JDK_AND_CLASSES_AND_TESTS, jreHome);
diff --git a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java
index 69b426a9d5df..c942d4d7251e 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java
@@ -98,6 +98,6 @@ public class JUnitEntryPoint extends EntryPoint {
@Override
public String[] getIgnoreAnnotations() {
- return new String[]{"org.junit.Rule", "org.mockito.Mock"};
+ return new String[]{"org.junit.Rule", "org.mockito.Mock", "org.junit.ClassRule"};
}
} \ No newline at end of file
diff --git a/plugins/junit/src/com/intellij/execution/junit2/ui/TestsPacketsReceiver.java b/plugins/junit/src/com/intellij/execution/junit2/ui/TestsPacketsReceiver.java
index c031ecaad075..db62cc6406d6 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/ui/TestsPacketsReceiver.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/ui/TestsPacketsReceiver.java
@@ -152,9 +152,9 @@ public class TestsPacketsReceiver implements OutputPacketProcessor, Disposable {
final String parentClass = currentTest.getInfo().getComment();
TestProxy dynamicParent = myKnownDynamicParents.get(parentClass);
if (dynamicParent == null) {
- if (Comparing
- .strEqual(parentClass, StringUtil.getQualifiedName(model.getRoot().getInfo().getComment(), model.getRoot().getName()))) {
- dynamicParent = model.getRoot();
+ final TestProxy root = model.getRoot();
+ if (Comparing.strEqual(parentClass, StringUtil.getQualifiedName(root.getInfo().getComment(), root.getName()))) {
+ dynamicParent = root;
}
else {
dynamicParent = new TestProxy(new ClassBasedInfo(DisplayTestInfoExtractor.FOR_CLASS) {
@@ -165,7 +165,7 @@ public class TestsPacketsReceiver implements OutputPacketProcessor, Disposable {
public void readFrom(ObjectReader reader) {
}
});
- model.getRoot().addChild(dynamicParent);
+ root.addChild(dynamicParent);
}
myKnownDynamicParents.put(parentClass, dynamicParent);
}
diff --git a/plugins/junit/src/com/intellij/execution/junit2/ui/model/JUnitListenersNotifier.java b/plugins/junit/src/com/intellij/execution/junit2/ui/model/JUnitListenersNotifier.java
index 28c8df1b3007..4a4097b61b1b 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/ui/model/JUnitListenersNotifier.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/ui/model/JUnitListenersNotifier.java
@@ -16,9 +16,9 @@
package com.intellij.execution.junit2.ui.model;
+import com.intellij.execution.junit2.TestProxy;
import com.intellij.execution.junit2.events.TestEvent;
import com.intellij.execution.junit2.events.TestEventsConsumer;
-import com.intellij.execution.junit2.TestProxy;
import com.intellij.execution.junit2.segments.DispatchListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java
index fa1bfe5eff0a..b43e632b8922 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java
@@ -122,6 +122,9 @@ public class JUnit4TestResultsSender extends RunListener {
if (message != null) {
PacketFactory notification = createExceptionNotification(assertion, message, "\nExpected: is \"(.*)\"\n\\s*got: \"(.*)\"\n");
if (notification == null) {
+ notification = createExceptionNotification(assertion, message, "\nExpected: is \"(.*)\"\n\\s*but: was \"(.*)\"");
+ }
+ if (notification == null) {
notification = createExceptionNotification(assertion, message, "\nExpected: (.*)\n\\s*got: (.*)");
}
if (notification == null) {
@@ -141,7 +144,7 @@ public class JUnit4TestResultsSender extends RunListener {
}
private static PacketFactory createExceptionNotification(Throwable assertion, String message, final String regex) {
- final Matcher matcher = Pattern.compile(regex, Pattern.DOTALL).matcher(message);
+ final Matcher matcher = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE).matcher(message);
if (matcher.matches()) {
return ComparisonDetailsExtractor.create(assertion, matcher.group(1).replaceAll("\\\\n", "\n"), matcher.group(2).replaceAll("\\\\n", "\n"));
}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
index 3029d36cb312..0caff4232991 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
@@ -3,6 +3,7 @@ package org.jetbrains.jps.maven.model.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.util.xmlb.XmlSerializer;
+import gnu.trove.THashMap;
import org.jdom.Document;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -19,6 +20,7 @@ import org.jetbrains.jps.model.module.JpsDependencyElement;
import org.jetbrains.jps.model.module.JpsModule;
import java.io.File;
+import java.util.Map;
/**
* @author nik
@@ -71,27 +73,25 @@ public class JpsMavenExtensionServiceImpl extends JpsMavenExtensionService {
return child != null && child.getData();
}
- private volatile MavenProjectConfiguration myConfig;
+ private final Map<File, MavenProjectConfiguration> myLoadedConfigs = new THashMap<File, MavenProjectConfiguration>();
@NotNull
@Override
public MavenProjectConfiguration getMavenProjectConfiguration(BuildDataPaths paths) {
- MavenProjectConfiguration config = myConfig;
- if (config == null) {
- synchronized (this) {
- config = myConfig;
- if (config == null) {
- config = new MavenProjectConfiguration();
- try {
- final File configFile = new File(paths.getDataStorageRoot(), MavenProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH);
- final Document document = JDOMUtil.loadDocument(configFile);
- XmlSerializer.deserializeInto(config, document.getRootElement());
- }
- catch (Exception e) {
- LOG.info(e);
- }
- myConfig = config;
+ final File configFile = new File(paths.getDataStorageRoot(), MavenProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH);
+ MavenProjectConfiguration config;
+ synchronized (myLoadedConfigs) {
+ config = myLoadedConfigs.get(configFile);
+ if (config == null) {
+ config = new MavenProjectConfiguration();
+ try {
+ final Document document = JDOMUtil.loadDocument(configFile);
+ XmlSerializer.deserializeInto(config, document.getRootElement());
}
+ catch (Exception e) {
+ LOG.info(e);
+ }
+ myLoadedConfigs.put(configFile, config);
}
}
return config;
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTarget.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTarget.java
index fdfc7fe63b38..ccb6c7ab4eae 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTarget.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTarget.java
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.*;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
@@ -141,7 +142,8 @@ public class MavenResourcesTarget extends ModuleBasedTarget<MavenResourceRootDes
}
@Override
- public void writeConfiguration(PrintWriter out, BuildDataPaths dataPaths, BuildRootIndex buildRootIndex) {
+ public void writeConfiguration(ProjectDescriptor pd, PrintWriter out) {
+ final BuildDataPaths dataPaths = pd.getTargetsState().getDataPaths();
final MavenModuleResourceConfiguration configuration = getModuleResourcesConfiguration(dataPaths);
if (configuration != null) {
out.write(Integer.toHexString(configuration.computeConfigurationHash(isTests())));
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenArtifact.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenArtifact.java
index 75ad374423de..c30101d8f82c 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenArtifact.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenArtifact.java
@@ -25,7 +25,9 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.Serializable;
-public class MavenArtifact implements Serializable {
+public class MavenArtifact implements Serializable, MavenCoordinate {
+
+ static long serialVersionUID = 6389627095309274357L;
public static final String MAVEN_LIB_PREFIX = "Maven: ";
@@ -47,6 +49,8 @@ public class MavenArtifact implements Serializable {
private transient volatile String myLibraryNameCache;
+ private transient volatile long myLastFileCheckTimeStamp; // File.exists() is a slow operation, don't run it more than once a second
+
public MavenArtifact(String groupId,
String artifactId,
String version,
@@ -124,7 +128,21 @@ public class MavenArtifact implements Serializable {
}
public boolean isResolved() {
- return myResolved && !myStubbed && myFile.exists();
+ if (myResolved && !myStubbed) {
+ long currentTime = System.currentTimeMillis();
+
+ if (myLastFileCheckTimeStamp + 2000 < currentTime) { // File.exists() is a slow operation, don't run it more than once a second
+ if (!myFile.exists()) {
+ return false; // Don't cache result if file is not exist.
+ }
+
+ myLastFileCheckTimeStamp = currentTime;
+ }
+
+ return true;
+ }
+
+ return false;
}
@NotNull
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenCoordinate.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenCoordinate.java
new file mode 100644
index 000000000000..e18d6cd8e4c5
--- /dev/null
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenCoordinate.java
@@ -0,0 +1,27 @@
+/*
+ * 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 org.jetbrains.idea.maven.model;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public interface MavenCoordinate {
+
+ String getGroupId();
+ String getArtifactId();
+ String getVersion();
+
+}
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenId.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenId.java
index d585d3a2afd2..4e24cb03cdcb 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenId.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenId.java
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
-public class MavenId implements Serializable {
+public class MavenId implements Serializable, MavenCoordinate {
public static final String UNKNOWN_VALUE = "Unknown";
@Nullable private final String myGroupId;
@@ -75,8 +75,8 @@ public class MavenId implements Serializable {
}
public boolean equals(@Nullable String groupId, @Nullable String artifactId) {
- if (myGroupId != null ? !myGroupId.equals(groupId) : groupId != null) return false;
if (myArtifactId != null ? !myArtifactId.equals(artifactId) : artifactId != null) return false;
+ if (myGroupId != null ? !myGroupId.equals(groupId) : groupId != null) return false;
return true;
}
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexFetcher.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexFetcher.java
index 81ea42e44411..7a17a7ee105b 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexFetcher.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexFetcher.java
@@ -16,7 +16,8 @@
package org.jetbrains.idea.maven.server;
import org.apache.maven.artifact.manager.WagonManager;
-import org.apache.maven.artifact.repository.DefaultArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.Wagon;
@@ -36,24 +37,28 @@ public class Maven3ServerIndexFetcher extends AbstractResourceFetcher {
private final String myOriginalRepositoryId;
private final String myOriginalRepositoryUrl;
private final WagonManager myWagonManager;
+ private final RepositorySystem myRepositorySystem;
private final TransferListener myListener;
private Wagon myWagon = null;
public Maven3ServerIndexFetcher(String originalRepositoryId,
String originalRepositoryUrl,
WagonManager wagonManager,
+ RepositorySystem repositorySystem,
TransferListener listener) {
myOriginalRepositoryId = originalRepositoryId;
myOriginalRepositoryUrl = originalRepositoryUrl;
myWagonManager = wagonManager;
+ myRepositorySystem = repositorySystem;
myListener = listener;
}
@Override
public void connect(String _ignoredContextId, String _ignoredUrl) throws IOException {
- String mirrorUrl = myWagonManager.getMirrorRepository(new DefaultArtifactRepository(myOriginalRepositoryId,
- myOriginalRepositoryUrl,
- null)).getUrl();
+ ArtifactRepository artifactRepository =
+ myRepositorySystem.createArtifactRepository(myOriginalRepositoryId, myOriginalRepositoryUrl, null, null, null);
+
+ String mirrorUrl = myWagonManager.getMirrorRepository(artifactRepository).getUrl();
String indexUrl = mirrorUrl + (mirrorUrl.endsWith("/") ? "" : "/") + ".index";
Repository repository = new Repository(myOriginalRepositoryId, indexUrl);
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
index fb80d905393a..199db3a52538 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
@@ -31,6 +31,7 @@ import org.apache.maven.archetype.source.ArchetypeDataSource;
import org.apache.maven.archetype.source.ArchetypeDataSourceException;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.wagon.events.TransferEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -161,6 +162,7 @@ public class Maven3ServerIndexerImpl extends MavenRemoteObject implements MavenS
request.setResourceFetcher(new Maven3ServerIndexFetcher(index.getRepositoryId(),
index.getRepositoryUrl(),
embedder.getComponent(WagonManager.class),
+ embedder.getComponent(RepositorySystem.class),
new WagonTransferListenerAdapter(indicator) {
@Override
protected void downloadProgress(long downloaded, long total) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java
index 0d84252a0397..ad5065cc785d 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.xml.XmlAttribute;
import com.intellij.util.ProcessingContext;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@@ -98,11 +99,23 @@ public class MavenFilteredPropertyPsiReferenceProvider extends PsiReferenceProvi
}
pattern.append(Pattern.quote(prefix)).append("(.+?)").append(Pattern.quote(suffix));
}
-
+
+ private static boolean shouldAddReference(@NotNull PsiElement element) {
+ if (element.getFirstChild() == element.getLastChild()) {
+ return true; // Add to all leaf elements
+ }
+
+ if (element instanceof XmlAttribute) {
+ return true;
+ }
+
+ return false; // Don't add references to all element to avoid performance problem.
+ }
+
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
- if (element.getFirstChild() != element.getLastChild()) {
+ if (!shouldAddReference(element)) {
// Add reference to element with one child or leaf element only to avoid performance problem.
return PsiReference.EMPTY_ARRAY;
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
index 93b046cb45db..b772d50ac580 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
@@ -27,6 +27,8 @@ import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdk;
@@ -231,18 +233,24 @@ public class MavenExternalParameters {
MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
- for (MavenProject mavenProject : manager.getProjects()) {
- res.setProperty(mavenProject.getMavenId().getGroupId()
- + ':' + mavenProject.getMavenId().getArtifactId()
- + ":pom"
- + ':' + mavenProject.getMavenId().getVersion(),
- mavenProject.getFile().getPath());
-
- res.setProperty(mavenProject.getMavenId().getGroupId()
- + ':' + mavenProject.getMavenId().getArtifactId()
- + ':' + mavenProject.getPackaging()
- + ':' + mavenProject.getMavenId().getVersion(),
- mavenProject.getOutputDirectory());
+ for (Module module : ModuleManager.getInstance(project).getModules()) {
+ if (manager.isMavenizedModule(module)) {
+ MavenProject mavenProject = manager.findProject(module);
+ if (mavenProject != null && !manager.isIgnored(mavenProject)) {
+ res.setProperty(mavenProject.getMavenId().getGroupId()
+ + ':' + mavenProject.getMavenId().getArtifactId()
+ + ":pom"
+ + ':' + mavenProject.getMavenId().getVersion(),
+ mavenProject.getFile().getPath());
+
+ res.setProperty(mavenProject.getMavenId().getGroupId()
+ + ':' + mavenProject.getMavenId().getArtifactId()
+ + ':' + mavenProject.getPackaging()
+ + ':' + mavenProject.getMavenId().getVersion(),
+ mavenProject.getOutputDirectory());
+
+ }
+ }
}
File file = new File(PathManager.getSystemPath(), "Maven/idea-projects-state-" + project.getLocationHash() + ".properties");
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 ccc1e1201099..e61305ee50f6 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
@@ -196,7 +196,7 @@ public class MavenRunConfigurationType implements ConfigurationType {
}
}
- static RunnerAndConfigurationSettings createRunnerAndConfigurationSettings(@Nullable MavenGeneralSettings generalSettings,
+ public static RunnerAndConfigurationSettings createRunnerAndConfigurationSettings(@Nullable MavenGeneralSettings generalSettings,
@Nullable MavenRunnerSettings runnerSettings,
MavenRunnerParameters params,
Project project) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java
index 085239a00820..fc5e457217d0 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java
@@ -237,6 +237,9 @@ public class MavenFoldersImporter {
addAllSubDirsAsSources(targetDir, isTestSources);
break;
+
+ case IGNORE:
+ break; // Ignore.
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
index 05c5d58551ae..81f52e9c3b67 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
@@ -81,52 +81,48 @@ public class MavenModuleImporter {
}
public void preConfigFacets() {
- if (myModule.isDisposed()) return;
+ MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() {
+ public void run() {
+ if (myModule.isDisposed()) return;
- final ModuleType moduleType = ModuleType.get(myModule);
+ final ModuleType moduleType = ModuleType.get(myModule);
- for (final MavenImporter importer : getSuitableImporters()) {
- final MavenProjectChanges changes;
- if (myMavenProjectChanges == null) {
- if (importer.processChangedModulesOnly()) continue;
- changes = MavenProjectChanges.NONE;
- }
- else {
- changes = myMavenProjectChanges;
- }
+ for (final MavenImporter importer : getSuitableImporters()) {
+ final MavenProjectChanges changes;
+ if (myMavenProjectChanges == null) {
+ if (importer.processChangedModulesOnly()) continue;
+ changes = MavenProjectChanges.NONE;
+ }
+ else {
+ changes = myMavenProjectChanges;
+ }
- if (importer.getModuleType() == moduleType) {
- // facets use FacetConfiguration and like that do not have modifiable models,
- // therefore we have to take write lock
- MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() {
- public void run() {
+ if (importer.getModuleType() == moduleType) {
importer.preProcess(myModule, myMavenProject, changes, myModifiableModelsProvider);
}
- });
+ }
}
- }
+ });
}
public void configFacets(final List<MavenProjectsProcessorTask> postTasks) {
- if (myModule.isDisposed()) return;
+ MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() {
+ public void run() {
+ if (myModule.isDisposed()) return;
- final ModuleType moduleType = ModuleType.get(myModule);
+ final ModuleType moduleType = ModuleType.get(myModule);
- for (final MavenImporter importer : getSuitableImporters()) {
- final MavenProjectChanges changes;
- if (myMavenProjectChanges == null) {
- if (importer.processChangedModulesOnly()) continue;
- changes = MavenProjectChanges.NONE;
- }
- else {
- changes = myMavenProjectChanges;
- }
+ for (final MavenImporter importer : getSuitableImporters()) {
+ final MavenProjectChanges changes;
+ if (myMavenProjectChanges == null) {
+ if (importer.processChangedModulesOnly()) continue;
+ changes = MavenProjectChanges.NONE;
+ }
+ else {
+ changes = myMavenProjectChanges;
+ }
- if (importer.getModuleType() == moduleType) {
- // facets use FacetConfiguration and like that do not have modifiable models,
- // therefore we have to take write lock
- MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() {
- public void run() {
+ if (importer.getModuleType() == moduleType) {
importer.process(myModifiableModelsProvider,
myModule,
myRootModelAdapter,
@@ -136,9 +132,9 @@ public class MavenModuleImporter {
myMavenProjectToModuleName,
postTasks);
}
- });
+ }
}
- }
+ });
}
private List<MavenImporter> getSuitableImporters() {
@@ -166,7 +162,9 @@ public class MavenModuleImporter {
addAttachArtifactDependency(buildHelperCfg, scope, depProject, artifact);
}
}
- else {
+ else if ("system".equals(artifact.getScope())) {
+ myRootModelAdapter.addSystemDependency(artifact, scope);
+ } else {
myRootModelAdapter.addLibraryDependency(artifact, scope, myModifiableModelsProvider, myMavenProject);
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
index 9597e89f5bc8..a21d56081311 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
@@ -285,10 +285,31 @@ public class MavenRootModelAdapter {
return myModuleModel.findModuleByName(moduleName);
}
+ public void addSystemDependency(MavenArtifact artifact, DependencyScope scope) {
+ assert MavenConstants.SCOPE_SYSTEM.equals(artifact.getScope());
+
+ String libraryName = artifact.getLibraryName();
+
+ Library library = myRootModel.getModuleLibraryTable().getLibraryByName(libraryName);
+ if (library == null) {
+ library = myRootModel.getModuleLibraryTable().createLibrary(libraryName);
+ }
+
+ LibraryOrderEntry orderEntry = myRootModel.findLibraryOrderEntry(library);
+ assert orderEntry != null;
+ orderEntry.setScope(scope);
+
+ Library.ModifiableModel modifiableModel = library.getModifiableModel();
+ updateUrl(modifiableModel, OrderRootType.CLASSES, artifact, null, null, true);
+ modifiableModel.commit();
+ }
+
public void addLibraryDependency(MavenArtifact artifact,
DependencyScope scope,
MavenModifiableModelsProvider provider,
MavenProject project) {
+ assert !MavenConstants.SCOPE_SYSTEM.equals(artifact.getScope()); // System dependencies must be added ad module library, not as project wide library.
+
String libraryName = artifact.getLibraryName();
Library library = provider.getLibraryByName(libraryName);
@@ -298,10 +319,8 @@ public class MavenRootModelAdapter {
Library.ModifiableModel libraryModel = provider.getLibraryModel(library);
updateUrl(libraryModel, OrderRootType.CLASSES, artifact, null, null, true);
- if (!MavenConstants.SCOPE_SYSTEM.equals(artifact.getScope())) {
- updateUrl(libraryModel, OrderRootType.SOURCES, artifact, MavenExtraArtifactType.SOURCES, project, false);
- updateUrl(libraryModel, JavadocOrderRootType.getInstance(), artifact, MavenExtraArtifactType.DOCS, project, false);
- }
+ updateUrl(libraryModel, OrderRootType.SOURCES, artifact, MavenExtraArtifactType.SOURCES, project, false);
+ updateUrl(libraryModel, JavadocOrderRootType.getInstance(), artifact, MavenExtraArtifactType.DOCS, project, false);
LibraryOrderEntry e = myRootModel.addLibraryEntry(library);
e.setScope(scope);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java
index 142e4f7c5290..950cf49a9fef 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java
@@ -28,6 +28,7 @@ import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.treeStructure.*;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
+import icons.MavenIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -509,7 +510,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
public ProjectsGroupNode(MavenSimpleNode parent) {
super(parent);
- setUniformIcon(icons.MavenIcons.ModulesClosed);
+ setUniformIcon(MavenIcons.ModulesClosed);
}
@Override
@@ -570,7 +571,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
public ProfilesNode(MavenSimpleNode parent) {
super(parent);
- setUniformIcon(icons.MavenIcons.ProfilesClosed);
+ setUniformIcon(MavenIcons.ProfilesClosed);
}
protected List<? extends MavenSimpleNode> doGetChildren() {
@@ -656,7 +657,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
myDependenciesNode = new DependenciesNode(this, mavenProject);
myModulesNode = new ModulesNode(this);
- setUniformIcon(icons.MavenIcons.MavenProject);
+ setUniformIcon(MavenIcons.MavenProject);
updateProject();
}
@@ -809,7 +810,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
public class ModulesNode extends ProjectsGroupNode {
public ModulesNode(ProjectNode parent) {
super(parent);
- setUniformIcon(icons.MavenIcons.ModulesClosed);
+ setUniformIcon(MavenIcons.ModulesClosed);
}
@Override
@@ -840,7 +841,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
myMavenProject = findParent(ProjectNode.class).getMavenProject();
myGoal = goal;
myDisplayName = displayName;
- setUniformIcon(icons.MavenIcons.Phase);
+ setUniformIcon(MavenIcons.Phase);
}
public String getProjectPath() {
@@ -904,7 +905,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
for (String goal : PHASES) {
myGoalNodes.add(new StandardGoalNode(this, goal));
}
- setUniformIcon(icons.MavenIcons.PhasesClosed);
+ setUniformIcon(MavenIcons.PhasesClosed);
}
@Override
@@ -934,7 +935,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
public PluginsNode(ProjectNode parent) {
super(parent);
- setUniformIcon(icons.MavenIcons.PhasesClosed);
+ setUniformIcon(MavenIcons.PhasesClosed);
}
@Override
@@ -949,7 +950,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
public void updatePlugins(MavenProject mavenProject) {
List<MavenPlugin> plugins = mavenProject.getDeclaredPlugins();
- for (PluginNode each : new ArrayList<PluginNode>(myPluginNodes)) {
+ for (PluginNode each : myPluginNodes.toArray(new PluginNode[myPluginNodes.size()])) {
if (plugins.contains(each.getPlugin())) {
each.updatePlugin();
}
@@ -984,7 +985,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
super(parent);
myPlugin = plugin;
- setUniformIcon(icons.MavenIcons.MavenPlugin);
+ setUniformIcon(MavenIcons.MavenPlugin);
updatePlugin();
}
@@ -1035,7 +1036,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
public class PluginGoalNode extends GoalNode {
public PluginGoalNode(PluginNode parent, String goal, String displayName) {
super(parent, goal, displayName);
- setUniformIcon(icons.MavenIcons.PluginGoal);
+ setUniformIcon(MavenIcons.PluginGoal);
}
}
@@ -1058,22 +1059,55 @@ public class MavenProjectsStructure extends SimpleTreeStructure {
}
protected void updateChildren(List<MavenArtifactNode> children, MavenProject mavenProject) {
- List<DependencyNode> newNodes = new ArrayList<DependencyNode>(children.size());
+ List<DependencyNode> newNodes = null;
+ int validChildCount = 0;
+
for (MavenArtifactNode each : children) {
if (each.getState() != MavenArtifactState.ADDED) continue;
- DependencyNode newNode = findOrCreateNodeFor(each, mavenProject);
+ if (newNodes == null) {
+ if (validChildCount < myChildren.size()) {
+ DependencyNode currentValidNode = myChildren.get(validChildCount);
+
+ if (currentValidNode.myArtifact.equals(each.getArtifact())) {
+ currentValidNode.updateChildren(each.getDependencies(), mavenProject);
+ currentValidNode.updateDependency();
+
+ validChildCount++;
+ continue;
+ }
+ }
+
+ newNodes = new ArrayList<DependencyNode>(children.size());
+ newNodes.addAll(myChildren.subList(0, validChildCount));
+ }
+
+ DependencyNode newNode = findOrCreateNodeFor(each, mavenProject, validChildCount);
newNodes.add(newNode);
newNode.updateChildren(each.getDependencies(), mavenProject);
newNode.updateDependency();
}
+
+ if (newNodes == null) {
+ if (validChildCount == myChildren.size()) {
+ return; // All nodes are valid, child did not changed.
+ }
+
+ assert validChildCount < myChildren.size();
+
+ newNodes = new ArrayList<DependencyNode>(myChildren.subList(0, validChildCount));
+ }
+
myChildren = newNodes;
childrenChanged();
}
- private DependencyNode findOrCreateNodeFor(MavenArtifactNode artifact, MavenProject mavenProject) {
- for (DependencyNode each : myChildren) {
- if (each.myArtifact.equals(artifact.getArtifact())) return each;
+ private DependencyNode findOrCreateNodeFor(MavenArtifactNode artifact, MavenProject mavenProject, int from) {
+ for (int i = from; i < myChildren.size(); i++) {
+ DependencyNode node = myChildren.get(i);
+ if (node.myArtifact.equals(artifact.getArtifact())) {
+ return node;
+ }
}
return new DependencyNode(this, artifact, mavenProject);
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java
index 0aee05f9e8dc..9cea30ec0e0b 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java
@@ -91,7 +91,13 @@ public class MavenArtifactDownloader {
}
finally {
boolean isAsync = !ApplicationManager.getApplication().isUnitTestMode();
- LocalFileSystem.getInstance().refreshIoFiles(downloadedFiles, isAsync, false, null);
+
+ Set<File> parentsToRefresh = new HashSet<File>(); // We have to refresh parents of downloaded files, because some additional files could be download.
+ for (File file : downloadedFiles) {
+ parentsToRefresh.add(file.getParentFile());
+ }
+
+ LocalFileSystem.getInstance().refreshIoFiles(parentsToRefresh, isAsync, false, null);
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java
index 9c75cdb97554..12f7adeba2ba 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java
@@ -53,6 +53,7 @@ public class MavenImportingSettings implements Cloneable {
private List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
public enum GeneratedSourcesFolder {
+ IGNORE("Don't detect"),
AUTODETECT("Detect automatically"),
GENERATED_SOURCE_FOLDER("target/generated-sources"),
SUBFOLDER("subdirectories of \"target/generated-sources\"");
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
index 689561e1e017..4a94b6cc31c6 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
@@ -844,10 +844,10 @@ public class MavenProject {
return findDependencies(depProject.getMavenId());
}
- public List<MavenArtifact> findDependencies(MavenId id) {
+ public List<MavenArtifact> findDependencies(@NotNull MavenId id) {
List<MavenArtifact> result = new SmartList<MavenArtifact>();
for (MavenArtifact each : getDependencies()) {
- if (each.getMavenId().equals(id)) result.add(each);
+ if (id.equals(each.getGroupId(), each.getArtifactId(), each.getVersion())) result.add(each);
}
return result;
}
@@ -856,7 +856,9 @@ public class MavenProject {
public List<MavenArtifact> findDependencies(@Nullable String groupId, @Nullable String artifactId) {
List<MavenArtifact> result = new SmartList<MavenArtifact>();
for (MavenArtifact each : getDependencies()) {
- if (each.getMavenId().equals(groupId, artifactId)) result.add(each);
+ if (Comparing.equal(artifactId, each.getArtifactId()) && Comparing.equal(groupId, each.getGroupId())) {
+ result.add(each);
+ }
}
return result;
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
index 7f338bfe8931..6e57648089f4 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
@@ -334,17 +334,14 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
// import only updated projects and dependents of them (we need to update faced-deps, packaging etc);
List<Pair<MavenProject, MavenProjectChanges>> toImport = new ArrayList<Pair<MavenProject, MavenProjectChanges>>(updated);
- for (MavenProject each : updatedProjects) {
- for (MavenProject eachDependent : myProjectsTree.getDependentProjects(each)) {
- toImport.add(Pair.create(eachDependent, MavenProjectChanges.DEPENDENCIES));
- }
+
+ for (MavenProject eachDependent : myProjectsTree.getDependentProjects(updatedProjects)) {
+ toImport.add(Pair.create(eachDependent, MavenProjectChanges.DEPENDENCIES));
}
// resolve updated, theirs dependents, and dependents of deleted
Set<MavenProject> toResolve = new THashSet<MavenProject>(updatedProjects);
- for (MavenProject each : ContainerUtil.concat(updatedProjects, deleted)) {
- toResolve.addAll(myProjectsTree.getDependentProjects(each));
- }
+ toResolve.addAll(myProjectsTree.getDependentProjects(ContainerUtil.concat(updatedProjects, deleted)));
// do not try to resolve projects with syntactic errors
Iterator<MavenProject> it = toResolve.iterator();
@@ -472,8 +469,8 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
}
}
- private String getMavenizedModuleOptionName() {
- return getComponentName() + ".isMavenModule";
+ private static String getMavenizedModuleOptionName() {
+ return "org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule";
}
@TestOnly
@@ -587,8 +584,8 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
}
@NotNull
- public Set<MavenProject> findInheritors(@Nullable MavenProject parent) {
- if (parent == null || !isInitialized()) return Collections.emptySet();
+ public Collection<MavenProject> findInheritors(@Nullable MavenProject parent) {
+ if (parent == null || !isInitialized()) return Collections.emptyList();
return myProjectsTree.findInheritors(parent);
}
@@ -992,10 +989,15 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
final Runnable r = new Runnable() {
public void run() {
- importer.set(
- new MavenProjectImporter(myProject, myProjectsTree, getFileToModuleMapping(modelsProvider), projectsToImportWithChanges,
- importModuleGroupsRequired, modelsProvider, getImportingSettings()));
- postTasks.set(importer.get().importProject());
+ MavenProjectImporter projectImporter = new MavenProjectImporter(myProject,
+ myProjectsTree,
+ getFileToModuleMapping(modelsProvider),
+ projectsToImportWithChanges,
+ importModuleGroupsRequired,
+ modelsProvider,
+ getImportingSettings());
+ importer.set(projectImporter);
+ postTasks.set(projectImporter.importProject());
}
};
@@ -1027,7 +1029,10 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
// do not block user too often
myImportingQueue.restartTimer();
- return importer.get().getCreatedModules();
+ MavenProjectImporter projectImporter = importer.get();
+ if (projectImporter == null) return Collections.emptyList();
+
+ return projectImporter.getCreatedModules();
}
public void generateBuildConfiguration(boolean force) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
index 9e4950bc5ede..8af95731bd9d 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
@@ -27,12 +27,11 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
-import com.intellij.util.SmartList;
import com.intellij.util.containers.ArrayListSet;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
-import gnu.trove.THashMap;
import gnu.trove.THashSet;
+import gnu.trove.TObjectHashingStrategy;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -64,17 +63,17 @@ public class MavenProjectsTree {
private volatile List<String> myIgnoredFilesPatterns = new ArrayList<String>();
private volatile Pattern myIgnoredFilesPatternsCache;
- private Set<String> myExplicitProfiles = new THashSet<String>();
- private final Set<String> myTemporarilyRemovedExplicitProfiles = new THashSet<String>();
+ private Set<String> myExplicitProfiles = new HashSet<String>();
+ private final Set<String> myTemporarilyRemovedExplicitProfiles = new HashSet<String>();
private final List<MavenProject> myRootProjects = new ArrayList<MavenProject>();
- private final Map<MavenProject, MavenProjectTimestamp> myTimestamps = new THashMap<MavenProject, MavenProjectTimestamp>();
+ private final Map<MavenProject, MavenProjectTimestamp> myTimestamps = new HashMap<MavenProject, MavenProjectTimestamp>();
private final MavenWorkspaceMap myWorkspaceMap = new MavenWorkspaceMap();
- private final Map<MavenId, MavenProject> myMavenIdToProjectMapping = new THashMap<MavenId, MavenProject>();
- private final Map<VirtualFile, MavenProject> myVirtualFileToProjectMapping = new THashMap<VirtualFile, MavenProject>();
- private final Map<MavenProject, List<MavenProject>> myAggregatorToModuleMapping = new THashMap<MavenProject, List<MavenProject>>();
- private final Map<MavenProject, MavenProject> myModuleToAggregatorMapping = new THashMap<MavenProject, MavenProject>();
+ private final Map<MavenId, MavenProject> myMavenIdToProjectMapping = new HashMap<MavenId, MavenProject>();
+ private final Map<VirtualFile, MavenProject> myVirtualFileToProjectMapping = new HashMap<VirtualFile, MavenProject>();
+ private final Map<MavenProject, List<MavenProject>> myAggregatorToModuleMapping = new HashMap<MavenProject, List<MavenProject>>();
+ private final Map<MavenProject, MavenProject> myModuleToAggregatorMapping = new HashMap<MavenProject, MavenProject>();
private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
@@ -520,9 +519,11 @@ public class MavenProjectsTree {
process.setText2("");
List<MavenProject> prevModules = getModules(mavenProject);
- Set<MavenProject> prevInheritors = isNew
- ? new THashSet<MavenProject>()
- : findInheritors(mavenProject);
+
+ Set<MavenProject> prevInheritors = new HashSet<MavenProject>();
+ if (!isNew) {
+ prevInheritors.addAll(findInheritors(mavenProject));
+ }
MavenProjectTimestamp timestamp = calculateTimestamp(mavenProject, explicitProfiles, generalSettings);
boolean isChanged = force || !timestamp.equals(myTimestamps.get(mavenProject));
@@ -628,9 +629,9 @@ public class MavenProjectsTree {
}
}
- Set<MavenProject> allInheritors = findInheritors(mavenProject);
- allInheritors.addAll(prevInheritors);
- for (MavenProject each : allInheritors) {
+ prevInheritors.addAll(findInheritors(mavenProject));
+
+ for (MavenProject each : prevInheritors) {
doUpdate(each,
findAggregator(each),
false,
@@ -1103,26 +1104,54 @@ public class MavenProjectsTree {
return findProject(project.getParentId());
}
- public Set<MavenProject> findInheritors(MavenProject project) {
- Set<MavenProject> result = new THashSet<MavenProject>();
- MavenId id = project.getMavenId();
+ public Collection<MavenProject> findInheritors(MavenProject project) {
+ readLock();
+ try {
+ List<MavenProject> result = null;
+ MavenId id = project.getMavenId();
- for (MavenProject each : getProjects()) {
- if (each == project) continue;
- if (id.equals(each.getParentId())) result.add(each);
+ for (MavenProject each : myVirtualFileToProjectMapping.values()) {
+ if (each == project) continue;
+ if (id.equals(each.getParentId())) {
+ if (result == null) result = new ArrayList<MavenProject>();
+ result.add(each);
+ }
+ }
+
+ return result == null ? Collections.<MavenProject>emptyList() : result;
+ }
+ finally {
+ readUnlock();
}
- return result;
}
- public List<MavenProject> getDependentProjects(MavenProject project) {
- List<MavenProject> result = new SmartList<MavenProject>();
- for (MavenProject eachProject : getProjects()) {
- if (eachProject == project) continue;
- if (!eachProject.findDependencies(project).isEmpty()) {
- result.add(eachProject);
+ public List<MavenProject> getDependentProjects(Collection<MavenProject> projects) {
+ readLock();
+ try {
+ List<MavenProject> result = null;
+
+ Set<MavenCoordinate> projectIds = new THashSet<MavenCoordinate>(new MavenCoordinateHashCodeStrategy());
+
+ for (MavenProject project : projects) {
+ projectIds.add(project.getMavenId());
}
+
+ for (MavenProject project : myVirtualFileToProjectMapping.values()) {
+ for (MavenArtifact dep : project.getDependencies()) {
+ if (projectIds.contains(dep)) {
+ if (result == null) result = new ArrayList<MavenProject>();
+
+ result.add(project);
+ break;
+ }
+ }
+ }
+
+ return result == null ? Collections.<MavenProject>emptyList() : result;
+ }
+ finally {
+ readUnlock();
}
- return result;
}
public void resolve(@NotNull Project project,
@@ -1522,4 +1551,20 @@ public class MavenProjectsTree {
public void artifactsDownloaded(MavenProject project) {
}
}
+
+ private static class MavenCoordinateHashCodeStrategy implements TObjectHashingStrategy<MavenCoordinate> {
+
+ @Override
+ public int computeHashCode(MavenCoordinate object) {
+ String artifactId = object.getArtifactId();
+ return artifactId == null ? 0 : artifactId.hashCode();
+ }
+
+ @Override
+ public boolean equals(MavenCoordinate o1, MavenCoordinate o2) {
+ return Comparing.equal(o1.getArtifactId(), o2.getArtifactId())
+ && Comparing.equal(o1.getVersion(), o2.getVersion())
+ && Comparing.equal(o1.getGroupId(), o2.getGroupId());
+ }
+ }
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
index 6603f0d2d3df..dc1bbdb79a8e 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
@@ -16,7 +16,6 @@
package org.jetbrains.idea.maven.project;
import com.intellij.openapi.components.*;
-import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java
index 9eb88b27f1b5..e3a14b2613ac 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenJDOMUtil.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.encoding.EncodingRegistry;
import com.intellij.psi.impl.source.parsing.xml.XmlBuilder;
import com.intellij.psi.impl.source.parsing.xml.XmlBuilderDriver;
import org.jdom.Element;
@@ -57,7 +58,7 @@ public class MavenJDOMUtil {
@Nullable
public static Element read(byte[] bytes, @Nullable ErrorHandler handler) {
- return doRead(CharsetToolkit.bytesToString(bytes), handler);
+ return doRead(CharsetToolkit.bytesToString(bytes, EncodingRegistry.getInstance().getDefaultCharset()), handler);
}
@Nullable
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java
index 88f5be3ed97d..dcf900e1f087 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java
@@ -481,7 +481,7 @@ public abstract class MavenTestCase extends UsefulTestCase {
@Override
protected void run(Result<VirtualFile> result) throws Throwable {
if (advanceStamps) {
- file.setBinaryContent(content.getBytes(), file.getModificationStamp() + 4000, file.getTimeStamp() + 4000);
+ file.setBinaryContent(content.getBytes(), -1, file.getTimeStamp() + 4000);
}
else {
file.setBinaryContent(content.getBytes(), file.getModificationStamp(), file.getTimeStamp());
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java
index 1211ce5c60e6..f47b6e152bdf 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java
@@ -99,9 +99,9 @@ public abstract class MavenDomTestCase extends MavenImportingTestCase {
}
protected void configTest(VirtualFile f) throws IOException {
- if (Comparing.equal(myConfigTimestamps.get(f), f.getModificationStamp())) return;
+ if (Comparing.equal(myConfigTimestamps.get(f), f.getTimeStamp())) return;
myFixture.configureFromExistingVirtualFile(f);
- myConfigTimestamps.put(f, f.getModificationStamp());
+ myConfigTimestamps.put(f, f.getTimeStamp());
}
protected void type(VirtualFile f, char c) throws IOException {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java
index f0547d2b4ede..add5f3e88acd 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java
@@ -18,10 +18,9 @@ package org.jetbrains.idea.maven.dom;
import com.intellij.idea.Bombed;
import com.intellij.lang.properties.IProperty;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.PsiReference;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.xml.XmlAttribute;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.model.MavenDomProfilesModel;
import org.jetbrains.idea.maven.dom.references.MavenPropertyPsiReference;
@@ -605,4 +604,39 @@ public class MavenFilteredPropertiesCompletionAndResolutionTest extends MavenDom
checkHighlighting();
}
+ public void testReferencesInXml() throws Exception {
+ createProjectSubDir("res");
+
+ importProject("<groupId>test</groupId>" +
+ "<artifactId>project</artifactId>" +
+ "<version>1</version>" +
+
+ "<build>" +
+ " <resources>" +
+ " <resource>" +
+ " <directory>res</directory>" +
+ " <filtering>true</filtering>" +
+ " </resource>" +
+ " </resources>" +
+ "</build>");
+
+ VirtualFile f = createProjectSubFile("res/foo.xml",
+ "<root attr='${based<caret>ir}'>" +
+ "</root>");
+
+ myFixture.configureFromExistingVirtualFile(f);
+
+ XmlAttribute attribute = PsiTreeUtil.getParentOfType(myFixture.getFile().findElementAt(myFixture.getCaretOffset()), XmlAttribute.class);
+
+ PsiReference[] references = attribute.getReferences();
+
+ for (PsiReference ref : references) {
+ if (ref.resolve() instanceof PsiDirectory) {
+ return; // Maven references was added.
+ }
+ }
+
+ assertTrue("Maven filter refrence was not added", false);
+ }
+
}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java
index 06ba195b3250..abf3f3dc4121 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java
@@ -349,7 +349,6 @@ public class MavenPluginCompletionAndResolutionTest extends MavenDomWithIndicesT
checkHighlighting();
}
- @Bombed(day = 25, month = Calendar.JANUARY, year = 2013)
public void testDontHighlightGoalsForUnresolvedPlugin() throws Throwable {
createProjectPom("<groupId>test</groupId>\n" +
"<artifactId>project</artifactId>\n" +
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenClasspathsAndSearchScopesTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenClasspathsAndSearchScopesTest.java
index 95c445193055..5704f3aea793 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenClasspathsAndSearchScopesTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenClasspathsAndSearchScopesTest.java
@@ -19,15 +19,19 @@ import com.intellij.execution.configurations.JavaParameters;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.module.impl.scopes.LibraryRuntimeClasspathScope;
import com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope;
-import com.intellij.openapi.roots.*;
+import com.intellij.openapi.roots.CompilerModuleExtension;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
+import com.intellij.openapi.roots.OrderEnumerator;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.roots.impl.LibraryScopeCache;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.PathsList;
-import com.intellij.util.Processor;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.MavenImportingTestCase;
import org.jetbrains.idea.maven.importing.MavenModuleImporter;
@@ -36,6 +40,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
public class MavenClasspathsAndSearchScopesTest extends MavenImportingTestCase {
@@ -707,6 +712,44 @@ public class MavenClasspathsAndSearchScopesTest extends MavenImportingTestCase {
getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar");
}
+ public void testLibraryScopeForTwoDependentModules() throws IOException {
+ VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
+ "<artifactId>m1</artifactId>" +
+ "<version>1</version>" +
+
+ "<dependencies>" +
+ " <dependency>" +
+ " <groupId>test</groupId>" +
+ " <artifactId>m2</artifactId>" +
+ " <version>1</version>" +
+ " </dependency>" +
+ "</dependencies>");
+
+ VirtualFile m2 = createModulePom("m2", "<groupId>test</groupId>" +
+ "<artifactId>m2</artifactId>" +
+ "<version>1</version>" +
+ " <dependencies>" +
+ " <dependency>" +
+ " <groupId>junit</groupId>" +
+ " <artifactId>junit</artifactId>" +
+ " <version>4.0</version>" +
+ " <scope>provided</scope>" +
+ " </dependency>" +
+ " </dependencies>");
+ importProjects(m1, m2);
+ assertModules("m1", "m2");
+
+ List<Module> modules = Arrays.asList(getModule("m1"), getModule("m2"));
+ GlobalSearchScope scope = LibraryScopeCache.getInstance(myProject).getScopeForLibraryUsedIn(modules);
+ String libraryPath = getRepositoryPath() + "/junit/junit/4.0/junit-4.0.jar";
+ assertSearchScope(scope,
+ getProjectPath() + "/m1/src/main/java",
+ getProjectPath() + "/m1/src/test/java",
+ getProjectPath() + "/m2/src/main/java",
+ getProjectPath() + "/m2/src/test/java",
+ libraryPath);
+ }
+
public void testDoNotIncludeConflictingTransitiveDependenciesInTheClasspath() throws Exception {
VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
"<artifactId>m1</artifactId>" +
@@ -1026,7 +1069,7 @@ public class MavenClasspathsAndSearchScopesTest extends MavenImportingTestCase {
assertSearchScope(moduleName, Scope.RUNTIME, Type.TESTS, paths);
}
- private void assertSearchScope(String moduleName, Scope scope, Type type, String... expectedPaths) throws Exception {
+ private void assertSearchScope(String moduleName, Scope scope, Type type, String... expectedPaths) {
createOutputDirectories();
Module module = getModule(moduleName);
@@ -1043,26 +1086,23 @@ public class MavenClasspathsAndSearchScopesTest extends MavenImportingTestCase {
break;
}
- final List<VirtualFile> entries = new ArrayList<VirtualFile>(((ModuleWithDependenciesScope)searchScope).getRoots());
+ assertSearchScope(searchScope, expectedPaths);
+ }
- OrderEnumerator.orderEntries(module).recursively().compileOnly().forEach(new Processor<OrderEntry>() {
- @Override
- public boolean process(OrderEntry orderEntry) {
- if (orderEntry instanceof JdkOrderEntry) {
- entries.removeAll(Arrays.asList(((JdkOrderEntry)orderEntry).getRootFiles(OrderRootType.CLASSES)));
- }
- return true;
- }
- });
+ private void assertSearchScope(GlobalSearchScope searchScope, String... expectedPaths) {
+ Collection<VirtualFile> roots;
+ if (searchScope instanceof ModuleWithDependenciesScope) {
+ roots = ((ModuleWithDependenciesScope)searchScope).getRoots();
+ }
+ else {
+ roots = ((LibraryRuntimeClasspathScope)searchScope).getRoots();
+ }
+ final List<VirtualFile> entries = new ArrayList<VirtualFile>(roots);
+ entries.removeAll(Arrays.asList(ProjectRootManager.getInstance(myProject).orderEntries().sdkOnly().classes().getRoots()));
List<String> actualPaths = new ArrayList<String>();
for (VirtualFile each : entries) {
- if (each.getFileSystem() == JarFileSystem.getInstance()) {
- actualPaths.add(JarFileSystem.getInstance().getVirtualFileForJar(each).getPath());
- }
- else {
- actualPaths.add(each.getPath());
- }
+ actualPaths.add(each.getPresentableUrl());
}
assertPaths(expectedPaths, actualPaths);
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenResolveToWorkspaceTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenResolveToWorkspaceTest.java
new file mode 100644
index 000000000000..3cfb1a4ca46d
--- /dev/null
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenResolveToWorkspaceTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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 org.jetbrains.idea.maven.execution;
+
+import com.intellij.execution.configurations.JavaParameters;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.artifactResolver.common.MavenModuleMap;
+import org.jetbrains.idea.maven.project.MavenProjectsManager;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class MavenResolveToWorkspaceTest extends MavenImportingTestCase {
+
+ public void _testIgnoredProject() throws Exception {
+ createProjectPom("<groupId>test</groupId>" +
+ "<artifactId>project</artifactId>" +
+ "<version>1</version>" +
+ "<modules>" +
+ " <module>moduleA</module>" +
+ " <module>moduleIgnored</module>" +
+ " <module>moduleB</module>" +
+ "</modules>");
+
+ VirtualFile moduleA = createModulePom("moduleA", "<groupId>test</groupId>" +
+ "<artifactId>moduleA</artifactId>" +
+ "<version>1</version>");
+
+ VirtualFile moduleIgnored = createModulePom("moduleIgnored", "<groupId>test</groupId>" +
+ "<artifactId>moduleIgnored</artifactId>" +
+ "<version>1</version>");
+
+ VirtualFile moduleB = createModulePom("moduleB", "<groupId>test</groupId>" +
+ "<artifactId>moduleB</artifactId>" +
+ "<version>1</version>" +
+ "<dependencies>" +
+ " <dependency>" +
+ " <groupId>test</groupId>" +
+ " <artifactId>moduleA</artifactId>" +
+ " <version>1</version>" +
+ " </dependency>" +
+ " <dependency>" +
+ " <groupId>test</groupId>" +
+ " <artifactId>moduleIgnored</artifactId>" +
+ " <version>1</version>" +
+ " </dependency>" +
+ "</dependencies>"
+ );
+
+ MavenProjectsManager.getInstance(myProject).setIgnoredFilesPaths(Collections.singletonList(moduleIgnored.getPath()));
+
+ importProject();
+
+ MavenProjectsManager.getInstance(myProject).setIgnoredFilesPaths(Collections.singletonList(moduleIgnored.getPath()));
+
+ //assertModules("project", "moduleA", "moduleB");
+
+ AccessToken accessToken = WriteAction.start();
+ try {
+ ProjectRootManager.getInstance(myProject).setProjectSdk(createJdk("Java 1.5"));
+ }
+ finally {
+ accessToken.finish();
+ }
+
+ MavenRunnerParameters runnerParameters = new MavenRunnerParameters(moduleB.getParent().getPath(), false, Collections.singletonList("jetty:run"), Collections.<String, Boolean>emptyMap());
+ runnerParameters.setResolveToWorkspace(true);
+
+ MavenRunnerSettings runnerSettings = MavenRunner.getInstance(myProject).getSettings().clone();
+ runnerSettings.setJreName(MavenRunnerSettings.USE_INTERNAL_JAVA);
+
+ JavaParameters parameters = MavenExternalParameters.createJavaParameters(myProject,
+ runnerParameters,
+ MavenProjectsManager.getInstance(myProject).getGeneralSettings(),
+ runnerSettings);
+
+ String resolveMapFile = null;
+
+ String prefix = "-D" + MavenModuleMap.PATHS_FILE_PROPERTY + "=";
+
+ for (String param : parameters.getVMParametersList().getParameters()) {
+ if (param.startsWith(prefix)) {
+ resolveMapFile = param.substring(prefix.length());
+ break;
+ }
+ }
+
+ assertNotNull(resolveMapFile);
+
+ Properties properties = readProperties(resolveMapFile);
+
+ assertEquals(moduleA.getPath(), properties.getProperty("test:moduleA:pom:1"));
+ assert properties.getProperty("test:moduleA:jar:1").endsWith("/moduleA/target/classes");
+
+ assertNull(properties.getProperty("test:moduleIgnored:pom:1"));
+ assertNull(properties.getProperty("test:moduleIgnored:jar:1"));
+ }
+
+ private static Properties readProperties(String filePath) throws IOException {
+ InputStream is = new BufferedInputStream(new FileInputStream(filePath));
+ try {
+ Properties properties = new Properties();
+ properties.load(is);
+
+ for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+ String value = (String)entry.getValue();
+ entry.setValue(value.replace('\\', '/'));
+ }
+
+ return properties;
+ }
+ finally {
+ is.close();
+ }
+ }
+
+}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java
index 007908d9c015..4f72d4e50e27 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java
@@ -1577,53 +1577,47 @@ public class DependenciesImportingTest extends MavenImportingTestCase {
Arrays.asList("jar://" + getRepositoryPath() + "/junit/junit/4.0/junit-4.0-javadoc.jar!/", "file://foo.javadoc"));
}
- public void testDoNotResetCustomRootForSystemLibraries() throws Exception {
- importProject("<groupId>test</groupId>" +
- "<artifactId>project</artifactId>" +
- "<version>1</version>" +
-
- "<dependencies>" +
- " <dependency>" +
- " <groupId>xxx</groupId>" +
- " <artifactId>yyy</artifactId>" +
- " <version>1</version>" +
- " <scope>system</scope>" +
- " <systemPath>" + getRoot() + "/foo/foo.jar</systemPath>" +
- " </dependency>" +
- "</dependencies>");
-
- assertProjectLibraries("Maven: xxx:yyy:1");
- assertModuleLibDeps("project", "Maven: xxx:yyy:1");
+ public void testDifferentSystemDependenciesWithSameId() throws Exception {
+ createModulePom("m1", "<groupId>test</groupId>" +
+ "<artifactId>m1</artifactId>" +
+ "<version>1</version>" +
- // add sources and javadoc near the jar, just like in the local repository
- addLibraryRoot("Maven: xxx:yyy:1", OrderRootType.SOURCES, "jar://" + getRoot() + "/foo/foo-sources.jar!/");
- addLibraryRoot("Maven: xxx:yyy:1", JavadocOrderRootType.getInstance(), "jar://" + getRoot() + "/foo/foo-javadoc.jar!/");
+ "<dependencies>" +
+ " <dependency>" +
+ " <groupId>xxx</groupId>" +
+ " <artifactId>yyy</artifactId>" +
+ " <version>1</version>" +
+ " <scope>system</scope>" +
+ " <systemPath>" + getRoot() + "/m1/foo.jar</systemPath>" +
+ " </dependency>" +
+ "</dependencies>");
+ createModulePom("m2", "<groupId>test</groupId>" +
+ "<artifactId>m2</artifactId>" +
+ "<version>1</version>" +
- assertModuleLibDep("project", "Maven: xxx:yyy:1",
- Arrays.asList("jar://" + getRoot() + "/foo/foo.jar!/"),
- Arrays.asList("jar://" + getRoot() + "/foo/foo-sources.jar!/"),
- Arrays.asList("jar://" + getRoot() + "/foo/foo-javadoc.jar!/"));
+ "<dependencies>" +
+ " <dependency>" +
+ " <groupId>xxx</groupId>" +
+ " <artifactId>yyy</artifactId>" +
+ " <version>1</version>" +
+ " <scope>system</scope>" +
+ " <systemPath>" + getRoot() + "/m2/foo.jar</systemPath>" +
+ " </dependency>" +
+ "</dependencies>");
- createProjectPom("<groupId>test</groupId>" +
+ importProject("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<version>1</version>" +
+ "<packaging>pom</packaging>" +
- "<dependencies>" +
- " <dependency>" +
- " <groupId>xxx</groupId>" +
- " <artifactId>yyy</artifactId>" +
- " <version>1</version>" +
- " <scope>system</scope>" +
- " <systemPath>" + getRoot() + "/bar/bar.jar</systemPath>" +
- " </dependency>" +
- "</dependencies>");
- scheduleResolveAll();
- resolveDependenciesAndImport();
+ "<modules>" +
+ " <module>m1</module>" +
+ " <module>m2</module>" +
+ "</modules>");
- assertModuleLibDep("project", "Maven: xxx:yyy:1",
- Arrays.asList("jar://" + getRoot() + "/bar/bar.jar!/"),
- Arrays.asList("jar://" + getRoot() + "/foo/foo-sources.jar!/"),
- Arrays.asList("jar://" + getRoot() + "/foo/foo-javadoc.jar!/"));
+// assertProjectLibraries("Maven: xxx:yyy:1");
+ assertModuleLibDep("m1", "Maven: xxx:yyy:1", "jar://" + getRoot() + "/m1/foo.jar!/");
+ assertModuleLibDep("m2", "Maven: xxx:yyy:1", "jar://" + getRoot() + "/m2/foo.jar!/");
}
public void testUpdateRootEntriesWithActualPath() throws Exception {
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 c8136e07144d..6f3db95647c0 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java
@@ -123,6 +123,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
private String selectedPropertyName;
private PropertiesFile selectedPropertiesFile;
+ @Override
public void valueChanged(TreeSelectionEvent e) {
// filter out temp unselect/select events
if (getSelectedPropertyName() == null) return;
@@ -149,7 +150,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
}
myDataProviderPanel = new DataProviderPanel(myPanel);
- getSplitter().setSplitterProportionKey(getClass() + ".splitter");
+ getSplitter().setAndLoadSplitterProportionKey(getClass() + ".splitter");
project.getMessageBus().connect(project).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
@Override
public void selectionChanged(FileEditorManagerEvent event) {
@@ -300,6 +301,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
}
editor.getContentComponent().addFocusListener(new FocusAdapter() {
+ @Override
public void focusGained(FocusEvent e) {
mySelectedEditor = editor;
}
@@ -392,22 +394,27 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
virtualFileManager.addVirtualFileListener(myVfsListener, this);
PsiTreeChangeAdapter psiTreeChangeAdapter = new PsiTreeChangeAdapter() {
+ @Override
public void childAdded(@NotNull PsiTreeChangeEvent event) {
childrenChanged(event);
}
+ @Override
public void childRemoved(@NotNull PsiTreeChangeEvent event) {
childrenChanged(event);
}
+ @Override
public void childReplaced(@NotNull PsiTreeChangeEvent event) {
childrenChanged(event);
}
+ @Override
public void childMoved(@NotNull PsiTreeChangeEvent event) {
childrenChanged(event);
}
+ @Override
public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
final PsiFile file = event.getFile();
PropertiesFile propertiesFile = PropertiesUtil.getPropertiesFile(file);
@@ -431,6 +438,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
private void updateEditorsFromProperties() {
myUpdateEditorAlarm.cancelAllRequests();
myUpdateEditorAlarm.addRequest(new Runnable() {
+ @Override
public void run() {
if (!isValid()) return;
// there is pending update which is going to change prop file anyway
@@ -461,8 +469,10 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
}
final Document document = editor.getDocument();
CommandProcessor.getInstance().executeCommand(null, new Runnable() {
+ @Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
public void run() {
updateDocumentFromPropertyValue(value, document, propertiesFile);
}
@@ -523,10 +533,12 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
DocumentAdapter listener = new DocumentAdapter() {
private String oldText;
+ @Override
public void beforeDocumentChange(DocumentEvent e) {
oldText = e.getDocument().getText();
}
+ @Override
public void documentChanged(DocumentEvent e) {
Document document = e.getDocument();
String text = document.getText();
@@ -542,10 +554,14 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
List<PropertiesFile> propertiesFiles = myResourceBundle.getPropertiesFiles(myProject);
for (final PropertiesFile propertiesFile : propertiesFiles) {
Editor editor = myEditors.get(propertiesFile);
- DocumentListener listener = myDocumentListeners.remove(editor);
- if (listener != null) {
- editor.getDocument().removeDocumentListener(listener);
- }
+ uninstallDocumentListener(editor);
+ }
+ }
+
+ private void uninstallDocumentListener(Editor editor) {
+ DocumentListener listener = myDocumentListeners.remove(editor);
+ if (listener != null) {
+ editor.getDocument().removeDocumentListener(listener);
}
}
@@ -553,11 +569,14 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
private void updatePropertyValueFor(final Document document, final PropertiesFile propertiesFile, final String text, final String oldText) {
myUpdatePsiAlarm.cancelAllRequests();
myUpdatePsiAlarm.addRequest(new Runnable() {
+ @Override
public void run() {
if (!isValid()) return;
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ @Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
public void run() {
Project project = propertiesFile.getProject();
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
@@ -598,6 +617,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
return getNodeValue((DefaultMutableTreeNode)selected.getLastPathComponent());
}
+ @Override
@NotNull
public JComponent getComponent() {
return myDataProviderPanel;
@@ -606,11 +626,13 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
private Object getData(final String dataId) {
if (SelectInContext.DATA_KEY.is(dataId)) {
return new SelectInContext(){
+ @Override
@NotNull
public Project getProject() {
return myProject;
}
+ @Override
@NotNull
public VirtualFile getVirtualFile() {
PropertiesFile selectedFile = getSelectedPropertiesFile();
@@ -620,14 +642,17 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
return virtualFile;
}
+ @Override
public Object getSelectorInFile() {
return getSelectedPropertiesFile();
}
+ @Override
public FileEditorProvider getFileEditorProvider() {
final PropertiesFile selectedPropertiesFile = getSelectedPropertiesFile();
if (selectedPropertiesFile == null) return null;
return new FileEditorProvider() {
+ @Override
public FileEditor openFileEditor() {
final VirtualFile file = selectedPropertiesFile.getVirtualFile();
if (file == null) {
@@ -656,15 +681,18 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
return selectedFile;
}
+ @Override
public JComponent getPreferredFocusedComponent() {
return myStructureViewPanel;
}
+ @Override
@NotNull
public String getName() {
return "Resource Bundle";
}
+ @Override
@NotNull
public ResourceBundleEditorState getState(@NotNull FileEditorStateLevel level) {
return new ResourceBundleEditorState(getSelectedPropertyName());
@@ -674,6 +702,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
return (JBSplitter)mySplitParent.getComponents()[0];
}
+ @Override
public void setState(@NotNull FileEditorState state) {
ResourceBundleEditorState myState = (ResourceBundleEditorState)state;
String propertyName = myState.myPropertyName;
@@ -683,42 +712,52 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
}
}
+ @Override
public boolean isModified() {
return false;
}
+ @Override
public boolean isValid() {
return !myDisposed && !myProject.isDisposed();
}
+ @Override
public void selectNotify() {
}
+ @Override
public void deselectNotify() {
}
+ @Override
public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) {
}
+ @Override
public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) {
}
+ @Override
public BackgroundEditorHighlighter getBackgroundHighlighter() {
return null;
}
+ @Override
public FileEditorLocation getCurrentLocation() {
return null;
}
+ @Override
public StructureViewBuilder getStructureViewBuilder() {
return null;
}
+ @Override
public void dispose() {
VirtualFileManager.getInstance().removeVirtualFileListener(myVfsListener);
@@ -729,13 +768,18 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
private void releaseAllEditors() {
for (Editor editor : myEditors.values()) {
- if (!editor.isDisposed()) {
- EditorFactory.getInstance().releaseEditor(editor);
- }
+ releaseEditor(editor);
}
myEditors.clear();
}
+ private void releaseEditor(Editor editor) {
+ if (!editor.isDisposed()) {
+ uninstallDocumentListener(editor);
+ EditorFactory.getInstance().releaseEditor(editor);
+ }
+ }
+
/**
* Renames target property if the one is available.
* <p/>
@@ -760,6 +804,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
myPropertyName = propertyName;
}
+ @Override
public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) {
return false;
}
@@ -801,6 +846,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
add(panel, BorderLayout.CENTER);
}
+ @Override
@Nullable
public Object getData(String dataId) {
return ResourceBundleEditor.this.getData(dataId);
@@ -812,23 +858,28 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
super(layout);
}
+ @Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
+ @Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
Editor editor = myEditors.values().iterator().next();
return editor.getLineHeight()*4;
}
+ @Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return visibleRect.height;
}
+ @Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
+ @Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
diff --git a/plugins/properties/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java b/plugins/properties/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java
index 5b351239b641..bd3393591167 100644
--- a/plugins/properties/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java
+++ b/plugins/properties/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java
@@ -150,7 +150,7 @@ public class GroupByWordPrefixes implements Grouper, Sorter {
public ActionPresentation getPresentation() {
return new ActionPresentationData(PropertiesBundle.message("structure.view.group.by.prefixes.action.name"),
PropertiesBundle.message("structure.view.group.by.prefixes.action.description"),
- AllIcons.Actions.FileStatus);
+ AllIcons.Actions.GroupByPrefix);
}
@NotNull
diff --git a/plugins/properties/testData/propertiesFile/projectView/bundle/X.java b/plugins/properties/testData/propertiesFile/projectView/bundle/X.java
new file mode 100644
index 000000000000..e9d8ee4c9055
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/bundle/X.java
@@ -0,0 +1,3 @@
+class X {
+ String s= "a.b";
+} \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/bundle/xxx.properties b/plugins/properties/testData/propertiesFile/projectView/bundle/xxx.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/bundle/xxx.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/bundle/xxx_en.properties b/plugins/properties/testData/propertiesFile/projectView/bundle/xxx_en.properties
new file mode 100644
index 000000000000..ea293077ac70
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/bundle/xxx_en.properties
@@ -0,0 +1 @@
+a.b= \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/bundle/xxx_ru_RU.properties b/plugins/properties/testData/propertiesFile/projectView/bundle/xxx_ru_RU.properties
new file mode 100644
index 000000000000..f0c6a965a243
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/bundle/xxx_ru_RU.properties
@@ -0,0 +1 @@
+a.b=ee ry \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/bundle/yyy.properties b/plugins/properties/testData/propertiesFile/projectView/bundle/yyy.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/bundle/yyy.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/sortByType/X.java b/plugins/properties/testData/propertiesFile/projectView/sortByType/X.java
new file mode 100644
index 000000000000..e9d8ee4c9055
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/sortByType/X.java
@@ -0,0 +1,3 @@
+class X {
+ String s= "a.b";
+} \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/sortByType/a.properties b/plugins/properties/testData/propertiesFile/projectView/sortByType/a.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/sortByType/a.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx.properties b/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx2.properties b/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx2.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx2.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx_en.properties b/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx_en.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/sortByType/xxx_en.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/sortByType/yyy.properties b/plugins/properties/testData/propertiesFile/projectView/sortByType/yyy.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/sortByType/yyy.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/standAlone/X.java b/plugins/properties/testData/propertiesFile/projectView/standAlone/X.java
new file mode 100644
index 000000000000..e9d8ee4c9055
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/standAlone/X.java
@@ -0,0 +1,3 @@
+class X {
+ String s= "a.b";
+} \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/standAlone/a.properties b/plugins/properties/testData/propertiesFile/projectView/standAlone/a.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/standAlone/a.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/standAlone/xxx.properties b/plugins/properties/testData/propertiesFile/projectView/standAlone/xxx.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/standAlone/xxx.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/standAlone/xxx2.properties b/plugins/properties/testData/propertiesFile/projectView/standAlone/xxx2.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/standAlone/xxx2.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testData/propertiesFile/projectView/standAlone/yyy.properties b/plugins/properties/testData/propertiesFile/projectView/standAlone/yyy.properties
new file mode 100644
index 000000000000..a1a1e3168c79
--- /dev/null
+++ b/plugins/properties/testData/propertiesFile/projectView/standAlone/yyy.properties
@@ -0,0 +1 @@
+a.b=ccc \ No newline at end of file
diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesProjectViewTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesProjectViewTest.java
new file mode 100644
index 000000000000..2e44168b2e1b
--- /dev/null
+++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesProjectViewTest.java
@@ -0,0 +1,114 @@
+package com.intellij.lang.properties;
+
+import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane;
+import com.intellij.ide.projectView.impl.GroupByTypeComparator;
+import com.intellij.lang.properties.projectView.ResourceBundleGrouper;
+import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.projectView.TestProjectTreeStructure;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.PlatformTestUtil;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+public class PropertiesProjectViewTest extends LightPlatformCodeInsightFixtureTestCase {
+ private TestProjectTreeStructure myStructure;
+
+ public PropertiesProjectViewTest() {
+ PlatformTestCase.initPlatformLangPrefix();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myStructure = new TestProjectTreeStructure(getProject(), myTestRootDisposable);
+ }
+
+ @Override
+ protected String getTestDataPath() {
+ return PluginPathManager.getPluginHomePath("properties") + "/testData/propertiesFile/projectView";
+ }
+
+ public void testBundle() {
+ myFixture.copyDirectoryToProject(getTestName(true), getTestName(true));
+ final AbstractProjectViewPSIPane pane = setupPane(true);
+
+ String structure = "-Project\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: bundle\n" +
+ " yyy.properties\n" +
+ " -Resource Bundle 'xxx'\n" +
+ " xxx.properties\n" +
+ " xxx_en.properties\n" +
+ " xxx_ru_RU.properties\n" +
+ " X.java\n" +
+ myStructure.getProjectFileRepresentation() +
+ " External Libraries\n";
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), structure);
+ }
+
+ public void testStandAlone() {
+ myFixture.copyDirectoryToProject(getTestName(true), getTestName(true));
+ final AbstractProjectViewPSIPane pane = setupPane(true);
+
+ String structure = "-Project\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: standAlone\n" +
+ " a.properties\n" +
+ " xxx.properties\n" +
+ " xxx2.properties\n" +
+ " yyy.properties\n" +
+ " X.java\n" +
+ myStructure.getProjectFileRepresentation() +
+ " External Libraries\n";
+
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), structure);
+ }
+
+ public void testSortByType() {
+ myFixture.copyDirectoryToProject(getTestName(true), getTestName(true));
+ AbstractProjectViewPSIPane pane = setupPane(true);
+
+ String structure = "-Project\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: sortByType\n" +
+ " a.properties\n" +
+ " xxx2.properties\n" +
+ " yyy.properties\n" +
+ " -Resource Bundle 'xxx'\n" +
+ " xxx.properties\n" +
+ " xxx_en.properties\n" +
+ " X.java\n" +
+ myStructure.getProjectFileRepresentation() +
+ " External Libraries\n";
+
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), structure);
+
+ pane = setupPane(false);
+
+ structure = "-Project\n" +
+ " -PsiDirectory: src\n" +
+ " -PsiDirectory: sortByType\n" +
+ " a.properties\n" +
+ " X.java\n" +
+ " -Resource Bundle 'xxx'\n" +
+ " xxx.properties\n" +
+ " xxx_en.properties\n" +
+ " xxx2.properties\n" +
+ " yyy.properties\n" +
+ myStructure.getProjectFileRepresentation() +
+ " External Libraries\n";
+
+ PlatformTestUtil.assertTreeEqual(pane.getTree(), structure);
+ }
+
+ private AbstractProjectViewPSIPane setupPane(final boolean sortByType) {
+ myStructure.setProviders(new ResourceBundleGrouper(getProject()));
+ final AbstractProjectViewPSIPane pane = myStructure.createPane();
+ pane.getTreeBuilder().setNodeDescriptorComparator(new GroupByTypeComparator(sortByType));
+ // there should be xxx.properties in all test data
+ PsiFile psiFile = getPsiManager().findFile(myFixture.findFileInTempDir(getTestName(true) + "/xxx.properties"));
+ assert psiFile != null;
+ pane.select(psiFile, psiFile.getVirtualFile(), sortByType);
+ return pane;
+ }
+}
diff --git a/plugins/svn4idea/bindSvn/bindSvn.iml b/plugins/svn4idea/bindSvn/bindSvn.iml
new file mode 100644
index 000000000000..846587cef36f
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/bindSvn.iml
@@ -0,0 +1,25 @@
+<?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="platform-api" />
+ <orderEntry type="module" module-name="vcs-api" />
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/javahl.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/lib/javahlsrc.zip!/src" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ </component>
+</module>
+
diff --git a/plugins/svn4idea/bindSvn/lib/javahl.jar b/plugins/svn4idea/bindSvn/lib/javahl.jar
new file mode 100644
index 000000000000..a0c5370065af
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/lib/javahl.jar
Binary files differ
diff --git a/plugins/svn4idea/bindSvn/lib/javahlsrc.zip b/plugins/svn4idea/bindSvn/lib/javahlsrc.zip
new file mode 100644
index 000000000000..9c50118203b7
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/lib/javahlsrc.zip
Binary files differ
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/AuthenticationCallback.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/AuthenticationCallback.java
new file mode 100644
index 000000000000..0d3314f1ece5
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/AuthenticationCallback.java
@@ -0,0 +1,109 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+/**
+ * Passed for authentication purpose to SvnLineCommand
+ * Called when svn command indicates that it needs credentials. It also means that credential was not found in standard place
+ * (Subversion config directory)
+ *
+ * Implementations should 1) ask credential from user or take it from any other storage (memory, for instance)
+ * 2) write credential in Subversion standard form into
+ * a) standard config directory if user allowed to save *all* credentials
+ * b) TMP directory and return path to the directory from getSpecialConfigDir() - if user rejected at least one credential storing
+ *
+ * Please note that several credentials could be asked during the command and therefore implementation class is used as
+ * keeping its state, and that TMP directory should be reused for all written credentials
+ *
+ * User: Irina.Chernushina
+ * Date: 2/26/13
+ * Time: 1:05 PM
+ */
+public interface AuthenticationCallback {
+ /**
+ * Authenticate for realm and base file belonging to corresponding working copy
+ *
+ * @param realm - realm that should be used for credential retrieval/storage.
+ * @param base - file target of the operation
+ * @param previousFailed - whether previous credentials were correct
+ * @param passwordRequest - if true, password should be asked. Otherwise that may be a certificate (determined by the protocol)
+ * @return false if authentication canceled or was unsuccessful
+ */
+ boolean authenticateFor(@Nullable String realm, File base, boolean previousFailed, boolean passwordRequest);
+
+ /**
+ * @return config directory if TMP was created
+ */
+ @Nullable
+ File getSpecialConfigDir();
+
+ /**
+ * Ask user or read from memory storage whether server certificate should be accepted
+ *
+ * @param url - that we used for request
+ * @param realm - realm that should be used for credential retrieval/storage.
+ * @return true is certificate was accepted
+ */
+ boolean acceptSSLServerCertificate(String url, final String realm);
+
+ /**
+ * Ask user or read from memory storage whether server certificate should be accepted
+ *
+ * @param file - that we used for request
+ * @param realm - realm that should be used for credential retrieval/storage.
+ * @return true is certificate was accepted
+ */
+ boolean acceptSSLServerCertificate(File file, final String realm);
+
+ /**
+ * Clear credentials stored anywhere - in case they were not full, wrong or anything else
+ *
+ * @param realm - required that credential
+ * @param base - file used in command
+ * @param password - whether password credential should be deleted or certificate, if protocol might demand certificate
+ */
+ void clearPassiveCredentials(String realm, File base, boolean password);
+
+ /**
+ * @return true if there's something from IDEA config that should be persisted into Subversion tmp config directory
+ * for successful call
+ * (now it's IDEA proxy settings)
+ */
+ boolean haveDataForTmpConfig();
+
+ /**
+ * writes IDEA config settings (that should be written) into tmp config directory
+ * (now it's IDEA proxy settings)
+ * @return true if have written data, false if wasn't able to determine parameters etc
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ boolean persistDataToTmpConfig(File baseFile) throws IOException, URISyntaxException;
+
+ /**
+ * Ask for IDEA-defined proxy credentials, using standard authenticator
+ * Store data into tmp config
+ *
+ * @return false if authentication was canceled or related calculations were unsuccessful
+ */
+ boolean askProxyCredentials(File base);
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventHandler.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventHandler.java
new file mode 100644
index 000000000000..7f3bcf3bf4a5
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventHandler.java
@@ -0,0 +1,30 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import java.io.File;
+
+/**
+ * Used to listen to commit events to display progress to user
+ *
+ * User: Irina.Chernushina
+ * Date: 2/26/13
+ * Time: 10:12 AM
+ */
+public interface CommitEventHandler {
+ void commitEvent(final CommitEventType type, final File target);
+ void committedRevision(final long revNum);
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventType.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventType.java
new file mode 100644
index 000000000000..46609e40532c
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/CommitEventType.java
@@ -0,0 +1,49 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/25/13
+ * Time: 6:51 PM
+ */
+public enum CommitEventType {
+ adding("Adding"),
+ deleting("Deleting"),
+ sending("Sending"),
+ replacing("Replacing"),
+ transmittingDeltas("Transmitting file data"),
+ committedRevision("Committed revision");
+
+ private final String myText;
+
+ CommitEventType(String text) {
+ myText = text;
+ }
+
+ public String getText() {
+ return myText;
+ }
+
+ public static CommitEventType create(String text) {
+ text = text.trim();
+ for (CommitEventType value : CommitEventType.values()) {
+ if (value.getText().equals(text)) return value;
+ }
+ return null;
+ }
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindClient.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindClient.java
new file mode 100644
index 000000000000..c155b78ddc53
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindClient.java
@@ -0,0 +1,925 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import org.tigris.subversion.javahl.*;
+
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/5/13
+ * Time: 3:08 PM
+ */
+public class SvnBindClient implements SVNClientInterface {
+ private final String myExecutablePath;
+ private CommitEventHandler myHandler;
+ private AuthenticationCallback myAuthenticationCallback;
+
+ public SvnBindClient(String path) {
+ myExecutablePath = path;
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public Version getVersion() {
+ // todo real version
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getAdminDirectoryName() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isAdminDirectory(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getLastPath() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Status singleStatus(String path, boolean onServer) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Status[] status(String path, boolean descend, boolean onServer, boolean getAll) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Status[] status(String path, boolean descend, boolean onServer, boolean getAll, boolean noIgnore) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Status[] status(String path, boolean descend, boolean onServer, boolean getAll, boolean noIgnore, boolean ignoreExternals)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void status(String path,
+ int depth,
+ boolean onServer,
+ boolean getAll,
+ boolean noIgnore,
+ boolean ignoreExternals,
+ String[] changelists,
+ StatusCallback callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DirEntry[] list(String url, Revision revision, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DirEntry[] list(String url, Revision revision, Revision pegRevision, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void list(String url,
+ Revision revision,
+ Revision pegRevision,
+ int depth,
+ int direntFields,
+ boolean fetchLocks,
+ ListCallback callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void username(String username) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void password(String password) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setPrompt(PromptUserPassword prompt) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd, boolean stopOnCopy) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public LogMessage[] logMessages(String path, Revision revisionStart, Revision revisionEnd, boolean stopOnCopy, boolean discoverPath)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public LogMessage[] logMessages(String path,
+ Revision revisionStart,
+ Revision revisionEnd,
+ boolean stopOnCopy,
+ boolean discoverPath,
+ long limit) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void logMessages(String path,
+ Revision pegRevision,
+ Revision revisionStart,
+ Revision revisionEnd,
+ boolean stopOnCopy,
+ boolean discoverPath,
+ boolean includeMergedRevisions,
+ String[] revProps,
+ long limit,
+ LogMessageCallback callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void logMessages(String path,
+ Revision pegRevision,
+ RevisionRange[] ranges,
+ boolean stopOnCopy,
+ boolean discoverPath,
+ boolean includeMergedRevisions,
+ String[] revProps,
+ long limit,
+ LogMessageCallback callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long checkout(String moduleName, String destPath, Revision revision, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long checkout(String moduleName,
+ String destPath,
+ Revision revision,
+ Revision pegRevision,
+ boolean recurse,
+ boolean ignoreExternals) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long checkout(String moduleName,
+ String destPath,
+ Revision revision,
+ Revision pegRevision,
+ int depth,
+ boolean ignoreExternals,
+ boolean allowUnverObstructions) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void notification(Notify notify) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void notification2(Notify2 notify) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setConflictResolver(ConflictResolverCallback listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setProgressListener(ProgressListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void commitMessageHandler(CommitMessage messageHandler) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void remove(String[] path, String message, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void remove(String[] path, String message, boolean force, boolean keepLocal, Map revpropTable) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void revert(String path, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void revert(String path, int depth, String[] changelists) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(String path, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(String path, boolean recurse, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(String path, int depth, boolean force, boolean noIgnores, boolean addParents) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long update(String path, Revision revision, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long[] update(String[] path, Revision revision, boolean recurse, boolean ignoreExternals) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long update(String path,
+ Revision revision,
+ int depth,
+ boolean depthIsSticky,
+ boolean ignoreExternals,
+ boolean allowUnverObstructions) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long[] update(String[] path,
+ Revision revision,
+ int depth,
+ boolean depthIsSticky,
+ boolean ignoreExternals,
+ boolean allowUnverObstructions) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long commit(String[] path, String message, boolean recurse) throws ClientException {
+ return commit(path, message, recurse? 3 : 0, false, false, null, null);
+ }
+
+ @Override
+ public long commit(String[] path, String message, boolean recurse, boolean noUnlock) throws ClientException {
+ return commit(path, message, recurse? 3 : 0, noUnlock, false, null, null);
+ }
+
+ @Override
+ public long commit(String[] path,
+ String message,
+ int depth,
+ boolean noUnlock,
+ boolean keepChangelist,
+ String[] changelists,
+ Map revpropTable) throws ClientException {
+ final long commit = new SvnCommitRunner(myExecutablePath, myHandler, myAuthenticationCallback).
+ commit(path, message, depth, noUnlock, keepChangelist, changelists, revpropTable);
+ if (commit < 0) {
+ throw new BindClientException("Wrong committed revision number: " + commit, null, -1);
+ }
+ return commit;
+ }
+
+ @Override
+ public void copy(CopySource[] sources,
+ String destPath,
+ String message,
+ boolean copyAsChild,
+ boolean makeParents,
+ boolean ignoreExternals,
+ Map revpropTable) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void copy(CopySource[] sources, String destPath, String message, boolean copyAsChild, boolean makeParents, Map revpropTable)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void copy(String srcPath, String destPath, String message, Revision revision) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void move(String[] srcPaths,
+ String destPath,
+ String message,
+ boolean force,
+ boolean moveAsChild,
+ boolean makeParents,
+ Map revpropTable) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void move(String srcPath, String destPath, String message, Revision ignored, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void move(String srcPath, String destPath, String message, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void mkdir(String[] path, String message, boolean makeParents, Map revpropTable) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void mkdir(String[] path, String message) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void cleanup(String path) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void resolve(String path, int depth, int conflictResult) throws SubversionException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void resolved(String path, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long doExport(String srcPath, String destPath, Revision revision, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long doExport(String srcPath,
+ String destPath,
+ Revision revision,
+ Revision pegRevision,
+ boolean force,
+ boolean ignoreExternals,
+ boolean recurse,
+ String nativeEOL) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long doExport(String srcPath,
+ String destPath,
+ Revision revision,
+ Revision pegRevision,
+ boolean force,
+ boolean ignoreExternals,
+ int depth,
+ String nativeEOL) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long doSwitch(String path, String url, Revision revision, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long doSwitch(String path,
+ String url,
+ Revision revision,
+ Revision pegRevision,
+ int depth,
+ boolean depthIsSticky,
+ boolean ignoreExternals,
+ boolean allowUnverObstructions) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void doImport(String path, String url, String message, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void doImport(String path,
+ String url,
+ String message,
+ int depth,
+ boolean noIgnore,
+ boolean ignoreUnknownNodeTypes,
+ Map revpropTable) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String[] suggestMergeSources(String path, Revision pegRevision) throws SubversionException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void merge(String path1, Revision revision1, String path2, Revision revision2, String localPath, boolean force, boolean recurse)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void merge(String path1,
+ Revision revision1,
+ String path2,
+ Revision revision2,
+ String localPath,
+ boolean force,
+ boolean recurse,
+ boolean ignoreAncestry,
+ boolean dryRun) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void merge(String path1,
+ Revision revision1,
+ String path2,
+ Revision revision2,
+ String localPath,
+ boolean force,
+ int depth,
+ boolean ignoreAncestry,
+ boolean dryRun,
+ boolean recordOnly) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void merge(String path,
+ Revision pegRevision,
+ Revision revision1,
+ Revision revision2,
+ String localPath,
+ boolean force,
+ boolean recurse,
+ boolean ignoreAncestry,
+ boolean dryRun) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void merge(String path,
+ Revision pegRevision,
+ RevisionRange[] revisions,
+ String localPath,
+ boolean force,
+ int depth,
+ boolean ignoreAncestry,
+ boolean dryRun,
+ boolean recordOnly) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void mergeReintegrate(String path, Revision pegRevision, String localPath, boolean dryRun) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Mergeinfo getMergeinfo(String path, Revision pegRevision) throws SubversionException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getMergeinfoLog(int kind,
+ String pathOrUrl,
+ Revision pegRevision,
+ String mergeSourceUrl,
+ Revision srcPegRevision,
+ boolean discoverChangedPaths,
+ int depth,
+ String[] revProps,
+ LogMessageCallback callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getMergeinfoLog(int kind,
+ String pathOrUrl,
+ Revision pegRevision,
+ String mergeSourceUrl,
+ Revision srcPegRevision,
+ boolean discoverChangedPaths,
+ String[] revProps,
+ LogMessageCallback callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diff(String target1, Revision revision1, String target2, Revision revision2, String outFileName, boolean recurse)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diff(String target1,
+ Revision revision1,
+ String target2,
+ Revision revision2,
+ String outFileName,
+ boolean recurse,
+ boolean ignoreAncestry,
+ boolean noDiffDeleted,
+ boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diff(String target1,
+ Revision revision1,
+ String target2,
+ Revision revision2,
+ String relativeToDir,
+ String outFileName,
+ int depth,
+ String[] changelists,
+ boolean ignoreAncestry,
+ boolean noDiffDeleted,
+ boolean force,
+ boolean copiesAsAdds) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diff(String target1,
+ Revision revision1,
+ String target2,
+ Revision revision2,
+ String relativeToDir,
+ String outFileName,
+ int depth,
+ String[] changelists,
+ boolean ignoreAncestry,
+ boolean noDiffDeleted,
+ boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diff(String target,
+ Revision pegRevision,
+ Revision startRevision,
+ Revision endRevision,
+ String outFileName,
+ boolean recurse,
+ boolean ignoreAncestry,
+ boolean noDiffDeleted,
+ boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diff(String target,
+ Revision pegRevision,
+ Revision startRevision,
+ Revision endRevision,
+ String relativeToDir,
+ String outFileName,
+ int depth,
+ String[] changelists,
+ boolean ignoreAncestry,
+ boolean noDiffDeleted,
+ boolean force,
+ boolean copiesAsAdds) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diff(String target,
+ Revision pegRevision,
+ Revision startRevision,
+ Revision endRevision,
+ String relativeToDir,
+ String outFileName,
+ int depth,
+ String[] changelists,
+ boolean ignoreAncestry,
+ boolean noDiffDeleted,
+ boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diffSummarize(String target1,
+ Revision revision1,
+ String target2,
+ Revision revision2,
+ int depth,
+ String[] changelists,
+ boolean ignoreAncestry,
+ DiffSummaryReceiver receiver) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void diffSummarize(String target,
+ Revision pegRevision,
+ Revision startRevision,
+ Revision endRevision,
+ int depth,
+ String[] changelists,
+ boolean ignoreAncestry,
+ DiffSummaryReceiver receiver) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PropertyData[] properties(String path) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PropertyData[] properties(String path, Revision revision) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PropertyData[] properties(String path, Revision revision, Revision pegRevision) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void properties(String path, Revision revision, Revision pegRevision, int depth, String[] changelists, ProplistCallback callback)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertySet(String path, String name, String value, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertySet(String path, String name, String value, boolean recurse, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertySet(String path, String name, byte[] value, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertySet(String path, String name, byte[] value, boolean recurse, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertySet(String path, String name, String value, int depth, String[] changelists, boolean force, Map revpropTable)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertyRemove(String path, String name, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertyRemove(String path, String name, int depth, String[] changelists) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertyCreate(String path, String name, String value, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertyCreate(String path, String name, String value, boolean recurse, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertyCreate(String path, String name, byte[] value, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertyCreate(String path, String name, byte[] value, boolean recurse, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void propertyCreate(String path, String name, String value, int depth, String[] changelists, boolean force)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PropertyData revProperty(String path, String name, Revision rev) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PropertyData[] revProperties(String path, Revision rev) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setRevProperty(String path, String name, Revision rev, String value, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setRevProperty(String path, String name, Revision rev, String value, String originalValue, boolean force)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PropertyData propertyGet(String path, String name) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PropertyData propertyGet(String path, String name, Revision revision) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PropertyData propertyGet(String path, String name, Revision revision, Revision pegRevision) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] fileContent(String path, Revision revision) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] fileContent(String path, Revision revision, Revision pegRevision) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void streamFileContent(String path, Revision revision, Revision pegRevision, int bufferSize, OutputStream stream)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void relocate(String from, String to, String path, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] blame(String path, Revision revisionStart, Revision revisionEnd) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void blame(String path, Revision revisionStart, Revision revisionEnd, BlameCallback callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void blame(String path, Revision pegRevision, Revision revisionStart, Revision revisionEnd, BlameCallback callback)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void blame(String path,
+ Revision pegRevision,
+ Revision revisionStart,
+ Revision revisionEnd,
+ boolean ignoreMimeType,
+ boolean includeMergedRevisions,
+ BlameCallback2 callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void blame(String path,
+ Revision pegRevision,
+ Revision revisionStart,
+ Revision revisionEnd,
+ boolean ignoreMimeType,
+ boolean includeMergedRevisions,
+ BlameCallback3 callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setConfigDirectory(String configDir) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getConfigDirectory() throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void cancelOperation() throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Info info(String path) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void addToChangelist(String[] paths, String changelist, int depth, String[] changelists) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void removeFromChangelists(String[] paths, int depth, String[] changelists) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getChangelists(String rootPath, String[] changelists, int depth, ChangelistCallback callback) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void lock(String[] path, String comment, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unlock(String[] path, boolean force) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Info2[] info2(String pathOrUrl, Revision revision, Revision pegRevision, boolean recurse) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void info2(String pathOrUrl, Revision revision, Revision pegRevision, int depth, String[] changelists, InfoCallback callback)
+ throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getVersionInfo(String path, String trailUrl, boolean lastChanged) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void upgrade(String path) throws ClientException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setHandler(CommitEventHandler handler) {
+ myHandler = handler;
+ }
+
+ public void setAuthenticationCallback(AuthenticationCallback authenticationCallback) {
+ myAuthenticationCallback = authenticationCallback;
+ }
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindUtil.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindUtil.java
new file mode 100644
index 000000000000..1fec6b3bf865
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnBindUtil.java
@@ -0,0 +1,104 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import java.io.File;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/5/13
+ * Time: 4:56 PM
+ */
+public class SvnBindUtil {
+ /**
+ * SVN_ASP_DOT_NET_HACK allows use of an alternate name for Subversion working copy
+ * administrative directories on Windows (which were formerly always
+ * named ".svn"), by setting the SVN_ASP_DOT_NET_HACK environment variable.
+ * When the variable is set (to any value), the administrative directory
+ * will be "_svn" instead of ".svn".
+ *
+ * http://svn.apache.org/repos/asf/subversion/trunk/notes/asp-dot-net-hack.txt
+ */
+ public static final String ADM_NAME = System.getenv("SVN_ASP_DOT_NET_HACK") != null ? "_svn" : ".svn";
+ private final static List<DateFormat> ourFormats = new ArrayList<DateFormat>();
+
+ static {
+ ourFormats.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"));
+ ourFormats.add(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'000Z'"));
+ ourFormats.add(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.US));
+ ourFormats.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z (EE, d MMM yyyy)", Locale.getDefault()));
+ ourFormats.add(new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss' 'ZZZZ' ('E', 'dd' 'MMM' 'yyyy')'"));
+ ourFormats.add(new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss'Z'"));
+ ourFormats.add(new SimpleDateFormat("EEE' 'MMM' 'dd' 'HH:mm:ss' 'yyyy"));
+ ourFormats.add(new SimpleDateFormat("MM' 'dd' 'yyyy"));
+ ourFormats.add(new SimpleDateFormat("MM' 'dd' 'HH:mm"));
+ ourFormats.add(new SimpleDateFormat("MM' 'dd' 'HH:mm:ss"));
+ }
+
+ public static Date parseDate(final String date) {
+ for (DateFormat format : ourFormats) {
+ try {
+ return format.parse(date);
+ }
+ catch (ParseException e) {
+ continue;
+ }
+ }
+ return new Date(0);
+ }
+
+ public static void changelistsToCommand(String[] changeLists, final List<String> list) {
+ if (changeLists != null) {
+ for (String name : changeLists) {
+ list.add("--cl");
+ list.add(name);
+ }
+ }
+ }
+
+ public static String getDepthName(final int i) {
+ return org.tigris.subversion.javahl.Depth.toADepth(i).name();
+ }
+
+ public static File correctUpToExistingParent(File base) {
+ while (base != null) {
+ if (base.exists() && base.isDirectory()) return base;
+ base = base.getParentFile();
+ }
+ return null;
+ }
+
+ public static File getWcRoot(File base) {
+ File current = base;
+ while (current != null) {
+ if (getWcDbUnder(current).exists()) return current;
+ current = current.getParentFile();
+ }
+ return null;
+ }
+
+ public static File getWcDbUnder(final File file) {
+ return new File(file, ADM_NAME + File.separator + "wc.db");
+ }
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnCommitRunner.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnCommitRunner.java
new file mode 100644
index 000000000000..525d675303fc
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/SvnCommitRunner.java
@@ -0,0 +1,217 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ArrayUtil;
+import org.apache.subversion.javahl.types.Revision;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.commandLine.LineCommandListener;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+import org.jetbrains.idea.svn.commandLine.SvnLineCommand;
+import org.jetbrains.idea.svn.config.SvnBindException;
+import org.tigris.subversion.javahl.BindClientException;
+import org.tigris.subversion.javahl.ClientException;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/25/13
+ * Time: 4:56 PM
+ */
+public class SvnCommitRunner {
+ private final String myExePath;
+ @Nullable private final AuthenticationCallback myAuthenticationCallback;
+ private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.SvnCommitRunner");
+ private SvnCommitRunner.CommandListener myCommandListener;
+
+ public SvnCommitRunner(@NotNull String path, @Nullable CommitEventHandler handler, @Nullable AuthenticationCallback authenticationCallback) {
+ myExePath = path;
+ myCommandListener = new CommandListener(handler);
+ myAuthenticationCallback = authenticationCallback;
+ }
+
+ public long commit(String[] paths,
+ String message,
+ int depth,
+ boolean noUnlock,
+ boolean keepChangelist,
+ String[] changelists,
+ Map revpropTable) throws ClientException {
+ if (paths.length == 0) return Revision.SVN_INVALID_REVNUM;
+
+ final List<String> parameters = new ArrayList<String>();
+ parameters.add("--depth");
+ parameters.add(SvnBindUtil.getDepthName(depth));
+ if (noUnlock) {
+ parameters.add("--no-unlock");
+ }
+ if (keepChangelist) {
+ parameters.add("--keep-changelists");
+ }
+ if (changelists != null && changelists.length > 0) {
+ SvnBindUtil.changelistsToCommand(changelists, parameters);
+ }
+ if (revpropTable != null && ! revpropTable.isEmpty()) {
+ final Set<Map.Entry<Object, Object>> set = revpropTable.entrySet();
+ for (Map.Entry<Object, Object> entry : set) {
+ parameters.add("--with-revprop");
+ parameters.add(entry.getKey() + "=" + entry.getValue());
+ }
+ }
+ parameters.add("-m");
+ parameters.add(message);
+ Arrays.sort(paths);
+ parameters.addAll(Arrays.asList(paths));
+
+ try {
+ SvnLineCommand.runWithAuthenticationAttempt(myExePath, new File(paths[0]), SvnCommandName.ci,
+ myCommandListener, myAuthenticationCallback, ArrayUtil.toStringArray(parameters));
+ }
+ catch (SvnBindException e) {
+ throw BindClientException.create(e, Revision.SVN_INVALID_REVNUM);
+ }
+ myCommandListener.throwExceptionIfOccurred();
+
+ return myCommandListener.getCommittedRevision();
+ }
+
+ private static class CommandListener extends LineCommandListener {
+ @Nullable private final CommitEventHandler myHandler;
+ private SvnBindException myException;
+ private long myCommittedRevision = Revision.SVN_INVALID_REVNUM;
+ private File myBase;
+
+ public CommandListener(@Nullable CommitEventHandler handler) {
+ myHandler = handler;
+ }
+
+ public void throwExceptionIfOccurred() throws BindClientException {
+ if (myException != null) {
+ throw BindClientException.create(myException, Revision.SVN_INVALID_REVNUM);
+ }
+ }
+
+ private long getCommittedRevision() {
+ return myCommittedRevision;
+ }
+
+ @Override
+ public void baseDirectory(File file) {
+ myBase = file;
+ }
+
+ @Override
+ public void onLineAvailable(String line, Key outputType) {
+ final String trim = line.trim();
+ if (ProcessOutputTypes.STDOUT.equals(outputType)) {
+ try {
+ parseLine(trim);
+ }
+ catch (SvnBindException e) {
+ myException = e;
+ }
+ }
+ }
+
+ private void parseLine(String line) throws SvnBindException {
+ if (StringUtil.isEmptyOrSpaces(line)) return;
+ if (line.startsWith(CommitEventType.transmittingDeltas.getText())) {
+ if (myHandler != null) {
+ myHandler.commitEvent(CommitEventType.transmittingDeltas, myBase);
+ }
+ return;
+ }
+ if (line.startsWith(CommitEventType.committedRevision.getText())) {
+ final String substring = line.substring(CommitEventType.committedRevision.getText().length());
+ int cnt = 0;
+ while (StringUtil.isWhiteSpace(substring.charAt(cnt))) {
+ ++ cnt;
+ }
+ final StringBuilder num = new StringBuilder();
+ while (Character.isDigit(substring.charAt(cnt))) {
+ num.append(substring.charAt(cnt));
+ ++ cnt;
+ }
+ if (num.length() > 0) {
+ try {
+ myCommittedRevision = Long.parseLong(num.toString());
+ if (myHandler != null) {
+ myHandler.committedRevision(myCommittedRevision);
+ }
+ } catch (NumberFormatException e) {
+ final String message = "Wrong committed revision number: " + num.toString() + ", string: " + line;
+ LOG.info(message, e);
+ throw new SvnBindException(message);
+ }
+ } else {
+ final String message = "Missing committed revision number: " + num.toString() + ", string: " + line;
+ LOG.info(message);
+ throw new SvnBindException(message);
+ }
+ } else {
+ if (myHandler == null) return;
+ final int idxSpace = line.indexOf(' ');
+ if (idxSpace == -1) {
+ LOG.info("Can not parse event type: " + line);
+ return;
+ }
+ final CommitEventType type = CommitEventType.create(line.substring(0, idxSpace));
+ if (type == null) {
+ LOG.info("Can not parse event type: " + line);
+ return;
+ }
+ final File target = new File(myBase, new String(line.substring(idxSpace + 1).trim()));
+ myHandler.commitEvent(type, target);
+ }
+ }
+ }
+
+/*C:\TestProjects\sortedProjects\Subversion\local2\preRelease\mod2\src\com\test>sv
+ n st
+ D gggG
+ D gggG\Rrr.java
+ D gggG\and555.txt
+ D gggG\test.txt
+ A + gggGA
+ D + gggGA\Rrr.java
+ A + gggGA\RrrAA.java
+ D + gggGA\and.txt
+ M + gggGA\and555.txt
+ A gggGA\someNewFile.txt
+
+ --- Changelist 'New changelistrwerwe':
+ A ddd.jpg
+
+ C:\TestProjects\sortedProjects\Subversion\local2\preRelease\mod2\src\com\test>sv
+ n ci -m 123
+ Adding ddd.jpg
+ Deleting gggG
+ Adding gggGA
+ Deleting gggGA\Rrr.java
+ Adding gggGA\RrrAA.java
+ Sending gggGA\and555.txt
+ Adding gggGA\someNewFile.txt
+ Transmitting file data ....
+ Committed revision 165.*/
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/LineCommandListener.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/LineCommandListener.java
new file mode 100644
index 000000000000..ccbc5c37db61
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/LineCommandListener.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.jetbrains.idea.svn.commandLine;
+
+import com.intellij.openapi.vcs.LineProcessEventListenerAdapter;
+
+import java.io.File;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/26/13
+ * Time: 10:38 AM
+ */
+public abstract class LineCommandListener extends LineProcessEventListenerAdapter {
+ private boolean myCanceled;
+
+ public abstract void baseDirectory(final File file);
+
+ public void cancel() {
+ myCanceled = true;
+ }
+
+ protected boolean isCanceled() {
+ return myCanceled;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java
index 5ef336a98428..a1e358b6f4a0 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,14 +20,12 @@ import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessListener;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vcs.ProcessEventListener;
import com.intellij.util.EventDispatcher;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.idea.svn.SvnApplicationSettings;
-import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.List;
@@ -39,9 +37,8 @@ import java.util.List;
* Time: 12:58 PM
*/
public abstract class SvnCommand {
- private static final Logger LOG = Logger.getInstance(SvnCommand.class.getName());
+ static final Logger LOG = Logger.getInstance(SvnCommand.class.getName());
- protected final Project myProject;
private boolean myIsDestroyed;
private int myExitCode;
protected final GeneralCommandLine myCommandLine;
@@ -56,14 +53,20 @@ public abstract class SvnCommand {
/*c:\Program Files (x86)\CollabNet\Subversion Client17>svn --version --quiet
1.7.2*/
- public SvnCommand(Project project, File workingDirectory, @NotNull SvnCommandName commandName) {
+ public SvnCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath) {
+ this(workingDirectory, commandName, exePath, null);
+ }
+
+ public SvnCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath,
+ @Nullable File configDir) {
myLock = new Object();
- myProject = project;
myCommandLine = new GeneralCommandLine();
myWorkingDirectory = workingDirectory;
- final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
- myCommandLine.setExePath(applicationSettings17.getCommandLinePath());
+ myCommandLine.setExePath(exePath);
myCommandLine.setWorkDirectory(workingDirectory);
+ if (configDir != null) {
+ myCommandLine.addParameters("--config-dir", configDir.getPath());
+ }
myCommandLine.addParameter(commandName.getName());
}
@@ -73,10 +76,12 @@ public abstract class SvnCommand {
try {
myProcess = myCommandLine.createProcess();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(myCommandLine.toString());
+ }
myHandler = new OSProcessHandler(myProcess, myCommandLine.getCommandLineString());
startHandlingStreams();
} catch (Throwable t) {
- SvnVcs.getInstance(myProject).checkCommandLineVersion();
myListeners.getMulticaster().startFailed(t);
}
}
@@ -92,7 +97,6 @@ public abstract class SvnCommand {
final int exitCode = event.getExitCode();
try {
setExitCode(exitCode);
- //cleanupEnv(); todo
SvnCommand.this.processTerminated(exitCode);
} finally {
listeners().processTerminated(exitCode);
@@ -210,4 +214,8 @@ public abstract class SvnCommand {
return myExitCode;
}
}
+
+ protected File getWorkingDirectory() {
+ return myWorkingDirectory;
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
index 950ec7f9eb1b..58c2ff2ab308 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,18 +22,26 @@ package org.jetbrains.idea.svn.commandLine;
* Time: 1:49 PM
*/
public enum SvnCommandName {
- version("--version"),
- info("info"),
- st("st"),
- up("up");
+ version("--version", false),
+ info("info", false),
+ st("st", false),
+ up("up", true),
+ ci("commit", true),
+ cleanup("cleanup", true);
private final String myName;
+ private final boolean myWriteable;
- private SvnCommandName(String name) {
+ private SvnCommandName(String name, boolean writeable) {
myName = name;
+ myWriteable = writeable;
}
public String getName() {
return myName;
}
+
+ public boolean isWriteable() {
+ return myWriteable;
+ }
}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
new file mode 100644
index 000000000000..3554b1cd4d81
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
@@ -0,0 +1,415 @@
+/*
+ * 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 org.jetbrains.idea.svn.commandLine;
+
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.LineHandlerHelper;
+import com.intellij.openapi.vcs.LineProcessEventListener;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.EventDispatcher;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.AuthenticationCallback;
+import org.jetbrains.idea.svn.SvnBindUtil;
+import org.jetbrains.idea.svn.config.SvnBindException;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 1/25/12
+ * Time: 4:05 PM
+ *
+ * honestly stolen from GitLineHandler
+ */
+public class SvnLineCommand extends SvnCommand {
+ public static final String AUTHENTICATION_REALM = "Authentication realm:";
+ public static final String CERTIFICATE_ERROR = "Error validating server certificate for";
+ public static final String PASSPHRASE_FOR = "Passphrase for";
+ public static final String UNABLE_TO_CONNECT = "svn: E170001:";
+ public static final String CANNOT_AUTHENTICATE_TO_PROXY = "Could not authenticate to proxy server";
+
+ // kept for exact text
+ //public static final String CLIENT_CERTIFICATE_FILENAME = "Client certificate filename:";
+ /**
+ * the partial line from stdout stream
+ */
+ private final StringBuilder myStdoutLine = new StringBuilder();
+ /**
+ * the partial line from stderr stream
+ */
+ private final StringBuilder myStderrLine = new StringBuilder();
+ private final EventDispatcher<LineProcessEventListener> myLineListeners;
+ private final AtomicReference<Integer> myExitCode;
+ private final StringBuffer myErr;
+
+ public SvnLineCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath) {
+ this(workingDirectory, commandName, exePath, null);
+ }
+
+ public SvnLineCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath, File configDir) {
+ super(workingDirectory, commandName, exePath, configDir);
+ myLineListeners = EventDispatcher.create(LineProcessEventListener.class);
+ myExitCode = new AtomicReference<Integer>();
+ myErr = new StringBuffer();
+ }
+
+ @Override
+ protected void processTerminated(int exitCode) {
+ // force newline
+ if (myStdoutLine.length() != 0) {
+ onTextAvailable("\n\r", ProcessOutputTypes.STDOUT);
+ }
+ else if (myStderrLine.length() != 0) {
+ onTextAvailable("\n\r", ProcessOutputTypes.STDERR);
+ }
+ }
+
+ public static void runWithAuthenticationAttempt(final String exePath,
+ final File firstFile,
+ SvnCommandName commandName,
+ final LineCommandListener listener,
+ @Nullable AuthenticationCallback authenticationCallback,
+ final String... parameters) throws SvnBindException {
+ File base = firstFile.isDirectory() ? firstFile : firstFile.getParentFile();
+ base = SvnBindUtil.correctUpToExistingParent(base);
+
+ listener.baseDirectory(base);
+
+ File configDir = null;
+
+ // for IDEA proxy case
+ if (authenticationCallback != null && authenticationCallback.haveDataForTmpConfig()) {
+ try {
+ if (! authenticationCallback.persistDataToTmpConfig(base)) {
+ throw new SvnBindException("Can not persist " + ApplicationNamesInfo.getInstance().getProductName() +
+ " HTTP proxy information into tmp config directory");
+ }
+ }
+ catch (IOException e) {
+ throw new SvnBindException(e);
+ }
+ catch (URISyntaxException e) {
+ throw new SvnBindException(e);
+ }
+ assert authenticationCallback.getSpecialConfigDir() != null;
+ configDir = authenticationCallback.getSpecialConfigDir();
+ }
+
+ while (true) {
+ final SvnLineCommand command = runCommand(exePath, commandName, listener, base, configDir, parameters);
+ if (command.myErr.length() > 0) {
+ final String errText = command.myErr.toString().trim();
+ if (authenticationCallback != null) {
+ final AuthCallbackCase callback = createCallback(errText, authenticationCallback, base);
+ if (callback != null) {
+ cleanup(exePath, commandName, base);
+ if (callback.getCredentials(errText)) {
+ if (authenticationCallback.getSpecialConfigDir() != null) {
+ configDir = authenticationCallback.getSpecialConfigDir();
+ }
+ continue;
+ }
+ }
+ }
+ throw new SvnBindException(errText);
+ }
+ final Integer exitCode = command.myExitCode.get();
+ if (exitCode != 0) {
+ throw new SvnBindException("Svn process exited with error code: " + exitCode);
+ }
+ return;
+ }
+ //ok
+ }
+
+ private static AuthCallbackCase createCallback(final String errText, final AuthenticationCallback callback, final File base) {
+ if (errText.startsWith(CERTIFICATE_ERROR)) {
+ return new CertificateCallbackCase(callback, base);
+ }
+ if (errText.startsWith(AUTHENTICATION_REALM)) {
+ return new CredentialsCallback(callback, base);
+ }
+ if (errText.startsWith(PASSPHRASE_FOR)) {
+ return new PassphraseCallback(callback, base);
+ }
+ if (errText.startsWith(UNABLE_TO_CONNECT) && errText.contains(CANNOT_AUTHENTICATE_TO_PROXY)) {
+ return new ProxyCallback(callback, base);
+ }
+ return null;
+ }
+
+ private static class ProxyCallback extends AuthCallbackCase {
+ protected ProxyCallback(AuthenticationCallback callback, File base) {
+ super(callback, base);
+ }
+
+ @Override
+ boolean getCredentials(String errText) throws SvnBindException {
+ return myAuthenticationCallback.askProxyCredentials(myBase);
+ }
+ }
+
+ private static class CredentialsCallback extends AuthCallbackCase {
+ protected CredentialsCallback(AuthenticationCallback callback, File base) {
+ super(callback, base);
+ }
+
+ @Override
+ boolean getCredentials(String errText) throws SvnBindException {
+ final String realm = cutFirstLine(errText).substring(AUTHENTICATION_REALM.length()).trim();
+ final boolean isPassword = StringUtil.containsIgnoreCase(errText, "password");
+ if (myTried) {
+ myAuthenticationCallback.clearPassiveCredentials(realm, myBase, isPassword);
+ }
+ myTried = true;
+ if (myAuthenticationCallback.authenticateFor(realm, myBase, myAuthenticationCallback.getSpecialConfigDir() != null, isPassword)) {
+ return true;
+ }
+ throw new SvnBindException("Authentication canceled for realm: " + realm);
+ }
+ }
+
+ private static String cutFirstLine(final String text) {
+ final int idx = text.indexOf('\n');
+ if (idx == -1) return text;
+ return text.substring(0, idx);
+ }
+
+ private static class CertificateCallbackCase extends AuthCallbackCase {
+ private CertificateCallbackCase(AuthenticationCallback callback, File base) {
+ super(callback, base);
+ }
+
+ @Override
+ public boolean getCredentials(final String errText) throws SvnBindException {
+ String realm = cutFirstLine(errText).substring(CERTIFICATE_ERROR.length());
+ final int idx1 = realm.indexOf('\'');
+ if (idx1 == -1) {
+ throw new SvnBindException("Can not detect authentication realm name: " + errText);
+ }
+ final int idx2 = realm.indexOf('\'', idx1 + 1);
+ if (idx2== -1) {
+ throw new SvnBindException("Can not detect authentication realm name: " + errText);
+ }
+ realm = realm.substring(idx1 + 1, idx2);
+ if (! myTried && myAuthenticationCallback.acceptSSLServerCertificate(myBase, realm)) {
+ myTried = true;
+ return true;
+ }
+ throw new SvnBindException("Server SSL certificate rejected");
+ }
+ }
+
+ private static abstract class AuthCallbackCase {
+ protected boolean myTried = false;
+ protected final AuthenticationCallback myAuthenticationCallback;
+ protected final File myBase;
+
+ protected AuthCallbackCase(AuthenticationCallback callback, final File base) {
+ myAuthenticationCallback = callback;
+ myBase = base;
+ }
+
+ abstract boolean getCredentials(final String errText) throws SvnBindException;
+ }
+
+ private static void cleanup(String exePath, SvnCommandName commandName, File base) throws SvnBindException {
+ File wcRoot = SvnBindUtil.getWcRoot(base);
+ if (wcRoot == null) throw new SvnBindException("Can not find working copy root for: " + base.getPath());
+
+ //cleanup -> check command type
+ if (commandName.isWriteable()) {
+ final SvnSimpleCommand command = new SvnSimpleCommand(wcRoot, SvnCommandName.cleanup, exePath);
+ try {
+ command.run();
+ }
+ catch (VcsException e) {
+ throw new SvnBindException(e);
+ }
+ }
+ }
+
+ /*svn: E170001: Commit failed (details follow):
+ svn: E170001: Unable to connect to a repository at URL 'htt../svn/secondRepo/local2/trunk/mod2/src/com/test/gggGA'
+ svn: E170001: OPTIONS of 'htt.../svn/secondRepo/local2/trunk/mod2/src/com/test/gggGA': authorization failed: Could not authenticate to server: rejected Basic challenge (ht)*/
+ private final static String ourAuthFailed = "authorization failed";
+ private final static String ourAuthFailed2 = "Could not authenticate to server";
+
+ private static boolean isAuthenticationFailed(String s) {
+ return s.trim().startsWith(AUTHENTICATION_REALM);
+ //return s.contains(ourAuthFailed) && s.contains(ourAuthFailed2);
+ }
+
+ private static SvnLineCommand runCommand(String exePath,
+ SvnCommandName commandName,
+ final LineCommandListener listener,
+ File base, File configDir,
+ String... parameters) throws SvnBindException {
+ final SvnLineCommand command = new SvnLineCommand(base, commandName, exePath, configDir) {
+ int myErrCnt = 0;
+
+ @Override
+ protected void onTextAvailable(String text, Key outputType) {
+
+ // we won't stop right now if got "authentication realm" -> since we want to get "password" string (that would mean password is expected
+ // or certificate maybe is expected
+ // but for certificate passphrase we get just "Passphrase for ..." - one line without line feed
+
+ // for client certificate (when no path in servers file) we get
+ // Authentication realm: <text>
+ // Client certificate filename:
+ if (ProcessOutputTypes.STDERR.equals(outputType)) {
+ ++ myErrCnt;
+ final String trim = text.trim();
+ if (trim.startsWith(UNABLE_TO_CONNECT)) {
+ // wait for 3 lines of text then
+ if (myErrCnt >= 3) {
+ destroyProcess();
+ }
+ } else if (trim.startsWith(PASSPHRASE_FOR) || myErrCnt >= 2) {
+ destroyProcess();
+ }
+ }
+ super.onTextAvailable(text, outputType);
+ }
+ };
+
+ //command.addParameters("--non-interactive");
+ command.addParameters(parameters);
+ final AtomicReference<Throwable> exceptionRef = new AtomicReference<Throwable>();
+ // several threads
+ command.addLineListener(new LineProcessEventListener() {
+ @Override
+ public void onLineAvailable(String line, Key outputType) {
+ if (SvnCommand.LOG.isDebugEnabled()) {
+ SvnCommand.LOG.debug("==> " + line);
+ }
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ System.out.println("==> " + line);
+ }
+ listener.onLineAvailable(line, outputType);
+ if (listener.isCanceled()) {
+ command.destroyProcess();
+ return;
+ }
+ if (ProcessOutputTypes.STDERR.equals(outputType)) {
+ if (command.myErr.length() > 0) {
+ command.myErr.append('\n');
+ }
+ command.myErr.append(line);
+ }
+ }
+
+ @Override
+ public void processTerminated(int exitCode) {
+ listener.processTerminated(exitCode);
+ command.myExitCode.set(exitCode);
+ }
+
+ @Override
+ public void startFailed(Throwable exception) {
+ listener.startFailed(exception);
+ exceptionRef.set(exception);
+ }
+ });
+ command.start();
+ command.waitFor();
+ if (exceptionRef.get() != null) {
+ throw new SvnBindException(exceptionRef.get());
+ }
+ return command;
+ }
+
+ @Override
+ protected void onTextAvailable(String text, Key outputType) {
+ Iterator<String> lines = LineHandlerHelper.splitText(text).iterator();
+ if (ProcessOutputTypes.STDOUT == outputType) {
+ notifyLines(outputType, lines, myStdoutLine);
+ }
+ else if (ProcessOutputTypes.STDERR == outputType) {
+ notifyLines(outputType, lines, myStderrLine);
+ }
+ }
+
+ private void notifyLines(final Key outputType, final Iterator<String> lines, final StringBuilder lineBuilder) {
+ if (!lines.hasNext()) return;
+ if (lineBuilder.length() > 0) {
+ lineBuilder.append(lines.next());
+ if (lines.hasNext()) {
+ // line is complete
+ final String line = lineBuilder.toString();
+ notifyLine(line, outputType);
+ lineBuilder.setLength(0);
+ }
+ }
+ while (true) {
+ String line = null;
+ if (lines.hasNext()) {
+ line = lines.next();
+ }
+
+ if (lines.hasNext()) {
+ notifyLine(line, outputType);
+ }
+ else {
+ if (line != null && line.length() > 0) {
+ lineBuilder.append(line);
+ }
+ break;
+ }
+ }
+ }
+
+ private void notifyLine(final String line, final Key outputType) {
+ String trimmed = LineHandlerHelper.trimLineSeparator(line);
+ myLineListeners.getMulticaster().onLineAvailable(trimmed, outputType);
+ }
+
+ public void addLineListener(LineProcessEventListener listener) {
+ myLineListeners.addListener(listener);
+ super.addListener(listener);
+ }
+
+ private static class PassphraseCallback extends AuthCallbackCase {
+ public PassphraseCallback(AuthenticationCallback callback, File base) {
+ super(callback, base);
+ }
+
+ @Override
+ boolean getCredentials(String errText) throws SvnBindException {
+ // try to get from file
+ /*if (myTried) {
+ myAuthenticationCallback.clearPassiveCredentials(null, myBase);
+ }*/
+ myTried = true;
+ if (myAuthenticationCallback.authenticateFor(null, myBase, myAuthenticationCallback.getSpecialConfigDir() != null, false)) {
+ return true;
+ }
+ throw new SvnBindException("Authentication canceled for : " + errText.substring(PASSPHRASE_FOR.length()));
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java
index 6f68d390798e..da5df9e6d299 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/commandLine/SvnSimpleCommand.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
package org.jetbrains.idea.svn.commandLine;
import com.intellij.execution.process.ProcessOutputTypes;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vcs.ProcessEventListener;
import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -36,8 +36,8 @@ public class SvnSimpleCommand extends SvnCommand {
private VcsException myException;
private final Object myDataLock;
- public SvnSimpleCommand(Project project, File workingDirectory, @NotNull SvnCommandName commandName) {
- super(project, workingDirectory, commandName);
+ public SvnSimpleCommand(File workingDirectory, @NotNull SvnCommandName commandName, @NotNull @NonNls String exePath) {
+ super(workingDirectory, commandName, exePath);
myDataLock = new Object();
myStderr = new StringBuilder();
@@ -96,13 +96,9 @@ public class SvnSimpleCommand extends SvnCommand {
if (code == 0) {
return myStdout.toString();
} else {
- String msg = myStderr.toString();
- if (msg.length() == 0) {
- msg = getStdout().toString();
- }
- if (msg.length() == 0) {
- msg = "Svn process exited with error code: " + code;
- }
+ final String msg = new StringBuilder("Svn process exited with error code: ").append(code).append("\n")
+ .append("stderr: ").append(myStderr.toString()).append("\nstdout: ").append(getStdout().toString())
+ .append("\nCommand was: ").append(myCommandLine.getCommandLineString()).toString();
throw new VcsException(msg);
}
}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/config/SvnBindException.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/config/SvnBindException.java
new file mode 100644
index 000000000000..8957843e911c
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/config/SvnBindException.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.jetbrains.idea.svn.config;
+
+import com.intellij.openapi.vcs.VcsException;
+
+import java.util.Collection;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/25/13
+ * Time: 5:57 PM
+ *
+ * Marker exception
+ */
+public class SvnBindException extends VcsException {
+ public SvnBindException(String message) {
+ super(message);
+ }
+
+ public SvnBindException(Throwable throwable, boolean isWarning) {
+ super(throwable, isWarning);
+ }
+
+ public SvnBindException(Throwable throwable) {
+ super(throwable);
+ }
+
+ public SvnBindException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public SvnBindException(String message, boolean isWarning) {
+ super(message, isWarning);
+ }
+
+ public SvnBindException(Collection<String> messages) {
+ super(messages);
+ }
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/status/LockWrapper.java b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/status/LockWrapper.java
new file mode 100644
index 000000000000..f4e0f4cf2269
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/jetbrains/idea/svn/status/LockWrapper.java
@@ -0,0 +1,121 @@
+/*
+ * 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 org.jetbrains.idea.svn.status;
+
+import org.apache.subversion.javahl.types.Lock;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Date;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/21/12
+ * Time: 2:33 PM
+ */
+public class LockWrapper {
+ private String myPath;
+ private String myID;
+ private String myOwner;
+ private String myComment;
+ private Date myCreationDate;
+ private Date myExpirationDate;
+
+ public LockWrapper(String path, String ID, String owner, String comment, Date creationDate, Date expirationDate) {
+ myPath = path;
+ myID = ID;
+ myOwner = owner;
+ myComment = comment;
+ myCreationDate = creationDate;
+ myExpirationDate = expirationDate;
+ }
+
+ public LockWrapper() {
+ }
+
+ public String getPath() {
+ return myPath;
+ }
+
+ public void setPath(String path) {
+ myPath = path;
+ }
+
+ public String getID() {
+ return myID;
+ }
+
+ public void setID(String ID) {
+ myID = ID;
+ }
+
+ public String getOwner() {
+ return myOwner;
+ }
+
+ public void setOwner(String owner) {
+ myOwner = owner;
+ }
+
+ public String getComment() {
+ return myComment;
+ }
+
+ public void setComment(String comment) {
+ myComment = comment;
+ }
+
+ public Date getCreationDate() {
+ return myCreationDate;
+ }
+
+ public void setCreationDate(Date creationDate) {
+ myCreationDate = creationDate;
+ }
+
+ public Date getExpirationDate() {
+ return myExpirationDate;
+ }
+
+ public void setExpirationDate(Date expirationDate) {
+ myExpirationDate = expirationDate;
+ }
+
+ public org.tigris.subversion.javahl.Lock create() {
+ final Date creation = getCreationDate();
+ final Date expiration = getExpirationDate();
+ final Lock newLock = new Lock(getOwner(), getPath(), getID(), getComment(), creation == null ? 0 : creation.getTime(),
+ expiration == null ? 0 : expiration.getTime());
+ try {
+ final Constructor<org.tigris.subversion.javahl.Lock> constructor = org.tigris.subversion.javahl.Lock.class.getConstructor(Lock.class);
+ constructor.setAccessible(true);
+ return constructor.newInstance(newLock);
+ }
+ catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ }
+ catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/plugins/svn4idea/bindSvn/src/org/tigris/subversion/javahl/BindClientException.java b/plugins/svn4idea/bindSvn/src/org/tigris/subversion/javahl/BindClientException.java
new file mode 100644
index 000000000000..f8acc17d0558
--- /dev/null
+++ b/plugins/svn4idea/bindSvn/src/org/tigris/subversion/javahl/BindClientException.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.tigris.subversion.javahl;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/25/13
+ * Time: 6:29 PM
+ */
+public class BindClientException extends ClientException {
+ private Throwable myCause;
+
+ public BindClientException(String message, String source, int aprError) {
+ super(message, source, aprError);
+ }
+
+ public BindClientException(org.apache.subversion.javahl.ClientException ex) {
+ super(ex);
+ }
+
+ public static BindClientException create(@NotNull final Throwable t, final int code) {
+ final BindClientException exception = new BindClientException(t.getMessage(), null, code);
+ exception.myCause = t;
+ return exception;
+ }
+
+ @Override
+ public Throwable getCause() {
+ return myCause;
+ }
+}
diff --git a/plugins/svn4idea/lib/sqljet.jar b/plugins/svn4idea/lib/sqljet.jar
index d9aa77b29c3f..d6e0232c1001 100644
--- a/plugins/svn4idea/lib/sqljet.jar
+++ b/plugins/svn4idea/lib/sqljet.jar
Binary files differ
diff --git a/plugins/svn4idea/lib/svnkit-javahl.jar b/plugins/svn4idea/lib/svnkit-javahl.jar
index 8fbe09f66c57..265fda0bb963 100644
--- a/plugins/svn4idea/lib/svnkit-javahl.jar
+++ b/plugins/svn4idea/lib/svnkit-javahl.jar
Binary files differ
diff --git a/plugins/svn4idea/lib/svnkit-javahl16.zip b/plugins/svn4idea/lib/svnkit-javahl16.zip
index 7661a0365e9d..da9b8269cbb5 100644
--- a/plugins/svn4idea/lib/svnkit-javahl16.zip
+++ b/plugins/svn4idea/lib/svnkit-javahl16.zip
Binary files differ
diff --git a/plugins/svn4idea/lib/svnkit.jar b/plugins/svn4idea/lib/svnkit.jar
index 203ef4a61af2..46a3ab556976 100644
--- a/plugins/svn4idea/lib/svnkit.jar
+++ b/plugins/svn4idea/lib/svnkit.jar
Binary files differ
diff --git a/plugins/svn4idea/lib/svnkitsrc.zip b/plugins/svn4idea/lib/svnkitsrc.zip
index d31e1a5a49f6..ab1a19f594c0 100644
--- a/plugins/svn4idea/lib/svnkitsrc.zip
+++ b/plugins/svn4idea/lib/svnkitsrc.zip
Binary files differ
diff --git a/plugins/svn4idea/lib/trilead.jar b/plugins/svn4idea/lib/trilead.jar
index 1351e821540a..7fca04a83626 100644
--- a/plugins/svn4idea/lib/trilead.jar
+++ b/plugins/svn4idea/lib/trilead.jar
Binary files differ
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java
new file mode 100644
index 000000000000..b46b7a875b51
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/28/13
+ * Time: 10:14 AM
+ */
+public enum AuthManagerType {
+ active, passive, usual;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java
index 0202a3c28604..8efa61780535 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java
@@ -27,17 +27,22 @@ import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.CalledInAwt;
import com.intellij.openapi.vcs.changes.committed.AbstractCalledLater;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.util.EventDispatcher;
+import com.intellij.util.messages.Topic;
import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.proxy.CommonProxy;
import com.intellij.util.ui.UIUtil;
+import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.auth.ProviderType;
import org.jetbrains.idea.svn.auth.SvnAuthenticationInteraction;
import org.jetbrains.idea.svn.auth.SvnAuthenticationListener;
+import org.jetbrains.idea.svn.config.ProxyGroup;
+import org.jetbrains.idea.svn.config.SvnServerFileKeys;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNProperties;
@@ -60,6 +65,10 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
public static final String SVN_SSH = "svn+ssh";
public static final String HTTP = "http";
public static final String HTTPS = "https";
+ public static final String HTTP_PROXY_HOST = "http-proxy-host";
+ public static final String HTTP_PROXY_PORT = "http-proxy-port";
+ public static final String HTTP_PROXY_USERNAME = "http-proxy-username";
+ public static final String HTTP_PROXY_PASSWORD = "http-proxy-password";
private Project myProject;
private File myConfigDirectory;
private PersistentAuthenticationProviderProxy myPersistentAuthenticationProviderProxy;
@@ -71,6 +80,10 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
private final ThreadLocalSavePermissions mySavePermissions;
private final Map<Thread, String> myKeyAlgorithm;
private boolean myArtificialSaving;
+ private ISVNAuthenticationProvider myProvider;
+ public static final Topic<ISVNAuthenticationProviderListener> AUTHENTICATION_PROVIDER_LISTENER =
+ new Topic<ISVNAuthenticationProviderListener>("AUTHENTICATION_PROVIDER_LISTENER", ISVNAuthenticationProviderListener.class);
+ private final static ThreadLocal<ISVNAuthenticationProvider> ourThreadLocalProvider = new ThreadLocal<ISVNAuthenticationProvider>();
public SvnAuthenticationManager(final Project project, final File configDirectory) {
super(configDirectory, true, null, null);
@@ -106,6 +119,69 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
});
}
+ private class AuthenticationProviderProxy implements ISVNAuthenticationProvider {
+ private final ISVNAuthenticationProvider myDelegate;
+
+ private AuthenticationProviderProxy(ISVNAuthenticationProvider delegate) {
+ myDelegate = delegate;
+ }
+
+ @Override
+ public SVNAuthentication requestClientAuthentication(String kind,
+ SVNURL url,
+ String realm,
+ SVNErrorMessage errorMessage,
+ SVNAuthentication previousAuth, boolean authMayBeStored) {
+ final SVNAuthentication authentication =
+ myDelegate.requestClientAuthentication(kind, url, realm, errorMessage, previousAuth, authMayBeStored);
+ if (myProject != null && ! myProject.isDisposed()) {
+ myProject.getMessageBus().syncPublisher(AUTHENTICATION_PROVIDER_LISTENER)
+ .requestClientAuthentication(kind, url, realm, errorMessage, previousAuth, authMayBeStored, authentication);
+ }
+ return authentication;
+ }
+
+ @Override
+ public int acceptServerAuthentication(SVNURL url,
+ String realm,
+ Object certificate,
+ boolean resultMayBeStored) {
+ final int result = myDelegate.acceptServerAuthentication(url, realm, certificate, resultMayBeStored);
+ if (myProject != null && ! myProject.isDisposed()) {
+ myProject.getMessageBus().syncPublisher(AUTHENTICATION_PROVIDER_LISTENER)
+ .acceptServerAuthentication(url, realm, certificate, resultMayBeStored, result);
+ }
+ return result;
+ }
+ }
+
+ public interface ISVNAuthenticationProviderListener {
+ void requestClientAuthentication(String kind, SVNURL url, String realm, SVNErrorMessage errorMessage,
+ SVNAuthentication previousAuth, boolean authMayBeStored, SVNAuthentication authentication);
+ void acceptServerAuthentication(SVNURL url, String realm, Object certificate, boolean resultMayBeStored, @MagicConstant int acceptResult);
+ }
+
+ @Override
+ public void setAuthenticationProvider(ISVNAuthenticationProvider provider) {
+ ISVNAuthenticationProvider useProvider = provider;
+ if (! (provider instanceof AuthenticationProviderProxy)) {
+ useProvider = new AuthenticationProviderProxy(provider);
+ }
+ myProvider = useProvider;
+ super.setAuthenticationProvider(myProvider);
+ }
+
+ public ISVNAuthenticationProvider getProvider() {
+ final ISVNAuthenticationProvider threadProvider = ourThreadLocalProvider.get();
+ if (threadProvider != null) return threadProvider;
+ return myProvider;
+ }
+
+ @Override
+ public ISVNAuthenticationStorage getRuntimeAuthStorage() {
+ return super.getRuntimeAuthStorage();
+ }
+
// since set to null during dispose and we have background processes
private SvnConfiguration getConfig() {
if (myConfig == null) throw new ProcessCanceledException();
@@ -361,6 +437,16 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
public void acknowledgeConnectionSuccessful(SVNURL url) {
CommonProxy.getInstance().removeNoProxy(url.getProtocol(), url.getHost(), url.getPort());
SSLExceptionsHelper.removeInfo();
+ ourThreadLocalProvider.remove();
+ }
+
+ @Override
+ public void acknowledgeAuthentication(boolean accepted,
+ String kind,
+ String realm,
+ SVNErrorMessage errorMessage,
+ SVNAuthentication authentication) throws SVNException {
+ acknowledgeAuthentication(accepted, kind, realm, errorMessage, authentication, null);
}
@Override
@@ -371,7 +457,10 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
SVNAuthentication authentication,
SVNURL url) throws SVNException {
SSLExceptionsHelper.removeInfo();
- CommonProxy.getInstance().removeNoProxy(url.getProtocol(), url.getHost(), url.getPort());
+ ourThreadLocalProvider.remove();
+ if (url != null) {
+ CommonProxy.getInstance().removeNoProxy(url.getProtocol(), url.getHost(), url.getPort());
+ }
boolean successSaving = false;
myListener.getMulticaster().acknowledge(accepted, kind, realm, errorMessage, authentication);
try {
@@ -382,18 +471,40 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
} finally {
mySavePermissions.remove();
if (myArtificialSaving) {
+ myArtificialSaving = false;
throw new CredentialsSavedException(successSaving);
}
}
}
+ public void acknowledgeForSSL(boolean accepted, String kind, String realm, SVNErrorMessage message, SVNAuthentication proxy) {
+ if (accepted && proxy instanceof SVNSSLAuthentication && (((SVNSSLAuthentication) proxy).getCertificateFile() != null)) {
+ final SVNSSLAuthentication svnsslAuthentication = (SVNSSLAuthentication)proxy;
+ final SVNURL url = svnsslAuthentication.getURL();
+
+ final IdeaSVNHostOptionsProvider provider = getHostOptionsProvider();
+ final SVNCompositeConfigFile serversFile = provider.getServersFile();
+ String groupName = getGroupName(serversFile.getProperties("groups"), url.getHost());
+
+ if (StringUtil.isEmptyOrSpaces(groupName)) {
+ serversFile.setPropertyValue("global", SvnServerFileKeys.SSL_CLIENT_CERT_FILE, svnsslAuthentication.getCertificateFile().getPath(), true);
+ //serversFile.setPropertyValue("global", SvnServerFileKeys.SSL_CLIENT_CERT_PASSWORD, null, true);
+ } else {
+ serversFile.setPropertyValue(groupName, SvnServerFileKeys.SSL_CLIENT_CERT_FILE, svnsslAuthentication.getCertificateFile().getPath(), true);
+ //serversFile.setPropertyValue(groupName, SvnServerFileKeys.SSL_CLIENT_CERT_PASSWORD, null, true);
+ }
+ serversFile.save();
+ }
+ }
+
public ISVNProxyManager getProxyManager(SVNURL url) throws SVNException {
SSLExceptionsHelper.addInfo("Accessing URL: " + url.toString());
CommonProxy.getInstance().noProxy(url.getProtocol(), url.getHost(), url.getPort());
+ ourThreadLocalProvider.set(myProvider);
// this code taken from default manager (changed for system properties reading)
String host = url.getHost();
- String proxyHost = getServersPropertyIdea(host, "http-proxy-host");
+ String proxyHost = getServersPropertyIdea(host, HTTP_PROXY_HOST);
if ((proxyHost == null) || "".equals(proxyHost.trim())) {
if (getConfig().isIsUseDefaultProxy()) {
// ! use common proxy if it is set
@@ -431,9 +542,9 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
}
}
}
- String proxyPort = getServersPropertyIdea(host, "http-proxy-port");
- String proxyUser = getServersPropertyIdea(host, "http-proxy-username");
- String proxyPassword = getServersPropertyIdea(host, "http-proxy-password");
+ String proxyPort = getServersPropertyIdea(host, HTTP_PROXY_PORT);
+ String proxyUser = getServersPropertyIdea(host, HTTP_PROXY_USERNAME);
+ String proxyPassword = getServersPropertyIdea(host, HTTP_PROXY_PASSWORD);
return new MySimpleProxyManager(proxyHost, proxyPort, proxyUser, proxyPassword);
}
@@ -601,21 +712,35 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im
return false;
}
+ @Nullable
+ public static String getGroupForHost(final String host, final IdeaSVNConfigFile serversFile) {
+ final Map<String,ProxyGroup> groups = serversFile.getAllGroups();
+ for (Map.Entry<String, ProxyGroup> entry : groups.entrySet()) {
+ if (matchesGroupPattern(host, entry.getValue().getPatterns())) return entry.getKey();
+ }
+ return null;
+ }
+
// taken from default manager as is
private static String getGroupName(Map groups, String host) {
- for (Iterator names = groups.keySet().iterator(); names.hasNext();) {
- String name = (String) names.next();
- String pattern = (String) groups.get(name);
- for(StringTokenizer tokens = new StringTokenizer(pattern, ","); tokens.hasMoreTokens();) {
- String token = tokens.nextToken();
- if (DefaultSVNOptions.matches(token, host)) {
- return name;
- }
- }
- }
+ for (Object o : groups.keySet()) {
+ final String name = (String) o;
+ final String pattern = (String) groups.get(name);
+ if (matchesGroupPattern(host, pattern)) return name;
+ }
return null;
}
+ private static boolean matchesGroupPattern(String host, String pattern) {
+ for(StringTokenizer tokens = new StringTokenizer(pattern, ","); tokens.hasMoreTokens();) {
+ String token = tokens.nextToken();
+ if (DefaultSVNOptions.matches(token, host)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
// default = yes
private static boolean isTurned(final String value) {
return value == null || "yes".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
index d2e430e91b2a..0cf1b0a5eb25 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
@@ -435,7 +435,7 @@ checkout.options.recursive.label=Checkout directories recursively
checkout.options.externals.label=Include externals locations
configure.branches.title=Configure Subversion Branches
configure.branches.error.no.connection.title=Repository root was not found
-configure.branches.error.wrong.url=Trunk location must be under repository root
+configure.branches.error.wrong.url=Trunk location must be under repository root\n''{0}''
configure.branches.trunk.location=Trunk location:
configure.branches.branch.locations=Branch locations:
configure.branches.item=Configure Branches...
@@ -648,4 +648,10 @@ svn.create.external.below.action=Create External...
svn.create.external.below.description=Select URL, add svn\:external property, and optionally checkout it
svn.edit.commit.message.title=Edit Revision #{0} Comment
svn.edit.commit.message.attention=Attention! Previous message will be lost!
-svn.edit.commit.message.prompt=New revision comment: \ No newline at end of file
+svn.edit.commit.message.prompt=New revision comment:
+quick.merge.variants.merge.all.explanation=All not merged revisions will be merged.\n\
+Subversion will find not merged revisions using svn\:mergeinfo property recorded in local copy.
+quick.merge.variants.quick.select.explanation=Shows all revisions from target branch, merged and not merged.\n\
+For manual selection. Very quick.
+quick.merge.variants.pre.select.explanation=Finds where one of involved branches was copied from another.\n\
+Loads only not yet merged revisions for selection. Can take long time for execution. \ No newline at end of file
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
index ebdf274bb4d7..3d837368ed66 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
@@ -113,7 +113,7 @@ public class SvnChangeProvider implements ChangeProvider {
throw new VcsException(e.getCause());
} catch (SVNException e) {
if (e.getCause() != null) {
- throw new VcsException(e.getMessage() + e.getCause().getMessage(), e);
+ throw new VcsException(e.getMessage() + " " + e.getCause().getMessage(), e);
}
throw new VcsException(e);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
index 14c005427be6..66132f516be6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
@@ -17,6 +17,8 @@
package org.jetbrains.idea.svn;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -24,11 +26,14 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.changes.VcsAnnotationRefresher;
import org.jdom.Attribute;
import org.jdom.DataConversionException;
import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.config.ProxyGroup;
import org.jetbrains.idea.svn.config.SvnServerFileKeys;
import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider;
import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider;
@@ -48,6 +53,9 @@ import org.tmatesoft.svn.core.wc.SVNWCUtil;
import java.io.File;
import java.io.FilenameFilter;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
+import java.net.Proxy;
import java.util.*;
@State(
@@ -166,6 +174,47 @@ public class SvnConfiguration implements PersistentStateComponent<Element> {
myConfigFile.save();
}
+ public static void putProxyIntoServersFile(final File configDir, final String host, final Proxy proxyInfo) {
+ final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME));
+ configFile.updateGroups();
+
+ String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile);
+
+ if (StringUtil.isEmptyOrSpaces(groupName)) {
+ groupName = StringUtil.replace(host, " ", "_");
+ final Map<String,ProxyGroup> groups = configFile.getAllGroups();
+ while (true) {
+ if (! groups.containsKey(groupName)) break;
+ groupName += "1";
+ }
+ }
+
+ final HashMap<String, String> map = new HashMap<String, String>();
+ final InetSocketAddress address = ((InetSocketAddress) proxyInfo.address());
+ map.put(SvnAuthenticationManager.HTTP_PROXY_HOST, address.getHostName());
+ map.put(SvnAuthenticationManager.HTTP_PROXY_PORT, String.valueOf(address.getPort()));
+ configFile.addGroup(groupName, host + "*", map);
+ configFile.save();
+ }
+
+ public static boolean putProxyCredentialsIntoServerFile(@NotNull final File configDir, @NotNull final String host,
+ @NotNull final PasswordAuthentication authentication) {
+ final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME));
+ configFile.updateGroups();
+
+ String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile);
+ // no proxy defined in group -> no sense in password
+ if (StringUtil.isEmptyOrSpaces(groupName)) return false;
+ final Map<String, String> properties = configFile.getAllGroups().get(groupName).getProperties();
+ if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_HOST))) return false;
+ if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_PORT))) return false;
+
+ configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_USERNAME, authentication.getUserName());
+ configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_PASSWORD, String.valueOf(authentication.getPassword()));
+ configFile.save();
+ return true;
+ }
+
public static SvnConfiguration getInstance(final Project project) {
return ServiceManager.getService(project, SvnConfiguration.class);
}
@@ -281,19 +330,33 @@ public class SvnConfiguration implements PersistentStateComponent<Element> {
}
public static SvnAuthenticationManager createForTmpDir(final Project project, final File dir) {
+ return createForTmpDir(project, dir, null);
+ }
+
+ public static SvnAuthenticationManager createForTmpDir(final Project project, final File dir,
+ @Nullable final SvnInteractiveAuthenticationProvider provider) {
final SvnVcs vcs = SvnVcs.getInstance(project);
- //final SvnAuthenticationManager manager = new SvnAuthenticationManager(project, dir);
final SvnAuthenticationManager interactive = new SvnAuthenticationManager(project, dir);
interactive.setRuntimeStorage(RUNTIME_AUTH_CACHE);
- final SvnInteractiveAuthenticationProvider interactiveProvider = new SvnInteractiveAuthenticationProvider(vcs, interactive);
+ final SvnInteractiveAuthenticationProvider interactiveProvider = provider == null ?
+ new SvnInteractiveAuthenticationProvider(vcs, interactive) : provider;
interactive.setAuthenticationProvider(interactiveProvider);
- //manager.setAuthenticationProvider(new SvnAuthenticationProvider(vcs, interactiveProvider, RUNTIME_AUTH_CACHE));
- //manager.setRuntimeStorage(RUNTIME_AUTH_CACHE);
return interactive;
}
+ public SvnAuthenticationManager getManager(final AuthManagerType type, final SvnVcs vcs) {
+ if (AuthManagerType.active.equals(type)) {
+ return getInteractiveManager(vcs);
+ } else if (AuthManagerType.passive.equals(type)) {
+ return getPassiveAuthenticationManager(vcs.getProject());
+ } else if (AuthManagerType.usual.equals(type)) {
+ return getAuthenticationManager(vcs);
+ }
+ throw new IllegalArgumentException();
+ }
+
public SvnAuthenticationManager getAuthenticationManager(final SvnVcs svnVcs) {
if (myAuthManager == null) {
// reloaded when configuration directory changes
@@ -565,7 +628,7 @@ public class SvnConfiguration implements PersistentStateComponent<Element> {
public void clearAuthenticationDirectory(@Nullable Project project) {
final File authDir = new File(getConfigurationDirectory(), "auth");
if (authDir.exists()) {
- ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
+ final Runnable process = new Runnable() {
public void run() {
final ProgressIndicator ind = ProgressManager.getInstance().getProgressIndicator();
if (ind != null) {
@@ -585,7 +648,13 @@ public class SvnConfiguration implements PersistentStateComponent<Element> {
FileUtil.delete(dir);
}
}
- }, "button.text.clear.authentication.cache", false, project);
+ };
+ final Application application = ApplicationManager.getApplication();
+ if (application.isUnitTestMode() || ! application.isDispatchThread()) {
+ process.run();
+ } else {
+ ProgressManager.getInstance().runProcessWithProgressSynchronously(process, "button.text.clear.authentication.cache", false, project);
+ }
}
}
@@ -601,6 +670,11 @@ public class SvnConfiguration implements PersistentStateComponent<Element> {
RUNTIME_AUTH_CACHE.putData(kind, realm, null);
}
+ public void clearRuntimeStorage() {
+ RUNTIME_AUTH_CACHE.clear();
+ }
+
+
public int getMaxAnnotateRevisions() {
return myMaxAnnotateRevisions;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java
index 105b156a914e..38c099ba4136 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnContentRevision.java
@@ -29,12 +29,9 @@ import com.intellij.openapi.vcs.impl.CurrentRevisionProvider;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNStatus;
-import org.tmatesoft.svn.core.wc.SVNWCClient;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -116,29 +113,7 @@ public class SvnContentRevision implements ContentRevision, MarkerVcsContentRevi
if (lock.exists()) {
throw new VcsException("Can not access file base revision contents: administrative area is locked");
}
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- SVNWCClient wcClient = myVcs.createWCClient();
- try {
- wcClient.doGetFileContents(file, SVNRevision.UNDEFINED, myUseBaseRevision ? SVNRevision.BASE : myRevision, true, buffer);
- buffer.close();
- }
- catch (SVNException e) {
- /*try {
- final SVNInfo info = wcClient.doInfo(file, SVNRevision.UNDEFINED);
- //todo
- }
- catch (SVNException e1) {
- throw new VcsException(e);
- }*/
- throw new VcsException(e);
- }
- catch (IOException e) {
- throw new VcsException(e);
- }
- final byte[] bytes = buffer.toByteArray();
- /*final Charset charset = myFile.getCharset();
- return charset == null ? bytes : SvnUtil.decode(charset, bytes);*/
- return bytes;
+ return SvnUtil.getFileContents(myVcs, file.getPath(), false, myUseBaseRevision ? SVNRevision.BASE : myRevision, SVNRevision.UNDEFINED);
}
@NotNull
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
index 30cb2a92a6af..062c412f2336 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
@@ -228,6 +228,8 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
}
public boolean rename(VirtualFile file, String newName) throws IOException {
+ FileDocumentManager.getInstance().saveAllDocuments();
+
File srcFile = getIOFile(file);
File dstFile = new File(srcFile.getParentFile(), newName);
SvnVcs vcs = getVCS(file);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
index 22f8b05ca71f..94d21dbbbd9d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
@@ -173,7 +173,7 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector {
private static boolean displayUpgradeDialog(Project project, File path, final boolean dispay13format, String[] newMode) {
UpgradeFormatDialog dialog = new UpgradeFormatDialog(project, path, false);
- dialog.setData(dispay13format, newMode[0]);
+ dialog.setData(newMode[0]);
dialog.show();
if (dialog.isOK()) {
newMode[0] = dialog.getUpgradeMode();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
index f4fdfac1114d..4a49dc16a153 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
@@ -16,6 +16,7 @@
package org.jetbrains.idea.svn;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
@@ -28,6 +29,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import com.intellij.vcsUtil.VcsUtil;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
import org.jetbrains.idea.svn.portable.JavaHLSvnStatusClient;
import org.jetbrains.idea.svn.portable.SvnStatusClientI;
@@ -43,6 +45,7 @@ import java.io.File;
import java.util.LinkedList;
public class SvnRecursiveStatusWalker {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnRecursiveStatusWalker");
private final StatusWalkerPartner myPartner;
private final Project myProject;
private final StatusReceiver myReceiver;
@@ -71,8 +74,9 @@ public class SvnRecursiveStatusWalker {
if (path.isDirectory()) {
myHandler.setCurrentItem(item);
try {
- item.getClient(ioFile).doStatus(ioFile, SVNRevision.WORKING, item.getDepth(), false, false, true, true, myHandler, null);
- myHandler.checkIfCopyRootWasReported();
+ final SvnStatusClientI client = item.getClient(ioFile);
+ client.doStatus(ioFile, SVNRevision.WORKING, item.getDepth(), false, false, true, true, myHandler, null);
+ myHandler.checkIfCopyRootWasReported(null, ioFile);
}
catch (SVNException e) {
handleStatusException(item, path, e);
@@ -223,10 +227,18 @@ public class SvnRecursiveStatusWalker {
myMetCurrentItem = false;
}
- public void checkIfCopyRootWasReported() {
- if (! myMetCurrentItem) {
+ public void checkIfCopyRootWasReported(@Nullable final SVNStatus ioFileStatus, final File ioFile) {
+ if (! myMetCurrentItem && FileUtil.filesEqual(ioFile, myCurrentItem.getPath().getIOFile())) {
myMetCurrentItem = true;
- final SVNStatus statusInner = SvnUtil.getStatus(SvnVcs.getInstance(myProject), myCurrentItem.getPath().getIOFile());
+ SVNStatus statusInner;
+ try {
+ statusInner = ioFileStatus != null ? ioFileStatus :
+ myCurrentItem.getClient().doStatus(myCurrentItem.getPath().getIOFile(), false);
+ }
+ catch (SVNException e) {
+ LOG.info(e);
+ statusInner = null;
+ }
if (statusInner == null) return;
final SVNStatusType status = statusInner.getNodeStatus();
@@ -261,7 +273,7 @@ public class SvnRecursiveStatusWalker {
public void handleStatus(final SVNStatus status) throws SVNException {
myPartner.checkCanceled();
final File ioFile = status.getFile();
- checkIfCopyRootWasReported();
+ checkIfCopyRootWasReported(status, ioFile);
final VirtualFile vFile = getVirtualFile(ioFile);
if (vFile != null) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
index ee25402d8ff0..0c049ac4671d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.vcs.AbstractVcsHelper;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangesUtil;
+import com.intellij.openapi.vcs.impl.ContentRevisionCache;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -38,6 +39,7 @@ import com.intellij.openapi.wm.impl.status.StatusBarUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
+import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -52,7 +54,10 @@ import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
+import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.*;
public class SvnUtil {
@@ -298,7 +303,7 @@ public class SvnUtil {
}
public static Collection<List<Change>> splitChangesIntoWc(final SvnVcs vcs, final List<Change> changes) {
- return splitIntoWc(vcs, changes, new Convertor<Change, File>() {
+ return splitIntoRepositories(vcs, changes, new Convertor<Change, File>() {
@Override
public File convert(Change o) {
return ChangesUtil.getFilePath(o).getIOFile();
@@ -306,16 +311,30 @@ public class SvnUtil {
});
}
- public static Collection<List<File>> splitFilesIntoWc(final SvnVcs vcs, final List<File> committables) {
- return splitIntoWc(vcs, committables, Convertor.SELF);
+ public static Collection<List<File>> splitFilesIntoRepositories(final SvnVcs vcs, final List<File> committables) {
+ return splitIntoRepositories(vcs, committables, Convertor.SELF);
}
- public static <T> Collection<List<T>> splitIntoWc(final SvnVcs vcs, final List<T> committables,
- Convertor<T, File> convertor) {
+ public static <T> Collection<List<T>> splitIntoRepositories(final SvnVcs vcs, final List<T> committables,
+ Convertor<T, File> convertor) {
if (committables.size() == 1) {
return Collections.singletonList(committables);
}
+ final MultiMap<Pair<SVNURL, WorkingCopyFormat>, T> result = splitIntoRepositoriesMap(vcs, committables, convertor);
+
+ if (result.size() == 1) {
+ return Collections.singletonList(committables);
+ }
+ final Collection<List<T>> result2 = new ArrayList<List<T>>();
+ for (Map.Entry<Pair<SVNURL, WorkingCopyFormat>, Collection<T>> entry : result.entrySet()) {
+ result2.add((List<T>)entry.getValue());
+ }
+ return result2;
+ }
+
+ public static <T> MultiMap<Pair<SVNURL, WorkingCopyFormat>, T> splitIntoRepositoriesMap(SvnVcs vcs,
+ List<T> committables, Convertor<T, File> convertor) {
final MultiMap<Pair<SVNURL, WorkingCopyFormat>, T> result = new MultiMap<Pair<SVNURL, WorkingCopyFormat>, T>() {
@Override
protected Collection<T> createCollection() {
@@ -330,15 +349,7 @@ public class SvnUtil {
result.putValue(new Pair<SVNURL, WorkingCopyFormat>(path.getRepositoryUrlUrl(), path.getFormat()), committable);
}
}
-
- if (result.size() == 1) {
- return Collections.singletonList(committables);
- }
- final Collection<List<T>> result2 = new ArrayList<List<T>>();
- for (Map.Entry<Pair<SVNURL, WorkingCopyFormat>, Collection<T>> entry : result.entrySet()) {
- result2.add((List<T>)entry.getValue());
- }
- return result2;
+ return result;
}
private static class LocationsCrawler implements SvnWCRootCrawler {
@@ -578,6 +589,12 @@ public class SvnUtil {
return false;
}
+ public static SVNURL getCommittedURL(final SvnVcs vcs, final File file) {
+ final File root = getWorkingCopyRoot(file);
+ if (root == null) return null;
+ return getUrl(vcs, root);
+ }
+
@Nullable
public static SVNURL getUrl(final SvnVcs vcs, final File file) {
try {
@@ -626,12 +643,22 @@ public class SvnUtil {
}
public static File getWcDb(final File file) {
- return new File(file, ".svn/wc.db");
+ return new File(file, SVN_ADMIN_DIR_NAME + "/wc.db");
}
@Nullable
public static File getWcCopyRootIf17(final File file, @Nullable final File upperBound) {
File current = file;
+ boolean wcDbFound = false;
+ while (current != null) {
+ File wcDb;
+ if ((wcDb = getWcDb(current)).exists() && ! wcDb.isDirectory()) {
+ wcDbFound = true;
+ break;
+ }
+ current = current.getParentFile();
+ }
+ if (! wcDbFound) return null;
while (current != null) {
try {
final SvnWcGeneration svnWcGeneration = SvnOperationFactory.detectWcGeneration(current, false);
@@ -675,4 +702,45 @@ public class SvnUtil {
}
return result;
}
+
+ public static byte[] getFileContents(final SvnVcs vcs, final String path, final boolean isUrl, final SVNRevision revision,
+ final SVNRevision pegRevision)
+ throws VcsException {
+ final int maxSize = VcsUtil.getMaxVcsLoadedFileSize();
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream() {
+ @Override
+ public synchronized void write(int b) {
+ if (size() > maxSize) throw new FileTooBigRuntimeException();
+ super.write(b);
+ }
+
+ @Override
+ public synchronized void write(byte[] b, int off, int len) {
+ if (size() > maxSize) throw new FileTooBigRuntimeException();
+ super.write(b, off, len);
+ }
+
+ @Override
+ public synchronized void writeTo(OutputStream out) throws IOException {
+ if (size() > maxSize) throw new FileTooBigRuntimeException();
+ super.writeTo(out);
+ }
+ };
+ SVNWCClient wcClient = vcs.createWCClient();
+ try {
+ if (isUrl) {
+ wcClient.doGetFileContents(SVNURL.parseURIEncoded(path), pegRevision, revision, true, buffer);
+ } else {
+ wcClient.doGetFileContents(new File(path), pegRevision, revision, true, buffer);
+ }
+ ContentRevisionCache.checkContentsSize(path, buffer.size());
+ } catch (FileTooBigRuntimeException e) {
+ ContentRevisionCache.checkContentsSize(path, buffer.size());
+ } catch (SVNException e) {
+ throw new VcsException(e);
+ }
+ return buffer.toByteArray();
+ }
+
+ private static class FileTooBigRuntimeException extends RuntimeException {}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
index 838295cb20a7..dbc78b2799d8 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
@@ -77,7 +77,8 @@ import org.jetbrains.idea.svn.history.LoadedRevisionsCache;
import org.jetbrains.idea.svn.history.SvnChangeList;
import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider;
import org.jetbrains.idea.svn.history.SvnHistoryProvider;
-import org.jetbrains.idea.svn.lowLevel.SvnIdeaRepositoryPoolManager;
+import org.jetbrains.idea.svn.lowLevel.PrimitivePool;
+import org.jetbrains.idea.svn.networking.SSLProtocolExceptionParser;
import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment;
import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment;
import org.jetbrains.idea.svn.update.SvnUpdateEnvironment;
@@ -88,6 +89,7 @@ import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
+import org.tmatesoft.svn.core.internal.util.SVNSSLUtil;
import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil;
import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea14;
@@ -100,10 +102,12 @@ import org.tmatesoft.svn.util.SVNDebugLogAdapter;
import org.tmatesoft.svn.util.SVNLogType;
import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLProtocolException;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.util.*;
+import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
@@ -127,7 +131,6 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
private final Map<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>> myPropertyCache =
new SoftHashMap<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>>();
- private SvnIdeaRepositoryPoolManager myPool;
private final SvnConfiguration myConfiguration;
private final SvnEntriesFileListener myEntriesFileListener;
@@ -436,7 +439,6 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
@Override
public void activate() {
- createPool();
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
if (!myProject.isDefault()) {
ChangeListManager.getInstance(myProject).addChangeListListener(myChangeListListener);
@@ -593,8 +595,6 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
mySvnBranchPointsCalculator = null;
myWorkingCopiesContent.deactivate();
myLoadedBranchesStorage.deactivate();
- myPool.dispose();
- myPool = null;
}
public VcsShowConfirmationOption getAddConfirmation() {
@@ -640,29 +640,17 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
return repos;
}
- private void createPool() {
- if (myPool != null) return;
- final String property = System.getProperty(KEEP_CONNECTIONS_KEY);
- final boolean keep;
- boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();
- // pool variant by default
- if (StringUtil.isEmptyOrSpaces(property) || unitTestMode) {
- keep = ! unitTestMode; // default
- } else {
- keep = Boolean.getBoolean(KEEP_CONNECTIONS_KEY);
- }
- myPool = new SvnIdeaRepositoryPoolManager(false, myConfiguration.getAuthenticationManager(this), myConfiguration.getOptions(myProject));
+ @NotNull
+ private ISVNRepositoryPool getPool() {
+ return getPool(myConfiguration.getAuthenticationManager(this));
}
@NotNull
- private ISVNRepositoryPool getPool() {
+ private ISVNRepositoryPool getPool(ISVNAuthenticationManager manager) {
if (myProject.isDisposed()) {
throw new ProcessCanceledException();
}
- if (myPool == null) {
- createPool();
- }
- return myPool;
+ return new PrimitivePool(manager, myConfiguration.getOptions(myProject));
}
public SVNUpdateClient createUpdateClient() {
@@ -672,7 +660,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
}
public SVNUpdateClient createUpdateClient(@NotNull ISVNAuthenticationManager manager) {
- final SVNUpdateClient client = new SVNUpdateClient(getPool(), myConfiguration.getOptions(myProject));
+ final SVNUpdateClient client = new SVNUpdateClient(getPool(manager), myConfiguration.getOptions(myProject));
client.getOperationsFactory().setAuthenticationManager(manager);
return client;
}
@@ -691,7 +679,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
}
public SVNWCClient createWCClient(@NotNull ISVNAuthenticationManager manager) {
- final SVNWCClient client = new SVNWCClient(getPool(), myConfiguration.getOptions(myProject));
+ final SVNWCClient client = new SVNWCClient(getPool(manager), myConfiguration.getOptions(myProject));
client.getOperationsFactory().setAuthenticationManager(manager);
return client;
}
@@ -715,7 +703,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
}
public SVNLogClient createLogClient(@NotNull ISVNAuthenticationManager manager) {
- final SVNLogClient client = new SVNLogClient(getPool(), myConfiguration.getOptions(myProject));
+ final SVNLogClient client = new SVNLogClient(getPool(manager), myConfiguration.getOptions(myProject));
client.getOperationsFactory().setAuthenticationManager(manager);
return client;
}
@@ -957,7 +945,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
private final boolean myLoggingEnabled;
private final boolean myLogNative;
private final Logger myLog;
- private final static long ourErrorNotificationInterval = 10000;
+ private final static long ourErrorNotificationInterval = TimeUnit.MINUTES.toMillis(2);
private long myPreviousTime = 0;
public JavaSVNDebugLogger(boolean loggingEnabled, boolean logNative, Logger log) {
@@ -972,23 +960,46 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
@Override
public void log(final SVNLogType logType, final Throwable th, final Level logLevel) {
+ handleSpecificSSLExceptions(th);
+ if (shouldLog(logType)) {
+ myLog.info(th);
+ }
+ }
+
+ private void handleSpecificSSLExceptions(Throwable th) {
+ final long time = System.currentTimeMillis();
+ if ((time - myPreviousTime) <= ourErrorNotificationInterval) {
+ return;
+ }
if (th instanceof SSLHandshakeException) {
- final long time = System.currentTimeMillis();
- if ((time - myPreviousTime) > ourErrorNotificationInterval) {
+ // not trusted certificate exception is not the problem, just part of normal behaviour
+ if (th.getCause() instanceof SVNSSLUtil.CertificateNotTrustedException) {
+ LOG.info(th);
+ return;
+ }
+
+ myPreviousTime = time;
+ String info = SSLExceptionsHelper.getAddInfo();
+ info = info == null ? "" : " (" + info + ") ";
+ if (th.getCause() instanceof CertificateException) {
+ PopupUtil.showBalloonForActiveFrame("Subversion: " + info + th.getCause().getMessage(), MessageType.ERROR);
+ } else {
+ final String postMessage = "\nPlease check Subversion SSL settings (Settings | Version Control | Subversion | Network)\n" +
+ "Maybe you should specify SSL protocol manually - SSLv3 or TLSv1";
+ PopupUtil.showBalloonForActiveFrame("Subversion: " + info + th.getMessage() + postMessage, MessageType.ERROR);
+ }
+ } else if (th instanceof SSLProtocolException) {
+ final String message = th.getMessage();
+ if (! StringUtil.isEmptyOrSpaces(message)) {
myPreviousTime = time;
String info = SSLExceptionsHelper.getAddInfo();
info = info == null ? "" : " (" + info + ") ";
- if (th.getCause() instanceof CertificateException) {
- PopupUtil.showBalloonForActiveComponent("Subversion: " + info + th.getCause().getMessage(), MessageType.ERROR);
- } else {
- final String postMessage = "\nPlease check Subversion SSL settings (Settings | Version Control | Subversion | Network)";
- PopupUtil.showBalloonForActiveComponent("Subversion: " + info + th.getMessage() + postMessage, MessageType.ERROR);
- }
+ final SSLProtocolExceptionParser parser = new SSLProtocolExceptionParser(message);
+ parser.parse();
+ final String errMessage = "Subversion: " + info + parser.getParsedMessage();
+ PopupUtil.showBalloonForActiveFrame(errMessage, MessageType.ERROR);
}
}
- if (shouldLog(logType)) {
- myLog.info(th);
- }
}
@Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java
new file mode 100644
index 000000000000..3bd8256e7b02
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.jetbrains.idea.svn.checkin;
+
+import com.intellij.openapi.progress.ProgressIndicator;
+import org.jetbrains.idea.svn.CommitEventHandler;
+import org.jetbrains.idea.svn.CommitEventType;
+import org.jetbrains.idea.svn.SvnBundle;
+
+import java.io.File;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/26/13
+ * Time: 11:13 AM
+ */
+public class IdeaCommitHandler implements CommitEventHandler {
+ private final ProgressIndicator myPi;
+
+ public IdeaCommitHandler(ProgressIndicator pi) {
+ myPi = pi;
+ }
+
+ @Override
+ public void commitEvent(CommitEventType type, File target) {
+ if (myPi == null) return;
+ myPi.checkCanceled();
+
+ if (CommitEventType.adding.equals(type)) {
+ myPi.setText2(SvnBundle.message("progress.text2.adding", target));
+ } else if (CommitEventType.deleting.equals(type)) {
+ myPi.setText2(SvnBundle.message("progress.text2.deleting", target));
+ } else if (CommitEventType.sending.equals(type)) {
+ myPi.setText2(SvnBundle.message("progress.text2.sending", target));
+ } else if (CommitEventType.replacing.equals(type)) {
+ myPi.setText2(SvnBundle.message("progress.text2.replacing", target));
+ } else if (CommitEventType.transmittingDeltas.equals(type)) {
+ myPi.setText2(SvnBundle.message("progress.text2.transmitting.delta", target));
+ }
+ }
+
+ @Override
+ public void committedRevision(long revNum) {
+ if (myPi == null) return;
+ myPi.checkCanceled();
+ myPi.setText2(SvnBundle.message("status.text.comitted.revision", revNum));
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java
new file mode 100644
index 000000000000..618507117bee
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java
@@ -0,0 +1,591 @@
+/*
+ * 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 org.jetbrains.idea.svn.checkin;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.ui.popup.util.PopupUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
+import com.intellij.util.ThrowableRunnable;
+import com.intellij.util.messages.MessageBusConnection;
+import com.intellij.util.net.HttpConfigurable;
+import com.intellij.util.proxy.CommonProxy;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.*;
+import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.auth.*;
+import org.tmatesoft.svn.core.internal.util.SVNBase64;
+import org.tmatesoft.svn.core.internal.util.SVNHashMap;
+import org.tmatesoft.svn.core.internal.util.SVNSSLUtil;
+import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
+import org.tmatesoft.svn.core.internal.wc.SVNWCProperties;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.*;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/26/13
+ * Time: 1:27 PM
+ */
+public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCallback {
+ private final SvnVcs myVcs;
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback");
+ private File myTempDirectory;
+ private boolean myProxyCredentialsWereReturned;
+
+ public IdeaSvnkitBasedAuthenticationCallback(SvnVcs vcs) {
+ myVcs = vcs;
+ }
+
+ @Override
+ public boolean authenticateFor(String realm, File file, boolean previousFailed, boolean passwordRequest) {
+ final File base = getExistingParent(file);
+ if (base == null) return false;
+ final SVNURL url = SvnUtil.getCommittedURL(myVcs, base);
+ if (url == null) return false;
+
+ return new CredentialsAuthenticator(myVcs).tryAuthenticate(realm, url, file, previousFailed, passwordRequest);
+ }
+
+ @Override
+ public boolean acceptSSLServerCertificate(final File file, final String realm) {
+ final File base = getExistingParent(file);
+ if (base == null) return false;
+ final SVNURL url = SvnUtil.getCommittedURL(myVcs, base);
+ if (url == null) return false;
+
+ return new SSLServerCertificateAuthenticator(myVcs).tryAuthenticate(url, realm);
+ }
+
+ @Override
+ public void clearPassiveCredentials(String realm, File file, boolean password) {
+ final File base = getExistingParent(file);
+ if (base == null) return;
+ final SVNURL url = SvnUtil.getCommittedURL(myVcs, base);
+ if (url == null) return;
+ final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject());
+ final List<String> kinds = getKinds(url, password);
+
+ for (String kind : kinds) {
+ configuration.clearCredentials(kind, realm);
+ }
+ }
+
+ @Override
+ public boolean haveDataForTmpConfig() {
+ final HttpConfigurable instance = HttpConfigurable.getInstance();
+ return SvnConfiguration.getInstance(myVcs.getProject()).isIsUseDefaultProxy() &&
+ (instance.USE_HTTP_PROXY || instance.USE_PROXY_PAC);
+ }
+
+ @Override
+ public boolean persistDataToTmpConfig(final File baseFile) throws IOException, URISyntaxException {
+ final File base = getExistingParent(baseFile);
+ if (base == null) return false;
+ final SVNURL url = SvnUtil.getCommittedURL(myVcs, base);
+ if (url == null) return false;
+
+ final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject());
+ initTmpDir(configuration);
+
+ final Proxy proxy = getIdeaDefinedProxy(url);
+ if (proxy != null){
+ SvnConfiguration.putProxyIntoServersFile(myTempDirectory, url.getHost(), proxy);
+ }
+ return true;
+ }
+
+ @Nullable
+ private static Proxy getIdeaDefinedProxy(final SVNURL url) throws URISyntaxException {
+ final List<Proxy> proxies = CommonProxy.getInstance().select(new URI(url.toString()));
+ if (proxies != null && ! proxies.isEmpty()) {
+ for (Proxy proxy : proxies) {
+ if (HttpConfigurable.isRealProxy(proxy) && Proxy.Type.HTTP.equals(proxy.type())) {
+ return proxy;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean askProxyCredentials(File baseFile) {
+ final File base = getExistingParent(baseFile);
+ if (base == null) return false;
+ final SVNURL url = SvnUtil.getCommittedURL(myVcs, base);
+ if (url == null) return false;
+
+ final Proxy proxy;
+ try {
+ proxy = getIdeaDefinedProxy(url);
+ }
+ catch (URISyntaxException e) {
+ LOG.info(e);
+ return false;
+ }
+ if (proxy == null) return false;
+ if (myProxyCredentialsWereReturned){
+ // ask loud
+ final HttpConfigurable instance = HttpConfigurable.getInstance();
+ if (instance.USE_HTTP_PROXY || instance.USE_PROXY_PAC) {
+ PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy. You can change proxy credentials in HTTP proxy settings.", MessageType.ERROR);
+ } else {
+ PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy.", MessageType.ERROR);
+ }
+ return false;
+ }
+ final InetSocketAddress address = (InetSocketAddress)proxy.address();
+ final PasswordAuthentication authentication;
+ try {
+ authentication = Authenticator.requestPasswordAuthentication(url.getHost(), address.getAddress(),
+ url.getPort(), url.getProtocol(), url.getHost(), url.getProtocol(),
+ new URL(url.toString()), Authenticator.RequestorType.PROXY);
+ } catch (MalformedURLException e) {
+ LOG.info(e);
+ return false;
+ }
+ if (authentication != null) {
+ myProxyCredentialsWereReturned = true;
+ return SvnConfiguration.putProxyCredentialsIntoServerFile(myTempDirectory, url.getHost(), authentication);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean acceptSSLServerCertificate(final String url, final String realm) {
+ try {
+ return new SSLServerCertificateAuthenticator(myVcs).tryAuthenticate(SVNURL.parseURIEncoded(url), realm);
+ }
+ catch (SVNException e) {
+ return false;
+ }
+ }
+
+ public void reset() {
+ if (myTempDirectory != null) {
+ FileUtil.delete(myTempDirectory);
+ }
+ }
+
+ private abstract class AbstractAuthenticator<T> {
+ protected final SvnVcs myVcs;
+ protected boolean myStoreInUsual;
+ protected SvnAuthenticationManager myTmpDirManager;
+
+ protected AbstractAuthenticator(SvnVcs vcs) {
+ myVcs = vcs;
+ }
+
+ protected boolean tryAuthenticate() {
+ final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject());
+ final SvnAuthenticationManager passive = configuration.getPassiveAuthenticationManager(myVcs.getProject());
+ final SvnAuthenticationManager manager = configuration.getAuthenticationManager(myVcs);
+
+ try {
+ T svnAuthentication = getWithPassive(passive);
+ if (svnAuthentication == null) {
+ svnAuthentication = getWithActive(manager);
+ }
+ if (svnAuthentication == null) return false;
+
+ if (myStoreInUsual) {
+ manager.setArtificialSaving(true);
+ return acknowledge(manager, svnAuthentication);
+ } else {
+ if (myTmpDirManager == null) {
+ initTmpDir(configuration);
+ myTmpDirManager = createTmpManager();
+ }
+ myTmpDirManager.setArtificialSaving(true);
+ return acknowledge(myTmpDirManager, svnAuthentication);
+ }
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR);
+ return false;
+ }
+ catch (SVNException e) {
+ LOG.info(e);
+ VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR);
+ return false;
+ }
+ }
+
+ protected SvnAuthenticationManager createTmpManager() {
+ return SvnConfiguration.createForTmpDir(myVcs.getProject(), myTempDirectory);
+ }
+
+ protected abstract T getWithPassive(SvnAuthenticationManager passive) throws SVNException;
+ protected abstract T getWithActive(SvnAuthenticationManager active) throws SVNException;
+ protected abstract boolean acknowledge(SvnAuthenticationManager manager, T svnAuthentication) throws SVNException;
+ }
+
+ private void initTmpDir(SvnConfiguration configuration) throws IOException {
+ if (myTempDirectory == null) {
+ myTempDirectory = FileUtil.createTempDirectory("tmp", "Subversion");
+ FileUtil.copyDir(new File(configuration.getConfigurationDirectory()), myTempDirectory);
+ }
+ }
+
+ private void doWithSubscribeToAuthProvider(SvnAuthenticationManager.ISVNAuthenticationProviderListener listener,
+ final ThrowableRunnable<SVNException> runnable) throws SVNException {
+ MessageBusConnection connection = null;
+ try {
+ final Project project = myVcs.getProject();
+ connection = project.getMessageBus().connect(project);
+ connection.subscribe(SvnAuthenticationManager.AUTHENTICATION_PROVIDER_LISTENER, listener);
+ runnable.run();
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ }
+
+ // plus seems that we also should ask for credentials; but we didn't receive realm name yet
+ private class SSLServerCertificateAuthenticator extends AbstractAuthenticator<Boolean> {
+ private SVNURL myUrl;
+ private String myRealm;
+ private String myCertificateRealm;
+ private String myCredentialsRealm;
+ private Object myCertificate;
+ private int myResult;
+ private SVNAuthentication myAuthentication;
+
+ protected SSLServerCertificateAuthenticator(SvnVcs vcs) {
+ super(vcs);
+ }
+
+ public boolean tryAuthenticate(final SVNURL url, final String realm) {
+ myUrl = url;
+ myRealm = realm;
+ myResult = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY;
+ myStoreInUsual = false;
+ return tryAuthenticate();
+ }
+
+ @Override
+ protected Boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException {
+ String stored = (String) passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm);
+ if (stored == null) return null;
+ CertificateFactory cf;
+ try {
+ cf = CertificateFactory.getInstance("X509");
+ final byte[] buffer = new byte[stored.length()];
+ SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer);
+ myCertificate = cf.generateCertificate(new ByteArrayInputStream(buffer));
+ }
+ catch (CertificateException e) {
+ throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e));
+ }
+ myCertificateRealm = myRealm;
+ return myCertificate != null ? true : null;
+ }
+
+ @Override
+ protected Boolean getWithActive(final SvnAuthenticationManager active) throws SVNException {
+ doWithSubscribeToAuthProvider(new SvnAuthenticationManager.ISVNAuthenticationProviderListener() {
+ @Override
+ public void requestClientAuthentication(String kind,
+ SVNURL url,
+ String realm,
+ SVNErrorMessage errorMessage,
+ SVNAuthentication previousAuth,
+ boolean authMayBeStored,
+ SVNAuthentication authentication) {
+ if (!myUrl.equals(url)) return;
+ myCredentialsRealm = realm;
+ myAuthentication = authentication;
+ if (myAuthentication != null) {
+ myStoreInUsual &= myAuthentication.isStorageAllowed();
+ }
+ }
+
+ @Override
+ public void acceptServerAuthentication(SVNURL url,
+ String realm,
+ Object certificate,
+ boolean resultMayBeStored,
+ int accepted) {
+ if (!myUrl.equals(url)) return;
+ myCertificateRealm = realm;
+ myCertificate = certificate;
+ myResult = accepted;
+ }
+ }, new ThrowableRunnable<SVNException>() {
+ @Override
+ public void run() throws SVNException {
+ myVcs.createWCClient(active).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
+ }
+ }
+ );
+
+ myStoreInUsual &= myCertificate != null && ISVNAuthenticationProvider.ACCEPTED == myResult;
+ return ISVNAuthenticationProvider.REJECTED != myResult && myCertificate != null;
+ }
+
+ @Override
+ protected boolean acknowledge(SvnAuthenticationManager manager, Boolean svnAuthentication) throws SVNException {
+ // we should store certificate, if it wasn't accepted (if temporally tmp)
+ if (myCertificate == null) { // this is if certificate was stored only in passive area
+ String stored = (String) manager.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm);
+ if (StringUtil.isEmptyOrSpaces(stored)) {
+ throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "No stored server certificate was found in runtime"));
+ }
+ CertificateFactory cf;
+ try {
+ cf = CertificateFactory.getInstance("X509");
+ final byte[] buffer = new byte[stored.length()];
+ SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer);
+ myCertificate = cf.generateCertificate(new ByteArrayInputStream(buffer));
+ }
+ catch (CertificateException e) {
+ throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e));
+ }
+ myCertificateRealm = myRealm;
+ }
+ if (myTempDirectory != null && myCertificate != null) {
+ if (! (myCertificate instanceof X509Certificate)) {
+ throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not store server certificate: " + myCertificate));
+ }
+ X509Certificate x509Certificate = (X509Certificate) myCertificate;
+ String stored;
+ try {
+ stored = SVNBase64.byteArrayToBase64(x509Certificate.getEncoded());
+ }
+ catch (CertificateEncodingException e) {
+ throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e));
+ }
+ int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost());
+ storeServerCertificate(myTempDirectory, myCertificateRealm, stored, failures);
+ if (myAuthentication != null) {
+ final String realm = myCredentialsRealm == null ? myCertificateRealm : myCredentialsRealm;
+ return storeCredentials(manager, myAuthentication, realm);
+ }
+ }
+ return true;
+ }
+
+ private void storeServerCertificate(final File configDir, String realm, String data, int failures) throws SVNException {
+ //noinspection ResultOfMethodCallIgnored
+ configDir.mkdirs();
+
+ File file = new File(configDir, "auth/svn.ssl.server/" + SVNFileUtil.computeChecksum(realm));
+ SVNHashMap map = new SVNHashMap();
+ map.put("ascii_cert", data);
+ map.put("svn:realmstring", realm);
+ map.put("failures", Integer.toString(failures));
+
+ SVNFileUtil.deleteFile(file);
+
+ File tmpFile = SVNFileUtil.createUniqueFile(configDir, "auth", ".tmp", true);
+ try {
+ SVNWCProperties.setProperties(SVNProperties.wrap(map), file, tmpFile, SVNWCProperties.SVN_HASH_TERMINATOR);
+ } finally {
+ SVNFileUtil.deleteFile(tmpFile);
+ }
+ }
+ }
+
+ private boolean storeCredentials(SvnAuthenticationManager manager, final SVNAuthentication authentication, final String realm) throws SVNException {
+ try {
+ final String kind = getFromType(authentication);
+ if (! acknowledgeSSL(manager, authentication)) {
+ manager.acknowledgeAuthentication(true, kind, realm, null, authentication, authentication.getURL());
+ }
+ } catch (SvnAuthenticationManager.CredentialsSavedException e) {
+ return e.isSuccess();
+ }
+ return true;
+ }
+
+ private class CredentialsAuthenticator extends AbstractAuthenticator<SVNAuthentication> {
+ private String myKind;
+ private String myRealm;
+ // sometimes realm string is different (with <>), so store credentials for both strings..
+ private String myRealm2;
+ private SVNURL myUrl;
+ private SVNAuthentication myAuthentication;
+ private File myFile;
+
+ protected CredentialsAuthenticator(SvnVcs vcs) {
+ super(vcs);
+ }
+
+ public boolean tryAuthenticate(String realm, SVNURL url, File file, boolean previousFailed, boolean passwordRequest) {
+ myFile = file;
+ realm = realm == null ? url.getHost() : realm;
+ myRealm = realm;
+ myUrl = url;
+ final List<String> kinds = getKinds(url, passwordRequest);
+ for (String kind : kinds) {
+ myKind = kind;
+ if (! tryAuthenticate()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ protected SVNAuthentication getWithPassive(SvnAuthenticationManager passive) throws SVNException {
+ final SVNAuthentication impl = getWithPassiveImpl(passive);
+ if (impl != null && ! checkAuthOk(impl)) {
+ clearPassiveCredentials(myRealm, myFile, impl instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath
+ return null;
+ }
+ return impl;
+ }
+
+ private SVNAuthentication getWithPassiveImpl(SvnAuthenticationManager passive) throws SVNException {
+ try {
+ return passive.getFirstAuthentication(myKind, myRealm, myUrl);
+ } catch (SVNCancelException e) {
+ return null;
+ }
+ }
+
+ private boolean checkAuthOk(SVNAuthentication authentication) {
+ if (authentication instanceof SVNPasswordAuthentication && StringUtil.isEmptyOrSpaces(authentication.getUserName())) return false;
+ if (authentication instanceof SVNSSLAuthentication) {
+ if (StringUtil.isEmptyOrSpaces(((SVNSSLAuthentication)authentication).getPassword())) return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected SVNAuthentication getWithActive(final SvnAuthenticationManager active) throws SVNException {
+ if (ISVNAuthenticationManager.SSL.equals(myKind)) {
+ doWithSubscribeToAuthProvider(new SvnAuthenticationManager.ISVNAuthenticationProviderListener() {
+ @Override
+ public void requestClientAuthentication(String kind,
+ SVNURL url,
+ String realm,
+ SVNErrorMessage errorMessage,
+ SVNAuthentication previousAuth,
+ boolean authMayBeStored,
+ SVNAuthentication authentication) {
+ if (!myUrl.equals(url)) return;
+ myAuthentication = authentication;
+ myRealm2 = realm;
+ myStoreInUsual = myAuthentication != null && myAuthentication.isStorageAllowed();
+ }
+
+ @Override
+ public void acceptServerAuthentication(SVNURL url,
+ String realm,
+ Object certificate,
+ boolean resultMayBeStored,
+ int accepted) {
+ }
+ }, new ThrowableRunnable<SVNException>() {
+ @Override
+ public void run() throws SVNException {
+ myVcs.createWCClient(active).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
+ }
+ }
+ );
+ if (myAuthentication != null) return myAuthentication;
+ }
+ myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true);
+ myStoreInUsual = myTempDirectory == null && myAuthentication != null && myAuthentication.isStorageAllowed();
+ return myAuthentication;
+ }
+
+ @Override
+ protected boolean acknowledge(SvnAuthenticationManager manager, SVNAuthentication svnAuthentication) throws SVNException {
+ if (! StringUtil.isEmptyOrSpaces(myRealm2) && ! myRealm2.equals(myRealm)) {
+ storeCredentials(manager, svnAuthentication, myRealm2);
+ }
+ return storeCredentials(manager, svnAuthentication, myRealm);
+ }
+ }
+
+ private boolean acknowledgeSSL(SvnAuthenticationManager manager, SVNAuthentication svnAuthentication) throws SVNException {
+ if (svnAuthentication instanceof SVNSSLAuthentication && (((SVNSSLAuthentication) svnAuthentication).getCertificateFile() != null)) {
+ manager.acknowledgeForSSL(true, getFromType(svnAuthentication),
+ ((SVNSSLAuthentication) svnAuthentication).getCertificateFile().getPath(),
+ null, svnAuthentication);
+ manager.acknowledgeAuthentication(true, getFromType(svnAuthentication),
+ ((SVNSSLAuthentication) svnAuthentication).getCertificateFile().getPath(),
+ null, svnAuthentication, svnAuthentication.getURL());
+ return true;
+ }
+ return false;
+ }
+
+ private File getExistingParent(final File file) {
+ File current = file;
+ while (current != null) {
+ if (current.exists()) return current;
+ current = current.getParentFile();
+ }
+ return null;
+ }
+
+ private static List<String> getKinds(final SVNURL url, boolean passwordRequest) {
+ if (passwordRequest || "http".equals(url.getProtocol())) {
+ return Collections.singletonList(ISVNAuthenticationManager.PASSWORD);
+ } else if ("https".equals(url.getProtocol())) {
+ return Collections.singletonList(ISVNAuthenticationManager.SSL);
+ } else if ("svn".equals(url.getProtocol())) {
+ return Collections.singletonList(ISVNAuthenticationManager.PASSWORD);
+ } else if (url.getProtocol().contains("svn+")) { // todo +-
+ return Arrays.asList(ISVNAuthenticationManager.SSH, ISVNAuthenticationManager.USERNAME);
+ } else if ("file".equals(url.getProtocol())) {
+ return Collections.singletonList(ISVNAuthenticationManager.USERNAME);
+ }
+ return Collections.singletonList(ISVNAuthenticationManager.USERNAME);
+ }
+
+ @Nullable
+ @Override
+ public File getSpecialConfigDir() {
+ return myTempDirectory;
+ }
+
+ private String getFromType(SVNAuthentication authentication) {
+ if (authentication instanceof SVNPasswordAuthentication) {
+ return ISVNAuthenticationManager.PASSWORD;
+ }
+ if (authentication instanceof SVNSSHAuthentication) {
+ return ISVNAuthenticationManager.SSH;
+ }
+ if (authentication instanceof SVNSSLAuthentication) {
+ return ISVNAuthenticationManager.SSL;
+ }
+ if (authentication instanceof SVNUserNameAuthentication) {
+ return ISVNAuthenticationManager.USERNAME;
+ }
+ throw new IllegalArgumentException();
+ }
+}
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 ea1a7ee6937e..433e4063e02c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
@@ -25,10 +25,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vcs.CheckinProjectPanel;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeList;
import com.intellij.openapi.vcs.changes.ChangesUtil;
@@ -39,20 +38,19 @@ import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.FunctionUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.PairConsumer;
+import com.intellij.util.containers.Convertor;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.SvnBundle;
-import org.jetbrains.idea.svn.SvnConfiguration;
-import org.jetbrains.idea.svn.SvnUtil;
-import org.jetbrains.idea.svn.SvnVcs;
-import org.tmatesoft.svn.core.SVNCancelException;
-import org.tmatesoft.svn.core.SVNCommitInfo;
-import org.tmatesoft.svn.core.SVNDepth;
-import org.tmatesoft.svn.core.SVNException;
+import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
+import org.tigris.subversion.javahl.ClientException;
+import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.*;
import javax.swing.*;
@@ -140,18 +138,18 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
}
if (progress != null) {
- doCommit(committables, progress, committer, comment, force, recursive, exception, feedback);
+ doCommit(committables, committer, comment, force, exception, feedback);
}
else if (ApplicationManager.getApplication().isDispatchThread()) {
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
public void run() {
ProgressIndicator p = ProgressManager.getInstance().getProgressIndicator();
- doCommit(committables, p, committer, comment, force, recursive, exception, feedback);
+ doCommit(committables, committer, comment, force, exception, feedback);
}
}, SvnBundle.message("progress.title.commit"), false, mySvnVcs.getProject());
}
else {
- doCommit(committables, progress, committer, comment, force, recursive, exception, feedback);
+ doCommit(committables, committer, comment, force, exception, feedback);
}
for(VirtualFile f : deletedFiles) {
@@ -161,28 +159,39 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
}
private void doCommit(List<File> committables,
- ProgressIndicator progress,
SVNCommitClient committer,
String comment,
boolean force,
- boolean recursive,
List<VcsException> exception, final Set<String> feedback) {
- final Collection<List<File>> collections = SvnUtil.splitFilesIntoWc(mySvnVcs, committables);
- for (List<File> collection : collections) {
- doCommitOneWc(collection, progress, committer, comment, force, recursive, exception, feedback);
+ final MultiMap<Pair<SVNURL,WorkingCopyFormat>,File> map = SvnUtil.splitIntoRepositoriesMap(mySvnVcs, committables, Convertor.SELF);
+ for (Map.Entry<Pair<SVNURL, WorkingCopyFormat>, Collection<File>> entry : map.entrySet()) {
+ doCommitOneRepo(entry.getValue(), committer, comment, force, exception, feedback, entry.getKey().getSecond(), entry.getKey().getFirst());
}
}
- private void doCommitOneWc(Collection<File> committables,
- ProgressIndicator progress,
- SVNCommitClient committer,
- String comment,
- boolean force,
- boolean recursive,
- List<VcsException> exception, final Set<String> feedback) {
+ private void doCommitOneRepo(Collection<File> committables,
+ SVNCommitClient committer,
+ String comment,
+ boolean force,
+ List<VcsException> exception, final Set<String> feedback, final WorkingCopyFormat format, SVNURL url) {
if (committables.isEmpty()) {
return;
}
+ if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format) &&
+ SvnConfiguration.UseAcceleration.commandLine.equals(SvnConfiguration.getInstance(mySvnVcs.getProject()).myUseAcceleration) &&
+ (SvnAuthenticationManager.HTTP.equals(url.getProtocol()) || SvnAuthenticationManager.HTTPS.equals(url.getProtocol()))) {
+ doWithCommandLine(committables, comment, exception, feedback);
+ return;
+ }
+
+ doWithSvnkit(committables, committer, comment, force, exception, feedback);
+ }
+
+ private void doWithSvnkit(Collection<File> committables,
+ SVNCommitClient committer,
+ String comment,
+ boolean force,
+ List<VcsException> exception, Set<String> feedback) {
File[] pathsToCommit = committables.toArray(new File[committables.size()]);
boolean keepLocks = SvnConfiguration.getInstance(mySvnVcs.getProject()).isKeepLocks();
SVNCommitPacket[] commitPackets = null;
@@ -224,22 +233,98 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
}
}
if (committedRevisions.length() > 0) {
- final Project project = mySvnVcs.getProject();
- final String message = SvnBundle.message("status.text.comitted.revision", committedRevisions);
- if (feedback == null) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- public void run() {
- new VcsBalloonProblemNotifier(project, message, MessageType.INFO).run();
- }
- }, new Condition<Object>() {
- @Override
- public boolean value(Object o) {
- return (! project.isOpen()) || project.isDisposed();
+ reportCommittedRevisions(feedback, committedRevisions.toString());
+ }
+ }
+
+ private void doWithCommandLine(Collection<File> committables, String comment, List<VcsException> exception, Set<String> feedback) {
+ // if directory renames were used, IDEA reports all files under them as moved, but for svn we can not pass some of them
+ // to commit command - since not all paths are registered as changes -> so we need to filter these cases, but only if
+ // there at least some child-parent relationships in passed paths
+ try {
+ committables = filterCommittables(committables);
+ } catch (SVNException e) {
+ exception.add(new VcsException(e));
+ return;
+ }
+
+ final List<String> paths = ObjectsConvertor.convert(committables, new Convertor<File, String>() {
+ @Override
+ public String convert(File o) {
+ return o.getPath();
+ }
+ });
+ final IdeaSvnkitBasedAuthenticationCallback authenticationCallback = new IdeaSvnkitBasedAuthenticationCallback(mySvnVcs);
+ try {
+ final SvnBindClient client = new SvnBindClient(SvnApplicationSettings.getInstance().getCommandLinePath());
+ client.setAuthenticationCallback(authenticationCallback);
+ client.setHandler(new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()));
+ final long revision = client.commit(ArrayUtil.toStringArray(paths), comment, false, false);
+ reportCommittedRevisions(feedback, String.valueOf(revision));
+ }
+ catch (ClientException e) {
+ exception.add(new VcsException(e));
+ } finally {
+ authenticationCallback.reset();
+ }
+ }
+
+ private Collection<File> filterCommittables(Collection<File> committables) throws SVNException {
+ final Set<File> childrenOfSomebody = new HashSet<File>();
+ new AbstractFilterChildren<File>() {
+ @Override
+ protected void sortAscending(List<File> list) {
+ Collections.sort(list);
+ }
+
+ @Override
+ protected boolean isAncestor(File parent, File child) {
+ final boolean isAncestor = FileUtil.isAncestor(parent, child, false);
+ if (isAncestor) {
+ childrenOfSomebody.add(child);
+ }
+ return isAncestor;
+ }
+ }.doFilter(new ArrayList<File>(committables));
+ if (! childrenOfSomebody.isEmpty()) {
+ final HashSet<File> result = new HashSet<File>(committables);
+ result.removeAll(childrenOfSomebody);
+ final SvnCommandLineStatusClient statusClient = new SvnCommandLineStatusClient(mySvnVcs.getProject());
+ for (File file : childrenOfSomebody) {
+ try {
+ final SVNStatus status = statusClient.doStatus(file, false);
+ if (status != null && ! SVNStatusType.STATUS_NONE.equals(status.getContentsStatus()) &&
+ ! SVNStatusType.STATUS_UNVERSIONED.equals(status.getContentsStatus())) {
+ result.add(file);
}
- });
- } else {
- feedback.add("Subversion: " + message);
+ }
+ catch (SVNException e) {
+ // not versioned
+ LOG.info(e);
+ throw e;
+ }
}
+ return result;
+ }
+ return committables;
+ }
+
+ private void reportCommittedRevisions(Set<String> feedback, String committedRevisions) {
+ final Project project = mySvnVcs.getProject();
+ final String message = SvnBundle.message("status.text.comitted.revision", committedRevisions);
+ if (feedback == null) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ public void run() {
+ new VcsBalloonProblemNotifier(project, message, MessageType.INFO).run();
+ }
+ }, new Condition<Object>() {
+ @Override
+ public boolean value(Object o) {
+ return (! project.isOpen()) || project.isDisposed();
+ }
+ });
+ } else {
+ feedback.add("Subversion: " + message);
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AddLineConverter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AddLineConverter.java
new file mode 100644
index 000000000000..46fec54d0a79
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AddLineConverter.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.jetbrains.idea.svn.commandLine;
+
+import org.tmatesoft.svn.core.wc.SVNEvent;
+
+import java.io.File;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/4/13
+ * Time: 3:49 PM
+ */
+public class AddLineConverter {
+ private final File myBase;
+
+ public AddLineConverter(File base) {
+ myBase = base;
+ }
+
+ public SVNEvent convert(final String line) {
+ return null;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandFactory.java
new file mode 100644
index 000000000000..085c8e54dc0f
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandFactory.java
@@ -0,0 +1,59 @@
+/*
+ * 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 org.jetbrains.idea.svn.commandLine;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.ProcessEventListener;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnApplicationSettings;
+import org.jetbrains.idea.svn.SvnVcs;
+
+import java.io.File;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/4/13
+ * Time: 4:58 PM
+ */
+public class SvnCommandFactory {
+ public static SvnSimpleCommand createSimpleCommand(final Project project, File workingDirectory, @NotNull SvnCommandName commandName) {
+ final SvnSimpleCommand command =
+ new SvnSimpleCommand(workingDirectory, commandName, SvnApplicationSettings.getInstance().getCommandLinePath());
+ addStartFailedListener(project, command);
+ return command;
+ }
+
+ private static void addStartFailedListener(final Project project, SvnCommand command) {
+ command.addListener(new ProcessEventListener() {
+ @Override
+ public void processTerminated(int exitCode) {
+ }
+
+ @Override
+ public void startFailed(Throwable exception) {
+ SvnVcs.getInstance(project).checkCommandLineVersion();
+ }
+ });
+ }
+
+ public static SvnLineCommand createLineCommand(Project project, File workingDirectory, @NotNull SvnCommandName commandName) {
+ final SvnLineCommand command =
+ new SvnLineCommand(workingDirectory, commandName, SvnApplicationSettings.getInstance().getCommandLinePath(), null);
+ addStartFailedListener(project, command);
+ return command;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
index c2a0be1e2d6d..0d2f4d00bd39 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.Consumer;
+import org.jetbrains.idea.svn.SvnBindUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.portable.SvnExceptionWrapper;
import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient;
@@ -70,12 +71,12 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient {
Collection changeLists,
final ISVNInfoHandler handler) throws SVNException {
File base = path.isDirectory() ? path : path.getParentFile();
- base = correctUpToExistingParent(base);
+ base = SvnBindUtil.correctUpToExistingParent(base);
if (base == null) {
// very unrealistic
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR), new RuntimeException("Can not find existing parent file"));
}
- final SvnSimpleCommand command = new SvnSimpleCommand(myProject, base, SvnCommandName.info);
+ final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, base, SvnCommandName.info);
if (depth != null) {
command.addParameters("--depth", depth.getName());
@@ -137,14 +138,6 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient {
}
}
- private File correctUpToExistingParent(File base) {
- while (base != null) {
- if (base.exists() && base.isDirectory()) return base;
- base = base.getParentFile();
- }
- return null;
- }
-
@Override
public void doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision, boolean recursive, ISVNInfoHandler handler)
throws SVNException {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java
index f45b5c7039d0..a1a31536c8a9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java
@@ -17,15 +17,15 @@ package org.jetbrains.idea.svn.commandLine;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.containers.Convertor;
+import org.jetbrains.idea.svn.SvnBindUtil;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.portable.PortableStatus;
import org.jetbrains.idea.svn.portable.SvnExceptionWrapper;
import org.jetbrains.idea.svn.portable.SvnStatusClientI;
-import org.tmatesoft.sqljet.core.SqlJetErrorCode;
-import org.tmatesoft.sqljet.core.SqlJetException;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.wc.*;
@@ -96,12 +96,12 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI {
boolean collectParentExternals,
final ISVNStatusHandler handler,
final Collection changeLists) throws SVNException {
- final File base = path.isDirectory() ? path : path.getParentFile();
+ File base = path.isDirectory() ? path : path.getParentFile();
+ base = SvnBindUtil.correctUpToExistingParent(base);
final SVNInfo infoBase = myInfoClient.doInfo(base, revision);
- // todo can not understand why revision can be used here
- final SvnSimpleCommand command = new SvnSimpleCommand(myProject, base, SvnCommandName.st);
+ final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, base, SvnCommandName.st);
putParameters(depth, remote, reportAll, includeIgnored, changeLists, command);
final SvnStatusHandler[] svnHandl = new SvnStatusHandler[1];
@@ -109,6 +109,9 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI {
try {
final String result = command.run();
+ if (StringUtil.isEmptyOrSpaces(result)) {
+ throw new VcsException("Status request returned nothing for command: " + command.myCommandLine.getCommandLineString());
+ }
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(new ByteArrayInputStream(result.getBytes(CharsetToolkit.UTF8_CHARSET)), svnHandl[0]);
if (! svnHandl[0].isAnythingReported()) {
@@ -192,10 +195,6 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI {
@Override
public void switchPath() {
final PortableStatus pending = svnHandl[0].getPending();
- if (pending.isLocked()) {
- throw new SvnExceptionWrapper(new SVNException(SVNErrorMessage.create(SVNErrorCode.SQLITE_ERROR),
- new SqlJetException(SqlJetErrorCode.BUSY)));
- }
pending.setChangelistName(changelistName[0]);
try {
//if (infoBase != null) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
index 4870183b9823..c0e9c8e79fa2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineUpdateClient.java
@@ -18,17 +18,21 @@ package org.jetbrains.idea.svn.commandLine;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
-import com.intellij.openapi.vcs.LineProcessEventListener;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.concurrency.Semaphore;
-import org.jetbrains.idea.svn.SvnAuthenticationManager;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.idea.svn.SvnApplicationSettings;
import org.jetbrains.idea.svn.SvnVcs;
-import org.jetbrains.idea.svn.portable.SvnExceptionWrapper;
+import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback;
+import org.jetbrains.idea.svn.config.SvnBindException;
import org.jetbrains.idea.svn.portable.SvnSvnkitUpdateClient;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.*;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -78,127 +82,105 @@ public class SvnCommandLineUpdateClient extends SvnSvnkitUpdateClient {
if (info == null || info.getURL() == null) {
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_WORKING_COPY, paths[0].getPath()));
}
- final long[] result = new long[paths.length];
+ final AtomicReference<long[]> updatedToRevision = new AtomicReference<long[]>();
+ updatedToRevision.set(new long[0]);
- new CommandLineAuthenticator(myProject, new CommandLineAuthenticator.AuthenticationRequiringCommand() {
- @Override
- public void run(File configDir) throws SVNException {
- File base = myCommonAncestor == null ? paths[0] : new File(myCommonAncestor.getPath());
- base = base.isDirectory() ? base : base.getParentFile();
- final SvnLineCommand command = new SvnLineCommand(myProject, base, SvnCommandName.up);
- if (revision != null && ! SVNRevision.UNDEFINED.equals(revision) && ! SVNRevision.WORKING.equals(revision)) {
- command.addParameters("-r", revision.toString());
- }
- // unknown depth is not used any more for 1.7 -> why?
- if (depth != null && ! SVNDepth.UNKNOWN.equals(depth)) {
- command.addParameters("--depth", depth.toString());
- }
- if (allowUnversionedObstructions) {
- command.addParameters("--force");
- }
- if (depthIsSticky && depth != null) {// !!! not sure, but not used
- command.addParameters("--set-depth", depth.toString());
- }
- if (makeParents) {
- command.addParameters("--parents");
- }
- if (myIgnoreExternals) {
- command.addParameters("--ignore-externals");
- }
- command.addParameters("--accept", "postpone");
- command.addParameters("--config-dir", configDir.getPath());
+ File base = myCommonAncestor == null ? paths[0] : new File(myCommonAncestor.getPath());
+ base = base.isDirectory() ? base : base.getParentFile();
+
+ final List<String> parameters = new ArrayList<String>();
+ if (revision != null && ! SVNRevision.UNDEFINED.equals(revision) && ! SVNRevision.WORKING.equals(revision)) {
+ parameters.add("-r");
+ parameters.add(revision.toString());
+ }
+ // unknown depth is not used any more for 1.7 -> why?
+ if (depth != null && ! SVNDepth.UNKNOWN.equals(depth)) {
+ parameters.add("--depth");
+ parameters.add(depth.toString());
+ }
+ if (allowUnversionedObstructions) {
+ parameters.add("--force");
+ }
+ if (depthIsSticky && depth != null) {// !!! not sure, but not used
+ parameters.add("--set-depth");
+ parameters.add(depth.toString());
+ }
+ if (makeParents) {
+ parameters.add("--parents");
+ }
+ if (myIgnoreExternals) {
+ parameters.add("--ignore-externals");
+ }
+ parameters.add("--accept");
+ parameters.add("postpone");
- for (File path : paths) {
- command.addParameters(path.getPath());
+ for (File path : paths) {
+ parameters.add(path.getPath());
+ }
+
+ final AtomicReference<SVNException> excRef = new AtomicReference<SVNException>();
+ final ISVNEventHandler handler = getEventHandler();
+ final UpdateOutputLineConverter converter = new UpdateOutputLineConverter(base);
+ try {
+ final LineCommandListener listener = new LineCommandListener() {
+ final long[] myRevisions = new long[paths.length];
+
+ @Override
+ public void baseDirectory(File file) {
}
- final StringBuffer sbError = new StringBuffer();
- final Semaphore semaphore = new Semaphore();
- semaphore.down();
- final ISVNEventHandler handler = getEventHandler();
- final UpdateOutputLineConverter converter = new UpdateOutputLineConverter(base);
- final SVNException[] innerException = new SVNException[1];
- command.addListener(new LineProcessEventListener() {
- @Override
- public void onLineAvailable(String line, Key outputType) {
- if (ProcessOutputTypes.STDOUT.equals(outputType)) {
- final SVNEvent event = converter.convert(line);
- if (event != null) {
- checkForUpdateCompleted(event);
- try {
- handler.handleEvent(event, 0.5);
- }
- catch (SVNException e) {
- command.cancel();
- semaphore.up();
- innerException[0] = e;
- }
+ @Override
+ public void onLineAvailable(String line, Key outputType) {
+ if (ProcessOutputTypes.STDOUT.equals(outputType)) {
+ final SVNEvent event = converter.convert(line);
+ if (event != null) {
+ checkForUpdateCompleted(event);
+ try {
+ handler.handleEvent(event, 0.5);
}
- } else if (ProcessOutputTypes.STDERR.equals(outputType)) {
- sbError.append(line);
- if (line.contains(ourAuthenticationRealm)) {
- command.cancel();
- semaphore.up();
+ catch (SVNException e) {
+ cancel();
+ excRef.set(e);
}
}
}
-
- @Override
- public void processTerminated(int exitCode) {
- semaphore.up();
- }
-
- @Override
- public void startFailed(Throwable exception) {
- semaphore.up();
- }
- });
- try {
- command.start();
- semaphore.waitFor();
-
- checkForException(sbError);
- } catch (SvnExceptionWrapper e){
- throw (SVNException) e.getCause();
}
- }
- @Override
- public void runWithSvnkitClient(File configDir, SvnAuthenticationManager manager) throws SVNException {
- final SVNUpdateClient client = SvnVcs.getInstance(myProject).createUpdateClient(manager);
- client.doUpdate(paths, revision, depth, allowUnversionedObstructions, depthIsSticky, makeParents);
- }
-
- private void checkForUpdateCompleted(SVNEvent event) {
- if (SVNEventAction.UPDATE_COMPLETED.equals(event.getAction())) {
- final long eventRevision = event.getRevision();
- for (int i = 0; i < paths.length; i++) {
- final File path = paths[i];
- if (path.equals(event.getFile())) {
- result[i] = eventRevision;
- break;
+ private void checkForUpdateCompleted(SVNEvent event) {
+ if (SVNEventAction.UPDATE_COMPLETED.equals(event.getAction())) {
+ final long eventRevision = event.getRevision();
+ for (int i = 0; i < paths.length; i++) {
+ final File path = paths[i];
+ if (FileUtil.filesEqual(path, event.getFile())) {
+ myRevisions[i] = eventRevision;
+ break;
+ }
}
}
}
- }
- @Override
- public SVNURL sampleUrl() {
- return info.getURL();
- }
-
- @Override
- public void cleanup() throws SVNException {
- final SvnVcs vcs17 = SvnVcs.getInstance(myProject);
- final SVNWCClient client = vcs17.createWCClient();
- for (File path : paths) {
- client.doCleanup(path);
+ @Override
+ public void processTerminated(int exitCode) {
+ super.processTerminated(exitCode);
+ updatedToRevision.set(myRevisions);
}
- }
- }).doWithAuthentication();
- return result;
+ };
+ SvnLineCommand.runWithAuthenticationAttempt(SvnApplicationSettings.getInstance().getCommandLinePath(),
+ base, SvnCommandName.up, listener,
+ new IdeaSvnkitBasedAuthenticationCallback(SvnVcs.getInstance(myProject)),
+ ArrayUtil.toStringArray(parameters));
+ }
+ catch (SvnBindException e) {
+ throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e));
+ }
+ if (excRef.get() != null) {
+ throw excRef.get();
+ }
+
+ return updatedToRevision.get();
}
+
private void checkForException(final StringBuffer sbError) throws SVNException {
if (sbError.length() == 0) return;
final String message = sbError.toString();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
deleted file mode 100644
index cf31abde7f1a..000000000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.idea.svn.commandLine;
-
-import com.intellij.execution.process.ProcessOutputTypes;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.vcs.LineHandlerHelper;
-import com.intellij.openapi.vcs.LineProcessEventListener;
-import com.intellij.util.EventDispatcher;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.File;
-import java.util.Iterator;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/25/12
- * Time: 4:05 PM
- *
- * honestly stolen from GitLineHandler
- */
-public class SvnLineCommand extends SvnCommand {
- /**
- * the partial line from stdout stream
- */
- private final StringBuilder myStdoutLine = new StringBuilder();
- /**
- * the partial line from stderr stream
- */
- private final StringBuilder myStderrLine = new StringBuilder();
- private final EventDispatcher<LineProcessEventListener> myLineListeners;
-
- public SvnLineCommand(Project project, File workingDirectory, @NotNull SvnCommandName commandName) {
- super(project, workingDirectory, commandName);
- myLineListeners = EventDispatcher.create(LineProcessEventListener.class);
- }
-
- @Override
- protected void processTerminated(int exitCode) {
- // force newline
- if (myStdoutLine.length() != 0) {
- onTextAvailable("\n\r", ProcessOutputTypes.STDOUT);
- }
- else if (myStderrLine.length() != 0) {
- onTextAvailable("\n\r", ProcessOutputTypes.STDERR);
- }
- }
-
- @Override
- protected void onTextAvailable(String text, Key outputType) {
- Iterator<String> lines = LineHandlerHelper.splitText(text).iterator();
- if (ProcessOutputTypes.STDOUT == outputType) {
- notifyLines(outputType, lines, myStdoutLine);
- }
- else if (ProcessOutputTypes.STDERR == outputType) {
- notifyLines(outputType, lines, myStderrLine);
- }
- }
-
- private void notifyLines(final Key outputType, final Iterator<String> lines, final StringBuilder lineBuilder) {
- if (!lines.hasNext()) return;
- if (lineBuilder.length() > 0) {
- lineBuilder.append(lines.next());
- if (lines.hasNext()) {
- // line is complete
- final String line = lineBuilder.toString();
- notifyLine(line, outputType);
- lineBuilder.setLength(0);
- }
- }
- while (true) {
- String line = null;
- if (lines.hasNext()) {
- line = lines.next();
- }
-
- if (lines.hasNext()) {
- notifyLine(line, outputType);
- }
- else {
- if (line != null && line.length() > 0) {
- lineBuilder.append(line);
- }
- break;
- }
- }
- }
-
- private void notifyLine(final String line, final Key outputType) {
- String trimmed = LineHandlerHelper.trimLineSeparator(line);
- myLineListeners.getMulticaster().onLineAvailable(trimmed, outputType);
- }
-
- public void addListener(LineProcessEventListener listener) {
- myLineListeners.addListener(listener);
- super.addListener(listener);
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java
index 84d25f59f4b3..7b789f92e7ed 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java
@@ -284,6 +284,7 @@ public class SvnStatusHandler extends DefaultHandler {
if (createNewChild) {
assertSAX(myElementsMap.containsKey(qName));
final ElementHandlerBase newChild = myElementsMap.get(qName).get();
+ newChild.preAttributesEffect(myDataCallback);
newChild.updateStatus(attributes, myPending, myLockWrapper);
newChild.preEffect(myDataCallback);
myParseStack.add(newChild);
@@ -547,12 +548,11 @@ public class SvnStatusHandler extends DefaultHandler {
private static class Lock extends ElementHandlerBase {
private Lock() {
- super(new String[]{"token","owner","comment","created"}, new String[]{});
+ super(new String[]{"token", "owner", "comment", "created"}, new String[]{});
}
@Override
protected void updateStatus(Attributes attributes, PortableStatus status, SVNLockWrapper lock) throws SAXException {
- // todo check inside-repository path
lock.setPath(status.getPath());
}
@@ -562,11 +562,15 @@ public class SvnStatusHandler extends DefaultHandler {
}
@Override
- public void preEffect(DataCallback callback) {
+ public void preAttributesEffect(DataCallback callback) {
callback.startLock();
}
@Override
+ public void preEffect(DataCallback callback) {
+ }
+
+ @Override
public void characters(String s, PortableStatus pending, SVNLockWrapper lock) {
}
}
@@ -587,8 +591,12 @@ public class SvnStatusHandler extends DefaultHandler {
}
@Override
+ public void preAttributesEffect(DataCallback callback) {
+ callback.startLock();
+ }
+
+ @Override
public void preEffect(DataCallback callback) {
- callback.startRemoteStatus();
}
@Override
@@ -851,6 +859,8 @@ and no "mod4" under
}
public abstract void characters(String s, PortableStatus pending, SVNLockWrapper lock);
+
+ public void preAttributesEffect(DataCallback callback) {}
}
public interface ExternalDataCallback {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form
index 170c92072c51..a416aa145505 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form
@@ -1,6 +1,6 @@
<?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">
- <grid id="27dc6" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <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>
<xy x="20" y="20" width="500" height="400"/>
@@ -50,6 +50,14 @@
</component>
</children>
</grid>
+ <component id="f6743" class="javax.swing.JLabel" binding="myErrorPrompt">
+ <constraints>
+ <grid row="3" 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="Label"/>
+ </properties>
+ </component>
</children>
</grid>
</form>
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
index aa6506917005..221ba2abbce2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
@@ -20,15 +20,14 @@ import com.intellij.openapi.actionSystem.ActionToolbarPosition;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.MultiLineLabelUI;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.AnActionButton;
-import com.intellij.ui.AnActionButtonRunnable;
-import com.intellij.ui.DocumentAdapter;
-import com.intellij.ui.ToolbarDecorator;
+import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
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;
@@ -54,11 +53,11 @@ public class BranchConfigurationDialog extends DialogWrapper {
private TextFieldWithBrowseButton myTrunkLocationTextField;
private JList myLocationList;
private JPanel myListPanel;
+ private JLabel myErrorPrompt;
private final SvnBranchConfigManager mySvnBranchConfigManager;
private final VirtualFile myRoot;
- public BranchConfigurationDialog(final Project project, final SvnBranchConfigurationNew configuration, final String rootUrl,
- final VirtualFile root) {
+ public BranchConfigurationDialog(@NotNull final Project project, @NotNull final SvnBranchConfigurationNew configuration, final @NotNull String rootUrl, @NotNull final VirtualFile root, @NotNull String url) {
super(project, true);
myRoot = root;
init();
@@ -66,7 +65,7 @@ public class BranchConfigurationDialog extends DialogWrapper {
final String trunkUrl = configuration.getTrunkUrl();
if (trunkUrl == null || trunkUrl.trim().length() == 0) {
- configuration.setTrunkUrl(rootUrl);
+ configuration.setTrunkUrl(url);
}
mySvnBranchConfigManager = SvnBranchConfigurationManager.getInstance(project).getSvnBranchConfigManager();
@@ -85,6 +84,9 @@ public class BranchConfigurationDialog extends DialogWrapper {
myTrunkLocationTextField.getTextField().getDocument().addDocumentListener(trunkUrlValidator);
trunkUrlValidator.textChanged(null);
+ myErrorPrompt.setUI(new MultiLineLabelUI());
+ myErrorPrompt.setForeground(SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor());
+
final MyListModel listModel = new MyListModel(configuration);
myLocationList = new JBList(listModel);
@@ -142,11 +144,10 @@ public class BranchConfigurationDialog extends DialogWrapper {
(currentValue.length() > myRootUrlPrefix.length());
myTrunkLocationTextField.getButton().setEnabled(valueOk);
- setOKActionEnabled(prefixOk);
if (prefixOk) {
myConfiguration.setTrunkUrl(currentValue.endsWith("/") ? currentValue.substring(0, currentValue.length() - 1) : currentValue);
}
- setErrorText(prefixOk ? null : SvnBundle.message("configure.branches.error.wrong.url"));
+ myErrorPrompt.setText(prefixOk ? "" : SvnBundle.message("configure.branches.error.wrong.url", myRootUrl));
}
}
@@ -197,7 +198,7 @@ public class BranchConfigurationDialog extends DialogWrapper {
}
final SvnBranchConfigurationNew clonedConfiguration = configuration.copy();
- BranchConfigurationDialog dlg = new BranchConfigurationDialog(project, clonedConfiguration, rootUrl, vcsRoot);
+ BranchConfigurationDialog dlg = new BranchConfigurationDialog(project, clonedConfiguration, rootUrl, vcsRoot, wcRoot.getUrl());
dlg.show();
if (dlg.isOK()) {
SvnBranchConfigurationManager.getInstance(project).setConfiguration(vcsRoot, clonedConfiguration);
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 d66cb6f0ae54..bfb5c645a46c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java
@@ -28,6 +28,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.DottedBorder;
+import com.intellij.ui.JBColor;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.labels.LinkListener;
@@ -36,6 +37,8 @@ import com.intellij.util.containers.Convertor;
import com.intellij.util.io.EqualityPolicy;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.NestedCopyType;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.WorkingCopyFormat;
@@ -43,6 +46,7 @@ import org.jetbrains.idea.svn.actions.CleanupWorker;
import org.jetbrains.idea.svn.actions.SelectBranchPopup;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
+import org.jetbrains.idea.svn.integrate.QuickMergeInteractionImpl;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -205,7 +209,7 @@ public class CopiesPanel {
final int result =
Messages.showOkCancelDialog(myVcs.getProject(), "You are going to checkout into '" + wcInfo.getPath() + "' with 'infinity' depth.\n" +
"This will update your working copy to HEAD revision as well.",
- "Set working copy infinity depth",
+ "Set Working Copy Infinity Depth",
Messages.getWarningIcon());
if (result == 0) {
// update of view will be triggered by roots changed event
@@ -258,6 +262,7 @@ public class CopiesPanel {
myPanel.repaint();
}
+ @SuppressWarnings("MethodMayBeStatic")
private String formatWc(WCInfo info) {
final StringBuilder sb = new StringBuilder().append("<html><head>").append(UIUtil.getCssFontDeclaration(UIUtil.getLabelFont()))
.append("</head><body><table bgColor=\"").append(ColorUtil.toHex(UIUtil.getPanelBackground())).append("\">");
@@ -297,17 +302,18 @@ public class CopiesPanel {
return sb.toString();
}
- private void mergeFrom(final WCInfo wcInfo, final VirtualFile root, final Component mergeLabel) {
+ private void mergeFrom(@NotNull final WCInfo wcInfo, @NotNull final VirtualFile root, @Nullable final Component mergeLabel) {
SelectBranchPopup.showForBranchRoot(myProject, root, new SelectBranchPopup.BranchSelectedCallback() {
@Override
public void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision) {
- new QuickMerge(project, url, wcInfo, SVNPathUtil.tail(url), root).execute();
+ new QuickMerge(project, url, wcInfo, SVNPathUtil.tail(url), root).execute(new QuickMergeInteractionImpl(myProject));
}
}, "Select branch", mergeLabel);
}
+ @SuppressWarnings("MethodMayBeStatic")
private void setFocusableForLinks(final LinkLabel label) {
- final Border border = new DottedBorder(new Insets(1,2,1,1), Color.black);
+ final Border border = new DottedBorder(new Insets(1,2,1,1), JBColor.BLACK);
label.setFocusable(true);
label.addFocusListener(new FocusAdapter() {
@Override
@@ -334,7 +340,7 @@ public class CopiesPanel {
private void changeFormat(final WCInfo wcInfo) {
ChangeFormatDialog dialog = new ChangeFormatDialog(myProject, new File(wcInfo.getPath()), false, ! wcInfo.isIsWcRoot());
- dialog.setData(true, wcInfo.getFormat().getOption());
+ dialog.setData(wcInfo.getFormat().getOption());
dialog.show();
if (! dialog.isOK()) {
return;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java
new file mode 100644
index 000000000000..7187613a0f86
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java
@@ -0,0 +1,145 @@
+/*
+ * 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 org.jetbrains.idea.svn.dialogs;
+
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.util.PairConsumer;
+import com.intellij.util.continuation.ContinuationContext;
+import com.intellij.util.continuation.TaskDescriptor;
+import com.intellij.util.continuation.Where;
+import org.jetbrains.idea.svn.SvnBundle;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.history.SvnChangeList;
+import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider;
+import org.jetbrains.idea.svn.history.SvnRepositoryLocation;
+import org.jetbrains.idea.svn.history.TreeStructureNode;
+import org.jetbrains.idea.svn.mergeinfo.OneShotMergeInfoHelper;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNLogEntry;
+import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Created with IntelliJ IDEA.
+* User: Irina.Chernushina
+* Date: 3/30/13
+* Time: 7:40 PM
+*/
+class LoadRecentBranchRevisions extends TaskDescriptor {
+ public static final String PROP_BUNCH_SIZE = "idea.svn.quick.merge.bunch.size";
+ private final static int BUNCH_SIZE = 100;
+ private int myBunchSize;
+ private long myFirst;
+ private boolean myLastLoaded;
+ private OneShotMergeInfoHelper myHelper;
+ private List<CommittedChangeList> myCommittedChangeLists;
+ private final WCInfo myWcInfo;
+ private final SvnVcs myVcs;
+ private final String mySourceUrl;
+ private final Integer myTestBunchSize;
+
+ LoadRecentBranchRevisions(String branchName, long first, WCInfo info, SvnVcs vcs, String url) {
+ super("Loading recent " + branchName + " revisions", Where.POOLED);
+ myFirst = first;
+ myWcInfo = info;
+ myVcs = vcs;
+ mySourceUrl = url;
+ // for test purposes!!!
+ myTestBunchSize = Integer.getInteger(PROP_BUNCH_SIZE);
+ if (myTestBunchSize != null) {
+ myBunchSize = myTestBunchSize.intValue();
+ } else {
+ myBunchSize = BUNCH_SIZE;
+ }
+ }
+
+ void setBunchSize(int bunchSize) {
+ if (myTestBunchSize != null) return;
+ myBunchSize = bunchSize;
+ }
+
+ public boolean isLastLoaded() {
+ return myLastLoaded;
+ }
+
+ @Override
+ public void run(ContinuationContext context) {
+ final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
+ final SvnCommittedChangesProvider committedChangesProvider = (SvnCommittedChangesProvider)myVcs.getCommittedChangesProvider();
+ final ChangeBrowserSettings settings = new ChangeBrowserSettings();
+ if (myFirst > 0){
+ settings.CHANGE_BEFORE = String.valueOf(myFirst);
+ settings.USE_CHANGE_BEFORE_FILTER = true;
+ }
+
+ String local = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), myWcInfo.getRootUrl());
+ final String relativeLocal = (local.startsWith("/") ? local : "/" + local);
+ String relativeBranch = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), mySourceUrl);
+ relativeBranch = (relativeBranch.startsWith("/") ? relativeBranch : "/" + relativeBranch);
+
+ ProgressManager.progress2(SvnBundle.message("progress.text2.collecting.history", mySourceUrl + (myFirst > 0 ? ("@" + myFirst) : "")));
+ final List<Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>>> list = new ArrayList<Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>>>();
+ try {
+ committedChangesProvider.getCommittedChangesWithMergedRevisons(settings, new SvnRepositoryLocation(mySourceUrl),
+ myBunchSize + (myFirst > 0 ? 2 : 1),
+ new PairConsumer<SvnChangeList, TreeStructureNode<SVNLogEntry>>() {
+ public void consume(SvnChangeList svnList, TreeStructureNode<SVNLogEntry> tree) {
+ indicator.setText2(SvnBundle.message("progress.text2.processing.revision", svnList.getNumber()));
+ list.add(new Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>>(svnList, tree));
+ }
+ });
+ } catch (VcsException e) {
+ context.handleException(e, true);
+ return;
+ }
+ myCommittedChangeLists = new ArrayList<CommittedChangeList>();
+ for (Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>> pair : list) {
+ // do not take first since it's equal
+ if (myFirst > 0 && myFirst == pair.getFirst().getNumber()) continue;
+ if (! QuickMerge.checkListForPaths(relativeLocal, relativeBranch, pair)) {
+ myCommittedChangeLists.add(pair.getFirst());
+ }
+ }
+
+ try {
+ myHelper = new OneShotMergeInfoHelper(myVcs.getProject(), myWcInfo, mySourceUrl);
+ ProgressManager.progress2("Calculating not merged revisions");
+ myHelper.prepare();
+ }
+ catch (SVNException e) {
+ context.handleException(new VcsException(e), true);
+ }
+ myLastLoaded = myCommittedChangeLists.size() < myBunchSize + 1;
+ if (myCommittedChangeLists.size() > myBunchSize){
+ myCommittedChangeLists = myCommittedChangeLists.subList(0, myBunchSize);
+ }
+ }
+
+ public OneShotMergeInfoHelper getHelper() {
+ return myHelper;
+ }
+
+ public List<CommittedChangeList> getCommittedChangeLists() {
+ return myCommittedChangeLists;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LocalChangesAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LocalChangesAction.java
new file mode 100644
index 000000000000..2520d7af2b6e
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LocalChangesAction.java
@@ -0,0 +1,29 @@
+/*
+ * 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 org.jetbrains.idea.svn.dialogs;
+
+/**
+* Created with IntelliJ IDEA.
+* User: Irina.Chernushina
+* Date: 3/27/13
+* Time: 12:37 PM
+*/
+public enum LocalChangesAction {
+ cancel,
+ continueMerge,
+ shelve,
+ inspect
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/MergeDialogI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/MergeDialogI.java
new file mode 100644
index 000000000000..83e514aabc80
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/MergeDialogI.java
@@ -0,0 +1,34 @@
+/*
+ * 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 org.jetbrains.idea.svn.dialogs;
+
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/30/13
+ * Time: 8:11 PM
+ */
+public interface MergeDialogI {
+ void setEverythingLoaded(boolean everythingLoaded);
+
+ long getLastNumber();
+
+ void addMoreLists(List<CommittedChangeList> list);
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java
index fa3428d2afd2..01e5a1d0342a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java
@@ -21,18 +21,15 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.RunBackgroundable;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.MessageType;
-import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.popup.util.PopupUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
-import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.VirtualFile;
@@ -78,6 +75,7 @@ public class QuickMerge {
private SvnVcs myVcs;
private final String myTitle;
private final Continuation myContinuation;
+ private QuickMergeInteraction myInteraction;
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.dialogs.QuickMerge");
public QuickMerge(Project project, String sourceUrl, WCInfo wcInfo, final String branchName, final VirtualFile root) {
@@ -110,10 +108,6 @@ public class QuickMerge {
}
}
- private boolean prompt(final String question) {
- return Messages.showOkCancelDialog(myProject, question, myTitle, Messages.getQuestionIcon()) == 0;
- }
-
private class MyInitChecks extends TaskDescriptor {
private MyInitChecks() {
super("initial checks", Where.AWT);
@@ -157,17 +151,104 @@ public class QuickMerge {
}
@CalledInAwt
- public void execute() {
+ public void execute(@NotNull final QuickMergeInteraction interaction, @NotNull final TaskDescriptor... finalTasks) {
+ myInteraction = interaction;
+ myInteraction.setTitle(myTitle);
+
FileDocumentManager.getInstance().saveAllDocuments();
final List<TaskDescriptor> tasks = new LinkedList<TaskDescriptor>();
tasks.add(new MyInitChecks());
tasks.add(new SourceUrlCorrection());
tasks.add(new CheckRepositorySupportsMergeinfo());
+ if (finalTasks.length > 0) {
+ tasks.addAll(Arrays.asList(finalTasks));
+ }
+ myContinuation.addExceptionHandler(VcsException.class, new Consumer<VcsException>() {
+ @Override
+ public void consume(VcsException e) {
+ myInteraction.showErrors(myTitle, Collections.singletonList(e));
+ }
+ });
+ myContinuation.addExceptionHandler(SVNException.class, new Consumer<SVNException>() {
+ @Override
+ public void consume(SVNException e) {
+ myInteraction.showErrors(myTitle, Collections.singletonList(new VcsException(e)));
+ }
+ });
+ myContinuation.addExceptionHandler(RuntimeException.class, new Consumer<RuntimeException>() {
+ @Override
+ public void consume(RuntimeException e) {
+ myInteraction.showError(e);
+ }
+ });
myContinuation.run(tasks);
}
+ private class ShowRecentInDialog extends TaskDescriptor {
+ private final LoadRecentBranchRevisions myLoader;
+
+ private ShowRecentInDialog(LoadRecentBranchRevisions loader) {
+ super("", Where.AWT);
+ myLoader = loader;
+ }
+
+ @Override
+ public void run(ContinuationContext context) {
+ final PairConsumer<Long, MergeDialogI> loader = new PairConsumer<Long, MergeDialogI>() {
+ @Override
+ public void consume(Long bunchSize, final MergeDialogI dialog) {
+ final LoadRecentBranchRevisions loader =
+ new LoadRecentBranchRevisions(myBranchName, dialog.getLastNumber(), myWcInfo, myVcs, mySourceUrl);
+ loader.setBunchSize(bunchSize.intValue());
+ final TaskDescriptor updater = new TaskDescriptor("", Where.AWT) {
+ @Override
+ public void run(ContinuationContext context) {
+ dialog.addMoreLists(loader.getCommittedChangeLists());
+ if (loader.isLastLoaded()) {
+ dialog.setEverythingLoaded(true);
+ }
+ }
+
+ @Override
+ public void canceled() {
+ dialog.addMoreLists(Collections.<CommittedChangeList>emptyList());
+ dialog.setEverythingLoaded(true);
+ }
+ };
+ final Continuation fragmented = Continuation.createFragmented(myProject, true);
+ fragmented.addExceptionHandler(VcsException.class, new Consumer<VcsException>() {
+ @Override
+ public void consume(VcsException e) {
+ PopupUtil.showBalloonForActiveComponent(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), MessageType.ERROR);
+ }
+ });
+ fragmented.run(loader, updater);
+ }
+ };
+ final List<CommittedChangeList> lists = myInteraction.showRecentListsForSelection(myLoader.getCommittedChangeLists(),
+ myTitle, myLoader.getHelper(), loader, myLoader.isLastLoaded());
+
+ if (lists != null && ! lists.isEmpty()){
+ final MergerFactory factory = new ChangeListsMergerFactory(lists) {
+ @Override
+ public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) {
+ return new GroupMerger(vcs, lists, target, handler, currentBranchUrl, branchName, false, false, false);
+ }
+ };
+ // fictive branch point, just for
+ final SvnBranchPointsCalculator.BranchCopyData copyData =
+ new SvnBranchPointsCalculator.BranchCopyData(myWcInfo.getUrl().toString(), -1, mySourceUrl, -1);
+ context.next(new LocalChangesPrompt(false, lists,
+ new SvnBranchPointsCalculator.WrapperInvertor<SvnBranchPointsCalculator.BranchCopyData>(false, copyData)),
+ new MergeTask(factory, myTitle));
+ } else {
+ context.cancelEverything();
+ }
+ }
+ }
+
private class MergeAllOrSelectedChooser extends TaskDescriptor {
private MergeAllOrSelectedChooser() {
super("merge source selector", Where.AWT);
@@ -175,13 +256,18 @@ public class QuickMerge {
@Override
public void run(final ContinuationContext context) {
- final int result = Messages.showYesNoCancelDialog(myProject, "Merge all?", myTitle,
- "Merge &all", "&Select revisions to merge", "Cancel", Messages.getQuestionIcon());
- if (result == 2) return;
- if (result == 0) {
+ final QuickMergeContentsVariants variant = myInteraction.selectMergeVariant();
+ if (QuickMergeContentsVariants.cancel == variant) return;
+ if (QuickMergeContentsVariants.all == variant) {
insertMergeAll(context);
return;
}
+ if (QuickMergeContentsVariants.showLatest == variant) {
+ final LoadRecentBranchRevisions loader = new LoadRecentBranchRevisions(myBranchName, -1, myWcInfo, myVcs, mySourceUrl);
+ final ShowRecentInDialog dialog = new ShowRecentInDialog(loader);
+ context.next(loader, dialog);
+ return;
+ }
final MergeCalculator calculator;
try {
@@ -197,7 +283,7 @@ public class QuickMerge {
}
private void insertMergeAll(final ContinuationContext context) {
- final List<TaskDescriptor> queue = new LinkedList<TaskDescriptor>();
+ final List<TaskDescriptor> queue = new ArrayList<TaskDescriptor>();
insertMergeAll(queue);
context.next(queue);
}
@@ -213,7 +299,7 @@ public class QuickMerge {
}
}
if (switchedFound) {
- return prompt("There are some switched paths in the working copy. Do you want to continue?");
+ return myInteraction.shouldContinueSwitchedRootFound();
}
return true;
}
@@ -229,20 +315,19 @@ public class QuickMerge {
context.next(new TaskDescriptor(message, Where.AWT) {
@Override
public void run(ContinuationContext context) {
- AbstractVcsHelper.getInstance(myProject).showErrors(exceptions, message);
+ myInteraction.showErrors(message, exceptions);
}
});
}
- // todo can be a very base class!
@CalledInAny
private void finishWithError(final ContinuationContext context, final String message, final boolean isError) {
LOG.info((isError ? "Error: " : "Info: ") + message);
- context.cancelEverything();
context.next(new TaskDescriptor(message, Where.AWT) {
@Override
public void run(ContinuationContext context) {
- VcsBalloonProblemNotifier.showOverChangesView(myProject, message, isError ? MessageType.ERROR : MessageType.WARNING);
+ myInteraction.showErrors(message, isError);
+ context.cancelEverything();
}
});
}
@@ -288,10 +373,7 @@ public class QuickMerge {
return;
}
final boolean reintegrate = invertor.isInvertedSense();
- if (reintegrate && (! prompt("<html><body>You are going to reintegrate changes.<br><br>This will make branch '" + mySourceUrl +
- "' <b>no longer usable for further work</b>." +
- "<br>It will not be able to correctly absorb new trunk (" + invertor.inverted().getTarget() +
- ") changes,<br>nor can this branch be properly reintegrated to trunk again.<br><br>Are you sure?</body></html>"))) {
+ if (reintegrate && (! myInteraction.shouldReintegrate(mySourceUrl, invertor.inverted().getTarget()))) {
context.cancelEverything();
return;
}
@@ -338,14 +420,12 @@ public class QuickMerge {
return;
}
- context.next(new TaskDescriptor(getName(), Where.POOLED) {
- @Override
- public void run(ContinuationContext context) {
- final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(SvnVcs.getInstance(myProject),
- new WorkingCopyInfo(myWcInfo.getPath(), true), myFactory, sourceUrlUrl, getName(), false, myBranchName);
- RunBackgroundable.run(task);
- }
- });
+ final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(SvnVcs.getInstance(myProject),
+ new WorkingCopyInfo(myWcInfo.getPath(), true), myFactory, sourceUrlUrl, getName(), false, myBranchName);
+ final TaskDescriptor taskDescriptor = TaskDescriptor.createForBackgroundableTask(task);
+ // merge task will be the next after...
+ context.next(taskDescriptor);
+ // ... after we create changelist
createChangelist(context);
}
@@ -383,6 +463,56 @@ public class QuickMerge {
}
}
+ // true if errors found
+ static boolean checkListForPaths(String relativeLocal,
+ String relativeBranch, Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>> pair) {
+ final List<TreeStructureNode<SVNLogEntry>> children = pair.getSecond().getChildren();
+ boolean localChange = false;
+ for (TreeStructureNode<SVNLogEntry> child : children) {
+ if (checkForSubtree(child, relativeLocal, relativeBranch)) {
+ localChange = true;
+ break;
+ }
+ }
+ if (! localChange) {
+ // check self
+ return checkForEntry(pair.getSecond().getMe(), relativeLocal, relativeBranch);
+ }
+ return localChange;
+ }
+
+ // true if errors found
+ private static boolean checkForSubtree(final TreeStructureNode<SVNLogEntry> tree,
+ String relativeBranch, final String localURL) {
+ final LinkedList<TreeStructureNode<SVNLogEntry>> queue = new LinkedList<TreeStructureNode<SVNLogEntry>>();
+ queue.addLast(tree);
+
+ while (! queue.isEmpty()) {
+ final TreeStructureNode<SVNLogEntry> element = queue.removeFirst();
+ ProgressManager.checkCanceled();
+
+ if (checkForEntry(element.getMe(), localURL, relativeBranch)) return true;
+ queue.addAll(element.getChildren());
+ }
+ return false;
+ }
+
+ // true if errors found
+ private static boolean checkForEntry(final SVNLogEntry entry, final String localURL, String relativeBranch) {
+ boolean atLeastOneUnderBranch = false;
+ final Map map = entry.getChangedPaths();
+ for (Object o : map.values()) {
+ final SVNLogEntryPath path = (SVNLogEntryPath) o;
+ if (SVNPathUtil.isAncestor(localURL, path.getPath())) {
+ return true;
+ }
+ if (! atLeastOneUnderBranch && SVNPathUtil.isAncestor(relativeBranch, path.getPath())) {
+ atLeastOneUnderBranch = true;
+ }
+ }
+ return ! atLeastOneUnderBranch;
+ }
+
private class MergeCalculator extends TaskDescriptor implements
Consumer<TransparentlyFailedValueI<SvnBranchPointsCalculator.WrapperInvertor<SvnBranchPointsCalculator.BranchCopyData>, SVNException>> {
private final static String ourOneShotStrategy = "svn.quickmerge.oneShotStrategy";
@@ -450,6 +580,8 @@ public class QuickMerge {
String local = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), myWcInfo.getRootUrl());
final String relativeLocal = (local.startsWith("/") ? local : "/" + local);
+ String relativeBranch = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), mySourceUrl);
+ relativeBranch = (relativeBranch.startsWith("/") ? relativeBranch : "/" + relativeBranch);
final LinkedList<Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>>> list =
new LinkedList<Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>>>();
@@ -476,14 +608,7 @@ public class QuickMerge {
if (SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(checkResult)) {
// additionally check for being 'local'
- final List<TreeStructureNode<SVNLogEntry>> children = pair.getSecond().getChildren();
- boolean localChange = false;
- for (TreeStructureNode<SVNLogEntry> child : children) {
- if (isLocalRevisionMergeIteration(child, relativeLocal, indicator)) {
- localChange = true;
- break;
- }
- }
+ boolean localChange = checkListForPaths(relativeLocal, relativeBranch, pair);
if (! localChange) {
myNotMerged.add(svnList);
@@ -498,29 +623,6 @@ public class QuickMerge {
context.next(new ShowRevisionSelector(copyDataValue));
}
- private boolean isLocalRevisionMergeIteration(final TreeStructureNode<SVNLogEntry> tree,
- final String localURL,
- ProgressIndicator indicator) {
- final LinkedList<TreeStructureNode<SVNLogEntry>> queue = new LinkedList<TreeStructureNode<SVNLogEntry>>();
- queue.addLast(tree);
-
- while (! queue.isEmpty()) {
- final TreeStructureNode<SVNLogEntry> element = queue.removeFirst();
- indicator.checkCanceled();
-
- final Map map = element.getMe().getChangedPaths();
- for (Object o : map.values()) {
- final SVNLogEntryPath path = (SVNLogEntryPath) o;
- if (SVNPathUtil.isAncestor(localURL, path.getPath())) {
- return true;
- }
- break; // do not check all. first should match or fail
- }
- queue.addAll(element.getChildren());
- }
- return false;
- }
-
private class ShowRevisionSelector extends TaskDescriptor {
private final SvnBranchPointsCalculator.WrapperInvertor<SvnBranchPointsCalculator.BranchCopyData> myCopyPoint;
@@ -531,16 +633,15 @@ public class QuickMerge {
@Override
public void run(ContinuationContext context) {
- final ToBeMergedDialog dialog = new ToBeMergedDialog(myProject, myNotMerged, myMergeTitle, myMergeChecker);
- dialog.show();
- if (dialog.getExitCode() == DialogWrapper.CANCEL_EXIT_CODE) {
+ final QuickMergeInteraction.SelectMergeItemsResult result = myInteraction.selectMergeItems(myNotMerged, myMergeTitle, myMergeChecker);
+ if (QuickMergeContentsVariants.cancel == result.getResultCode()) {
context.cancelEverything();
return;
}
- if (dialog.getExitCode() == ToBeMergedDialog.MERGE_ALL_CODE) {
+ if (QuickMergeContentsVariants.all == result.getResultCode()) {
insertMergeAll(context);
} else {
- final List<CommittedChangeList> lists = dialog.getSelected();
+ final List<CommittedChangeList> lists = result.getSelectedLists();
if (lists.isEmpty()) return;
final MergerFactory factory = new ChangeListsMergerFactory(lists) {
@Override
@@ -582,35 +683,18 @@ public class QuickMerge {
@Override
public void run(ContinuationContext context) {
- final String message;
final Intersection intersection;
final ChangeListManager listManager = ChangeListManager.getInstance(myProject);
final List<LocalChangeList> localChangeLists = listManager.getChangeListsCopy();
if (myMergeAll) {
intersection = getMergeAllIntersection(localChangeLists);
- message = "There are local changes that can potentially intersect with merge changes.\nDo you want to continue?";
} else {
intersection = checkIntersection(myLists, localChangeLists);
- message = "There are local changes that will intersect with merge changes.\nDo you want to continue?";
}
if (intersection == null || intersection.getChangesSubset().isEmpty()) return;
- final LocalChangesAction action;
- if (! myMergeAll) {
- final LocalChangesAction[] possibleResults = {LocalChangesAction.shelve, LocalChangesAction.inspect,
- LocalChangesAction.continueMerge, LocalChangesAction.cancel};
- final int result = Messages.showDialog(message, myTitle,
- new String[]{"Shelve local changes", "Inspect changes", "Continue merge", "Cancel"},
- 0, Messages.getQuestionIcon());
- action = possibleResults[result];
- } else {
- final LocalChangesAction[] possibleResults = {LocalChangesAction.shelve, LocalChangesAction.continueMerge, LocalChangesAction.cancel};
- final int result = Messages.showDialog(message, myTitle,
- new String[]{"Shelve local changes", "Continue merge", "Cancel"},
- 0, Messages.getQuestionIcon());
- action = possibleResults[result];
- }
+ final LocalChangesAction action = myInteraction.selectLocalChangesAction(myMergeAll);
switch (action) {
// shelve
case shelve:
@@ -625,12 +709,11 @@ public class QuickMerge {
return;
// inspect
case inspect:
- final Collection<Change> changes = (Collection<Change>) intersection.getChangesSubset().values();
+ // here's cast is due to generic's bug
+ @SuppressWarnings("unchecked") final Collection<Change> changes = (Collection<Change>) intersection.getChangesSubset().values();
final List<FilePath> paths = ChangesUtil.getPaths(changes);
Collections.sort(paths, FilePathByPathComparator.getInstance());
- // todo rework message
- IntersectingLocalChangesPanel.showInVersionControlToolWindow(myProject, myTitle + ", local changes intersection",
- paths, "The following file(s) have local changes that will intersect with merge changes:");
+ myInteraction.showIntersectedLocalPaths(paths);
context.cancelEverything();
return;
default:
@@ -673,13 +756,6 @@ public class QuickMerge {
}
}
- private enum LocalChangesAction {
- cancel,
- continueMerge,
- shelve,
- inspect
- }
-
private class ShelveLocalChanges extends TaskDescriptor {
private final Intersection myIntersection;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMergeContentsVariants.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMergeContentsVariants.java
new file mode 100644
index 000000000000..234126806081
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMergeContentsVariants.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.jetbrains.idea.svn.dialogs;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/27/13
+ * Time: 7:53 PM
+ */
+public enum QuickMergeContentsVariants {
+ all, select, cancel, showLatest
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSLCredentialsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSLCredentialsDialog.java
index 44e503fe08d2..ac8dc9760cc7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSLCredentialsDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSLCredentialsDialog.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnBundle;
@@ -103,7 +104,7 @@ public class SSLCredentialsDialog extends DialogWrapper {
@Override
public JComponent getPreferredFocusedComponent() {
- return myCertificatePath;
+ return StringUtil.isEmptyOrSpaces(myCertificatePath.getText()) ? myCertificatePath : myCertificatePassword;
}
public String getCertificatePath() {
@@ -126,4 +127,8 @@ public class SSLCredentialsDialog extends DialogWrapper {
protected JComponent createCenterPanel() {
return null;
}
+
+ public void setFile(@NotNull String file) {
+ myCertificatePath.setText(file);
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
index 8e0e4218d748..66ada39bd7b4 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
@@ -61,6 +61,11 @@ public class SelectLocationDialog extends DialogWrapper {
try {
SVNURL.parseURIEncoded(url);
final SVNURL svnurl = initRoot(project, url);
+ if (svnurl == null) {
+ Messages.showErrorDialog(project, "Can not detect repository root for URL: " + url,
+ SvnBundle.message("dialog.title.select.repository.location"));
+ return null;
+ }
SelectLocationDialog dialog = new SelectLocationDialog(project, svnurl, null, null, true);
dialog.show();
if (!dialog.isOK()) return null;
@@ -116,6 +121,7 @@ public class SelectLocationDialog extends DialogWrapper {
return "svn.repositoryBrowser";
}
+ @Nullable
private static SVNURL initRoot(final Project project, final String urlString) throws SVNException {
final Ref<SVNURL> result = new Ref<SVNURL>();
final Ref<SVNException> excRef = new Ref<SVNException>();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java
index 9caa86c08a2e..37b4f9d0448a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.util.SystemProperties;
import com.intellij.util.WaitForProgressToShow;
@@ -32,6 +33,7 @@ import org.jetbrains.idea.svn.auth.ProviderType;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.*;
+import org.tmatesoft.svn.core.internal.wc.ISVNHostOptions;
import javax.swing.*;
import java.io.File;
@@ -64,7 +66,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
public SVNAuthentication requestClientAuthentication(final String kind,
final SVNURL url,
final String realm,
- SVNErrorMessage errorMessage,
+ final SVNErrorMessage errorMessage,
final SVNAuthentication previousAuth,
final boolean authMayBeStored) {
final MyCallState callState = new MyCallState(true, false);
@@ -85,7 +87,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
public void run() {
SimpleCredentialsDialog dialog = new SimpleCredentialsDialog(myProject);
dialog.setup(realm, userName, authCredsOn);
- if (previousAuth == null) {
+ if (errorMessage == null) {
dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
}
else {
@@ -106,7 +108,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
public void run() {
UserNameCredentialsDialog dialog = new UserNameCredentialsDialog(myProject);
dialog.setup(realm, userName, authCredsOn);
- if (previousAuth == null) {
+ if (errorMessage == null) {
dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
}
else {
@@ -123,7 +125,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
command = new Runnable() {
public void run() {
SSHCredentialsDialog dialog = new SSHCredentialsDialog(myProject, realm, userName, authCredsOn, url.getPort());
- if (previousAuth == null) {
+ if (errorMessage == null) {
dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
}
else {
@@ -150,8 +152,13 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP
} else if (ISVNAuthenticationManager.SSL.equals(kind)) {
command = new Runnable() {
public void run() {
+ final ISVNHostOptions options = myManager.getHostOptionsProvider().getHostOptions(url);
+ final String file = options.getSSLClientCertFile();
final SSLCredentialsDialog dialog = new SSLCredentialsDialog(myProject, realm, authCredsOn);
- if (previousAuth == null) {
+ if (!StringUtil.isEmptyOrSpaces(file)) {
+ dialog.setFile(file);
+ }
+ if (errorMessage == null) {
dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
}
else {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java
index 91d8bdb4a422..97420a765ce0 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java
@@ -18,6 +18,7 @@ package org.jetbrains.idea.svn.dialogs;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonShortcuts;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
@@ -37,13 +38,19 @@ import com.intellij.openapi.vcs.changes.ui.ChangesBrowserNodeRenderer;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.ui.*;
import com.intellij.ui.table.TableView;
+import com.intellij.util.Alarm;
+import com.intellij.util.PairConsumer;
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import com.intellij.util.ui.UIUtil;
+import com.intellij.vcsUtil.MoreAction;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.history.SvnChangeList;
+import org.jetbrains.idea.svn.mergeinfo.ListMergeStatus;
import org.jetbrains.idea.svn.mergeinfo.MergeChecker;
+import org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
@@ -57,11 +64,12 @@ import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
-public class ToBeMergedDialog extends DialogWrapper {
+public class ToBeMergedDialog extends DialogWrapper implements MergeDialogI {
public static final int MERGE_ALL_CODE = 222;
private final JPanel myPanel;
private final Project myProject;
private final PageEngine<List<CommittedChangeList>> myListsEngine;
+ private final Alarm myAlarm;
private TableView<CommittedChangeList> myRevisionsList;
private RepositoryChangesBrowser myRepositoryChangesBrowser;
private Splitter mySplitter;
@@ -69,11 +77,28 @@ public class ToBeMergedDialog extends DialogWrapper {
private final QuantitySelection<Long> myWiseSelection;
private final Set<Change> myAlreadyMerged;
+ private final List<CommittedChangeList> myLists;
+ private final PairConsumer<Long, MergeDialogI> myMoreLoader;
private final MergeChecker myMergeChecker;
-
- public ToBeMergedDialog(final Project project, final List<CommittedChangeList> lists, final String title, final MergeChecker mergeChecker) {
+ private final boolean myAlreadyCalculatedState;
+ private volatile boolean myEverythingLoaded;
+
+ private final Map<Long, ListMergeStatus> myStatusMap;
+ private ToBeMergedDialog.MoreXAction myMore100Action;
+ private ToBeMergedDialog.MoreXAction myMore500Action;
+
+ public ToBeMergedDialog(final Project project,
+ final List<CommittedChangeList> lists,
+ final String title,
+ final MergeChecker mergeChecker,
+ final PairConsumer<Long, MergeDialogI> moreLoader) {
super(project, true);
+ myLists = lists;
+ myMoreLoader = moreLoader;
+ myEverythingLoaded = moreLoader == null;
+ myStatusMap = Collections.synchronizedMap(new HashMap<Long, ListMergeStatus>());
myMergeChecker = mergeChecker;
+ myAlreadyCalculatedState = moreLoader == null;
setTitle(title);
myProject = project;
@@ -82,22 +107,99 @@ public class ToBeMergedDialog extends DialogWrapper {
myListsEngine = new BasePageEngine<CommittedChangeList>(lists, lists.size());
myPanel = new JPanel(new BorderLayout());
- myWiseSelection = new QuantitySelection<Long>(true);
+ myWiseSelection = new QuantitySelection<Long>(myEverythingLoaded);
myAlreadyMerged = new HashSet<Change>();
setOKButtonText("Merge Selected");
initUI();
init();
+ enableMore();
+
+ myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, getDisposable());
+ if (! myAlreadyCalculatedState) {
+ refreshListStatus();
+ }
+ }
+
+ private void enableMore() {
+ myMore100Action.setVisible(!myEverythingLoaded);
+ myMore500Action.setVisible(!myEverythingLoaded);
+ myMore100Action.setEnabled(!myEverythingLoaded);
+ myMore500Action.setEnabled(! myEverythingLoaded);
}
- @NotNull
@Override
- protected Action[] createActions() {
- return new Action[]{getOKAction(), new DialogWrapperAction("Merge All") {
+ public void setEverythingLoaded(boolean everythingLoaded) {
+ myEverythingLoaded = everythingLoaded;
+ myMore100Action.setVisible(false);
+ myMore500Action.setVisible(false);
+ }
+
+ @Override
+ public long getLastNumber() {
+ return myLists.get(myLists.size() - 1).getNumber();
+ }
+
+ @Override
+ public void addMoreLists(final List<CommittedChangeList> list) {
+ myListsEngine.getCurrent().addAll(list);
+ myRevisionsList.revalidate();
+ myRevisionsList.repaint();
+ myMore100Action.setEnabled(true);
+ myMore500Action.setEnabled(true);
+ myMore500Action.setVisible(true);
+ refreshListStatus();
+ }
+
+ public void refreshListStatus() {
+ if (myAlarm.isDisposed()) return;
+ myAlarm.addRequest(new Runnable() {
@Override
- protected void doAction(ActionEvent e) {
- close(MERGE_ALL_CODE);
+ public void run() {
+ int cnt = 10;
+ for (CommittedChangeList list : myLists) {
+ final SvnMergeInfoCache.MergeCheckResult result = myMergeChecker.checkList((SvnChangeList)list);
+ // at the moment we calculate only "merged" since we don;t have branch copy point
+ if (SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result)) {
+ myStatusMap.put(list.getNumber(), ListMergeStatus.MERGED);
+ } else if (SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS.equals(result)) {
+ myStatusMap.put(list.getNumber(), ListMergeStatus.ALIEN);
+ } else if (SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS_PARTLY_MERGED.equals(result)) {
+ myStatusMap.put(list.getNumber(), ListMergeStatus.NOT_MERGED);
+ } else {
+ myStatusMap.put(list.getNumber(), ListMergeStatus.REFRESHING);
+ }
+
+ -- cnt;
+ if (cnt <= 0) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ myRevisionsList.revalidate();
+ myRevisionsList.repaint();
+ }
+ });
+ cnt = 10;
+ }
+ }
+ myRevisionsList.revalidate();
+ myRevisionsList.repaint();
}
- }, getCancelAction()};
+ }, 0);
+ }
+
+ @NotNull
+ @Override
+ protected Action[] createActions() {
+ if (myAlreadyCalculatedState) {
+ return new Action[]{getOKAction(), new DialogWrapperAction("Merge All") {
+ @Override
+ protected void doAction(ActionEvent e) {
+ close(MERGE_ALL_CODE);
+ }
+ }, getCancelAction()};
+ } else {
+ return super.createActions();
+ }
}
public List<CommittedChangeList> getSelected() {
@@ -229,8 +331,11 @@ public class ToBeMergedDialog extends DialogWrapper {
myRevisionsList.repaint();
}
};
+ myMore100Action = new MoreXAction(100);
+ myMore500Action = new MoreXAction(500);
final PagedListWithActions<CommittedChangeList> byRevisions =
- new PagedListWithActions<CommittedChangeList>(myListsEngine, listsManager, new MySelectAll(), new MyUnselectAll());
+ new PagedListWithActions<CommittedChangeList>(myListsEngine, listsManager, new MySelectAll(), new MyUnselectAll(),
+ myMore100Action, myMore500Action);
mySplitter = new Splitter(false, 0.7f);
mySplitter.setFirstComponent(byRevisions.getComponent());
@@ -317,6 +422,23 @@ public class ToBeMergedDialog extends DialogWrapper {
return myPanel;
}
+ private class MoreXAction extends MoreAction {
+ private final int myQuantity;
+
+ private MoreXAction(final int quantity) {
+ super("Load +" + quantity);
+ myQuantity = quantity;
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ myMore500Action.setVisible(false);
+ myMore100Action.setEnabled(false);
+ myMore500Action.setEnabled(false);
+ myMoreLoader.consume(Long.valueOf(myQuantity), ToBeMergedDialog.this);
+ }
+ }
+
private class MySelectAll extends DumbAwareAction {
private MySelectAll() {
super("Select All", "Select All", AllIcons.Actions.Selectall);
@@ -351,7 +473,18 @@ public class ToBeMergedDialog extends DialogWrapper {
myCheckBox = new JCheckBox();
myCheckBox.setEnabled(true);
myCheckBox.setSelected(true);
- myRenderer = new CommittedChangeListRenderer(myProject, Collections.<CommittedChangeListDecorator>emptyList());
+ myRenderer = new CommittedChangeListRenderer(myProject, Collections.<CommittedChangeListDecorator>singletonList(new CommittedChangeListDecorator() {
+ @Nullable
+ @Override
+ public Icon decorate(CommittedChangeList list) {
+ if (myAlreadyCalculatedState) return ListMergeStatus.NOT_MERGED.getIcon();
+ final ListMergeStatus status = myStatusMap.get(list.getNumber());
+ if (status != null) {
+ return status.getIcon();
+ }
+ return ListMergeStatus.REFRESHING.getIcon();
+ }
+ }));
}
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java
index a174c59f60d1..f9bf6bda943d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java
@@ -31,9 +31,6 @@ import java.awt.*;
import java.io.File;
public class UpgradeFormatDialog extends DialogWrapper {
- private JRadioButton myUpgradeNoneButton;
- private JRadioButton myUpgradeAutoButton;
- private JRadioButton myUpgradeAuto15Button;
private JRadioButton myUpgradeAuto16Button;
private JRadioButton myUpgradeAuto17Button;
@@ -64,21 +61,11 @@ public class UpgradeFormatDialog extends DialogWrapper {
return "svn.upgradeDialog";
}
- public void setData(final boolean display13format, final String selectedFormat) {
+ public void setData(final String selectedFormat) {
if (SvnConfiguration.UPGRADE_AUTO_17.equals(selectedFormat)) {
myUpgradeAuto17Button.setSelected(true);
- } else if (SvnConfiguration.UPGRADE_AUTO_16.equals(selectedFormat)) {
- myUpgradeAuto16Button.setSelected(true);
- } else if (SvnConfiguration.UPGRADE_AUTO.equals(selectedFormat)) {
- myUpgradeAutoButton.setSelected(true);
- } else if (SvnConfiguration.UPGRADE_AUTO_15.equals(selectedFormat)) {
- myUpgradeAuto15Button.setSelected(true);
} else {
- myUpgradeNoneButton.setSelected(true);
- }
- myUpgradeNoneButton.setVisible(display13format);
- if (myUpgradeNoneButton.isSelected() && (! display13format)) {
- myUpgradeAutoButton.setSelected(true);
+ myUpgradeAuto16Button.setSelected(true);
}
}
@@ -114,31 +101,18 @@ public class UpgradeFormatDialog extends DialogWrapper {
panel.add(topLabel, gb);
gb.gridy += 1;
- myUpgradeNoneButton = new JRadioButton(SvnBundle.message("radio.configure." + label + ".none"));
- myUpgradeAutoButton = new JRadioButton(SvnBundle.message("radio.configure." + label + ".auto"));
- myUpgradeAuto15Button = new JRadioButton(SvnBundle.message("radio.configure." + label + ".auto.15format"));
+
myUpgradeAuto16Button = new JRadioButton(SvnBundle.message("radio.configure." + label + ".auto.16format"));
myUpgradeAuto17Button = new JRadioButton(SvnBundle.message("radio.configure." + label + ".auto.17format"));
ButtonGroup group = new ButtonGroup();
- group.add(myUpgradeNoneButton);
- group.add(myUpgradeAutoButton);
- group.add(myUpgradeAuto15Button);
group.add(myUpgradeAuto16Button);
group.add(myUpgradeAuto17Button);
- panel.add(myUpgradeNoneButton, gb);
- gb.gridy += 1;
- panel.add(myUpgradeAutoButton, gb);
- gb.gridy += 1;
- panel.add(myUpgradeAuto15Button, gb);
- gb.gridy += 1;
panel.add(myUpgradeAuto16Button, gb);
gb.gridy += 1;
panel.add(myUpgradeAuto17Button, gb);
gb.gridy += 1;
- myUpgradeNoneButton.setSelected(true);
-
final JPanel auxiliaryPanel = getBottomAuxiliaryPanel();
if (auxiliaryPanel != null) {
panel.add(auxiliaryPanel, gb);
@@ -165,12 +139,6 @@ public class UpgradeFormatDialog extends DialogWrapper {
public String getUpgradeMode() {
if (myUpgradeAuto17Button.isSelected()) {
return SvnConfiguration.UPGRADE_AUTO_17;
- } else if (myUpgradeNoneButton.isSelected()) {
- return SvnConfiguration.UPGRADE_NONE;
- } else if (myUpgradeAutoButton.isSelected()) {
- return SvnConfiguration.UPGRADE_AUTO;
- } else if (myUpgradeAuto15Button.isSelected()) {
- return SvnConfiguration.UPGRADE_AUTO_15;
} else if (myUpgradeAuto16Button.isSelected()) {
return SvnConfiguration.UPGRADE_AUTO_16;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java
index b0733e38717e..320c24248516 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/RootsAndBranches.java
@@ -44,6 +44,7 @@ import org.jetbrains.idea.svn.actions.RecordOnlyMergerFactory;
import org.jetbrains.idea.svn.actions.ShowSvnMapAction;
import org.jetbrains.idea.svn.dialogs.WCInfoWithBranches;
import org.jetbrains.idea.svn.integrate.*;
+import org.jetbrains.idea.svn.mergeinfo.ListMergeStatus;
import org.jetbrains.idea.svn.mergeinfo.MergeInfoHolder;
import org.jetbrains.idea.svn.update.UpdateEventHandler;
import org.tmatesoft.svn.core.SVNURL;
@@ -199,8 +200,8 @@ public class RootsAndBranches implements CommittedChangeListDecorator {
}
public Icon decorate(final CommittedChangeList list) {
- final MergeInfoHolder.ListMergeStatus status = getStatus(list, false);
- return (status == null) ? MergeInfoHolder.ListMergeStatus.ALIEN.getIcon() : status.getIcon();
+ final ListMergeStatus status = getStatus(list, false);
+ return (status == null) ? ListMergeStatus.ALIEN.getIcon() : status.getIcon();
}
private void createPanels(final RepositoryLocation location, final Runnable afterRefresh) {
@@ -566,16 +567,16 @@ public class RootsAndBranches implements CommittedChangeListDecorator {
}
private boolean mergeEnabled(final CommittedChangeList list, final boolean forMerge) {
- final MergeInfoHolder.ListMergeStatus mergeStatus = getStatus(list, true);
- if ((mergeStatus == null) || (MergeInfoHolder.ListMergeStatus.ALIEN.equals(mergeStatus))) {
+ final ListMergeStatus mergeStatus = getStatus(list, true);
+ if ((mergeStatus == null) || (ListMergeStatus.ALIEN.equals(mergeStatus))) {
return false;
- } else if (MergeInfoHolder.ListMergeStatus.REFRESHING.equals(mergeStatus)) {
+ } else if (ListMergeStatus.REFRESHING.equals(mergeStatus)) {
return true;
}
if (forMerge) {
- return MergeInfoHolder.ListMergeStatus.NOT_MERGED.equals(mergeStatus);
+ return ListMergeStatus.NOT_MERGED.equals(mergeStatus);
}
- return MergeInfoHolder.ListMergeStatus.MERGED.equals(mergeStatus);
+ return ListMergeStatus.MERGED.equals(mergeStatus);
}
private class MarkAsMerged extends AbstractIntegrateChangesAction<SelectedChangeListsChecker> {
@@ -782,7 +783,7 @@ public class RootsAndBranches implements CommittedChangeListDecorator {
}
@Nullable
- public MergeInfoHolder.ListMergeStatus getStatus(final CommittedChangeList list, final boolean ignoreEnabled) {
+ public ListMergeStatus getStatus(final CommittedChangeList list, final boolean ignoreEnabled) {
if (! (list instanceof SvnChangeList)) {
return null;
}
@@ -867,14 +868,14 @@ public class RootsAndBranches implements CommittedChangeListDecorator {
final List<CommittedChangeList> result = new ArrayList<CommittedChangeList>();
for (CommittedChangeList list : changeLists) {
- final MergeInfoHolder.ListMergeStatus status = getStatus(list, true);
- if (MergeInfoHolder.ListMergeStatus.REFRESHING.equals(status)) {
+ final ListMergeStatus status = getStatus(list, true);
+ if (ListMergeStatus.REFRESHING.equals(status)) {
result.add(list);
- } else if ((status == null) || MergeInfoHolder.ListMergeStatus.ALIEN.equals(status)) {
+ } else if ((status == null) || ListMergeStatus.ALIEN.equals(status)) {
if (! myFilterAlien.isSelected(null)) {
result.add(list);
}
- } else if (MergeInfoHolder.ListMergeStatus.MERGED.equals(status) || MergeInfoHolder.ListMergeStatus.COMMON.equals(status)) {
+ } else if (ListMergeStatus.MERGED.equals(status) || ListMergeStatus.COMMON.equals(status)) {
if (! myFilterMerged.isSelected(null)) {
result.add(list);
}
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 bbe4f8a04362..bcb40a034ac9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java
@@ -29,16 +29,12 @@ import com.intellij.openapi.vcs.impl.ContentRevisionCache;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnRevisionNumber;
+import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
-import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
-import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
-import org.tmatesoft.svn.core.wc.SVNWCClient;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
@@ -143,22 +139,24 @@ public class SvnFileRevision implements VcsFileRevision {
}
public byte[] loadContent() throws IOException, VcsException {
- ByteArrayOutputStream contents = new ByteArrayOutputStream();
- ContentLoader loader = new ContentLoader(myURL, contents, myRevision, myPegRevision);
+ ContentLoader loader = new ContentLoader(myURL, myRevision, myPegRevision);
if (ApplicationManager.getApplication().isDispatchThread() &&
!myRevision.isLocal()) {
- ProgressManager.getInstance().runProcessWithProgressSynchronously(loader, SvnBundle.message("progress.title.loading.file.content"), false, myVCS.getProject());
+ ProgressManager.getInstance().runProcessWithProgressSynchronously(loader, SvnBundle.message("progress.title.loading.file.content"),
+ false, myVCS.getProject());
}
else {
loader.run();
}
if (loader.getException() == null) {
- return contents.toByteArray();
+ final byte[] contents = loader.getContents();
+ ContentRevisionCache.checkContentsSize(myURL, contents.length);
+ return contents;
}
else {
- final SVNException svnException = loader.getException();
- LOG.info("Failed to load file '" + myURL + "' content at revision: " + myRevision + "\n" + svnException.getMessage(), svnException);
- throw new VcsException(svnException);
+ final VcsException vcsException = loader.getException();
+ LOG.info("Failed to load file '" + myURL + "' content at revision: " + myRevision + "\n" + vcsException.getMessage(), vcsException);
+ throw vcsException;
}
}
@@ -188,31 +186,34 @@ public class SvnFileRevision implements VcsFileRevision {
private final SVNRevision myRevision;
private final SVNRevision myPegRevision;
private final String myURL;
- private final OutputStream myDst;
- private SVNException myException;
+ private VcsException myException;
+ private byte[] myContents;
- public ContentLoader(String url, OutputStream dst, SVNRevision revision, SVNRevision pegRevision) {
+ public ContentLoader(String url, SVNRevision revision, SVNRevision pegRevision) {
myURL = url;
- myDst = dst;
myRevision = revision;
myPegRevision = pegRevision;
}
- public SVNException getException() {
+ public VcsException getException() {
return myException;
}
+ private byte[] getContents() {
+ return myContents;
+ }
+
public void run() {
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
if (progress != null) {
progress.setText(SvnBundle.message("progress.text.loading.contents", myURL));
progress.setText2(SvnBundle.message("progress.text2.revision.information", myRevision));
}
+
try {
- SVNWCClient client = myVCS.createWCClient();
- client.doGetFileContents(SVNURL.parseURIEncoded(myURL), myRevision, myRevision, true, myDst);
+ myContents = SvnUtil.getFileContents(myVCS, myURL, true, myRevision, myPegRevision);
}
- catch (SVNException e) {
+ catch (VcsException e) {
myException = e;
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
index 9294fbe2ff8e..4a2c8725a898 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.annotate.ShowAllAffectedGenericAction;
import com.intellij.openapi.vcs.changes.Change;
@@ -163,7 +164,8 @@ public class SvnHistoryProvider
}
public void reportAppendableHistory(FilePath path, final VcsAppendableHistorySessionPartner partner) throws VcsException {
- reportAppendableHistory(path, partner, null, null, 0, null, false);
+ // we need + 1 rows to be reported to further detect that number of rows exceeded the limit
+ reportAppendableHistory(path, partner, null, null, VcsConfiguration.getInstance(myVcs.getProject()).MAXIMUM_HISTORY_ROWS + 1, null, false);
}
public void reportAppendableHistory(FilePath path, final VcsAppendableHistorySessionPartner partner,
@@ -319,10 +321,11 @@ public class SvnHistoryProvider
final SVNRevision pegRevision = myInfo.getRevision();
SVNLogClient client = myVcs.createLogClient();
try {
+ // a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
client
.doLog(new File[]{new File(myFile.getIOFile().getAbsolutePath())},
myFrom == null ? SVNRevision.HEAD : myFrom, myTo == null ? SVNRevision.create(1) : myTo, myPeg,
- false, true, myShowMergeSources && mySupport15, myLimit, null,
+ false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl, createConsumerAdapter(myConsumer), repoRootURL, myFile.getCharset()));
}
catch (SVNCancelException e) {
@@ -393,8 +396,9 @@ public class SvnHistoryProvider
relativeUrl = myUrl.substring(root.length());
}
SVNLogClient client = myVcs.createLogClient();
+ // a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
client.doLog(svnurl, new String[]{}, myPeg == null ? myFrom : myPeg,
- operationalFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, myShowMergeSources && mySupport15, myLimit, null,
+ operationalFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, createConsumerAdapter(myConsumer), rootURL));
}
catch (SVNCancelException e) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
index 459e9ab3a30e..a668a54f953a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
@@ -112,6 +112,7 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC
if (exception != null) {
throw new VcsException(exception);
}
+ ContentRevisionCache.checkContentsSize(myPath, buffer.size());
return buffer;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
index 0366c21ea202..3d5bcaf0d92b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
@@ -16,18 +16,12 @@
package org.jetbrains.idea.svn.history;
import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.RepositoryLocation;
import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.RootUrlInfo;
-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 org.tmatesoft.svn.core.internal.util.SVNURLUtil;
import java.io.File;
@@ -68,26 +62,9 @@ public class SvnRepositoryLocation implements RepositoryLocation {
@Nullable
public static FilePath getLocalPath(final String fullPath, final NotNullFunction<File, Boolean> detector, final SvnVcs vcs) {
if (vcs.getProject().isDefault()) return null;
- final SVNURL fullPathURL;
- try {
- fullPathURL = SVNURL.parseURIEncoded(fullPath);
- }
- catch (SVNException e) {
- return null;
- }
final RootUrlInfo rootForUrl = vcs.getSvnFileUrlMapping().getWcRootForUrl(fullPath);
if (rootForUrl != null) {
return LocationDetector.filePathByUrlAndPath(fullPath, rootForUrl.getUrl().toString(), rootForUrl.getIoFile().getAbsolutePath(), detector);
- } else {
- final VirtualFile[] underVcs = ProjectLevelVcsManager.getInstance(vcs.getProject()).getRootsUnderVcs(vcs);
- if (underVcs.length == 0) return null;
- for (VirtualFile vf : underVcs) {
- final File ioFile = new File(vf.getPath());
- final SVNURL url = SvnUtil.getUrl(vcs, ioFile);
- if (url != null && SVNURLUtil.isAncestor(url, fullPathURL)) {
- return LocationDetector.filePathByUrlAndPath(fullPath, url.toString(), ioFile.getPath(), detector);
- }
- }
}
return null;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteraction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteraction.java
new file mode 100644
index 000000000000..def31a2c3e74
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteraction.java
@@ -0,0 +1,68 @@
+/*
+ * 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 org.jetbrains.idea.svn.integrate;
+
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.util.PairConsumer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.dialogs.LocalChangesAction;
+import org.jetbrains.idea.svn.dialogs.MergeDialogI;
+import org.jetbrains.idea.svn.dialogs.QuickMergeContentsVariants;
+import org.jetbrains.idea.svn.mergeinfo.MergeChecker;
+
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/26/13
+ * Time: 8:29 PM
+ */
+public interface QuickMergeInteraction {
+ void setTitle(@NotNull final String title);
+ /**
+ * @return {@link com.intellij.openapi.ui.Messages.CANCEL} - cancel,
+ * {@link com.intellij.openapi.ui.Messages.OK} - merge all, {@link com.intellij.openapi.ui.Messages.NO} - select revisions to merge
+ */
+ QuickMergeContentsVariants selectMergeVariant();
+ boolean shouldContinueSwitchedRootFound();
+
+ boolean shouldReintegrate(@NotNull final String sourceUrl, @NotNull final String targetUrl);
+
+ @NotNull
+ SelectMergeItemsResult selectMergeItems(final List<CommittedChangeList> lists, final String mergeTitle, final MergeChecker mergeChecker);
+
+ @NotNull
+ LocalChangesAction selectLocalChangesAction(boolean mergeAll);
+
+ void showIntersectedLocalPaths(final List<FilePath> paths);
+
+ void showError(@NotNull Exception exception);
+ void showErrors(final String message, final List<VcsException> exceptions);
+ void showErrors(final String message, final boolean isError);
+
+ List<CommittedChangeList> showRecentListsForSelection(@NotNull List<CommittedChangeList> list,
+ @NotNull String mergeTitle,
+ @NotNull MergeChecker mergeChecker,
+ @NotNull PairConsumer<Long, MergeDialogI> loader, boolean everyThingLoaded);
+
+ interface SelectMergeItemsResult {
+ QuickMergeContentsVariants getResultCode();
+ List<CommittedChangeList> getSelectedLists();
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteractionImpl.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteractionImpl.java
new file mode 100644
index 000000000000..93790e91ba66
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteractionImpl.java
@@ -0,0 +1,164 @@
+/*
+ * 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 org.jetbrains.idea.svn.integrate;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogBuilder;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.vcs.AbstractVcsHelper;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.util.PairConsumer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.dialogs.*;
+import org.jetbrains.idea.svn.mergeinfo.MergeChecker;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/27/13
+ * Time: 11:40 AM
+ */
+public class QuickMergeInteractionImpl implements QuickMergeInteraction {
+ private final Project myProject;
+ private String myTitle;
+
+ public QuickMergeInteractionImpl(Project project) {
+ myProject = project;
+ }
+
+ @Override
+ public void setTitle(@NotNull String title) {
+ myTitle = title;
+ }
+
+ @Override
+ public QuickMergeContentsVariants selectMergeVariant() {
+ final QuickMergeWayOptionsPanel panel = new QuickMergeWayOptionsPanel();
+ final DialogBuilder builder = new DialogBuilder(myProject);
+ builder.removeAllActions();
+ builder.setTitle("Select Merge Variant");
+ builder.setCenterPanel(panel.getMainPanel());
+ panel.setWrapper(builder.getDialogWrapper());
+ builder.show();
+
+ return panel.getVariant();
+ }
+
+ @Override
+ public boolean shouldContinueSwitchedRootFound() {
+ return prompt("There are some switched paths in the working copy. Do you want to continue?");
+ }
+
+ @Override
+ public boolean shouldReintegrate(@NotNull final String sourceUrl, @NotNull final String targetUrl) {
+ return prompt("<html><body>You are going to reintegrate changes.<br><br>This will make branch '" + sourceUrl +
+ "' <b>no longer usable for further work</b>." +
+ "<br>It will not be able to correctly absorb new trunk (" + targetUrl +
+ ") changes,<br>nor can this branch be properly reintegrated to trunk again.<br><br>Are you sure?</body></html>");
+ }
+
+ @NotNull
+ @Override
+ public SelectMergeItemsResult selectMergeItems(List<CommittedChangeList> lists, String mergeTitle, MergeChecker mergeChecker) {
+ final ToBeMergedDialog dialog = new ToBeMergedDialog(myProject, lists, mergeTitle, mergeChecker, null);
+ dialog.show();
+ return new SelectMergeItemsResult() {
+ @Override
+ public QuickMergeContentsVariants getResultCode() {
+ final int code = dialog.getExitCode();
+ if (ToBeMergedDialog.MERGE_ALL_CODE == code) {
+ return QuickMergeContentsVariants.all;
+ }
+ return DialogWrapper.OK_EXIT_CODE == code ? QuickMergeContentsVariants.select : QuickMergeContentsVariants.cancel;
+ }
+
+ @Override
+ public List<CommittedChangeList> getSelectedLists() {
+ return dialog.getSelected();
+ }
+ };
+ }
+
+ @NotNull
+ @Override
+ public LocalChangesAction selectLocalChangesAction(final boolean mergeAll) {
+ if (! mergeAll) {
+ final LocalChangesAction[] possibleResults = {LocalChangesAction.shelve, LocalChangesAction.inspect,
+ LocalChangesAction.continueMerge, LocalChangesAction.cancel};
+ final int result = Messages.showDialog("There are local changes that will intersect with merge changes.\nDo you want to continue?", myTitle,
+ new String[]{"Shelve local changes", "Inspect changes", "Continue merge", "Cancel"},
+ 0, Messages.getQuestionIcon());
+ return possibleResults[result];
+ } else {
+ final LocalChangesAction[] possibleResults = {LocalChangesAction.shelve, LocalChangesAction.continueMerge, LocalChangesAction.cancel};
+ final int result = Messages.showDialog("There are local changes that can potentially intersect with merge changes.\nDo you want to continue?", myTitle,
+ new String[]{"Shelve local changes", "Continue merge", "Cancel"},
+ 0, Messages.getQuestionIcon());
+ return possibleResults[result];
+ }
+ }
+
+ @Override
+ public void showIntersectedLocalPaths(final List<FilePath> paths) {
+ IntersectingLocalChangesPanel.showInVersionControlToolWindow(myProject, myTitle + ", local changes intersection",
+ paths, "The following file(s) have local changes that will intersect with merge changes:");
+ }
+
+ @Override
+ public void showError(@NotNull Exception exception) {
+ AbstractVcsHelper.getInstance(myProject).showErrors(Collections.singletonList(new VcsException(exception)),
+ exception.getMessage() == null ? exception.getClass().getName() : exception.getMessage());
+ }
+
+ @Override
+ public void showErrors(String message, List<VcsException> exceptions) {
+ AbstractVcsHelper.getInstance(myProject).showErrors(exceptions, message);
+ }
+
+ @Override
+ public void showErrors(String message, boolean isError) {
+ VcsBalloonProblemNotifier.showOverChangesView(myProject, message, isError ? MessageType.ERROR : MessageType.WARNING);
+ }
+
+ @Override
+ public List<CommittedChangeList> showRecentListsForSelection(@NotNull List<CommittedChangeList> list,
+ @NotNull String mergeTitle,
+ @NotNull MergeChecker mergeChecker,
+ @NotNull PairConsumer<Long, MergeDialogI> loader,
+ boolean everyThingLoaded) {
+ final ToBeMergedDialog dialog = new ToBeMergedDialog(myProject, list, mergeTitle, mergeChecker, loader);
+ if (everyThingLoaded) {
+ dialog.setEverythingLoaded(true);
+ }
+ dialog.show();
+ if (DialogWrapper.OK_EXIT_CODE == dialog.getExitCode()) {
+ return dialog.getSelected();
+ }
+ return null;
+ }
+
+ private boolean prompt(final String question) {
+ return Messages.showOkCancelDialog(myProject, question, myTitle, Messages.getQuestionIcon()) == 0;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeWayOptionsPanel.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeWayOptionsPanel.form
new file mode 100644
index 000000000000..a48870b200f0
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeWayOptionsPanel.form
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.svn.integrate.QuickMergeWayOptionsPanel">
+ <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="8" 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="754" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="3c8e5" class="javax.swing.JButton" binding="myMergeAllButton" default-binding="true">
+ <constraints>
+ <grid row="0" 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="Merge All"/>
+ </properties>
+ </component>
+ <vspacer id="66429">
+ <constraints>
+ <grid row="7" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <hspacer id="54e1">
+ <constraints>
+ <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ <component id="2abc7" class="javax.swing.JButton" binding="myQuickManualSelectButton" default-binding="true">
+ <constraints>
+ <grid row="2" 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="Quick Manual Select"/>
+ </properties>
+ </component>
+ <component id="76374" class="javax.swing.JButton" binding="mySelectWithPreFilterButton" default-binding="true">
+ <constraints>
+ <grid row="4" 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="Select With Pre-Filter"/>
+ </properties>
+ </component>
+ <component id="e43e9" class="javax.swing.JButton" binding="myCancelButton" default-binding="true">
+ <constraints>
+ <grid row="6" 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="Cancel"/>
+ </properties>
+ </component>
+ <component id="54a5b" class="javax.swing.JLabel" binding="myAllNotMergedRevisionsLabel">
+ <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 resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="quick.merge.variants.merge.all.explanation"/>
+ </properties>
+ </component>
+ <component id="18321" class="javax.swing.JLabel" binding="myShowsAllRevisionsFromLabel">
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="quick.merge.variants.quick.select.explanation"/>
+ </properties>
+ </component>
+ <component id="f8a4d" class="javax.swing.JLabel" binding="myFindsWhereOneOfLabel">
+ <constraints>
+ <grid row="5" 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 resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="quick.merge.variants.pre.select.explanation"/>
+ </properties>
+ </component>
+ <hspacer id="3de54">
+ <constraints>
+ <grid row="1" column="1" row-span="1" col-span="2" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ <hspacer id="4ab9a">
+ <constraints>
+ <grid row="3" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ <hspacer id="a4a34">
+ <constraints>
+ <grid row="5" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+</form>
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeWayOptionsPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeWayOptionsPanel.java
new file mode 100644
index 000000000000..430da5256080
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeWayOptionsPanel.java
@@ -0,0 +1,85 @@
+/*
+ * 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 org.jetbrains.idea.svn.integrate;
+
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.MultiLineLabelUI;
+import org.jetbrains.idea.svn.dialogs.QuickMergeContentsVariants;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/29/13
+ * Time: 7:27 PM
+ */
+public class QuickMergeWayOptionsPanel {
+ private JButton myMergeAllButton;
+ private JButton myQuickManualSelectButton;
+ private JButton mySelectWithPreFilterButton;
+ private JButton myCancelButton;
+ private JPanel myMainPanel;
+ private JLabel myAllNotMergedRevisionsLabel;
+ private JLabel myShowsAllRevisionsFromLabel;
+ private JLabel myFindsWhereOneOfLabel;
+ private DialogWrapper myWrapper;
+
+ private QuickMergeContentsVariants myVariant = QuickMergeContentsVariants.cancel;
+
+ public QuickMergeWayOptionsPanel() {
+ myMergeAllButton.addActionListener(setCodeAndClose(QuickMergeContentsVariants.all));
+ myQuickManualSelectButton.addActionListener(setCodeAndClose(QuickMergeContentsVariants.showLatest));
+ mySelectWithPreFilterButton.addActionListener(setCodeAndClose(QuickMergeContentsVariants.select));
+ myCancelButton.addActionListener(setCodeAndClose(QuickMergeContentsVariants.cancel));
+
+ myAllNotMergedRevisionsLabel.setUI(new MultiLineLabelUI());
+ myShowsAllRevisionsFromLabel.setUI(new MultiLineLabelUI());
+ myFindsWhereOneOfLabel.setUI(new MultiLineLabelUI());
+
+ myAllNotMergedRevisionsLabel.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
+ myShowsAllRevisionsFromLabel.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
+ myFindsWhereOneOfLabel.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
+ }
+
+ private ActionListener setCodeAndClose(final QuickMergeContentsVariants variant) {
+ return new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myVariant = variant;
+ close();
+ }
+ };
+ }
+
+ private void close() {
+ myWrapper.close(DialogWrapper.OK_EXIT_CODE);
+ }
+
+ public void setWrapper(DialogWrapper wrapper) {
+ myWrapper = wrapper;
+ }
+
+ public QuickMergeContentsVariants getVariant() {
+ return myVariant;
+ }
+
+ public JPanel getMainPanel() {
+ return myMainPanel;
+ }
+}
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 1133e8b32ef7..00f839776120 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java
@@ -215,7 +215,8 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable {
private void finishActions(final boolean wasCanceled) {
if (! wasCanceled) {
- if ((! myDryRun) && (myExceptions.isEmpty()) && (! myAccomulatedFiles.containErrors()) &&
+ if (! ApplicationManager.getApplication().isUnitTestMode() &&
+ (! myDryRun) && (myExceptions.isEmpty()) && (! myAccomulatedFiles.containErrors()) &&
((! myAccomulatedFiles.isEmpty()) || (myMergeTarget != null))) {
if (myInfo.isUnderProjectRoot()) {
showLocalCommit();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/lowLevel/PrimitivePool.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/lowLevel/PrimitivePool.java
new file mode 100644
index 000000000000..0b7e7ae67f05
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/lowLevel/PrimitivePool.java
@@ -0,0 +1,113 @@
+/*
+ * 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 org.jetbrains.idea.svn.lowLevel;
+
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import org.tmatesoft.svn.core.ISVNCanceller;
+import org.tmatesoft.svn.core.SVNCancelException;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
+import org.tmatesoft.svn.core.io.ISVNSession;
+import org.tmatesoft.svn.core.io.ISVNTunnelProvider;
+import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
+import org.tmatesoft.svn.core.wc.ISVNRepositoryPool;
+import org.tmatesoft.svn.util.ISVNDebugLog;
+import org.tmatesoft.svn.util.SVNDebugLog;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/27/13
+ * Time: 10:41 PM
+ */
+public class PrimitivePool implements ISVNRepositoryPool, ISVNSession {
+ private final ISVNAuthenticationManager myManager;
+ private final ISVNTunnelProvider myTunnelProvider;
+
+ public PrimitivePool(ISVNAuthenticationManager manager, ISVNTunnelProvider tunnelProvider) {
+ myManager = manager;
+ myTunnelProvider = tunnelProvider;
+ }
+
+ @Override
+ public SVNRepository createRepository(SVNURL url, boolean mayReuse) throws SVNException {
+ final SVNRepository repos = SVNRepositoryFactory.create(url, this);
+ repos.setAuthenticationManager(myManager);
+ repos.setTunnelProvider(myTunnelProvider);
+ repos.setDebugLog(new ProxySvnLog(SVNDebugLog.getDefaultLog()));
+ repos.setCanceller(new MyCanceller());
+ return repos;
+ }
+
+ @Override
+ public void setAuthenticationManager(ISVNAuthenticationManager authManager) {
+ }
+
+ @Override
+ public void setCanceller(ISVNCanceller canceller) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setDebugLog(ISVNDebugLog log) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void shutdownConnections(boolean shutdownAll) {
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public boolean keepConnection(SVNRepository repository) {
+ return false;
+ }
+
+ @Override
+ public void saveCommitMessage(SVNRepository repository, long revision, String message) {
+ }
+
+ @Override
+ public String getCommitMessage(SVNRepository repository, long revision) {
+ return null;
+ }
+
+ @Override
+ public boolean hasCommitMessage(SVNRepository repository, long revision) {
+ return false;
+ }
+
+ private static class MyCanceller implements ISVNCanceller {
+ @Override
+ public void checkCancelled() throws SVNCancelException {
+ final ProgressManager pm = ProgressManager.getInstance();
+ final ProgressIndicator pi = pm.getProgressIndicator();
+ if (pi != null) {
+ if (pi.isCanceled()) throw new SVNCancelException();
+ }
+ ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
+ if (indicator != null && indicator.isCanceled()) {
+ throw new SVNCancelException();
+ }
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/ListMergeStatus.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/ListMergeStatus.java
new file mode 100644
index 000000000000..750a1fc46ff9
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/ListMergeStatus.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.jetbrains.idea.svn.mergeinfo;
+
+import icons.SvnIcons;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+* Created with IntelliJ IDEA.
+* User: Irina.Chernushina
+* Date: 3/30/13
+* Time: 2:41 PM
+*/
+public enum ListMergeStatus {
+ COMMON(SvnIcons.Common),
+ MERGED(SvnIcons.Integrated),
+ NOT_MERGED(SvnIcons.Notintegrated),
+ ALIEN(null),
+ REFRESHING(SvnIcons.IntegrationStatusUnknown);
+
+ @Nullable
+ private final Icon myIcon;
+
+ ListMergeStatus(@Nullable final Icon icon) {
+ myIcon = icon;
+ }
+
+ @Nullable
+ public Icon getIcon() {
+ return myIcon;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java
index a08bc68ea618..fb0f52362cdf 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeInfoHolder.java
@@ -24,14 +24,12 @@ import com.intellij.openapi.vcs.changes.committed.DecoratorManager;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.Consumer;
-import icons.SvnIcons;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.dialogs.WCInfoWithBranches;
import org.jetbrains.idea.svn.dialogs.WCPaths;
import org.jetbrains.idea.svn.history.SvnChangeList;
-import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.HashMap;
@@ -165,25 +163,6 @@ public class MergeInfoHolder {
}
}
- public static enum ListMergeStatus {
- COMMON(SvnIcons.Common),
- MERGED(SvnIcons.Integrated),
- NOT_MERGED(SvnIcons.Notintegrated),
- //ALIEN(IconLoader.getIcon("/icons/OnDefault.png")),
- ALIEN(null),
- REFRESHING(SvnIcons.IntegrationStatusUnknown);
-
- private final Icon myIcon;
-
- private ListMergeStatus(final Icon icon) {
- myIcon = icon;
- }
-
- public Icon getIcon() {
- return myIcon;
- }
- }
-
public static interface ListChecker {
ListMergeStatus check(final CommittedChangeList list, final boolean ignoreEnabled);
}
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 5eda9a30ff54..e2962ed58222 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
@@ -39,10 +39,12 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker {
private final WCInfo myWCInfo;
// subpath [file] (local) to (subpathURL - merged FROM - to ranges list)
private final AreaMap<String, Map<String, SVNMergeRangeList>> myDataMap;
- private String myFromUrlRelative;
+ private final Object myLock;
+ private final String myFromUrlRelative;
public OneRecursiveShotMergeInfoWorker(final Project project, final WCInfo WCInfo, final String fromUrl) {
myProject = project;
+ myLock = new Object();
myWCInfo = WCInfo;
myDataMap = AreaMap.create(new PairProcessor<String, String>() {
@@ -68,7 +70,9 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker {
depth, new ISVNPropertyHandler() {
public void handleProperty(File path, SVNPropertyData property) throws SVNException {
final String key = keyFromFile(path);
- myDataMap.put(key, SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(property.getValue().getString())), null));
+ synchronized (myLock) {
+ myDataMap.put(key, SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(property.getValue().getString())), null));
+ }
}
public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
@@ -84,7 +88,9 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker {
if (relativeToWc == null) return SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS;
final InfoProcessor processor = new InfoProcessor(relativeToWc, myFromUrlRelative, revisionNumber);
- myDataMap.getSimiliar(keyFromPath(relativeToWc), processor);
+ synchronized (myLock) {
+ myDataMap.getSimiliar(keyFromPath(relativeToWc), processor);
+ }
return SvnMergeInfoCache.MergeCheckResult.getInstance(processor.isMerged());
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/networking/SSLProtocolExceptionParser.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/networking/SSLProtocolExceptionParser.java
new file mode 100644
index 000000000000..51813274257b
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/networking/SSLProtocolExceptionParser.java
@@ -0,0 +1,87 @@
+/*
+ * 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 org.jetbrains.idea.svn.networking;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/25/13
+ * Time: 5:44 PM
+ */
+public class SSLProtocolExceptionParser {
+ private final String myMessage;
+ private String myParsedMessage;
+ private byte myFieldValue;
+ private String myFieldName;
+
+ public SSLProtocolExceptionParser(@NotNull String message) {
+ myMessage = message;
+ }
+
+ public void parse() {
+ myParsedMessage = myMessage;
+ myFieldValue = 0;
+ myFieldName = null;
+
+ final List<String> words = StringUtil.split(myMessage.trim(), " ");
+ if (words.isEmpty()) return;
+ // we'll try to parse by last word - it's just an attempt so ok if failed - just will show the real message
+
+ final String[] possiblePlaces = {"com.sun.net.ssl.internal.ssl.Alerts", "sun.security.ssl.Alerts"};
+ for (String place : possiblePlaces) {
+ try {
+ final Class<?> clazz = Class.forName(place);
+ if (tryByStaticField(clazz, words.get(words.size() - 1))) {
+ return;
+ }
+ }
+ catch (ClassNotFoundException e) {
+ //
+ }
+ }
+ }
+
+ public String getParsedMessage() {
+ return myParsedMessage;
+ }
+
+ private boolean tryByStaticField(Class<?> clazz, String word) {
+ try {
+ final Field field = clazz.getDeclaredField("alert_" + word);
+ field.setAccessible(true);
+ myFieldValue = field.getByte(clazz);
+ myFieldName = field.getName();
+ myParsedMessage = "SSLProtocolException: alert code: " + Byte.toString(myFieldValue) + " alert name: " + myFieldName +
+ ", original message: " + myMessage;
+ if ("alert_unrecognized_name".equals(myFieldName)) {
+ myParsedMessage += "\nThis may be JDK bug 7127374 : JSSE creates SSLProtocolException on (common) warning: unrecognized_name for SNI";
+ }
+ }
+ catch (NoSuchFieldException e) {
+ return false;
+ }
+ catch (IllegalAccessException e) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/DiffContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/DiffContentRevision.java
index 2d280b21d3ec..bec2f3e963e9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/DiffContentRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/DiffContentRevision.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.encoding.EncodingRegistry;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,7 +60,7 @@ public class DiffContentRevision implements ContentRevision {
}
final byte[] bytes = bos.toByteArray();
final Charset charset = myFilePath.getCharset();
- myContents = charset == null ? CharsetToolkit.bytesToString(bytes) : CharsetToolkit.bytesToString(bytes, charset);
+ myContents = charset == null ? CharsetToolkit.bytesToString(bytes, EncodingRegistry.getInstance().getDefaultCharset()) : CharsetToolkit.bytesToString(bytes, charset);
}
return myContents;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnRevisionPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnRevisionPanel.java
index 45cdaf080ca4..897f5b76f72b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnRevisionPanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnRevisionPanel.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.history.SvnChangeList;
@@ -33,7 +34,7 @@ import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.ArrayList;
+import java.util.List;
public class SvnRevisionPanel extends JPanel {
private JRadioButton mySpecified;
@@ -42,7 +43,7 @@ public class SvnRevisionPanel extends JPanel {
private TextFieldWithBrowseButton myRevisionField;
private Project myProject;
private UrlProvider myUrlProvider;
- private final ArrayList<ChangeListener> myChangeListeners = new ArrayList<ChangeListener>();
+ private final List<ChangeListener> myChangeListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private VirtualFile myRoot;
public SvnRevisionPanel() {
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 559c8b72e2d9..80e43aaf7828 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
@@ -106,7 +106,10 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment
final SvnUpdateClientI updateClient;
// do not do from command line for switch now
if (! isSwitch && SvnConfiguration.UseAcceleration.commandLine.equals(configuration.myUseAcceleration) &&
- Svn17Detector.is17(myVcs.getProject(), root) && SvnAuthenticationManager.HTTP.equals(sourceUrl.getProtocol())) {
+ Svn17Detector.is17(myVcs.getProject(), root) && (
+ SvnAuthenticationManager.HTTP.equals(sourceUrl.getProtocol()) ||
+ SvnAuthenticationManager.HTTPS.equals(sourceUrl.getProtocol())
+ )) {
updateClient = new SvnCommandLineUpdateClient(myVcs.getProject(), null);
} else {
updateClient = new SvnSvnkitUpdateClient(myVcs.createUpdateClient());
diff --git a/plugins/svn4idea/svn4idea-tests.iml b/plugins/svn4idea/svn4idea-tests.iml
index 0b826ed87489..9a537c253abf 100644
--- a/plugins/svn4idea/svn4idea-tests.iml
+++ b/plugins/svn4idea/svn4idea-tests.iml
@@ -38,6 +38,7 @@
</SOURCES>
</library>
</orderEntry>
+ <orderEntry type="module" module-name="bindSvn" />
</component>
</module>
diff --git a/plugins/svn4idea/svn4idea.iml b/plugins/svn4idea/svn4idea.iml
index e27f7e52a099..a2785e1261f5 100644
--- a/plugins/svn4idea/svn4idea.iml
+++ b/plugins/svn4idea/svn4idea.iml
@@ -94,23 +94,22 @@
<orderEntry type="module-library">
<library>
<CLASSES>
- <root url="jar://$MODULE_DIR$/lib/javahl.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/svnkit-javahl.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$MODULE_DIR$/lib/javahlsrc.zip!/src" />
+ <root url="jar://$MODULE_DIR$/lib/svnkit-javahl16.zip!/" />
</SOURCES>
</library>
</orderEntry>
+ <orderEntry type="module" module-name="bindSvn" />
<orderEntry type="module-library">
<library>
<CLASSES>
- <root url="jar://$MODULE_DIR$/lib/svnkit-javahl.jar!/" />
+ <root url="jar://$MODULE_DIR$/bindSvn/lib/javahl.jar!/" />
</CLASSES>
<JAVADOC />
- <SOURCES>
- <root url="jar://$MODULE_DIR$/lib/svnkit-javahl16.zip!/" />
- </SOURCES>
+ <SOURCES />
</library>
</orderEntry>
</component>
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
index 25e5f71f7826..a1b7360206e7 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
@@ -83,11 +83,12 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
protected String myWcRootName;
protected boolean myUseNativeAcceleration = new GregorianCalendar().get(Calendar.HOUR_OF_DAY) % 2 == 0;
- private final String myTestDataDir;
+ protected final String myTestDataDir;
private File myRepoRoot;
private File myWcRoot;
private ChangeListManagerGate myGate;
protected String myAnotherRepoUrl;
+ protected File myPluginRoot;
protected SvnTestCase(@NotNull String testDataDir) {
PlatformTestCase.initPlatformLangPrefix();
@@ -128,15 +129,15 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
myRepoRoot = new File(myTempDirFixture.getTempDirPath(), "svnroot");
assert myRepoRoot.mkdir() || myRepoRoot.isDirectory() : myRepoRoot;
- File pluginRoot = new File(PluginPathManager.getPluginHomePath("svn4idea"));
- if (!pluginRoot.isDirectory()) {
+ myPluginRoot = new File(PluginPathManager.getPluginHomePath("svn4idea"));
+ if (!myPluginRoot.isDirectory()) {
// try standalone mode
Class aClass = SvnTestCase.class;
String rootPath = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
- pluginRoot = new File(rootPath).getParentFile().getParentFile().getParentFile();
+ myPluginRoot = new File(rootPath).getParentFile().getParentFile().getParentFile();
}
- File svnBinDir = new File(pluginRoot, myTestDataDir + "/svn/bin");
+ File svnBinDir = new File(myPluginRoot, myTestDataDir + "/svn/bin");
File svnExecutable = null;
if (SystemInfo.isWindows) {
svnExecutable = new File(svnBinDir, "windows/svn.exe");
@@ -154,7 +155,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
? createClientRunner(Collections.singletonMap("DYLD_LIBRARY_PATH", myClientBinaryPath.getPath()))
: createClientRunner();
- ZipUtil.extract(new File(pluginRoot, myTestDataDir + "/svn/newrepo.zip"), myRepoRoot, null);
+ ZipUtil.extract(new File(myPluginRoot, myTestDataDir + "/svn/newrepo.zip"), myRepoRoot, null);
myWcRoot = new File(myTempDirFixture.getTempDirPath(), myWcRootName);
assert myWcRoot.mkdir() || myWcRoot.isDirectory() : myWcRoot;
@@ -280,6 +281,43 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
});
}
+ protected void prepareInnerCopy(final boolean anotherRepository) throws Exception {
+ final String mainUrl = myRepoUrl + "/root/source";
+ final String externalURL;
+ if (anotherRepository) {
+ createAnotherRepo();
+ externalURL = myAnotherRepoUrl + "/root/target";
+ } else {
+ externalURL = myRepoUrl + "/root/target";
+ }
+
+ final ChangeListManagerImpl clManager = (ChangeListManagerImpl)ChangeListManager.getInstance(myProject);
+ final SubTree subTree = new SubTree(myWorkingCopyDir);
+ checkin();
+ clManager.stopEveryThingIfInTestMode();
+ sleep(100);
+ final File rootFile = new File(subTree.myRootDir.getPath());
+ FileUtil.delete(rootFile);
+ FileUtil.delete(new File(myWorkingCopyDir.getPath() + File.separator + ".svn"));
+ Assert.assertTrue(!rootFile.exists());
+ sleep(200);
+ myWorkingCopyDir.refresh(false, true);
+
+ runInAndVerifyIgnoreOutput("co", mainUrl);
+ final File sourceDir = new File(myWorkingCopyDir.getPath(), "source");
+ final File innerDir = new File(sourceDir, "inner1/inner2/inner");
+ runInAndVerifyIgnoreOutput("co", externalURL, innerDir.getPath());
+ sleep(100);
+ myWorkingCopyDir.refresh(false, true);
+ // above is preparation
+
+ // start change list manager again
+ clManager.forceGoInTestMode();
+ refreshSvnMappingsSynchronously();
+ //clManager.ensureUpToDate(false);
+ //clManager.ensureUpToDate(false);
+ }
+
protected class SubTree {
public VirtualFile myRootDir;
public VirtualFile mySourceDir;
@@ -412,7 +450,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
//clManager.ensureUpToDate(false);
}
- private void createAnotherRepo() throws Exception {
+ protected void createAnotherRepo() throws Exception {
final File repo = FileUtil.createTempDirectory("anotherRepo", "");
FileUtil.delete(repo);
FileUtil.copyDir(myRepoRoot, repo);
@@ -547,4 +585,11 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
final ProcessOutput output = runner.runClient("svn", null, workingDir, input);
primitiveVerifier.process(output);
}
+
+ protected void setNativeAcceleration(final boolean value) {
+ System.out.println("Set native acceleration to " + value);
+ SvnConfiguration.getInstance(myProject).myUseAcceleration =
+ value ? SvnConfiguration.UseAcceleration.commandLine : SvnConfiguration.UseAcceleration.nothing;
+ SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn");
+ }
}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/QuickMergeTestInteraction.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/QuickMergeTestInteraction.java
new file mode 100644
index 000000000000..6336da4b0606
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/QuickMergeTestInteraction.java
@@ -0,0 +1,149 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.util.PairConsumer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.dialogs.LocalChangesAction;
+import org.jetbrains.idea.svn.dialogs.MergeDialogI;
+import org.jetbrains.idea.svn.dialogs.QuickMergeContentsVariants;
+import org.jetbrains.idea.svn.integrate.QuickMergeInteraction;
+import org.jetbrains.idea.svn.mergeinfo.MergeChecker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/27/13
+ * Time: 6:56 PM
+ */
+public class QuickMergeTestInteraction implements QuickMergeInteraction {
+ private QuickMergeContentsVariants myMergeVariant = QuickMergeContentsVariants.all;
+ private boolean myReintegrateAnswer = false;
+ private LocalChangesAction myLocalChangesAction = LocalChangesAction.continueMerge;
+ private QuickMergeContentsVariants mySelectMergeAction2ndStep = QuickMergeContentsVariants.all;
+
+ private final List<Exception> myExceptions;
+
+ public QuickMergeTestInteraction() {
+ myExceptions = new ArrayList<Exception>();
+ }
+
+ @Override
+ public void setTitle(@NotNull String title) {
+ }
+
+ @Override
+ public QuickMergeContentsVariants selectMergeVariant() {
+ return myMergeVariant;
+ }
+
+ public void setMergeVariant(QuickMergeContentsVariants mergeVariant) {
+ myMergeVariant = mergeVariant;
+ }
+
+ @Override
+ public boolean shouldContinueSwitchedRootFound() {
+ // not gonna test this at the moment
+ return false;
+ }
+
+ @Override
+ public boolean shouldReintegrate(@NotNull String sourceUrl, @NotNull String targetUrl) {
+ return myReintegrateAnswer;
+ }
+
+ public void setReintegrateAnswer(boolean reintegrateAnswer) {
+ myReintegrateAnswer = reintegrateAnswer;
+ }
+
+ public void setSelectMergeAction2ndStep(QuickMergeContentsVariants selectMergeAction2ndStep) {
+ mySelectMergeAction2ndStep = selectMergeAction2ndStep;
+ }
+
+ @NotNull
+ @Override
+ public SelectMergeItemsResult selectMergeItems(List<CommittedChangeList> lists, String mergeTitle, MergeChecker mergeChecker) {
+ return new SelectMergeItemsResult() {
+ @Override
+ public QuickMergeContentsVariants getResultCode() {
+ return mySelectMergeAction2ndStep;
+ }
+
+ @Override
+ public List<CommittedChangeList> getSelectedLists() {
+ return null;
+ }
+ };
+ }
+
+ @Override
+ public List<CommittedChangeList> showRecentListsForSelection(@NotNull List<CommittedChangeList> list,
+ @NotNull String mergeTitle,
+ @NotNull MergeChecker mergeChecker,
+ @NotNull PairConsumer<Long, MergeDialogI> loader,
+ boolean everyThingLoaded) {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public LocalChangesAction selectLocalChangesAction(boolean mergeAll) {
+ return myLocalChangesAction;
+ }
+
+ public void setLocalChangesAction(LocalChangesAction localChangesAction) {
+ myLocalChangesAction = localChangesAction;
+ }
+
+ @Override
+ public void showIntersectedLocalPaths(List<FilePath> paths) {
+ }
+
+ @Override
+ public void showError(@NotNull Exception exception) {
+ myExceptions.add(exception);
+ }
+
+ @Override
+ public void showErrors(String message, List<VcsException> exceptions) {
+ if (exceptions != null && ! exceptions.isEmpty()) {
+ myExceptions.addAll(exceptions);
+ return;
+ }
+ myExceptions.add(new RuntimeException(message));
+ }
+
+ @Override
+ public void showErrors(String message, boolean isError) {
+ if (isError) {
+ myExceptions.add(new RuntimeException(message));
+ } else {
+ System.out.println("merge warning: " + message);
+ }
+ }
+
+ public void throwIfExceptions() throws Exception {
+ for (Exception exception : myExceptions) {
+ throw exception;
+ }
+ }
+}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SSLExceptionParserTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SSLExceptionParserTest.java
new file mode 100644
index 000000000000..3e83843c7d7b
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SSLExceptionParserTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import org.jetbrains.idea.svn.networking.SSLProtocolExceptionParser;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.net.ssl.SSLProtocolException;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/25/13
+ * Time: 6:09 PM
+ */
+public class SSLExceptionParserTest {
+ @Test
+ public void testRealLifeCase() throws Exception {
+ final String original = "handshake alert: unrecognized_name";
+ final SSLProtocolException exception = new SSLProtocolException(original);
+ final SSLProtocolExceptionParser parser = new SSLProtocolExceptionParser(exception.getMessage());
+ parser.parse();
+ final String message = parser.getParsedMessage();
+ System.out.println(message);
+ Assert.assertNotSame(original, message);
+ }
+}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java
index e699a1a8069b..b6ffb7e7e7fb 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java
@@ -2,6 +2,7 @@ package org.jetbrains.idea.svn;
import com.intellij.openapi.vcs.VcsException;
import junit.framework.Assert;
+import org.jetbrains.idea.svn.commandLine.SvnCommandFactory;
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
import org.jetbrains.idea.svn.commandLine.SvnSimpleCommand;
import org.junit.Test;
@@ -24,7 +25,7 @@ public class SvnCommandLineStabilityTest extends Svn17TestCase {
}
private void call() throws VcsException {
- final SvnSimpleCommand command = new SvnSimpleCommand(myProject, new File(myWorkingCopyDir.getPath()), SvnCommandName.info);
+ final SvnSimpleCommand command = SvnCommandFactory.createSimpleCommand(myProject, new File(myWorkingCopyDir.getPath()), SvnCommandName.info);
command.addParameters("--xml");
final String result = command.run();
System.out.println(result);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommitTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommitTest.java
new file mode 100644
index 000000000000..f4da04ea201a
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommitTest.java
@@ -0,0 +1,492 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.*;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
+import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.NullableFunction;
+import junit.framework.Assert;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 2/28/13
+ * Time: 11:59 AM
+ */
+public class SvnCommitTest extends Svn17TestCase {
+ private SvnVcs myVcs;
+ private VcsDirtyScopeManager myDirtyScopeManager;
+ private ChangeListManager myChangeListManager;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ myVcs = SvnVcs.getInstance(myProject);
+ myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
+ myChangeListManager = ChangeListManager.getInstance(myProject);
+ }
+
+ @Test
+ public void testSimpleCommit() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ run2variants(new MyRunner() {
+ private String myName = "a.txt";
+
+ @Override
+ protected void run() throws Exception {
+ final VirtualFile file = createFileInCommand(myWorkingCopyDir, myName, "123");
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFile(file, FileStatus.ADDED);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ myName = "b.txt";
+ }
+ });
+ }
+
+ @Test
+ public void testCommitRename() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ run2variants(new MyRunner() {
+ private String myName = "a.txt";
+ private String myRenamedName = "aRenamed.txt";
+
+ @Override
+ protected void run() throws Exception {
+ final VirtualFile file = createFileInCommand(myWorkingCopyDir, myName, "123");
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFile(file, FileStatus.ADDED);
+
+ renameFileInCommand(file, myRenamedName);
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFile(file, FileStatus.MODIFIED);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ myName = "b.txt";
+ myRenamedName = "bRenamed.txt";
+ }
+ });
+ }
+
+ @Test
+ public void testRenameReplace() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ run2variants(new MyRunner() {
+ private String myName = "a.txt";
+ private String myName2 = "aRenamed.txt";
+
+ @Override
+ protected void run() throws Exception {
+ final VirtualFile file = createFileInCommand(myWorkingCopyDir, myName, "123");
+ final VirtualFile file2 = createFileInCommand(myWorkingCopyDir, myName2, "1235");
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(file, file2);
+
+ renameFileInCommand(file, file.getName() + "7.txt");
+ renameFileInCommand(file2, myName);
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(file, file2);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ myName = "b.txt";
+ myName2 = "bRenamed.txt";
+ }
+ });
+ }
+
+ @Test
+ public void testRenameFolder() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ run2variants(new MyRunner() {
+ private String folder = "f";
+
+ @Override
+ protected void run() throws Exception {
+ final VirtualFile dir = createDirInCommand(myWorkingCopyDir, folder);
+ final VirtualFile file = createFileInCommand(dir, "a.txt", "123");
+ final VirtualFile file2 = createFileInCommand(dir, "b.txt", "1235");
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(dir, file, file2);
+
+ renameFileInCommand(dir, dir.getName() + "dd");
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(dir, file, file2);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ folder = "f1";
+ }
+ });
+ }
+
+ @Test
+ public void testCommitDeletion() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
+ run2variants(new MyRunner() {
+ private String folder = "f";
+
+ @Override
+ protected void run() throws Exception {
+ final VirtualFile dir = createDirInCommand(myWorkingCopyDir, folder);
+ final VirtualFile file = createFileInCommand(dir, "a.txt", "123");
+ final VirtualFile file2 = createFileInCommand(dir, "b.txt", "1235");
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(dir, file, file2);
+
+ final FilePath dirPath = new FilePathImpl(new File(dir.getPath()), true);
+ deleteFileInCommand(dir);
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinPaths(dirPath);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ folder = "f1";
+ }
+ });
+ }
+
+ @Test
+ public void testSameRepoPlusInnerCopyCommitNative() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
+ prepareInnerCopy(false);
+ final MyRunner runner = new MyRunner() {
+ @Override
+ protected void run() throws Exception {
+ final File file1 = new File(myWorkingCopyDir.getPath(), "source/s1.txt");
+ final File fileInner = new File(myWorkingCopyDir.getPath(), "source/inner1/inner2/inner/t11.txt");
+
+ Assert.assertTrue(file1.exists());
+ Assert.assertTrue(fileInner.exists());
+ final VirtualFile vf1 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file1);
+ final VirtualFile vf2 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fileInner);
+ Assert.assertNotNull(vf1);
+ Assert.assertNotNull(vf2);
+
+ editFileInCommand(vf1, "2317468732ghdwwe7y348rf");
+ editFileInCommand(vf2, "2317468732ghdwwe7y348rf csdjcjksw");
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ final HashSet<String> strings = checkinFiles(vf1, vf2);
+ System.out.println("" + StringUtil.join(strings, "\n"));
+ Assert.assertEquals(1, strings.size());
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ }
+ };
+ setNativeAcceleration(true);
+ runner.run();
+ }
+
+ @Test
+ public void testSameRepoPlusInnerCopyCommitSvnkit() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
+ prepareInnerCopy(false);
+ final MyRunner runner = new MyRunner() {
+ @Override
+ protected void run() throws Exception {
+ final File file1 = new File(myWorkingCopyDir.getPath(), "source/s1.txt");
+ final File fileInner = new File(myWorkingCopyDir.getPath(), "source/inner1/inner2/inner/t11.txt");
+
+ Assert.assertTrue(file1.exists());
+ Assert.assertTrue(fileInner.exists());
+ final VirtualFile vf1 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file1);
+ final VirtualFile vf2 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fileInner);
+ Assert.assertNotNull(vf1);
+ Assert.assertNotNull(vf2);
+
+ editFileInCommand(vf1, "2317468732ghdwwe7y348rf");
+ editFileInCommand(vf2, "2317468732ghdwwe7y348rf csdjcjksw");
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ final HashSet<String> strings = checkinFiles(vf1, vf2);
+ System.out.println("" + StringUtil.join(strings, "\n"));
+ Assert.assertEquals(1, strings.size());
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ }
+ };
+ setNativeAcceleration(true);
+ runner.run();
+ }
+
+ @Test
+ public void testAnotherRepoPlusInnerCopyCommitNative() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
+ prepareInnerCopy(true);
+ final MyRunner runner = new MyRunner() {
+ @Override
+ protected void run() throws Exception {
+ final File file1 = new File(myWorkingCopyDir.getPath(), "source/s1.txt");
+ final File fileInner = new File(myWorkingCopyDir.getPath(), "source/inner1/inner2/inner/t11.txt");
+
+ Assert.assertTrue(file1.exists());
+ Assert.assertTrue(fileInner.exists());
+ final VirtualFile vf1 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file1);
+ final VirtualFile vf2 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fileInner);
+ Assert.assertNotNull(vf1);
+ Assert.assertNotNull(vf2);
+
+ editFileInCommand(vf1, "2317468732ghdwwe7y348rf");
+ editFileInCommand(vf2, "2317468732ghdwwe7y348rf csdjcjksw");
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(vf1, vf2);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ }
+ };
+ setNativeAcceleration(true);
+ runner.run();
+ }
+
+ @Test
+ public void testAnotherRepoPlusInnerCopyCommitSvnkit() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
+ prepareInnerCopy(true);
+ final MyRunner runner = new MyRunner() {
+ @Override
+ protected void run() throws Exception {
+ final File file1 = new File(myWorkingCopyDir.getPath(), "source/s1.txt");
+ final File fileInner = new File(myWorkingCopyDir.getPath(), "source/inner1/inner2/inner/t11.txt");
+
+ Assert.assertTrue(file1.exists());
+ Assert.assertTrue(fileInner.exists());
+ final VirtualFile vf1 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file1);
+ final VirtualFile vf2 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fileInner);
+ Assert.assertNotNull(vf1);
+ Assert.assertNotNull(vf2);
+
+ editFileInCommand(vf1, "2317468732ghdwwe7y348rf");
+ editFileInCommand(vf2, "2317468732ghdwwe7y348rf csdjcjksw");
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(vf1, vf2);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ }
+ };
+ setNativeAcceleration(true);
+ runner.run();
+ }
+
+ @Test
+ public void testPlusExternalCopyCommitNative() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
+ prepareExternal();
+ final MyRunner runner = new MyRunner() {
+ @Override
+ protected void run() throws Exception {
+ final File file1 = new File(myWorkingCopyDir.getPath(), "source/s1.txt");
+ final File fileInner = new File(myWorkingCopyDir.getPath(), "source/external/t11.txt");
+
+ Assert.assertTrue(file1.exists());
+ Assert.assertTrue(fileInner.exists());
+ final VirtualFile vf1 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file1);
+ final VirtualFile vf2 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fileInner);
+ Assert.assertNotNull(vf1);
+ Assert.assertNotNull(vf2);
+
+ editFileInCommand(vf1, "2317468732ghdwwe7y348rf");
+ editFileInCommand(vf2, "2317468732ghdwwe7y348rf csdjcjksw");
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(vf1, vf2);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ }
+ };
+ setNativeAcceleration(true);
+ runner.run();
+ }
+
+ @Test
+ public void testPlusExternalCopyCommitSvnkit() throws Exception {
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
+ enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
+ prepareExternal();
+ final MyRunner runner = new MyRunner() {
+ @Override
+ protected void run() throws Exception {
+ final File file1 = new File(myWorkingCopyDir.getPath(), "source/s1.txt");
+ final File fileInner = new File(myWorkingCopyDir.getPath(), "source/external/t11.txt");
+
+ Assert.assertTrue(file1.exists());
+ Assert.assertTrue(fileInner.exists());
+ final VirtualFile vf1 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file1);
+ final VirtualFile vf2 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fileInner);
+ Assert.assertNotNull(vf1);
+ Assert.assertNotNull(vf2);
+
+ editFileInCommand(vf1, "2317468732ghdwwe7y348rf");
+ editFileInCommand(vf2, "2317468732ghdwwe7y348rf csdjcjksw");
+
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ checkinFiles(vf1, vf2);
+ }
+
+ @Override
+ protected void cleanup() throws Exception {
+ }
+ };
+ setNativeAcceleration(false);
+ runner.run();
+ }
+
+ private void checkinPaths(FilePath... files) {
+ final List<Change> changes = new ArrayList<Change>();
+ for (FilePath file : files) {
+ final Change change = myChangeListManager.getChange(file);
+ Assert.assertNotNull(change);
+ changes.add(change);
+ }
+ final List<VcsException> exceptions = myVcs.getCheckinEnvironment().commit(changes, "test comment list");
+ Assert.assertTrue(exceptions == null || exceptions.isEmpty());
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ for (FilePath file : files) {
+ final Change changeA = myChangeListManager.getChange(file);
+ Assert.assertNull(changeA);
+ }
+ }
+
+ private HashSet<String> checkinFiles(VirtualFile... files) {
+ final List<Change> changes = new ArrayList<Change>();
+ for (VirtualFile file : files) {
+ final Change change = myChangeListManager.getChange(file);
+ Assert.assertNotNull(change);
+ changes.add(change);
+ }
+ final HashSet<String> feedback = new HashSet<String>();
+ final List<VcsException> exceptions = myVcs.getCheckinEnvironment().commit(changes, "test comment list",
+ new NullableFunction<Object, Object>() {
+ @Nullable
+ @Override
+ public Object fun(Object o) {
+ return null;
+ }
+ }, feedback);
+ if (exceptions !=null && ! exceptions.isEmpty()) {
+ exceptions.get(0).printStackTrace();
+ }
+ Assert.assertTrue(exceptions == null || exceptions.isEmpty());
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ for (VirtualFile file : files) {
+ final Change changeA = myChangeListManager.getChange(file);
+ Assert.assertNull(changeA);
+ }
+ return feedback;
+ }
+
+ private void checkinFile(VirtualFile file, FileStatus status) {
+ final Change change = myChangeListManager.getChange(file);
+ Assert.assertNotNull(change);
+ Assert.assertEquals(status, change.getFileStatus());
+ final List<VcsException> exceptions = myVcs.getCheckinEnvironment().commit(Collections.singletonList(change), "test comment");
+ Assert.assertTrue(exceptions == null || exceptions.isEmpty());
+ myDirtyScopeManager.markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+ final Change changeA = myChangeListManager.getChange(file);
+ Assert.assertNull(changeA);
+ }
+
+ protected void run2variants(final MyRunner runner) throws Exception {
+ setNativeAcceleration(false);
+ runner.run();
+ runner.cleanup();
+ setNativeAcceleration(true);
+ runner.run();
+ }
+
+ private static abstract class MyRunner {
+ protected abstract void run() throws Exception;
+ protected abstract void cleanup() throws Exception;
+ }
+}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java
index 177f608ea768..500acbdff4c9 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalTests.java
@@ -91,31 +91,8 @@ public class SvnExternalTests extends Svn17TestCase {
Assert.assertTrue(expectedUrls.isEmpty());
}
- private void prepareInnerCopy() throws Exception {
- final SubTree subTree = new SubTree(myWorkingCopyDir);
- checkin();
- clManager.stopEveryThingIfInTestMode();
- sleep(100);
- final File rootFile = new File(subTree.myRootDir.getPath());
- FileUtil.delete(rootFile);
- FileUtil.delete(new File(myWorkingCopyDir.getPath() + File.separator + ".svn"));
- Assert.assertTrue(!rootFile.exists());
- sleep(200);
- myWorkingCopyDir.refresh(false, true);
-
- runInAndVerifyIgnoreOutput("co", myMainUrl);
- final File sourceDir = new File(myWorkingCopyDir.getPath(), "source");
- final File innerDir = new File(sourceDir, "inner1/inner2/inner");
- runInAndVerifyIgnoreOutput("co", myExternalURL, innerDir.getPath());
- sleep(100);
- myWorkingCopyDir.refresh(false, true);
- // above is preparation
-
- // start change list manager again
- clManager.forceGoInTestMode();
- refreshSvnMappingsSynchronously();
- //clManager.ensureUpToDate(false);
- //clManager.ensureUpToDate(false);
+ protected void prepareInnerCopy() throws Exception {
+ prepareInnerCopy(false);
}
@Test
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
new file mode 100644
index 000000000000..61aca5670867
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
@@ -0,0 +1,630 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.*;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.CurrentContentRevision;
+import com.intellij.openapi.vcs.update.SequentialUpdatesContext;
+import com.intellij.openapi.vcs.update.UpdateSession;
+import com.intellij.openapi.vcs.update.UpdatedFiles;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.Convertor;
+import junit.framework.Assert;
+import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
+import org.junit.Before;
+import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.auth.*;
+import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/4/13
+ * Time: 9:55 PM
+ */
+public class SvnNativeClientAuthTest extends Svn17TestCase {
+ private SvnVcs myVcs;
+ private int myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY;
+ private boolean myCredentialsCorrect = true;
+ private boolean mySaveCredentials = false;
+ private boolean myCancelAuth = false;
+
+ private String outHttpUser = "test";
+ private String outHttpPassword = "test";
+
+ private final static String ourHTTP_URL = "http://svnsrvtest/stuff/autoTest";
+ private final static String ourHTTPS_URL = "https://svnsrvtest:443/TestSSL/autoTest";
+
+ private int myCertificateAskedInteractivelyCount = 0;
+ private int myCredentialsAskedInteractivelyCount = 0;
+
+ private int myExpectedCreds = 0;
+ private int myExpectedCert = 0;
+ private boolean myIsSecure;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ final File certFile = new File(myPluginRoot, myTestDataDir + "/svn/____.pfx");
+ setNativeAcceleration(true);
+ myVcs = SvnVcs.getInstance(myProject);
+ // replace authentication provider so that pass credentials without dialogs
+ final SvnConfiguration configuration = SvnConfiguration.getInstance(myProject);
+ final File svnconfig = FileUtil.createTempDirectory("svnconfig", "");
+ configuration.setConfigurationDirParameters(false, svnconfig.getPath());
+
+ final SvnAuthenticationManager interactiveManager = configuration.getInteractiveManager(myVcs);
+ final SvnTestInteractiveAuthentication authentication = new SvnTestInteractiveAuthentication(interactiveManager) {
+ @Override
+ public int acceptServerAuthentication(SVNURL url, String realm, Object certificate, boolean resultMayBeStored) {
+ ++ myCertificateAskedInteractivelyCount;
+ return myCertificateAnswer;
+ }
+
+ @Override
+ public SVNAuthentication requestClientAuthentication(String kind,
+ SVNURL url,
+ String realm,
+ SVNErrorMessage errorMessage,
+ SVNAuthentication previousAuth,
+ boolean authMayBeStored) {
+ if (myCancelAuth) return null;
+ return super.requestClientAuthentication(kind, url, realm, errorMessage, previousAuth, authMayBeStored);
+ }
+ };
+ interactiveManager.setAuthenticationProvider(authentication);
+
+ final SvnAuthenticationManager manager = configuration.getAuthenticationManager(myVcs);
+ // will be the same as in interactive -> authentication notifier is not used
+ manager.setAuthenticationProvider(authentication);
+
+ authentication.addAuthentication(ISVNAuthenticationManager.PASSWORD,
+ new Convertor<SVNURL, SVNAuthentication>() {
+ @Override
+ public SVNAuthentication convert(SVNURL o) {
+ ++ myCredentialsAskedInteractivelyCount;
+ if (myCancelAuth) return null;
+ if (myCredentialsCorrect) {
+ return new SVNPasswordAuthentication(outHttpUser, outHttpPassword, mySaveCredentials, o, false);
+ } else {
+ myCredentialsCorrect = true;// only once
+ return new SVNPasswordAuthentication("1234214 23 4234", "324324", mySaveCredentials, o, false);
+ }
+ }
+ });
+ authentication.addAuthentication(ISVNAuthenticationManager.SSL,
+ new Convertor<SVNURL, SVNAuthentication>() {
+ @Override
+ public SVNAuthentication convert(SVNURL o) {
+ ++ myCredentialsAskedInteractivelyCount;
+ if (myCancelAuth) return null;
+ if (myCredentialsCorrect) {
+ return new SVNSSLAuthentication(certFile, "12345", mySaveCredentials, o, false);
+ } else {
+ myCredentialsCorrect = true;// only once
+ return new SVNSSLAuthentication(new File("1232432423"), "3245321532534235445", mySaveCredentials, o, false);
+ }
+ }
+ });
+ myCertificateAskedInteractivelyCount = 0;
+ myCredentialsAskedInteractivelyCount = 0;
+ }
+
+ @Test
+ public void testTmpHttpUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTP_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testTmpSSLUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testPermanentSSLUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = true;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testPermanentHttpUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTP_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = true;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testTmpHttpCommit() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTP_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ // credentials are cached now only
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testTmpSSLCommit() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testPermanentSSLCommit() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = true;
+
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ @Test
+ public void test2PermanentSSLCommit() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = true;
+ myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED;
+
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testMixedSSLCommit() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+ myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED;
+
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ //------------
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+ mySaveCredentials = true;
+ myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY;
+
+ testCommitImpl(wc1);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ testCommitImpl(wc1);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testPermanentHttpCommit() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTP_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = true;
+
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ // credentials are cached now only
+ testCommitImpl(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testFailedThenSuccessTmpHttpUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTP_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+ myCredentialsCorrect = false;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testFailedThenSuccessTmpSSLUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+ myCredentialsCorrect = false;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ // credentials wrong, but certificate was ok accepted
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testCertificateRejectedThenCredentialsFailedThenSuccessTmpSSLUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+ myCertificateAnswer = ISVNAuthenticationProvider.REJECTED;
+
+ updateExpectAuthCanceled(wc1, "Authentication canceled");
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY;
+ myCredentialsCorrect = false;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ // credentials wrong, but certificate was ok accepted
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testCanceledThenFailedThenSuccessTmpHttpUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTP_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+ myCredentialsCorrect = false;
+ myCancelAuth = true;
+ updateExpectAuthCanceled(wc1, "Authentication canceled");
+ myCancelAuth = false;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ }
+
+ @Test
+ public void testCanceledThenFailedThenSuccessTmpSSLUpdate() throws Exception {
+ final File wc1 = testCheckoutImpl(ourHTTPS_URL);
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
+ instance.clearAuthenticationDirectory(myProject);
+ instance.clearRuntimeStorage();
+
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ mySaveCredentials = false;
+ myCredentialsCorrect = false;
+ myCancelAuth = true;
+ updateExpectAuthCanceled(wc1, "Authentication canceled");
+ myCancelAuth = false;
+
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+
+ // credentials are cached now only
+ updateSimple(wc1);
+
+ //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
+ //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
+ }
+
+ private File testCommitImpl(File wc1) throws IOException {
+ Assert.assertTrue(wc1.isDirectory());
+ final File file = FileUtil.createTempFile(wc1, "file", ".txt");
+ final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+ Assert.assertNotNull(vf);
+ final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
+ files.add(vf);
+ final List<VcsException> exceptions = myVcs.getCheckinEnvironment().scheduleUnversionedFilesForAddition(files);
+ Assert.assertTrue(exceptions.isEmpty());
+
+ final Change change = new Change(null, new CurrentContentRevision(new FilePathImpl(vf)));
+ final List<VcsException> commit = myVcs.getCheckinEnvironment().commit(Collections.singletonList(change), "commit");
+ Assert.assertTrue(commit.isEmpty());
+ ++ myExpectedCreds;
+ ++ myExpectedCert;
+ return file;
+ }
+
+ private File testCheckoutImpl(final String url) throws IOException {
+ final File root = FileUtil.createTempDirectory("checkoutRoot", "");
+ root.deleteOnExit();
+ Assert.assertTrue(root.exists());
+ SvnCheckoutProvider
+ .checkout(myProject, root, url, SVNRevision.HEAD, SVNDepth.INFINITY, false, new CheckoutProvider.Listener() {
+ @Override
+ public void directoryCheckedOut(File directory, VcsKey vcs) {
+ }
+
+ @Override
+ public void checkoutCompleted() {
+ }
+ }, WorkingCopyFormat.ONE_DOT_SEVEN);
+ final int[] cnt = new int[1];
+ cnt[0] = 0;
+ FileUtil.processFilesRecursively(root, new Processor<File>() {
+ @Override
+ public boolean process(File file) {
+ ++ cnt[0];
+ return ! (cnt[0] > 1);
+ }
+ });
+ Assert.assertTrue(cnt[0] > 1);
+ myIsSecure = url.contains("https:");
+ if (myIsSecure) {
+ ++ myExpectedCreds;
+ ++ myExpectedCert;
+ }
+ ProjectLevelVcsManager.getInstance(myProject).setDirectoryMapping(root.getPath(), SvnVcs.VCS_NAME);
+ refreshSvnMappingsSynchronously();
+ return root;
+ }
+
+ private void updateExpectAuthCanceled(File wc1, String expectedText) {
+ Assert.assertTrue(wc1.isDirectory());
+ final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(wc1);
+ final UpdatedFiles files = UpdatedFiles.create();
+ final UpdateSession session =
+ myVcs.getUpdateEnvironment().updateDirectories(new FilePath[]{new FilePathImpl(vf)}, files, new EmptyProgressIndicator(),
+ new Ref<SequentialUpdatesContext>());
+ Assert.assertTrue(session.getExceptions() != null && ! session.getExceptions().isEmpty());
+ Assert.assertTrue(!session.isCanceled());
+ Assert.assertTrue(session.getExceptions().get(0).getMessage().contains(expectedText));
+
+ if (myIsSecure) {
+ ++ myExpectedCreds;
+ ++ myExpectedCert;
+ }
+ }
+
+ private void updateSimple(File wc1) {
+ Assert.assertTrue(wc1.isDirectory());
+ final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(wc1);
+ final UpdatedFiles files = UpdatedFiles.create();
+ final UpdateSession session =
+ myVcs.getUpdateEnvironment().updateDirectories(new FilePath[]{new FilePathImpl(vf)}, files, new EmptyProgressIndicator(),
+ new Ref<SequentialUpdatesContext>());
+ Assert.assertTrue(session.getExceptions() == null || session.getExceptions().isEmpty());
+ Assert.assertTrue(!session.isCanceled());
+ if (myIsSecure) {
+ ++ myExpectedCreds;
+ ++ myExpectedCert;
+ }
+ }
+
+ private void testBrowseRepositoryImpl(final String url) throws SVNException {
+ final List<SVNDirEntry> list = new ArrayList<SVNDirEntry>();
+ final SVNRepository repository = myVcs.createRepository(url);
+ repository.getDir(".", -1, null, new ISVNDirEntryHandler() {
+ @Override
+ public void handleDirEntry(SVNDirEntry dirEntry) throws SVNException {
+ list.add(dirEntry);
+ }
+ });
+
+ Assert.assertTrue(!list.isEmpty());
+ }
+
+ private static @interface Test {}
+}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java
index 3870bd3c6142..5bf5d7651f94 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java
@@ -611,7 +611,8 @@ public class SvnParseCommandLineParseTest extends TestCase {
}
private String changePathsIfNix(String s) {
- s = StringUtil.replace(s, "\\", "/");
+ if (SystemInfo.isWindows) return s;
+ s = FileUtil.toSystemIndependentName(s);
return StringUtil.replace(s, "C:/", LINUX_ROOT);
}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java
new file mode 100644
index 000000000000..d7b48df7b479
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java
@@ -0,0 +1,510 @@
+/*
+ * 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 org.jetbrains.idea.svn;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.FileStatus;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
+import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.PairConsumer;
+import com.intellij.util.SmartList;
+import com.intellij.util.concurrency.Semaphore;
+import com.intellij.util.continuation.ContinuationContext;
+import com.intellij.util.continuation.TaskDescriptor;
+import com.intellij.util.continuation.Where;
+import junit.framework.Assert;
+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.SvnBranchConfigurationNew;
+import org.jetbrains.idea.svn.dialogs.MergeDialogI;
+import org.jetbrains.idea.svn.dialogs.QuickMerge;
+import org.jetbrains.idea.svn.dialogs.QuickMergeContentsVariants;
+import org.jetbrains.idea.svn.dialogs.WCInfo;
+import org.jetbrains.idea.svn.integrate.SvnBranchItem;
+import org.jetbrains.idea.svn.mergeinfo.MergeChecker;
+import org.junit.Before;
+import org.junit.Test;
+import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
+import org.tmatesoft.svn.core.wc.SVNInfo;
+import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: Irina.Chernushina
+ * Date: 3/27/13
+ * Time: 12:58 PM
+ */
+public class SvnQuickMergeTest extends Svn17TestCase {
+ private SvnVcs myVcs;
+ private String myBranchUrl;
+ private File myBranchRoot;
+ private VirtualFile myBranchVf;
+ private SubTree myBranchTree;
+ private ChangeListManager myChangeListManager;
+ private SvnTestCase.SubTree myTree;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ myVcs = SvnVcs.getInstance(myProject);
+ myChangeListManager = ChangeListManager.getInstance(myProject);
+ myBranchUrl = prepareBranchesStructure();
+ myBranchRoot = new File(myTempDirFixture.getTempDirPath(), "b1");
+
+ runInAndVerifyIgnoreOutput("co", myBranchUrl, myBranchRoot.getPath());
+ Assert.assertTrue(myBranchRoot.exists());
+ myBranchVf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(myBranchRoot);
+ Assert.assertNotNull(myBranchVf);
+
+ myBranchTree = new SubTree(myBranchVf);
+ myTree = new SubTree(myWorkingCopyDir);
+
+ final SvnBranchConfigurationManager branchConfigurationManager = SvnBranchConfigurationManager.getInstance(myProject);
+ final SvnBranchConfigurationNew configuration = new SvnBranchConfigurationNew();
+ configuration.setTrunkUrl(myRepoUrl + "/trunk");
+ configuration.addBranches(myRepoUrl + "/branches",
+ new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty));
+ branchConfigurationManager.setConfiguration(myWorkingCopyDir, configuration);
+
+ //((ApplicationImpl) ApplicationManager.getApplication()).setRunPooledInTest(true);
+
+ runInAndVerifyIgnoreOutput(new File(myWorkingCopyDir.getPath()), "up");
+ Thread.sleep(10);
+ }
+
+ @Test
+ public void testSimpleMergeAllFromB1ToTrunk() throws Exception {
+ editFileInCommand(myProject, myBranchTree.myS1File, "edited in branch");
+ runInAndVerifyIgnoreOutput(myBranchRoot, "ci", "-m", "change in branch", myBranchTree.myS1File.getPath());
+
+ final WCInfo found = getWcInfo();
+ final QuickMerge quickMerge =
+ new QuickMerge(myProject, myBranchUrl, found, SVNPathUtil.tail(myBranchUrl), myWorkingCopyDir);
+ // by default merges all
+ final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction() {
+ @Override
+ public boolean shouldReintegrate(@NotNull String sourceUrl, @NotNull String targetUrl) {
+ return true;
+ }
+ };
+ final WaitingTaskDescriptor descriptor = new WaitingTaskDescriptor();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ quickMerge.execute(testInteraction, descriptor);
+ }
+ });
+ descriptor.waitForCompletion();
+ testInteraction.throwIfExceptions();
+
+ Assert.assertTrue(descriptor.isCompleted());
+
+ VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ // should have changed svn:mergeinfo on wc root and s1 file
+ final Change fileChange = myChangeListManager.getChange(myTree.myS1File);
+ Assert.assertNotNull(fileChange);
+ Assert.assertEquals(FileStatus.MODIFIED, fileChange.getFileStatus());
+
+ final Change dirChange = myChangeListManager.getChange(myWorkingCopyDir);
+ Assert.assertNotNull(dirChange);
+ Assert.assertEquals(FileStatus.MODIFIED, dirChange.getFileStatus());
+ }
+
+ // if we create branches like this:
+ // trunk -> b1, b1->b2, b2->b3, b1->b4, then we should be able to merge between b1 and b2. some time before we had bug with it
+ @Test
+ public void testMergeBetweenDifferentTimeCreatedBranches() throws Exception {
+ // b1 -> b2
+ runInAndVerifyIgnoreOutput("copy", "-q", "-m", "copy1", myBranchUrl, myRepoUrl + "/branches/b2");
+ // b2 -> b3
+ runInAndVerifyIgnoreOutput("copy", "-q", "-m", "copy1", myRepoUrl + "/branches/b2", myRepoUrl + "/branches/b3");
+ // b1 -> b4
+ runInAndVerifyIgnoreOutput("copy", "-q", "-m", "copy1", myBranchUrl, myRepoUrl + "/branches/b4");
+
+ testSimpleMergeAllFromB1ToTrunk();
+ }
+
+ @Test
+ public void testSelectRevisionsWithQuickSelectCheckForLocalChanges() throws Exception {
+ // get revision #
+ final SVNInfo info = myVcs.createWCClient().doInfo(new File(myBranchTree.myS1File.getPath()), SVNRevision.WORKING);
+ Assert.assertNotNull(info);
+
+ final long numberBefore = info.getRevision().getNumber();
+ final int totalChanges = 3;
+
+ final StringBuilder sb = new StringBuilder(FileUtil.loadFile(new File(myBranchTree.myS1File.getPath())));
+ for (int i = 0; i < totalChanges; i++) {
+ sb.append("\nedited in branch ").append(i);
+ editFileInCommand(myProject, myBranchTree.myS1File, sb.toString());
+ runInAndVerifyIgnoreOutput(myBranchRoot, "ci", "-m", "change in branch " + i, myBranchTree.myS1File.getPath());
+ Thread.sleep(10);
+ }
+
+ // we should get exactly 2 revisions for selection (copy and change in b2)
+ final WCInfo found = getWcInfo();
+ final QuickMerge quickMerge =
+ new QuickMerge(myProject, myBranchUrl, found, SVNPathUtil.tail(myBranchUrl), myWorkingCopyDir);
+ // by default merges all
+ final AtomicReference<String> selectionError = new AtomicReference<String>();
+ final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction() {
+ @Override
+ public boolean shouldReintegrate(@NotNull String sourceUrl, @NotNull String targetUrl) {
+ return true;
+ }
+
+ @Override
+ public List<CommittedChangeList> showRecentListsForSelection(@NotNull List<CommittedChangeList> list,
+ @NotNull String mergeTitle,
+ @NotNull MergeChecker mergeChecker,
+ @NotNull PairConsumer<Long, MergeDialogI> loader,
+ boolean everyThingLoaded) {
+ if (list.size() != 4) {
+ selectionError.set("List size: " + list.size());
+ } else if (list.get(3).getNumber() != numberBefore) {
+ selectionError.set("wrong revision for copy statement: " + list.get(3).getNumber());
+ }
+ return new SmartList<CommittedChangeList>(list.get(2)); // get a change
+ }
+ };
+ testInteraction.setMergeVariant(QuickMergeContentsVariants.showLatest);
+ final WaitingTaskDescriptor descriptor = new WaitingTaskDescriptor();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ quickMerge.execute(testInteraction, descriptor);
+ }
+ });
+ descriptor.waitForCompletion();
+ testInteraction.throwIfExceptions();
+ if (selectionError.get() != null){
+ throw new RuntimeException(selectionError.get());
+ }
+
+ Assert.assertTrue(descriptor.isCompleted());
+
+ VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ // should have changed svn:mergeinfo on wc root and s1 file
+ final Change fileChange = myChangeListManager.getChange(myTree.myS1File);
+ Assert.assertNotNull(fileChange);
+ Assert.assertEquals(FileStatus.MODIFIED, fileChange.getFileStatus());
+
+ final Change dirChange = myChangeListManager.getChange(myWorkingCopyDir);
+ Assert.assertNotNull(dirChange);
+ Assert.assertEquals(FileStatus.MODIFIED, dirChange.getFileStatus());
+
+ final SVNPropertyData data = myVcs.createWCClient()
+ .doGetProperty(new File(myWorkingCopyDir.getPath()), "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING);
+ System.out.println(data.getValue().getString());
+ Assert.assertEquals("/branches/b1:" + (numberBefore + 1), data.getValue().getString());
+ }
+
+ // this test is mainly to check revisions selection. at the moment we are not sure whether we support
+ // trunk->b1->b2 merges between trunk and b2
+ @Test
+ public void testSelectRevisionsWithQuickSelect() throws Exception {
+ // get revision #
+ final SVNInfo info = myVcs.createWCClient().doInfo(new File(myBranchTree.myS1File.getPath()), SVNRevision.WORKING);
+ Assert.assertNotNull(info);
+
+ final long numberBefore = info.getRevision().getNumber();
+ final int totalChanges = 3;
+
+ final StringBuilder sb = new StringBuilder(FileUtil.loadFile(new File(myBranchTree.myS1File.getPath())));
+ for (int i = 0; i < totalChanges; i++) {
+ sb.append("\nedited in branch ").append(i);
+ editFileInCommand(myProject, myBranchTree.myS1File, sb.toString());
+ runInAndVerifyIgnoreOutput(myBranchRoot, "ci", "-m", "change in branch " + i, myBranchTree.myS1File.getPath());
+ Thread.sleep(10);
+ }
+
+ // before copy
+ final SVNInfo info2 = myVcs.createWCClient().doInfo(new File(myBranchTree.myS1File.getPath()), SVNRevision.WORKING);
+ Assert.assertNotNull(info2);
+ final long numberBeforeCopy = info2.getRevision().getNumber();
+
+ runInAndVerifyIgnoreOutput("copy", "-q", "-m", "copy1", myBranchUrl, myRepoUrl + "/branches/b2");
+
+ // switch b1 to b2
+ runInAndVerifyIgnoreOutput(myBranchRoot, "switch", myRepoUrl + "/branches/b2", myBranchRoot.getPath());
+ myBranchTree = new SubTree(myBranchVf); //reload
+
+ // one commit in b2 in s2 file
+ editFileInCommand(myProject, myBranchTree.myS2File, "completely changed");
+ runInAndVerifyIgnoreOutput(myBranchRoot, "ci", "-m", "change in b2", myBranchTree.myS2File.getPath());
+
+ // we should get exactly 2 revisions for selection (copy and change in b2)
+ final WCInfo found = getWcInfo();
+ final QuickMerge quickMerge =
+ new QuickMerge(myProject, myRepoUrl + "/branches/b2", found, SVNPathUtil.tail(myRepoUrl + "/branches/b2"), myWorkingCopyDir);
+ // by default merges all
+ final AtomicReference<String> selectionError = new AtomicReference<String>();
+ final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction() {
+ @Override
+ public boolean shouldReintegrate(@NotNull String sourceUrl, @NotNull String targetUrl) {
+ return true;
+ }
+
+ @Override
+ public List<CommittedChangeList> showRecentListsForSelection(@NotNull List<CommittedChangeList> list,
+ @NotNull String mergeTitle,
+ @NotNull MergeChecker mergeChecker,
+ @NotNull PairConsumer<Long, MergeDialogI> loader,
+ boolean everyThingLoaded) {
+ if (list.size() != 2) {
+ selectionError.set("List size: " + list.size());
+ } else if (list.get(1).getNumber() != numberBeforeCopy + 1) {
+ selectionError.set("wrong revision for copy statement: " + list.get(1).getNumber());
+ }
+ return new SmartList<CommittedChangeList>(list.get(0)); // get a change
+ }
+ };
+ testInteraction.setMergeVariant(QuickMergeContentsVariants.showLatest);
+ final WaitingTaskDescriptor descriptor = new WaitingTaskDescriptor();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ quickMerge.execute(testInteraction, descriptor);
+ }
+ });
+ descriptor.waitForCompletion();
+ testInteraction.throwIfExceptions();
+ if (selectionError.get() != null){
+ throw new RuntimeException(selectionError.get());
+ }
+
+ Assert.assertTrue(descriptor.isCompleted());
+
+ VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ // should have changed svn:mergeinfo on wc root and s1 file
+ final Change fileChange = myChangeListManager.getChange(myTree.myS2File);
+ Assert.assertNotNull(fileChange);
+ Assert.assertEquals(FileStatus.MODIFIED, fileChange.getFileStatus());
+
+ final Change dirChange = myChangeListManager.getChange(myWorkingCopyDir);
+ Assert.assertNotNull(dirChange);
+ Assert.assertEquals(FileStatus.MODIFIED, dirChange.getFileStatus());
+
+ final SVNPropertyData data = myVcs.createWCClient()
+ .doGetProperty(new File(myWorkingCopyDir.getPath()), "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING);
+ System.out.println(data.getValue().getString());
+ Assert.assertEquals("/branches/b2:" + (numberBeforeCopy + 2), data.getValue().getString());
+ }
+
+ @Test
+ public void testSelectRevisions() throws Exception {
+ // get revision #
+ final SVNInfo info = myVcs.createWCClient().doInfo(new File(myBranchTree.myS1File.getPath()), SVNRevision.WORKING);
+ Assert.assertNotNull(info);
+
+ final long numberBefore = info.getRevision().getNumber();
+ final int totalChanges = 10;
+
+ final StringBuilder sb = new StringBuilder(FileUtil.loadFile(new File(myBranchTree.myS1File.getPath())));
+ for (int i = 0; i < totalChanges; i++) {
+ sb.append("\nedited in branch ").append(i);
+ editFileInCommand(myProject, myBranchTree.myS1File, sb.toString());
+ runInAndVerifyIgnoreOutput(myBranchRoot, "ci", "-m", "change in branch " + i, myBranchTree.myS1File.getPath());
+ Thread.sleep(10);
+ }
+
+ final WCInfo found = getWcInfo();
+ final QuickMerge quickMerge =
+ new QuickMerge(myProject, myBranchUrl, found, SVNPathUtil.tail(myBranchUrl), myWorkingCopyDir);
+ // by default merges all
+ final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction() {
+ @Override
+ public boolean shouldReintegrate(@NotNull String sourceUrl, @NotNull String targetUrl) {
+ return true;
+ }
+
+ @NotNull
+ @Override
+ public SelectMergeItemsResult selectMergeItems(final List<CommittedChangeList> lists,
+ String mergeTitle,
+ MergeChecker mergeChecker) {
+ return new SelectMergeItemsResult() {
+ @Override
+ public QuickMergeContentsVariants getResultCode() {
+ return QuickMergeContentsVariants.select;
+ }
+
+ @Override
+ public List<CommittedChangeList> getSelectedLists() {
+ final List<CommittedChangeList> result = new ArrayList<CommittedChangeList>();
+ for (CommittedChangeList list : lists) {
+ if (numberBefore + 1 == list.getNumber() || numberBefore + 2 == list.getNumber()) {
+ result.add(list);
+ }
+ }
+ return result;
+ }
+ };
+ }
+ };
+ testInteraction.setMergeVariant(QuickMergeContentsVariants.select);
+ final WaitingTaskDescriptor descriptor = new WaitingTaskDescriptor();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ quickMerge.execute(testInteraction, descriptor);
+ }
+ });
+ descriptor.waitForCompletion();
+ testInteraction.throwIfExceptions();
+
+ Assert.assertTrue(descriptor.isCompleted());
+
+ VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ // should have changed svn:mergeinfo on wc root and s1 file
+ final Change fileChange = myChangeListManager.getChange(myTree.myS1File);
+ Assert.assertNotNull(fileChange);
+ Assert.assertEquals(FileStatus.MODIFIED, fileChange.getFileStatus());
+
+ final Change dirChange = myChangeListManager.getChange(myWorkingCopyDir);
+ Assert.assertNotNull(dirChange);
+ Assert.assertEquals(FileStatus.MODIFIED, dirChange.getFileStatus());
+
+ final SVNPropertyData data = myVcs.createWCClient()
+ .doGetProperty(new File(myWorkingCopyDir.getPath()), "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING);
+ System.out.println(data.getValue().getString());
+ Assert.assertEquals("/branches/b1:" + (numberBefore + 1) + "-" + (numberBefore + 2), data.getValue().getString());
+ }
+
+ private WCInfo getWcInfo() {
+ WCInfo found = null;
+ final File workingIoFile = new File(myWorkingCopyDir.getPath());
+ final List<WCInfo> infos = myVcs.getAllWcInfos();
+ for (WCInfo info : infos) {
+ if (FileUtil.filesEqual(workingIoFile, new File(info.getPath()))) {
+ found = info;
+ break;
+ }
+ }
+ Assert.assertNotNull(found);
+ return found;
+ }
+
+ @Test
+ public void testSimpleMergeFromTrunkToB1() throws Exception {
+ // change in trunk
+ editFileInCommand(myProject, myTree.myS1File, "903403240328");
+ final File workingIoFile = new File(myWorkingCopyDir.getPath());
+ runInAndVerifyIgnoreOutput(workingIoFile, "ci", "-m", "change in trunk", myTree.myS1File.getPath());
+
+ final String trunkUrl = myRepoUrl + "/trunk";
+ // switch this copy to b1
+ runInAndVerifyIgnoreOutput(workingIoFile, "switch", myBranchUrl, workingIoFile.getPath());
+ myTree = new SubTree(myWorkingCopyDir); //reload
+
+ refreshSvnMappingsSynchronously();
+ final WCInfo found = getWcInfo();
+ final QuickMerge quickMerge =
+ new QuickMerge(myProject, trunkUrl, found, SVNPathUtil.tail(trunkUrl), myWorkingCopyDir);
+ // by default merges all
+ final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction();
+ final WaitingTaskDescriptor descriptor = new WaitingTaskDescriptor();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ quickMerge.execute(testInteraction, descriptor);
+ }
+ });
+ descriptor.waitForCompletion();
+ testInteraction.throwIfExceptions();
+
+ Assert.assertTrue(descriptor.isCompleted());
+
+ VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
+ myChangeListManager.ensureUpToDate(false);
+
+ // should have changed svn:mergeinfo on wc root and s1 file
+ final Change fileChange = myChangeListManager.getChange(myTree.myS1File);
+ Assert.assertNotNull(fileChange);
+ Assert.assertEquals(FileStatus.MODIFIED, fileChange.getFileStatus());
+
+ final Change dirChange = myChangeListManager.getChange(myWorkingCopyDir);
+ Assert.assertNotNull(dirChange);
+ Assert.assertEquals(FileStatus.MODIFIED, dirChange.getFileStatus());
+ }
+
+ private static class WaitingTaskDescriptor extends TaskDescriptor {
+ private static final long TEST_TIMEOUT = TimeUnit.MINUTES.toMillis(200);
+ private final Semaphore mySemaphore;
+ private volatile boolean myCompleted = false;
+ private volatile boolean myCanceled = false;
+
+ public WaitingTaskDescriptor() {
+ super("waiting", Where.POOLED);
+ mySemaphore = new Semaphore();
+ mySemaphore.down();
+ }
+
+ // will survive in Continuation if cancel occurred
+ @Override
+ public boolean isHaveMagicCure() {
+ return true;
+ }
+
+ @Override
+ public void run(ContinuationContext context) {
+ myCompleted = true;
+ mySemaphore.up();
+ }
+
+ public void waitForCompletion() {
+ mySemaphore.waitFor(TEST_TIMEOUT);
+ }
+
+ @Override
+ public void canceled() {
+ myCanceled = true;
+ mySemaphore.up();
+ }
+
+ private boolean isCompleted() {
+ return myCompleted;
+ }
+
+ private boolean isCanceled() {
+ return myCanceled;
+ }
+ }
+}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnRenameTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnRenameTest.java
index 486d97823815..c86ed0cc04aa 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnRenameTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnRenameTest.java
@@ -284,6 +284,7 @@ public class SvnRenameTest extends Svn17TestCase {
// IDEA-13824
@Test
public void testRenameFileRenameDir() throws Exception {
+ setNativeAcceleration(true); //todo debug
final VirtualFile child = prepareDirectoriesForRename();
final VirtualFile f = child.findChild("a.txt");
renameFileInCommand(f, "anew.txt");
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java
index 079ca66955d8..b686c94df7e4 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java
@@ -121,6 +121,7 @@ public class SvnExternalCommitNoticedTest extends Svn17TestCase {
runInAndVerifyIgnoreOutput("switch", branchUrl + "/root/source/s1.txt", tree.myS1File.getPath());
runInAndVerifyIgnoreOutput("switch", branchUrl + "/root/target", tree.myTargetDir.getPath());
+ sleep(50);
myWorkingCopyDir.refresh(false, true);
imitateEvent(myWorkingCopyDir);
// no dirty scope externally provided! just VFS refresh
diff --git a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java
index 02e3d431ce25..91763014b989 100644
--- a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java
+++ b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java
@@ -8,7 +8,6 @@ import com.intellij.openapi.util.KeyValue;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.tasks.LocalTask;
import com.intellij.tasks.Task;
-import com.intellij.tasks.TaskRepository;
import com.intellij.tasks.TaskState;
import com.intellij.tasks.impl.BaseRepositoryImpl;
import com.intellij.util.Function;
@@ -99,12 +98,7 @@ public class JiraRepository extends BaseRepositoryImpl {
LOG.info("JIRA: " + children.size() + " issues found");
final List<Task> tasks = ContainerUtil.map(children, new Function<Element, Task>() {
public Task fun(Element o) {
- return new JiraTask(new JIRAIssueBean(getUrl(), o, false)) {
- @Override
- public TaskRepository getRepository() {
- return JiraRepository.this;
- }
- };
+ return new JiraTask(new JIRAIssueBean(getUrl(), o, false), JiraRepository.this);
}
});
return tasks.toArray(new Task[tasks.size()]);
diff --git a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java
index e73a4616d5fd..804df7524513 100644
--- a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java
+++ b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java
@@ -19,10 +19,7 @@ package com.intellij.tasks.jira;
import com.atlassian.theplugin.idea.jira.CachedIconLoader;
import com.atlassian.theplugin.jira.api.JIRAComment;
import com.atlassian.theplugin.jira.api.JIRAIssue;
-import com.intellij.tasks.Comment;
-import com.intellij.tasks.Task;
-import com.intellij.tasks.TaskState;
-import com.intellij.tasks.TaskType;
+import com.intellij.tasks.*;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import icons.JiraConnectorIcons;
@@ -43,9 +40,11 @@ import java.util.Locale;
class JiraTask extends Task {
private final JIRAIssue myJiraIssue;
+ private final TaskRepository myRepository;
- public JiraTask(JIRAIssue jiraIssue) {
+ public JiraTask(JIRAIssue jiraIssue, TaskRepository repository) {
myJiraIssue = jiraIssue;
+ myRepository = repository;
}
@NotNull
@@ -153,4 +152,10 @@ class JiraTask extends Task {
public String getIssueUrl() {
return myJiraIssue.getIssueUrl();
}
+
+ @Nullable
+ @Override
+ public TaskRepository getRepository() {
+ return myRepository;
+ }
}
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java
index 415055a78d6f..c561c2e74c72 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java
@@ -77,6 +77,7 @@ public abstract class Task {
@Nullable
public abstract String getIssueUrl();
+ // todo it should be abstract @NotNull method
@Nullable
public TaskRepository getRepository() {
return null;
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java
index 9aaa0319ca64..915f96d31aa6 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.tasks.config.TaskRepositoryEditor;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.EnumSet;
@@ -39,6 +40,9 @@ public abstract class TaskRepositoryType<T extends TaskRepository> {
@NotNull
public abstract Icon getIcon();
+ @Nullable
+ public String getAdvertiser() { return null; }
+
@NotNull
public abstract TaskRepositoryEditor createEditor(T repository, Project project, Consumer<T> changeListener);
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form
index 4a6e4699f89c..a4acc2a2f8b2 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.form
@@ -3,7 +3,7 @@
<grid id="27dc6" binding="myPanel" 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>
- <xy x="20" y="20" width="552" height="306"/>
+ <xy x="20" y="20" width="473" height="308"/>
</constraints>
<properties/>
<border type="none"/>
@@ -144,6 +144,16 @@
</constraints>
<properties/>
</component>
+ <component id="8235d" class="javax.swing.JTextPane" binding="myAdvertiser">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <editable value="false"/>
+ <enabled value="true"/>
+ <text value="Not YouTrack customer yet? Get YouTrack"/>
+ </properties>
+ </component>
</children>
</grid>
<grid id="3d7e" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
index 7745a72f0c98..39f12a6435ed 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
import com.intellij.tasks.TaskManager;
import com.intellij.tasks.TaskRepository;
import com.intellij.tasks.impl.BaseRepository;
@@ -65,6 +66,7 @@ public class BaseRepositoryEditor<T extends BaseRepository> extends TaskReposito
private JPanel myEditorPanel;
protected JBCheckBox myLoginAnonymouslyJBCheckBox;
protected JBTabbedPane myTabbedPane;
+ private JTextPane myAdvertiser;
private boolean myApplying;
protected Project myProject;
@@ -115,6 +117,14 @@ public class BaseRepositoryEditor<T extends BaseRepository> extends TaskReposito
myEditor = EditorFactory.getInstance().createEditor(myDocument);
myEditorPanel.add(myEditor.getComponent(), BorderLayout.CENTER);
myComment.setText("Available placeholders: " + repository.getComment());
+ String advertiser = repository.getRepositoryType().getAdvertiser();
+ if (advertiser != null) {
+ Messages.installHyperlinkSupport(myAdvertiser);
+ myAdvertiser.setText(advertiser);
+ }
+ else {
+ myAdvertiser.setVisible(false);
+ }
installListener(myAddCommitMessage);
installListener(myDocument);
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/ShowTaskDescription.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/ShowTaskDescription.java
index d0cca68e03d9..bd8e2f83b94a 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/ShowTaskDescription.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/ShowTaskDescription.java
@@ -20,8 +20,6 @@ import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.project.DumbService;
-import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiManager;
import com.intellij.tasks.LocalTask;
@@ -51,16 +49,12 @@ public class ShowTaskDescription extends BaseTaskAction {
final Project project = getProject(e);
assert project != null;
final LocalTask task = getActiveTask(e);
- try {
- FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.quickjavadoc.ctrln");
- CommandProcessor.getInstance().executeCommand(project, new Runnable() {
- public void run() {
- DocumentationManager.getInstance(project).showJavaDocInfo(new TaskPsiElement(PsiManager.getInstance(project), task), null);
- }
- }, getCommandName(), null);
- } catch (IndexNotReadyException e1) {
- DumbService.getInstance(project).showDumbModeNotification("Documentation is not available until indices are built");
- }
+ FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.quickjavadoc.ctrln");
+ CommandProcessor.getInstance().executeCommand(project, new Runnable() {
+ public void run() {
+ DocumentationManager.getInstance(project).showJavaDocInfo(new TaskPsiElement(PsiManager.getInstance(project), task), null);
+ }
+ }, getCommandName(), null);
}
protected String getCommandName() {
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java
index 30ec06962558..8cbbc79f1b76 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java
@@ -146,7 +146,7 @@ public class SwitchTaskAction extends BaseTaskAction {
if (tasks.size() == 1 && task != null) {
group.add(new AnAction("&Switch to") {
public void actionPerformed(AnActionEvent e) {
- manager.activateTask(task, !shiftPressed.get(), false);
+ manager.activateTask(task, !shiftPressed.get(), true);
}
});
}
@@ -201,7 +201,7 @@ public class SwitchTaskAction extends BaseTaskAction {
group.add(new TaskListItem(task, group.size() == 1 ? "" : null, false) {
@Override
void select() {
- manager.activateTask(task, !shiftPressed.get(), false);
+ manager.activateTask(task, !shiftPressed.get(), true);
}
});
}
@@ -212,7 +212,7 @@ public class SwitchTaskAction extends BaseTaskAction {
group.add(new TaskListItem(task, i == 0 ? "Recently Closed Tasks" : null, true) {
@Override
void select() {
- manager.activateTask(task, !shiftPressed.get(), false);
+ manager.activateTask(task, !shiftPressed.get(), true);
}
});
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
index c411c50eb19d..ab4744b2b65a 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
@@ -16,6 +16,9 @@
package com.intellij.tasks.context;
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -36,6 +39,7 @@ import org.jdom.output.XMLOutputter;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import java.io.File;
import java.io.IOException;
@@ -112,9 +116,10 @@ public class WorkingContextManager {
saveContext(entryName, CONTEXT_ZIP_POSTFIX, comment);
}
- private void saveContext(@Nullable String entryName, String zipPostfix, @Nullable String comment) {
+ private synchronized void saveContext(@Nullable String entryName, String zipPostfix, @Nullable String comment) {
+ JBZipFile archive = null;
try {
- JBZipFile archive = getTasksArchive(zipPostfix);
+ archive = getTasksArchive(zipPostfix);
if (entryName == null) {
int i = archive.getEntries().size();
do {
@@ -128,15 +133,38 @@ public class WorkingContextManager {
Element element = new Element("context");
saveContext(element);
String s = new XMLOutputter().outputString(element);
- entry.setData(s.getBytes());
- archive.close();
+ entry.setData(s.getBytes("UTF-8"));
}
catch (IOException e) {
LOG.error(e);
}
+ finally {
+ closeArchive(archive);
+ }
}
private JBZipFile getTasksArchive(String postfix) throws IOException {
+ File file = getArchiveFile(postfix);
+ try {
+ return new JBZipFile(file);
+ }
+ catch (IOException e) {
+ file.delete();
+ JBZipFile zipFile = null;
+ try {
+ zipFile = new JBZipFile(file);
+ Notifications.Bus.notify(new Notification("Tasks", "Context Data Corrupted",
+ "Context information history for " + myProject.getName() + " was corrupted.\n" +
+ "The history was replaced with empty one.", NotificationType.ERROR), myProject);
+ }
+ catch (IOException e1) {
+ LOG.error("Can't repair form context data corruption", e1);
+ }
+ return zipFile;
+ }
+ }
+
+ private File getArchiveFile(String postfix) {
String configPath = PathManager.getConfigPath(true);
File tasksFolder = new File(configPath, TASKS_FOLDER);
if (!tasksFolder.exists()) {
@@ -144,39 +172,54 @@ public class WorkingContextManager {
tasksFolder.mkdir();
}
String projectName = myProject.getName();
- return new JBZipFile(new File(tasksFolder, projectName + postfix));
+ return new File(tasksFolder, projectName + postfix);
}
public void restoreContext(@NotNull Task task) {
loadContext(TASKS_ZIP_POSTFIX, task.getId() + TASK_XML_POSTFIX);
}
- private boolean loadContext(String zipPostfix, String entryName) {
+ private synchronized boolean loadContext(String zipPostfix, String entryName) {
+ JBZipFile archive = null;
try {
- JBZipFile archive = getTasksArchive(zipPostfix);
+ archive = getTasksArchive(zipPostfix);
JBZipEntry entry = archive.getEntry(StringUtil.startsWithChar(entryName, '/') ? entryName : "/" + entryName);
if (entry != null) {
byte[] bytes = entry.getData();
Document document = JDOMUtil.loadDocument(new String(bytes));
Element rootElement = document.getRootElement();
loadContext(rootElement);
- archive.close();
return true;
}
}
catch (Exception e) {
LOG.error(e);
}
+ finally {
+ closeArchive(archive);
+ }
return false;
}
+ private static void closeArchive(JBZipFile archive) {
+ if (archive != null) {
+ try {
+ archive.close();
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+ }
+
public List<ContextInfo> getContextHistory() {
return getContextHistory(CONTEXT_ZIP_POSTFIX);
}
- private List<ContextInfo> getContextHistory(String zipPostfix) {
+ private synchronized List<ContextInfo> getContextHistory(String zipPostfix) {
+ JBZipFile archive = null;
try {
- JBZipFile archive = getTasksArchive(zipPostfix);
+ archive = getTasksArchive(zipPostfix);
List<JBZipEntry> entries = archive.getEntries();
return ContainerUtil.mapNotNull(entries, new NullableFunction<JBZipEntry, ContextInfo>() {
public ContextInfo fun(JBZipEntry entry) {
@@ -188,6 +231,9 @@ public class WorkingContextManager {
LOG.error(e);
return Collections.emptyList();
}
+ finally {
+ closeArchive(archive);
+ }
}
public boolean loadContext(String name) {
@@ -203,17 +249,20 @@ public class WorkingContextManager {
}
private void removeContext(String name, String postfix) {
+ JBZipFile archive = null;
try {
- JBZipFile archive = getTasksArchive(postfix);
+ archive = getTasksArchive(postfix);
JBZipEntry entry = archive.getEntry(name);
if (entry != null) {
archive.eraseEntry(entry);
}
- archive.close();
}
catch (IOException e) {
LOG.error(e);
}
+ finally {
+ closeArchive(archive);
+ }
}
public void pack(int max, int delta) {
@@ -221,9 +270,10 @@ public class WorkingContextManager {
pack(max, delta, TASKS_ZIP_POSTFIX);
}
- private void pack(int max, int delta, String zipPostfix) {
+ private synchronized void pack(int max, int delta, String zipPostfix) {
+ JBZipFile archive = null;
try {
- JBZipFile archive = getTasksArchive(zipPostfix);
+ archive = getTasksArchive(zipPostfix);
List<JBZipEntry> entries = archive.getEntries();
if (entries.size() > max + delta) {
JBZipEntry[] array = entries.toArray(new JBZipEntry[entries.size()]);
@@ -232,11 +282,17 @@ public class WorkingContextManager {
archive.eraseEntry(array[i]);
}
}
- archive.close();
}
catch (IOException e) {
LOG.error(e);
}
+ finally {
+ closeArchive(archive);
+ }
+ }
+ @TestOnly
+ public File getContextFile() throws IOException {
+ return getArchiveFile(CONTEXT_ZIP_POSTFIX);
}
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/fogbugz/FogBugzRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/fogbugz/FogBugzRepository.java
index 983db33e690a..ed5f8852e7d4 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/fogbugz/FogBugzRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/fogbugz/FogBugzRepository.java
@@ -17,10 +17,7 @@ package com.intellij.tasks.fogbugz;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.tasks.Comment;
-import com.intellij.tasks.Task;
-import com.intellij.tasks.TaskRepositoryType;
-import com.intellij.tasks.TaskType;
+import com.intellij.tasks.*;
import com.intellij.tasks.impl.BaseRepository;
import com.intellij.tasks.impl.BaseRepositoryImpl;
import com.intellij.util.NotNullFunction;
@@ -211,6 +208,12 @@ public class FogBugzRepository extends BaseRepositoryImpl {
public String getIssueUrl() {
return getUrl() + "/default.asp?" + getId();
}
+
+ @Nullable
+ @Override
+ public TaskRepository getRepository() {
+ return FogBugzRepository.this;
+ }
};
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java
index ff823a60e1e9..6cf5f1e8f235 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java
@@ -1,13 +1,17 @@
package com.intellij.tasks.generic;
+import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.XmlElementFactory;
+import com.intellij.psi.xml.XmlTag;
import com.intellij.tasks.Task;
import com.intellij.tasks.TaskRepositoryType;
import com.intellij.tasks.actions.TaskSearchSupport;
import com.intellij.tasks.impl.BaseRepositoryImpl;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.annotations.Tag;
+import com.intellij.xml.util.XmlUtil;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
@@ -76,15 +80,19 @@ public class GenericRepository extends BaseRepositoryImpl {
if (!isLoginAnonymously() && !isUseHttpAuthentication()) login(httpClient);
- final List<String> placeholders = getPlaceholders(getTaskPattern());
- if (!placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) {
- throw new Exception("Incorrect Task Pattern");
- }
-
final HttpMethod method = getTaskListsMethod(query != null ? query : "", max);
httpClient.executeMethod(method);
if (method.getStatusCode() != 200) throw new Exception("Cannot get tasks: HTTP status code " + method.getStatusCode());
final String response = method.getResponseBodyAsString();
+ return parseResponse(query, max, response);
+ }
+
+ public Task[] parseResponse(String query, int max, String response) throws Exception {
+
+ final List<String> placeholders = getPlaceholders(getTaskPattern());
+ if (!placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) {
+ throw new Exception("Incorrect Task Pattern");
+ }
final String taskPatternWithoutPlaceholders = getTaskPattern().replaceAll("\\{.+?\\}", "");
Matcher matcher = Pattern
@@ -94,8 +102,12 @@ public class GenericRepository extends BaseRepositoryImpl {
List<Task> tasks = new ArrayList<Task>();
while (matcher.find()) {
- final String id = matcher.group(placeholders.indexOf(ID_PLACEHOLDER) + 1);
- final String summary = matcher.group(placeholders.indexOf(SUMMARY_PLACEHOLDER) + 1);
+ String id = matcher.group(placeholders.indexOf(ID_PLACEHOLDER) + 1);
+ String summary = matcher.group(placeholders.indexOf(SUMMARY_PLACEHOLDER) + 1);
+ if (myResponseType == ResponseType.XML && summary != null) {
+ XmlTag text = XmlElementFactory.getInstance(ProjectManager.getInstance().getDefaultProject()).createTagFromText("<a>" + summary + "</a>");
+ summary = XmlUtil.decode(text.getValue().getTrimmedText());
+ }
tasks.add(new GenericTask(id, summary, this));
}
@@ -232,12 +244,6 @@ public class GenericRepository extends BaseRepositoryImpl {
return answer;
}
- @Nullable
- @Override
- public String getTaskComment(final Task task) {
- return super.getTaskComment(task);
- }
-
public String getLoginURL() {
return myLoginURL;
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
index bd04257be74f..dea1205e56dc 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
@@ -52,6 +52,7 @@ import com.intellij.util.xmlb.annotations.Tag;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import javax.swing.Timer;
import javax.swing.event.HyperlinkEvent;
@@ -143,7 +144,14 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
myChangeListListener = new ChangeListAdapter() {
@Override
public void changeListRemoved(ChangeList list) {
- disassociateFromTask((LocalChangeList)list);
+ LocalTask task = getAssociatedTask((LocalChangeList)list);
+ if (task != null) {
+ for (ChangeListInfo info : task.getChangeLists()) {
+ if (Comparing.equal(info.id, ((LocalChangeList)list).getId())) {
+ info.id = "";
+ }
+ }
+ }
}
@Override
@@ -348,14 +356,15 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
if (!isVcsEnabled()) return;
List<ChangeListInfo> changeLists = task.getChangeLists();
if (!changeLists.isEmpty()) {
- String id = changeLists.get(0).id;
- LocalChangeList changeList = myChangeListManager.getChangeList(id);
- if (changeList != null) {
- myChangeListManager.setDefaultChangeList(changeList);
+ ChangeListInfo info = changeLists.get(0);
+ LocalChangeList changeList = myChangeListManager.getChangeList(info.id);
+ if (changeList == null) {
+ changeList = myChangeListManager.addChangeList(info.name, info.comment);
+ info.id = changeList.getId();
}
- return;
+ myChangeListManager.setDefaultChangeList(changeList);
}
- if (createChangelist) {
+ else if (createChangelist) {
String name = getChangelistName(origin);
String comment = TaskUtil.getChangeListComment(origin);
createChangeList(task, name, comment);
@@ -755,7 +764,16 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
@Override
public boolean isLocallyClosed(final LocalTask localTask) {
- return isVcsEnabled() && localTask.getChangeLists().isEmpty();
+ if (isVcsEnabled()) {
+ List<ChangeListInfo> lists = localTask.getChangeLists();
+ if (lists.isEmpty()) return true;
+ for (ChangeListInfo list : lists) {
+ if (StringUtil.isEmpty(list.id)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
@Nullable
@@ -829,11 +847,9 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe
return task.getSummary();
}
+ @TestOnly
public ChangeListAdapter getChangeListListener() {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- return myChangeListListener;
- }
- throw new UnsupportedOperationException();
+ return myChangeListListener;
}
public static class Config {
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java
index 92707d861fcd..3266f1c56500 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java
@@ -18,6 +18,7 @@ package com.intellij.tasks.trac;
import com.intellij.openapi.util.Comparing;
import com.intellij.tasks.Comment;
import com.intellij.tasks.Task;
+import com.intellij.tasks.TaskRepository;
import com.intellij.tasks.TaskType;
import com.intellij.tasks.impl.BaseRepository;
import com.intellij.tasks.impl.BaseRepositoryImpl;
@@ -118,7 +119,7 @@ public class TracRepository extends BaseRepositoryImpl {
}
@Nullable
- private static Task getTask(int id, XmlRpcClient client, Transport transport) throws IOException, XmlRpcException {
+ private Task getTask(int id, XmlRpcClient client, Transport transport) throws IOException, XmlRpcException {
XmlRpcRequest request = new XmlRpcRequest("ticket.get", new Vector(Arrays.asList(id)));
Object response = client.execute(request, transport);
if (response == null) return null;
@@ -194,6 +195,12 @@ public class TracRepository extends BaseRepositoryImpl {
public String getIssueUrl() {
return null;
}
+
+ @Nullable
+ @Override
+ public TaskRepository getRepository() {
+ return TracRepository.this;
+ }
};
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
index 0382c4a82147..6d16b395b27d 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
@@ -115,6 +115,9 @@ public class YouTrackRepository extends BaseRepositoryImpl {
}
private HttpClient login(PostMethod method) throws Exception {
+ if (method.getHostConfiguration().getProtocol() == null) {
+ throw new Exception("Protocol not specified");
+ }
HttpClient client = getHttpClient();
client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(getUsername(), getPassword()));
configureHttpMethod(method);
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryType.java
index 26877b8d022b..70bbd9507519 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryType.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryType.java
@@ -7,6 +7,7 @@ import com.intellij.tasks.impl.BaseRepositoryType;
import com.intellij.util.Consumer;
import icons.TasksIcons;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.EnumSet;
@@ -26,6 +27,12 @@ public class YouTrackRepositoryType extends BaseRepositoryType<YouTrackRepositor
return TasksIcons.Youtrack;
}
+ @Nullable
+ @Override
+ public String getAdvertiser() {
+ return "<html>Not YouTrack customer yet? Get <a href='http://www.jetbrains.com/youtrack/download/get_youtrack.html?idea_integration'>YouTrack</a></html>";
+ }
+
@NotNull
public YouTrackRepository createRepository() {
return new YouTrackRepository(this);
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUiTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUiTest.java
index afeadb7f9c71..e95af45e318e 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUiTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUiTest.java
@@ -19,7 +19,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.tasks.actions.SwitchTaskCombo;
import com.intellij.tasks.config.TaskSettings;
-import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.TestActionEvent;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
@@ -61,7 +61,13 @@ public class TaskUiTest extends CodeInsightFixtureTestCase {
assertTrue(task.isDefault());
presentation = doTest(combo);
- assertTrue(presentation.isVisible());
+ if (!presentation.isVisible()) {
+ LocalTask activeTask = manager.getActiveTask();
+ System.out.println(activeTask);
+ System.out.println(activeTask.getCreated());
+ System.out.println(activeTask.getUpdated());
+ fail();
+ }
}
private static Presentation doTest(AnAction action) {
@@ -72,6 +78,6 @@ public class TaskUiTest extends CodeInsightFixtureTestCase {
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
public TaskUiTest() {
- PlatformTestCase.initPlatformLangPrefix();
+ IdeaTestCase.initPlatformPrefix();
}
}
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java
index df86637fb2bb..40207a4be215 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java
@@ -15,12 +15,10 @@
*/
package com.intellij.tasks;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
-import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ChangeListManager;
-import com.intellij.openapi.vcs.changes.ChangeListManagerImpl;
-import com.intellij.openapi.vcs.changes.LocalChangeList;
+import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.committed.MockAbstractVcs;
import com.intellij.openapi.vcs.changes.ui.CommitChangeListDialog;
import com.intellij.openapi.vcs.impl.projectlevelman.AllVcses;
@@ -178,7 +176,7 @@ public class TaskVcsTest extends CodeInsightFixtureTestCase {
assertNotNull(anotherChangeList);
removeChangeList(anotherChangeList);
- assertEquals(0, anotherTask.getChangeLists().size());
+ assertEquals(1, anotherTask.getChangeLists().size());
assertEquals(1, defaultTask.getChangeLists().size());
assertEquals(1, myChangeListManager.getChangeListsCopy().size());
@@ -349,6 +347,25 @@ public class TaskVcsTest extends CodeInsightFixtureTestCase {
assertEquals(null, task.getProject());
}
+ public void testRestoreChangelist() throws Exception {
+ final LocalTaskImpl task = new LocalTaskImpl("foo", "bar");
+ myTaskManager.activateTask(task, true, true);
+ myTaskManager.activateTask(new LocalTaskImpl("next", ""), true, true);
+
+ final String changelistName = myTaskManager.getChangelistName(task);
+ myChangeListManager.removeChangeList(changelistName);
+
+ myChangeListManager.invokeAfterUpdate(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(myTaskManager.isLocallyClosed(task));
+ myTaskManager.activateTask(task, true, true);
+ assertNotNull(myChangeListManager.findChangeList(changelistName));
+ }
+ }, InvokeAfterUpdateMode.SYNCHRONOUS_NOT_CANCELLABLE, "foo", ModalityState.NON_MODAL);
+
+ }
+
private TestRepository myRepository;
private MockAbstractVcs myVcs;
@@ -364,8 +381,6 @@ public class TaskVcsTest extends CodeInsightFixtureTestCase {
myTaskManager = (TaskManagerImpl)TaskManager.getManager(getProject());
myTaskManager.projectOpened();
- myChangeListManager.removeChangeListListener(myTaskManager.getChangeListListener());
-
ProjectLevelVcsManager.getInstance(getProject()).setDirectoryMapping("", myVcs.getName());
ProjectLevelVcsManager.getInstance(getProject()).hasActiveVcss();
myRepository = new TestRepository();
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
index 9a56140acc28..d9471d75c047 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/context/ContextTest.java
@@ -16,8 +16,10 @@
package com.intellij.tasks.context;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.tasks.TaskManagerTestCase;
+import java.io.File;
import java.util.List;
/**
@@ -55,6 +57,15 @@ public class ContextTest extends TaskManagerTestCase {
assertEquals("/context2", history.get(0).name);
}
+ public void testContextFileRepair() throws Exception {
+ WorkingContextManager manager = getContextManager();
+ manager.saveContext("foo", "bar");
+ File file = manager.getContextFile();
+ assertTrue(file.length() > 0);
+ FileUtil.writeToFile(file, "123"); // corrupt it
+ manager.saveContext("foo", "bar");
+ }
+
private WorkingContextManager getContextManager() {
return WorkingContextManager.getInstance(getProject());
}
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java
new file mode 100644
index 000000000000..b7979309dbc4
--- /dev/null
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.tasks.integration;
+
+import com.intellij.tasks.Task;
+import com.intellij.tasks.TaskManagerTestCase;
+import com.intellij.tasks.generic.assembla.AssemblaRepository;
+import com.intellij.tasks.generic.assembla.AssemblaRepositoryType;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 4/1/13
+ */
+public class AssemblaIntegrationTest extends TaskManagerTestCase {
+
+ public void testParseCyrillic() throws Exception {
+
+ Task[] tasks = new AssemblaRepository(new AssemblaRepositoryType()).parseResponse("", 100, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<tickets type=\"array\">\n" +
+ "<ticket>\n" +
+ " <assigned-to-id>dsNkyYr0Gr4iEBeJe5cbCb</assigned-to-id>\n" +
+ " <completed-date type=\"datetime\"></completed-date>\n" +
+ " <component-id type=\"integer\"></component-id>\n" +
+ " <created-on type=\"datetime\">2013-04-01T10:45:06+03:00</created-on>\n" +
+ " <description></description>\n" +
+ " <from-support type=\"integer\">0</from-support>\n" +
+ " <id type=\"integer\">50351983</id>\n" +
+ " <importance type=\"integer\">-1</importance>\n" +
+ " <importance-float type=\"float\">-1.0</importance-float>\n" +
+ " <is-story type=\"boolean\">false</is-story>\n" +
+ " <milestone-id type=\"integer\"></milestone-id>\n" +
+ " <notification-list>dsNkyYr0Gr4iEBeJe5cbCb</notification-list>\n" +
+ " <number type=\"integer\">1</number>\n" +
+ " <priority type=\"integer\">3</priority>\n" +
+ " <reporter-id>dsNkyYr0Gr4iEBeJe5cbCb</reporter-id>\n" +
+ " <space-id>ab1WOCMQar4QGgacwqjQWU</space-id>\n" +
+ " <status type='integer'>0</status>\n" +
+ " <status-name>New</status-name>\n" +
+ " <story-importance type=\"integer\">0</story-importance>\n" +
+ " <summary>&#1055;&#1088;&#1080;&#1074;&#1077;&#1090;</summary>\n" +
+ " <updated-at type=\"datetime\">2013-04-01T10:48:19+03:00</updated-at>\n" +
+ " <working-hours type=\"float\">0.0</working-hours>\n" +
+ " <working-hour type=\"float\" warning=\"deprecated\">0.0</working-hour>\n" +
+ " <estimate type=\"string\">Small</estimate>\n" +
+ " <total-estimate type=\"float\">1.0</total-estimate>\n" +
+ " <invested-hours type=\"float\">0.0</invested-hours>\n" +
+ " <assigned-to><id>dsNkyYr0Gr4iEBeJe5cbCb</id><login>avdeev.dmitry</login><login_name warning=\"deprecated\">avdeev.dmitry</login_name><name>avdeev.dmitry</name></assigned-to>\n" +
+ " <reporter><id>dsNkyYr0Gr4iEBeJe5cbCb</id><login>avdeev.dmitry</login><login_name warning=\"deprecated\">avdeev.dmitry</login_name><name>avdeev.dmitry</name></reporter>\n" +
+ "</ticket>\n" +
+ "</tickets>");
+
+ assertEquals(1, tasks.length);
+ assertEquals("Привет", tasks[0].getSummary());
+ }
+}
diff --git a/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java
index 96d2e69f3e46..b78a24db5304 100644
--- a/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java
+++ b/plugins/tasks/tasks-time-tracking/src/com/intellij/tasks/timeTracking/TimeTrackingManager.java
@@ -76,16 +76,16 @@ public class TimeTrackingManager implements ProjectComponent, PersistentStateCom
toolWindow =
ToolWindowManager.getInstance(myProject).registerToolWindow(ToolWindowId.TASKS, true, ToolWindowAnchor.RIGHT, myProject, true);
new TasksToolWindowFactory().createToolWindowContent(myProject, toolWindow);
- final ToolWindow finalToolWindow = toolWindow;
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- finalToolWindow.setAvailable(true, null);
- finalToolWindow.show(null);
- finalToolWindow.activate(null);
- }
- });
}
+ final ToolWindow finalToolWindow = toolWindow;
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ finalToolWindow.setAvailable(true, null);
+ finalToolWindow.show(null);
+ finalToolWindow.activate(null);
+ }
+ });
}
else {
if (toolWindow != null) {
diff --git a/plugins/testng/src/com/theoryinpractice/testng/TestNGReferenceContributor.java b/plugins/testng/src/com/theoryinpractice/testng/TestNGReferenceContributor.java
index 6895ccd94f03..840dce8de9b6 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/TestNGReferenceContributor.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/TestNGReferenceContributor.java
@@ -26,8 +26,6 @@ import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.completion.CompletionUtil;
import com.intellij.codeInsight.lookup.LookupValueFactory;
import com.intellij.codeInspection.InspectionProfile;
-import com.intellij.codeInspection.InspectionProfileEntry;
-import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
@@ -248,8 +246,8 @@ public class TestNGReferenceContributor extends PsiReferenceContributor {
List<Object> list = new ArrayList<Object>();
InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
- final InspectionProfileEntry inspectionTool = inspectionProfile.getInspectionTool(DependsOnGroupsInspection.SHORT_NAME, myElement);
- DependsOnGroupsInspection inspection = (DependsOnGroupsInspection)((LocalInspectionToolWrapper)inspectionTool).getTool();
+ DependsOnGroupsInspection inspection = (DependsOnGroupsInspection)inspectionProfile.getUnwrappedTool(
+ DependsOnGroupsInspection.SHORT_NAME, myElement);
for (String groupName : inspection.groups) {
list.add(LookupValueFactory.createLookupValue(groupName, null));
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
index f850cb4ded69..9f4036f66584 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
@@ -57,6 +57,8 @@ import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
public class SearchingForTestsTask extends Task.Backgroundable {
private static final Logger LOG = Logger.getInstance("#" + SearchingForTestsTask.class.getName());
@@ -373,23 +375,57 @@ public class SearchingForTestsTask extends Task.Backgroundable {
return ClassUtil.findPsiClass(psiManager, className.replace('/', '.'), null, true, getSearchScope());
}
});
- if (psiClass == null) {
- throw new CantRunException("Class " + className + " not found");
+ if (psiClass != null) {
+ final Boolean hasTest = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ return TestNGUtil.hasTest(psiClass);
+ }
+ });
+ if (hasTest) {
+ if (StringUtil.isEmpty(methodName)) {
+ calculateDependencies(null, classes, psiClass);
+ }
+ else {
+ collectTestMethods(classes, psiClass, methodName);
+ }
+ } else {
+ throw new CantRunException("No tests found in class " + className);
+ }
}
- if (ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
- @Override
- public Boolean compute() {
- return TestNGUtil.hasTest(psiClass);
+ }
+ if (classes.size() != data.getPatterns().size()) {
+ TestSearchScope scope = myConfig.getPersistantData().getScope();
+ final List<Pattern> compilePatterns = new ArrayList<Pattern>();
+ for (String p : data.getPatterns()) {
+ final Pattern compilePattern;
+ try {
+ compilePattern = Pattern.compile(p);
}
- })) {
- if (StringUtil.isEmpty(methodName)) {
- calculateDependencies(null, classes, psiClass);
+ catch (PatternSyntaxException e) {
+ continue;
}
- else {
- collectTestMethods(classes, psiClass, methodName);
+ if (compilePattern != null) {
+ compilePatterns.add(compilePattern);
}
- } else {
- throw new CantRunException("No tests found in class " + className);
+ }
+ TestClassFilter projectFilter =
+ new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myProject, true, true){
+ @Override
+ public boolean isAccepted(PsiClass psiClass) {
+ if (super.isAccepted(psiClass)) {
+ final String qualifiedName = psiClass.getQualifiedName();
+ LOG.assertTrue(qualifiedName != null);
+ for (Pattern pattern : compilePatterns) {
+ if (pattern.matcher(qualifiedName).matches()) return true;
+ }
+ }
+ return false;
+ }
+ };
+ calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(projectFilter, false));
+ if (classes.size() == 0) {
+ throw new CantRunException("No tests found in for patterns \"" + StringUtil.join(data.getPatterns(), " || ") + '\"');
}
}
}
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java
index d2c33225f636..74edb5002935 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java
@@ -29,6 +29,7 @@ import com.intellij.execution.configurations.*;
import com.intellij.execution.junit.RefactoringListeners;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.testframework.SourceScope;
+import com.intellij.execution.testframework.TestSearchScope;
import com.intellij.execution.util.JavaParametersUtil;
import com.intellij.execution.util.ProgramParametersUtil;
import com.intellij.openapi.components.PathMacroManager;
@@ -39,7 +40,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.listeners.RefactoringElementAdapter;
@@ -47,7 +47,6 @@ import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.refactoring.listeners.UndoRefactoringElementListener;
import com.theoryinpractice.testng.model.TestData;
import com.theoryinpractice.testng.model.TestType;
-import com.theoryinpractice.testng.util.TestNGUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -275,6 +274,14 @@ public class TestNGConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
patterns.add(JavaExecutionUtil.getRuntimeQualifiedName(pattern) + suffix);
}
data.setPatterns(patterns);
+ final Module module = TestNGPatternConfigurationProducer.findModule(this, getConfigurationModule().getModule(), patterns);
+ if (module == null) {
+ data.setScope(TestSearchScope.WHOLE_PROJECT);
+ setModule(null);
+ }
+ else {
+ setModule(module);
+ }
setGeneratedName();
}
@@ -335,17 +342,6 @@ public class TestNGConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
if (patterns.isEmpty()) {
throw new RuntimeConfigurationWarning("No pattern selected");
}
- final GlobalSearchScope searchScope = GlobalSearchScope.allScope(getProject());
- for (String pattern : patterns) {
- final String className = pattern.contains(",") ? StringUtil.getPackageName(pattern, ',') : pattern;
- final PsiClass psiClass = JavaExecutionUtil.findMainClass(getProject(), className, searchScope);
- if (psiClass == null) {
- throw new RuntimeConfigurationWarning("Class " + className + " not found");
- }
- if (!TestNGUtil.hasTest(psiClass)) {
- throw new RuntimeConfigurationWarning("Class " + className + " not a test");
- }
- }
}
JavaRunConfigurationExtensionManager.checkConfigurationIsValid(this);
ProgramParametersUtil.checkWorkingDirectoryExist(this, getProject(), getConfigurationModule().getModule());
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
index 3f52715ee692..02caba250ac6 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
@@ -20,15 +20,19 @@
*/
package com.theoryinpractice.testng.configuration;
+import com.intellij.execution.JavaExecutionUtil;
import com.intellij.execution.JavaRunConfigurationExtensionManager;
import com.intellij.execution.Location;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ConfigurationContext;
+import com.intellij.execution.configurations.ModuleBasedConfiguration;
import com.intellij.execution.junit.JUnitUtil;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.theoryinpractice.testng.model.TestData;
import com.theoryinpractice.testng.model.TestType;
@@ -115,6 +119,21 @@ public class TestNGPatternConfigurationProducer extends TestNGConfigurationProdu
}
@Override
+ protected Module findModule(ModuleBasedConfiguration configuration, Module contextModule) {
+ final Set<String> patterns = ((TestNGConfiguration)configuration).data.getPatterns();
+ return findModule(configuration, contextModule, patterns);
+ }
+
+ public static Module findModule(ModuleBasedConfiguration configuration, Module contextModule, Set<String> patterns) {
+ return JavaExecutionUtil.findModule(contextModule, patterns, configuration.getProject(), new Condition<PsiClass>() {
+ @Override
+ public boolean value(PsiClass psiClass) {
+ return TestNGUtil.hasTest(psiClass);
+ }
+ });
+ }
+
+ @Override
protected RunnerAndConfigurationSettings findExistingByElement(@NotNull Location location,
@NotNull RunnerAndConfigurationSettings[] existingConfigurations,
ConfigurationContext context) {
diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGListenersTableModel.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGListenersTableModel.java
index da14fb0ecd15..3bebe8566e95 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGListenersTableModel.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGListenersTableModel.java
@@ -22,9 +22,9 @@
*/
package com.theoryinpractice.testng.model;
+import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
-import javax.swing.*;
public class TestNGListenersTableModel extends AbstractListModel
{
diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java
index 424a85a7ef00..e799929a5e01 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestProxy.java
@@ -79,7 +79,7 @@ public class TestProxy extends AbstractTestProxy {
if (psiElement != null) {
final Project project = psiElement.getProject();
PsiDocumentManager.getInstance(project).commitAllDocuments();
- this.psiElement = SmartPointerManager.getInstance(project).createLazyPointer(psiElement);
+ this.psiElement = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(psiElement);
} else {
this.psiElement = null;
}
diff --git a/plugins/ui-designer-core/src/META-INF/plugin.xml b/plugins/ui-designer-core/src/META-INF/plugin.xml
index adf91394abe6..18d7453c0226 100644
--- a/plugins/ui-designer-core/src/META-INF/plugin.xml
+++ b/plugins/ui-designer-core/src/META-INF/plugin.xml
@@ -22,4 +22,8 @@
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
</extensions>
+
+ <extensionPoints>
+ <extensionPoint qualifiedName="Designer.customizations" interface="com.intellij.designer.DesignerCustomizations"/>
+ </extensionPoints>
</idea-plugin>
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java
index 9d7d1c489330..fd0fbceee98a 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/AbstractToolWindowManager.java
@@ -111,6 +111,11 @@ public abstract class AbstractToolWindowManager implements ProjectComponent {
return null;
}
+ @Nullable
+ protected static DesignerCustomizations getCustomizations() {
+ return DesignerCustomizations.EP_NAME.findExtension(DesignerCustomizations.class);
+ }
+
private void bindToDesigner(final DesignerEditorPanel designer) {
myWindowQueue.cancelAllUpdates();
myWindowQueue.queue(new Update("update") {
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/DesignerCustomizations.java b/plugins/ui-designer-core/src/com/intellij/designer/DesignerCustomizations.java
new file mode 100644
index 000000000000..195d91e9012b
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/DesignerCustomizations.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class DesignerCustomizations {
+ public static final ExtensionPointName<DesignerCustomizations> EP_NAME = ExtensionPointName.create("Designer.customizations");
+
+ /**
+ * Default location of the palette
+ */
+ @NotNull
+ public ToolWindowAnchor getPaletteAnchor() {
+ return ToolWindowAnchor.RIGHT;
+ }
+
+ /**
+ * Default location of the designer/structure window
+ */
+ @NotNull
+ public ToolWindowAnchor getStructureAnchor() {
+ return ToolWindowAnchor.LEFT;
+ }
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java
index 6e8e76ba14e6..81e84153d586 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java
@@ -19,6 +19,7 @@ import com.intellij.designer.componentTree.ComponentTree;
import com.intellij.designer.componentTree.ComponentTreeBuilder;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.propertyTable.PropertyTablePanel;
+import com.intellij.designer.propertyTable.RadPropertyTable;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -78,6 +79,14 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager {
return project.getComponent(DesignerToolWindowManager.class);
}
+ public ComponentTree getComponentTree() {
+ return myComponentTree;
+ }
+
+ public RadPropertyTable getPropertyTable() {
+ return myPropertyTablePanel.getPropertyTable();
+ }
+
public void expandFromState() {
if (myTreeBuilder != null) {
myTreeBuilder.expandFromState();
@@ -146,9 +155,11 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager {
}
});
- myToolWindow =
- ToolWindowManager.getInstance(myProject)
- .registerToolWindow(DesignerBundle.message("designer.toolwindow.name"), false, ToolWindowAnchor.LEFT, myProject, true);
+ DesignerCustomizations customization = getCustomizations();
+ ToolWindowAnchor anchor = customization != null ? customization.getPaletteAnchor() : ToolWindowAnchor.LEFT;
+
+ myToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(DesignerBundle.message("designer.toolwindow.name"),
+ false, anchor, myProject, true);
myToolWindow.setIcon(UIDesignerNewIcons.ToolWindow);
myToolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true");
@@ -192,4 +203,4 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager {
public String getComponentName() {
return "UIDesignerToolWindowManager2";
}
-}
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.java
index 0043a617ce9d..e4a388a443f1 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.java
@@ -21,6 +21,7 @@ import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.designSurface.tools.ComponentPasteFactory;
import com.intellij.designer.designSurface.tools.PasteTool;
+import com.intellij.designer.model.IComponentDeletionParticipant;
import com.intellij.designer.model.IGroupDeleteComponent;
import com.intellij.designer.model.RadComponent;
import com.intellij.ide.CopyProvider;
@@ -40,6 +41,7 @@ import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.util.List;
+import java.util.Map;
/**
* @author Alexander Lobas
@@ -94,27 +96,56 @@ public class CommonEditActionsProvider implements DeleteProvider, CopyProvider,
}
myDesigner.getToolProvider().loadDefaultTool();
-
List<RadComponent> components = RadComponent.getPureSelection(selection);
+ updateSelectionBeforeDelete(area, components.get(0), selection);
+ handleDeletion(components);
+ }
+ }, DesignerBundle.message("command.delete.selection"), true);
+ }
- RadComponent newSelection = getNewSelection(components.get(0), selection);
- if (newSelection == null) {
- area.deselectAll();
- }
- else {
- area.select(newSelection);
- }
+ private static void handleDeletion(@NotNull List<RadComponent> components) throws Exception {
+ // Segment the deleted components into lists of siblings
+ Map<RadComponent, List<RadComponent>> siblingLists = RadComponent.groupSiblings(components);
+
+ // Notify parent components about children getting deleted
+ for (Map.Entry<RadComponent, List<RadComponent>> entry : siblingLists.entrySet()) {
+ RadComponent parent = entry.getKey();
+ List<RadComponent> children = entry.getValue();
+ boolean finished = false;
+ if (parent instanceof IComponentDeletionParticipant) {
+ IComponentDeletionParticipant handler = (IComponentDeletionParticipant)parent;
+ finished = handler.deleteChildren(parent, children);
+ }
+ else if (parent.getLayout() instanceof IComponentDeletionParticipant) {
+ IComponentDeletionParticipant handler = (IComponentDeletionParticipant)parent.getLayout();
+ finished = handler.deleteChildren(parent, children);
+ }
- if (components.get(0) instanceof IGroupDeleteComponent) {
- ((IGroupDeleteComponent)components.get(0)).delete(components);
- }
- else {
- for (RadComponent component : components) {
- component.delete();
- }
- }
+ if (!finished) {
+ deleteComponents(children);
}
- }, DesignerBundle.message("command.delete.selection"), true);
+ }
+ }
+
+ private static void deleteComponents(List<RadComponent> components) throws Exception {
+ if (components.get(0) instanceof IGroupDeleteComponent) {
+ ((IGroupDeleteComponent)components.get(0)).delete(components);
+ }
+ else {
+ for (RadComponent component : components) {
+ component.delete();
+ }
+ }
+ }
+
+ public static void updateSelectionBeforeDelete(EditableArea area, RadComponent component, List<RadComponent> excludes) {
+ RadComponent newSelection = getNewSelection(component, excludes);
+ if (newSelection == null) {
+ area.deselectAll();
+ }
+ else {
+ area.select(newSelection);
+ }
}
@Nullable
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/DeselectAllAction.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/DeselectAllAction.java
new file mode 100644
index 000000000000..4974c155c660
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/DeselectAllAction.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer.actions;
+
+import com.intellij.designer.designSurface.EditableArea;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class DeselectAllAction extends AnAction {
+ private final EditableArea myArea;
+
+ public DeselectAllAction(EditableArea area) {
+ super("Deselect All", "Deselect All", null);
+ myArea = area;
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ myArea.deselectAll();
+ }
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java
index 24a15a36953b..825a443ae804 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SideBorder;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.KeyEvent;
@@ -34,14 +35,14 @@ import java.util.List;
public class DesignerActionPanel implements DataProvider {
public static final String TOOLBAR = "DesignerToolbar";
- private final DefaultActionGroup myActionGroup = new DefaultActionGroup();
+ private final DefaultActionGroup myActionGroup;
private final DefaultActionGroup myStaticGroup = new DefaultActionGroup();
private final DefaultActionGroup myDynamicGroup = new DefaultActionGroup();
private final DefaultActionGroup myPopupGroup = new DefaultActionGroup();
private final DefaultActionGroup myDynamicPopupGroup = new DefaultActionGroup();
- private JComponent myToolbar;
- private final DesignerEditorPanel myDesigner;
+ protected final JComponent myToolbar;
+ protected final DesignerEditorPanel myDesigner;
private final CommonEditActionsProvider myCommonEditActionsProvider;
private final JComponent myShortcuts;
@@ -52,16 +53,50 @@ public class DesignerActionPanel implements DataProvider {
createInplaceEditingAction(myShortcuts).setDesignerPanel(designer);
- myActionGroup.add(myStaticGroup);
- myActionGroup.add(myDynamicGroup);
+ myActionGroup = createActionGroup();
+ myToolbar = createToolbar();
ActionManager actionManager = ActionManager.getInstance();
+ myPopupGroup.add(actionManager.getAction(IdeActions.ACTION_CUT));
+ myPopupGroup.add(actionManager.getAction(IdeActions.ACTION_COPY));
+ myPopupGroup.add(actionManager.getAction(IdeActions.ACTION_PASTE));
+ myPopupGroup.addSeparator();
+ myPopupGroup.add(actionManager.getAction(IdeActions.ACTION_DELETE));
+ myPopupGroup.addSeparator();
+ myPopupGroup.add(createSelectActionGroup(designer));
+ myPopupGroup.addSeparator();
+ myPopupGroup.add(myDynamicPopupGroup);
+
+ designer.getSurfaceArea().addSelectionListener(new ComponentSelectionListener() {
+ @Override
+ public void selectionChanged(EditableArea area) {
+ updateSelectionActions(area.getSelection());
+ }
+ });
+ }
+
+ protected DefaultActionGroup createActionGroup() {
+ DefaultActionGroup group = new DefaultActionGroup();
+ group.add(myStaticGroup);
+ group.add(myDynamicGroup);
+ return group;
+ }
+
+ protected JComponent createToolbar() {
+ ActionManager actionManager = ActionManager.getInstance();
ActionToolbar actionToolbar = actionManager.createActionToolbar(TOOLBAR, myActionGroup, true);
actionToolbar.setLayoutPolicy(ActionToolbar.WRAP_LAYOUT_POLICY);
- myToolbar = actionToolbar.getComponent();
- myToolbar.setBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM));
- myToolbar.setVisible(false);
+ JComponent toolbar = actionToolbar.getComponent();
+ toolbar.setBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM));
+ toolbar.setVisible(false);
+
+ return toolbar;
+ }
+
+ @NotNull
+ private ActionGroup createSelectActionGroup(DesignerEditorPanel designer) {
+ final DefaultActionGroup group = new DefaultActionGroup("_Select", true);
AnAction selectParent = new AnAction("Select Parent", "Select Parent", null) {
@Override
@@ -75,26 +110,23 @@ public class DesignerActionPanel implements DataProvider {
};
selectParent.registerCustomShortcutSet(KeyEvent.VK_ESCAPE, 0, null);
- SelectAllAction selectAllAction = new SelectAllAction(designer.getSurfaceArea());
+ EditableArea area = designer.getSurfaceArea();
+
+ AnAction selectSiblings = new SelectSiblingsAction(area);
+ AnAction selectSameType = new SelectSameTypeAction(area);
+ AnAction deselectAllAction = new DeselectAllAction(area);
+
+ SelectAllAction selectAllAction = new SelectAllAction(area);
registerAction(selectAllAction, "$SelectAll");
- myPopupGroup.add(actionManager.getAction(IdeActions.ACTION_CUT));
- myPopupGroup.add(actionManager.getAction(IdeActions.ACTION_COPY));
- myPopupGroup.add(actionManager.getAction(IdeActions.ACTION_PASTE));
- myPopupGroup.addSeparator();
- myPopupGroup.add(actionManager.getAction(IdeActions.ACTION_DELETE));
- myPopupGroup.addSeparator();
- myPopupGroup.add(selectParent);
- myPopupGroup.add(selectAllAction);
- myPopupGroup.addSeparator();
- myPopupGroup.add(myDynamicPopupGroup);
+ group.add(selectParent);
+ group.add(selectSiblings);
+ group.add(selectSameType);
+ group.addSeparator();
+ group.add(selectAllAction);
+ group.add(deselectAllAction);
- designer.getSurfaceArea().addSelectionListener(new ComponentSelectionListener() {
- @Override
- public void selectionChanged(EditableArea area) {
- updateSelectionActions(area.getSelection());
- }
- });
+ return group;
}
public static StartInplaceEditing createInplaceEditingAction(JComponent shortcuts) {
@@ -122,6 +154,14 @@ public class DesignerActionPanel implements DataProvider {
return myPopupGroup;
}
+ protected DefaultActionGroup getDynamicActionGroup() {
+ return myDynamicGroup;
+ }
+
+ protected JComponent getShortcuts() {
+ return myShortcuts;
+ }
+
public void update() {
boolean oldVisible = myToolbar.isVisible();
boolean newVisible = isVisible(myActionGroup);
@@ -150,7 +190,7 @@ public class DesignerActionPanel implements DataProvider {
}
private void updateSelectionActions(List<RadComponent> selection) {
- boolean update = isVisible(myDynamicGroup);
+ boolean oldVisible = isVisible(myDynamicGroup);
if (myDynamicGroup.getChildrenCount() > 0) {
for (AnAction action : myDynamicGroup.getChildActionsOrStubs()) {
@@ -159,16 +199,19 @@ public class DesignerActionPanel implements DataProvider {
myDynamicGroup.removeAll();
}
+ addSelectionActions(selection, myDynamicGroup);
+
+ if (oldVisible || isVisible(myDynamicGroup)) {
+ update();
+ }
+ }
+
+ protected void addSelectionActions(List<RadComponent> selection, DefaultActionGroup group) {
for (RadComponent parent : RadComponent.getParents(selection)) {
- parent.getLayout().addSelectionActions(myDesigner, myDynamicGroup, myShortcuts, selection);
+ parent.getLayout().addSelectionActions(myDesigner, group, myShortcuts, selection);
}
for (RadComponent component : selection) {
- component.addSelectionActions(myDesigner, myDynamicGroup, myShortcuts, selection);
- }
- update |= isVisible(myDynamicGroup);
-
- if (update) {
- update();
+ component.addSelectionActions(myDesigner, group, myShortcuts, selection);
}
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java
index a58bfa0f5ec4..eb915b1d9d02 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java
@@ -43,7 +43,9 @@ public class SelectAllAction extends AnAction {
rootComponent.accept(new RadComponentVisitor() {
@Override
public void endVisit(RadComponent component) {
- components.add(component);
+ if (!component.isBackground()) {
+ components.add(component);
+ }
}
}, true);
myArea.setSelection(components);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectSameTypeAction.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectSameTypeAction.java
new file mode 100644
index 000000000000..30cd92a67942
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectSameTypeAction.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer.actions;
+
+import com.intellij.designer.designSurface.EditableArea;
+import com.intellij.designer.model.RadComponent;
+import com.intellij.designer.model.RadComponentVisitor;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SelectSameTypeAction extends AnAction {
+ private final EditableArea myArea;
+
+ public SelectSameTypeAction(EditableArea area) {
+ super("Select Same Type", "Select Same Type", null);
+ myArea = area;
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ RadComponent rootComponent = myArea.getRootComponent();
+ if (rootComponent != null) {
+ final List<RadComponent> selection = myArea.getSelection();
+ final List<RadComponent> components = new ArrayList<RadComponent>();
+ rootComponent.accept(new RadComponentVisitor() {
+ @Override
+ public void endVisit(RadComponent component) {
+ if (!component.isBackground()) {
+ for (RadComponent selected : selection) {
+ if (selected.isSameType(component)) {
+ components.add(component);
+ break;
+ }
+ }
+ }
+ }
+ }, true);
+ myArea.setSelection(components);
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectSiblingsAction.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectSiblingsAction.java
new file mode 100644
index 000000000000..d0f1062bf147
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectSiblingsAction.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer.actions;
+
+import com.intellij.designer.designSurface.EditableArea;
+import com.intellij.designer.model.RadComponent;
+import com.intellij.designer.model.RadComponentVisitor;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class SelectSiblingsAction extends AnAction {
+ private final EditableArea myArea;
+
+ public SelectSiblingsAction(EditableArea area) {
+ super("Select Siblings", "Select Siblings", null);
+ myArea = area;
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ RadComponent rootComponent = myArea.getRootComponent();
+ if (rootComponent != null) {
+ final Set<RadComponent> parents = RadComponent.getParents(myArea.getSelection());
+ final List<RadComponent> components = new ArrayList<RadComponent>();
+ rootComponent.accept(new RadComponentVisitor() {
+ @Override
+ public void endVisit(RadComponent component) {
+ if (parents.contains(component.getParent())) {
+ components.add(component);
+ }
+ }
+ }, true);
+ myArea.setSelection(components);
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java
index 1800b233bcff..20038fa9c474 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTreeBuilder.java
@@ -15,6 +15,7 @@
*/
package com.intellij.designer.componentTree;
+import com.intellij.designer.designSurface.ComponentGlassLayer;
import com.intellij.designer.designSurface.ComponentSelectionListener;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.designSurface.EditableArea;
@@ -28,7 +29,7 @@ import javax.swing.tree.DefaultTreeModel;
public final class ComponentTreeBuilder extends AbstractTreeBuilder implements ComponentSelectionListener {
private final EditableArea mySurfaceArea;
private final TreeEditableArea myTreeArea;
- private final TreeGlassLayer myGlassLayer;
+ private final ComponentGlassLayer myGlassLayer;
private final ExpandStateHandler myExpandStateHandler;
public ComponentTreeBuilder(ComponentTree tree, DesignerEditorPanel designer) {
@@ -41,7 +42,7 @@ public final class ComponentTreeBuilder extends AbstractTreeBuilder implements C
mySurfaceArea = designer.getSurfaceArea();
myTreeArea = new TreeEditableArea(tree, this, designer.getActionPanel());
- myGlassLayer = new TreeGlassLayer(tree, designer.getToolProvider(), myTreeArea);
+ myGlassLayer = new ComponentGlassLayer(tree, designer.getToolProvider(), myTreeArea);
myExpandStateHandler = new ExpandStateHandler(tree, designer, this);
tree.setArea(myTreeArea);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeDropListener.java b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeDropListener.java
index 2dc2c2c648a0..321fc72fec64 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeDropListener.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeDropListener.java
@@ -86,9 +86,11 @@ public class TreeDropListener extends DropTargetAdapter {
@Override
public void drop(DropTargetDropEvent event) {
+ event.acceptDrop(event.getDropAction());
eraseFeedback();
executeCommand();
clearState(true);
+ event.dropComplete(true);
}
private void showFeedback() {
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/CaptionPanel.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/CaptionPanel.java
index 907b557363eb..e0714063bf12 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/CaptionPanel.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/CaptionPanel.java
@@ -55,8 +55,11 @@ public class CaptionPanel extends JBLayeredPane implements DataProvider, DeleteP
private List<RadComponent> myRootChildren = Collections.emptyList();
private ICaption myCaption;
- public CaptionPanel(DesignerEditorPanel designer, boolean horizontal) {
- setBorder(IdeBorderFactory.createBorder(horizontal ? SideBorder.BOTTOM : SideBorder.RIGHT));
+ public CaptionPanel(DesignerEditorPanel designer, boolean horizontal, boolean addBorder) {
+ if (addBorder) {
+ setBorder(IdeBorderFactory.createBorder(horizontal ? SideBorder.BOTTOM : SideBorder.RIGHT));
+ }
+
setFocusable(true);
myHorizontal = horizontal;
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeGlassLayer.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ComponentGlassLayer.java
index 9051d05e3fa6..4ae5ed37f5a8 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeGlassLayer.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ComponentGlassLayer.java
@@ -13,35 +13,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.designer.componentTree;
+package com.intellij.designer.designSurface;
-import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.designSurface.tools.ToolProvider;
+import javax.swing.*;
import java.awt.event.*;
/**
* @author Alexander Lobas
*/
-public final class TreeGlassLayer implements KeyListener, MouseListener, MouseMotionListener {
- private final ComponentTree myTree;
+public final class ComponentGlassLayer implements KeyListener, MouseListener, MouseMotionListener {
+ private final JComponent myComponent;
private final ToolProvider myToolProvider;
private final EditableArea myArea;
- public TreeGlassLayer(ComponentTree tree, ToolProvider provider, EditableArea area) {
- myTree = tree;
+ public ComponentGlassLayer(JComponent component, ToolProvider provider, EditableArea area) {
+ myComponent = component;
myToolProvider = provider;
myArea = area;
- myTree.addKeyListener(this);
- myTree.addMouseListener(this);
- myTree.addMouseMotionListener(this);
+ myComponent.addKeyListener(this);
+ myComponent.addMouseListener(this);
+ myComponent.addMouseMotionListener(this);
}
public void dispose() {
- myTree.removeKeyListener(this);
- myTree.removeMouseListener(this);
- myTree.removeMouseMotionListener(this);
+ myComponent.removeKeyListener(this);
+ myComponent.removeMouseListener(this);
+ myComponent.removeMouseMotionListener(this);
}
//////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
index 613b1e60ef16..cc5fa084a550 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
@@ -105,7 +105,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
protected CaptionPanel myHorizontalCaption;
protected CaptionPanel myVerticalCaption;
- private JScrollPane myScrollPane;
+ protected JScrollPane myScrollPane;
protected JLayeredPane myLayeredPane;
protected GlassLayer myGlassLayer;
private DecorationLayer myDecorationLayer;
@@ -223,7 +223,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
myToolProvider = new ToolProvider() {
@Override
public void loadDefaultTool() {
- setActiveTool(new SelectionTool());
+ setActiveTool(createDefaultTool());
}
@Override
@@ -280,6 +280,26 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
public void showError(@NonNls String message, Throwable e) {
DesignerEditorPanel.this.showError(message, e);
}
+
+ @Override
+ public boolean isZoomSupported() {
+ return DesignerEditorPanel.this.isZoomSupported();
+ }
+
+ @Override
+ public void zoom(@NotNull ZoomType type) {
+ DesignerEditorPanel.this.zoom(type);
+ }
+
+ @Override
+ public void setZoom(double zoom) {
+ DesignerEditorPanel.this.setZoom(zoom);
+ }
+
+ @Override
+ public double getZoom() {
+ return DesignerEditorPanel.this.getZoom();
+ }
};
myGlassLayer = new GlassLayer(myToolProvider, mySurfaceArea);
@@ -302,14 +322,14 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
gbc.gridy = 1;
gbc.fill = GridBagConstraints.VERTICAL;
- myVerticalCaption = new CaptionPanel(this, false);
+ myVerticalCaption = createCaptionPanel(false);
content.add(myVerticalCaption, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
- myHorizontalCaption = new CaptionPanel(this, true);
+ myHorizontalCaption = createCaptionPanel(true);
content.add(myHorizontalCaption, gbc);
gbc.gridx = 1;
@@ -318,8 +338,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
- myScrollPane = ScrollPaneFactory.createScrollPane(myLayeredPane);
- myScrollPane.setBackground(new JBColor(Color.WHITE, UIUtil.getListBackground()));
+ myScrollPane = createScrollPane(myLayeredPane);
content.add(myScrollPane, gbc);
myHorizontalCaption.attachToScrollPane(myScrollPane);
@@ -327,7 +346,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
myQuickFixManager = new QuickFixManager(this, myGlassLayer, myScrollPane.getViewport());
- myActionPanel = new DesignerActionPanel(this, myGlassLayer);
+ myActionPanel = createActionPanel();
myWarnAction = new FixableMessageAction();
add(myActionPanel.getToolbarComponent());
@@ -344,6 +363,20 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
});
}
+ protected CaptionPanel createCaptionPanel(boolean horizontal) {
+ return new CaptionPanel(this, horizontal, true);
+ }
+
+ protected JScrollPane createScrollPane(@NotNull JLayeredPane content) {
+ JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(content);
+ scrollPane.setBackground(new JBColor(Color.WHITE, UIUtil.getListBackground()));
+ return scrollPane;
+ }
+
+ protected DesignerActionPanel createActionPanel() {
+ return new DesignerActionPanel(this, myGlassLayer);
+ }
+
@Nullable
public final PaletteItem getActivePaletteItem() {
return myActivePaletteItem;
@@ -749,6 +782,22 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
public abstract List<PaletteGroup> getPaletteGroups();
+ /**
+ * Returns a suitable version label from the version attribute from a {@link PaletteItem} version
+ */
+ @NotNull
+ public String getVersionLabel(@Nullable String version) {
+ return StringUtil.notNullize(version);
+ }
+
+ public boolean isDeprecated(@Nullable String deprecatedIn) {
+ return !StringUtil.isEmpty(deprecatedIn);
+ }
+
+ protected InputTool createDefaultTool() {
+ return new SelectionTool();
+ }
+
@NotNull
protected abstract ComponentCreationFactory createCreationFactory(PaletteItem paletteItem);
@@ -812,6 +861,31 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
//////////////////////////////////////////////////////////////////////////////////////////
//
+ // Zooming
+ //
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ public boolean isZoomSupported() {
+ return false;
+ }
+
+ public void zoom(@NotNull ZoomType type) {
+ }
+
+ public void setZoom(double zoom) {
+ }
+
+ public double getZoom() {
+ return 1;
+ }
+
+ protected void viewZoomed() {
+ // Hide quickfix light bulbs; position can be obsolete after the zoom level has changed
+ myQuickFixManager.hideHint();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ //
// Inspection
//
//////////////////////////////////////////////////////////////////////////////////////////
@@ -888,6 +962,32 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
}
}
+ /**
+ * Size of the scene, in scroll pane view port pixels.
+ */
+ @NotNull
+ protected Dimension getSceneSize(Component target) {
+ int width = 0;
+ int height = 0;
+
+ if (myRootComponent != null) {
+ Rectangle bounds = myRootComponent.getBounds(target);
+ width = Math.max(width, (int)bounds.getMaxX());
+ height = Math.max(height, (int)bounds.getMaxY());
+
+ for (RadComponent component : myRootComponent.getChildren()) {
+ Rectangle childBounds = component.getBounds(target);
+ width = Math.max(width, (int)childBounds.getMaxX());
+ height = Math.max(height, (int)childBounds.getMaxY());
+ }
+ }
+
+ width += 50;
+ height += 40;
+
+ return new Dimension(width, height);
+ }
+
private final class MyLayeredPane extends JBLayeredPane implements Scrollable {
public void doLayout() {
for (int i = getComponentCount() - 1; i >= 0; i--) {
@@ -901,25 +1001,13 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
}
public Dimension getPreferredSize() {
- int width = 0;
- int height = 0;
-
- if (myRootComponent != null) {
- width = Math.max(width, (int)myRootComponent.getBounds().getMaxX());
- height = Math.max(height, (int)myRootComponent.getBounds().getMaxY());
-
- for (RadComponent component : myRootComponent.getChildren()) {
- width = Math.max(width, (int)component.getBounds().getMaxX());
- height = Math.max(height, (int)component.getBounds().getMaxY());
- }
- }
-
- width += 50;
- height += 40;
-
Rectangle bounds = myScrollPane.getViewport().getBounds();
+ Dimension size = getSceneSize(this);
+
+ size.width = Math.max(size.width, bounds.width);
+ size.height = Math.max(size.height, bounds.height);
- return new Dimension(Math.max(width, bounds.width), Math.max(height, bounds.height));
+ return size;
}
public Dimension getPreferredScrollableViewportSize() {
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/EmptyEditableArea.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/EmptyEditableArea.java
new file mode 100644
index 000000000000..e4f05ed3bbe5
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/EmptyEditableArea.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer.designSurface;
+
+import com.intellij.designer.designSurface.tools.InputTool;
+import com.intellij.designer.model.RadComponent;
+import com.intellij.openapi.actionSystem.ActionGroup;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author Alexander Lobas
+ */
+public class EmptyEditableArea extends ComponentEditableArea {
+ public EmptyEditableArea(JComponent component) {
+ super(component);
+ }
+
+ @Nullable
+ @Override
+ public RadComponent findTarget(int x, int y, @Nullable ComponentTargetFilter filter) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public InputTool findTargetTool(int x, int y) {
+ return null;
+ }
+
+ @Override
+ public void showSelection(boolean value) {
+ }
+
+ @Override
+ public ComponentDecorator getRootSelectionDecorator() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public EditOperation processRootOperation(OperationContext context) {
+ return null;
+ }
+
+ @Override
+ public FeedbackLayer getFeedbackLayer() {
+ return null;
+ }
+
+ @Override
+ public RadComponent getRootComponent() {
+ return null;
+ }
+
+ @Override
+ public ActionGroup getPopupActions() {
+ return null;
+ }
+
+ @Override
+ public String getPopupPlace() {
+ return null;
+ }
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java
index ac4215fc7505..b3a423d1e4ab 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java
@@ -36,6 +36,7 @@ public final class OperationContext {
private EditableArea myArea;
private List<RadComponent> myComponents;
private InputEvent myInputEvent;
+ private int myModifiers;
private Point myLocation;
private Point myMoveDelta;
private Dimension mySizeDelta;
@@ -138,6 +139,14 @@ public final class OperationContext {
myInputEvent = inputEvent;
}
+ public int getModifiers() {
+ return myModifiers;
+ }
+
+ public void setModifiers(int modifiers) {
+ myModifiers = modifiers;
+ }
+
public Point getLocation() {
return myLocation;
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/RootView.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/RootView.java
index 06d2c417510e..09bf5ebd25e4 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/RootView.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/RootView.java
@@ -23,16 +23,20 @@ import java.awt.image.BufferedImage;
* @author Alexander Lobas
*/
public class RootView extends JComponent {
- private final int myX;
- private final int myY;
+ protected int myX;
+ protected int myY;
protected BufferedImage myImage;
public RootView(int x, int y, BufferedImage image) {
- this(x, y);
+ updateLocation(x, y);
setImage(image);
}
public RootView(int x, int y) {
+ updateLocation(x, y);
+ }
+
+ public void updateLocation(int x, int y) {
myX = x;
myY = y;
}
@@ -41,9 +45,13 @@ public class RootView extends JComponent {
return myImage;
}
- public void setImage(BufferedImage image) {
+ public final void setImage(BufferedImage image) {
+ setImage(image, myX, myY, image.getWidth(), image.getHeight());
+ }
+
+ public void setImage(BufferedImage image, int x, int y, int width, int height) {
myImage = image;
- setBounds(myX, myY, image.getWidth(), image.getHeight());
+ setBounds(x, y, width, height);
repaint();
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ScalableComponent.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ScalableComponent.java
new file mode 100644
index 000000000000..56942ab19d4d
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ScalableComponent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer.designSurface;
+
+/**
+ * Interface implemented by a design view native component which implements zooming.
+ */
+public interface ScalableComponent {
+ /**
+ * Returns the scale to apply to coordinates in this view.
+ */
+ double getScale();
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ZoomProvider.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ZoomProvider.java
new file mode 100644
index 000000000000..ca25fe5b902b
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ZoomProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer.designSurface;
+
+import org.jetbrains.annotations.NotNull;
+
+public interface ZoomProvider {
+ /**
+ * Returns true if zooming is supported by this designer.
+ */
+ boolean isZoomSupported();
+
+ /**
+ * Zoom the editable area.
+ */
+ void zoom(@NotNull ZoomType type);
+
+ /**
+ * Sets the zoom level. Note that this should be 1, not 100 (percent), for an image at its actual size.
+ */
+ void setZoom(double zoom);
+
+ /**
+ * Returns the current zoom level. Note that this is 1, not 100 (percent) for an image at its actual size.
+ */
+ double getZoom();
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ZoomType.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ZoomType.java
new file mode 100644
index 000000000000..eadaaafdc218
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/ZoomType.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer.designSurface;
+
+public enum ZoomType {
+ /**
+ * Zoom in
+ */
+ IN,
+
+ /**
+ * Zoom out
+ */
+ OUT,
+
+ /**
+ * Zoom to actual size (100%)
+ */
+ ACTUAL,
+
+ /**
+ * Zoom to fit (the screen view port)
+ */
+ FIT,
+
+ /**
+ * Zoom to fit, but do not zoom more than 100%
+ */
+ FIT_INTO,
+
+ /**
+ * Zoom to match the exact device size (depends on the monitor dpi)
+ */
+ SCREEN
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/InsertFeedback.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/InsertFeedback.java
index 672f7e2cb25e..b7aa299c4c03 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/InsertFeedback.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/InsertFeedback.java
@@ -21,7 +21,7 @@ import java.awt.*;
* @author Alexander Lobas
*/
public class InsertFeedback extends LineInsertFeedback {
- private boolean myCross;
+ protected boolean myCross;
public InsertFeedback(Color color) {
super(color, false);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/LineFeedback.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/LineFeedback.java
index c14ef8120d51..cedf9b4780c9 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/LineFeedback.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/feedbacks/LineFeedback.java
@@ -24,7 +24,7 @@ import java.awt.*;
public class LineFeedback extends JComponent {
protected final Color myColor;
private final int myLine;
- private boolean myHorizontal;
+ protected boolean myHorizontal;
public LineFeedback(Color color, int line, boolean horizontal) {
myColor = color;
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java
index 68652083b873..2356e5e43d16 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/DirectionResizePoint.java
@@ -28,10 +28,10 @@ import java.awt.*;
* @author Alexander Lobas
*/
public class DirectionResizePoint extends ResizePoint {
- private int myDirection;
+ protected int myDirection;
final private Object myType;
- private double myXSeparator;
- private double myYSeparator;
+ protected double myXSeparator;
+ protected double myYSeparator;
private final String myDescription;
public DirectionResizePoint(int direction, Object type, @Nullable String description) {
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/ResizePoint.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/ResizePoint.java
index f2029e9e1dcf..15ab06607d35 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/ResizePoint.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/ResizePoint.java
@@ -44,6 +44,11 @@ public abstract class ResizePoint extends ComponentDecorator {
Point location = getLocation(layer, component);
Rectangle bounds = new Rectangle(location.x, location.y, getSize(), getSize());
+ int neighborhood = getNeighborhoodSize();
+ if (neighborhood > 0) {
+ bounds.grow(neighborhood, neighborhood);
+ }
+
if (bounds.contains(x, y)) {
return createTool(component);
}
@@ -71,4 +76,13 @@ public abstract class ResizePoint extends ComponentDecorator {
protected int getSize() {
return DEFAULT_SIZE;
}
+
+ /**
+ * Additional space range around the resize point that will also be considered a match.
+ * This lets you get near but not necessarily right on top of the resize point in order
+ * to act on it.
+ */
+ protected int getNeighborhoodSize() {
+ return 0;
+ }
} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/AbstractCreationTool.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/AbstractCreationTool.java
index 2343b667d63e..00f3039e39a8 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/AbstractCreationTool.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/AbstractCreationTool.java
@@ -131,6 +131,8 @@ public abstract class AbstractCreationTool extends TargetingTool {
@Override
public void keyPressed(KeyEvent event, EditableArea area) throws Exception {
+ super.keyPressed(event, area);
+
if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {
myToolProvider.loadDefaultTool();
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/InputTool.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/InputTool.java
index d03bdffa483a..b3c12ae19780 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/InputTool.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/InputTool.java
@@ -46,6 +46,7 @@ public abstract class InputTool {
protected int myCurrentScreenX;
protected int myCurrentScreenY;
protected InputEvent myInputEvent;
+ protected int myModifiers;
protected int myButton;
protected int myStartScreenX;
protected int myStartScreenY;
@@ -167,12 +168,35 @@ public abstract class InputTool {
//////////////////////////////////////////////////////////////////////////////////////////
public void keyTyped(KeyEvent event, EditableArea area) throws Exception {
+ setEvent(event);
+ setArea(area);
}
public void keyPressed(KeyEvent event, EditableArea area) throws Exception {
+ setEvent(event);
+ setArea(area);
}
public void keyReleased(KeyEvent event, EditableArea area) throws Exception {
+ setEvent(event);
+ setArea(area);
+ }
+
+ private void setEvent(KeyEvent event) {
+ myInputEvent = event;
+ myModifiers = event.getModifiers();
+ }
+
+ protected final boolean isShiftPressed() {
+ return (myModifiers & InputEvent.SHIFT_MASK) != 0;
+ }
+
+ protected final boolean isAltOptionPressed() {
+ return (myModifiers & InputEvent.ALT_MASK) != 0;
+ }
+
+ protected final boolean isCtrlCmdPressed() {
+ return (myModifiers & (InputEvent.CTRL_MASK | InputEvent.META_DOWN_MASK)) != 0;
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -185,6 +209,7 @@ public abstract class InputTool {
private void setEvent(MouseEvent event) {
myCurrentScreenX = event.getX();
myCurrentScreenY = event.getY();
+ myModifiers = event.getModifiers();
myButton = event.getButton();
myInputEvent = event;
myToolProvider.setEvent(event);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/MarqueeTracker.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/MarqueeTracker.java
index 6dcade1a1028..0f81a99820c6 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/MarqueeTracker.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/MarqueeTracker.java
@@ -15,6 +15,7 @@
*/
package com.intellij.designer.designSurface.tools;
+import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.designSurface.FeedbackLayer;
import com.intellij.designer.designSurface.feedbacks.AlphaFeedback;
import com.intellij.designer.model.RadComponent;
@@ -23,6 +24,7 @@ import com.intellij.designer.utils.Cursors;
import javax.swing.*;
import java.awt.*;
+import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
@@ -38,12 +40,20 @@ public class MarqueeTracker extends InputTool {
private JComponent myFeedback;
private int mySelectionMode;
+ private boolean mySelectBackground;
public MarqueeTracker() {
setDefaultCursor(Cursors.CROSS);
setDisabledCursor(Cursors.getNoCursor());
}
+ /**
+ * Set whether the background should be selected if none of its children are included.
+ */
+ public void setSelectBackground(boolean selectBackground) {
+ mySelectBackground = selectBackground;
+ }
+
@Override
protected void handleButtonDown(int button) {
if (button == MouseEvent.BUTTON1 || button == MouseEvent.BUTTON2) {
@@ -72,6 +82,9 @@ public class MarqueeTracker extends InputTool {
eraseFeedback();
performMarqueeSelect();
}
+ else if (mySelectBackground) {
+ performMarqueeSelect();
+ }
}
@Override
@@ -86,6 +99,26 @@ public class MarqueeTracker extends InputTool {
}
@Override
+ public void keyPressed(KeyEvent event, EditableArea area) throws Exception {
+ boolean changedModifiers = event.getModifiers() != myModifiers;
+ super.keyPressed(event, area);
+
+ if (changedModifiers) {
+ showFeedback();
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent event, EditableArea area) throws Exception {
+ boolean changedModifiers = event.getModifiers() != myModifiers;
+ super.keyReleased(event, area);
+
+ if (changedModifiers) {
+ showFeedback();
+ }
+ }
+
+ @Override
public void deactivate() {
if (myState == STATE_DRAG_IN_PROGRESS) {
eraseFeedback();
@@ -126,6 +159,14 @@ public class MarqueeTracker extends InputTool {
}
private Rectangle getSelectionRectangle() {
+ if (isAltOptionPressed()) {
+ // Alt/Option: Center selection around starting point
+ int deltaX = Math.abs(myStartScreenX - myCurrentScreenX);
+ int deltaY = Math.abs(myStartScreenY - myCurrentScreenY);
+ return new Rectangle(myStartScreenX - deltaX, myStartScreenY - deltaY, 2 * deltaX, 2 * deltaY);
+ }
+
+ // Select diagonally from upper left to lower right
return new Rectangle(myStartScreenX, myStartScreenY, 0, 0).union(new Rectangle(myCurrentScreenX, myCurrentScreenY, 0, 0));
}
@@ -138,11 +179,25 @@ public class MarqueeTracker extends InputTool {
rootComponent.accept(new RadComponentVisitor() {
@Override
public void endVisit(RadComponent component) {
- if (selectionRectangle.contains(component.getBounds(myArea.getNativeComponent()))) {
+ if (selectionRectangle.contains(component.getBounds(myArea.getNativeComponent())) && !component.isBackground()) {
newSelection.add(component);
}
}
}, true);
+
+ if (newSelection.isEmpty() && mySelectBackground) {
+ rootComponent.accept(new RadComponentVisitor() {
+ @Override
+ public void endVisit(RadComponent component) {
+ // Only select the bottom-most background
+ if (newSelection.isEmpty() &&
+ component.getBounds(myArea.getNativeComponent()).contains(selectionRectangle.x, selectionRectangle.y) &&
+ component.isBackground()) {
+ newSelection.add(component);
+ }
+ }
+ }, true);
+ }
}
if (mySelectionMode == TOGGLE_MODE) {
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ResizeTracker.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ResizeTracker.java
index 7317bbdc6fde..73df721e3ccb 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ResizeTracker.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ResizeTracker.java
@@ -151,6 +151,7 @@ public class ResizeTracker extends InputTool {
private void updateContext() {
myContext.setArea(myArea);
myContext.setInputEvent(myInputEvent);
+ myContext.setModifiers(myModifiers);
Point move = new Point();
Dimension size = new Dimension();
@@ -203,8 +204,32 @@ public class ResizeTracker extends InputTool {
@Override
public void keyPressed(KeyEvent event, EditableArea area) throws Exception {
+ boolean changedModifiers = event.getModifiers() != myModifiers;
+ super.keyPressed(event, area);
+
if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {
myToolProvider.loadDefaultTool();
}
+ else if (changedModifiers) {
+ handleKeyEvent();
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent event, EditableArea area) throws Exception {
+ boolean changedModifiers = event.getModifiers() != myModifiers;
+ super.keyReleased(event, area);
+
+ if (changedModifiers) {
+ handleKeyEvent();
+ }
+ }
+
+ private void handleKeyEvent() {
+ if (myContext != null) {
+ updateContext();
+ showFeedback();
+ updateCommand();
+ }
}
} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTool.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTool.java
index e6e6b05f92f1..c41f332b2a22 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTool.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTool.java
@@ -16,6 +16,7 @@
package com.intellij.designer.designSurface.tools;
import com.intellij.designer.designSurface.EditableArea;
+import com.intellij.designer.designSurface.ZoomType;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.propertyTable.InplaceContext;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -53,12 +54,11 @@ public class SelectionTool extends InputTool {
myState = STATE_DRAG;
deactivateTracker();
- if (!myArea.isTree()) {
- if (myInputEvent.isAltDown()) {
- setTracker(new MarqueeTracker());
- return;
- }
+ if (handleTracker()) {
+ return;
+ }
+ if (!myArea.isTree()) {
InputTool tracker = myArea.findTargetTool(myCurrentScreenX, myCurrentScreenY);
if (tracker != null) {
setTracker(tracker);
@@ -70,18 +70,32 @@ public class SelectionTool extends InputTool {
}
RadComponent component = myArea.findTarget(myCurrentScreenX, myCurrentScreenY, null);
- if (component == null) {
+ if (component == null || component.isBackground()) {
if (!myArea.isTree()) {
- setTracker(new MarqueeTracker());
+ MarqueeTracker tracker = new MarqueeTracker();
+
+ // Allow marquee dragging within the root (background) layout, and if you click
+ // without dragging, select that background component
+ tracker.setSelectBackground(component != null && component.isBackground());
+
+ setTracker(tracker);
}
}
else {
Point location = component.convertPoint(myArea.getNativeComponent(), myCurrentScreenX, myCurrentScreenY);
- setTracker(component.getDragTracker(location, myArea.isTree()));
+ setTracker(component.getDragTracker(location, myInputEvent, myArea.isTree()));
}
}
}
+ protected boolean handleTracker() {
+ if (!myArea.isTree() && myInputEvent.isAltDown()) {
+ setTracker(new MarqueeTracker());
+ return true;
+ }
+ return false;
+ }
+
@Override
protected void handleButtonUp(int button) {
myState = STATE_INIT;
@@ -129,6 +143,7 @@ public class SelectionTool extends InputTool {
myToolProvider.hideInspections();
myTracker.setToolProvider(myToolProvider);
myTracker.setArea(myArea);
+ myTracker.myModifiers = myModifiers;
myTracker.activate();
}
}
@@ -147,6 +162,7 @@ public class SelectionTool extends InputTool {
@Override
public void mouseDown(MouseEvent event, EditableArea area) throws Exception {
super.mouseDown(event, area);
+
if (myTracker != null) {
myTracker.mouseDown(event, area);
}
@@ -157,6 +173,7 @@ public class SelectionTool extends InputTool {
if (myTracker != null) {
myTracker.mouseUp(event, area);
}
+
super.mouseUp(event, area);
}
@@ -165,6 +182,7 @@ public class SelectionTool extends InputTool {
if (myTracker != null) {
myTracker.mouseMove(event, area);
}
+
super.mouseMove(event, area);
}
@@ -173,6 +191,7 @@ public class SelectionTool extends InputTool {
if (myTracker != null) {
myTracker.mouseDrag(event, area);
}
+
super.mouseDrag(event, area);
}
@@ -182,12 +201,14 @@ public class SelectionTool extends InputTool {
if (myTracker != null) {
myTracker.mousePopup(event, area);
}
+
super.mousePopup(event, area);
}
@Override
public void mouseDoubleClick(MouseEvent event, EditableArea area) throws Exception {
super.mouseDoubleClick(event, area);
+
if (myTracker != null) {
myTracker.mouseDoubleClick(event, area);
}
@@ -195,6 +216,8 @@ public class SelectionTool extends InputTool {
@Override
public void keyPressed(KeyEvent event, EditableArea area) throws Exception {
+ super.keyTyped(event, area);
+
if (myTracker != null) {
myTracker.keyPressed(event, area);
}
@@ -211,18 +234,51 @@ public class SelectionTool extends InputTool {
@Override
public void keyTyped(KeyEvent event, EditableArea area) throws Exception {
+ super.keyTyped(event, area);
+
if (myTracker != null) {
myTracker.keyTyped(event, area);
}
- else if (myToolProvider != null && !area.isTree() &&
- Character.isLetterOrDigit(event.getKeyChar()) &&
- (event.getModifiers() & (InputEvent.ALT_MASK | InputEvent.CTRL_MASK | InputEvent.META_MASK)) == 0) {
- myToolProvider.startInplaceEditing(new InplaceContext(event.getKeyChar()));
+ else if (myToolProvider != null && !area.isTree()) {
+ char keyChar = event.getKeyChar();
+ switch (keyChar) {
+ // Zoom
+ case '-':
+ case '+':
+ case '0':
+ case '1':
+ ZoomType type;
+ if (keyChar == '-') {
+ type = ZoomType.OUT;
+ }
+ else if (keyChar == '+') {
+ type = ZoomType.IN;
+ }
+ else if (keyChar == '0') {
+ type = ZoomType.FIT;
+ }
+ else { // '1'
+ type = ZoomType.ACTUAL;
+ }
+ if (myToolProvider.isZoomSupported()) {
+ myToolProvider.zoom(type);
+ event.consume();
+ return;
+ }
+ // else: fall through
+ default:
+ if (Character.isLetterOrDigit(keyChar) &&
+ (event.getModifiers() & (InputEvent.ALT_MASK | InputEvent.CTRL_MASK | InputEvent.META_MASK)) == 0) {
+ myToolProvider.startInplaceEditing(new InplaceContext(keyChar));
+ }
+ }
}
}
@Override
public void keyReleased(KeyEvent event, EditableArea area) throws Exception {
+ super.keyReleased(event, area);
+
if (myTracker != null) {
myTracker.keyReleased(event, area);
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java
index fb80d149d172..a8b35b1f4b68 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/SelectionTracker.java
@@ -17,6 +17,7 @@ package com.intellij.designer.designSurface.tools;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.model.RadComponent;
+import com.intellij.openapi.util.SystemInfo;
import java.awt.*;
import java.awt.event.KeyEvent;
@@ -26,7 +27,7 @@ import java.awt.event.MouseEvent;
* @author Alexander Lobas
*/
public class SelectionTracker extends TargetingTool {
- private final RadComponent myComponent;
+ protected final RadComponent myComponent;
private boolean mySelected;
public SelectionTracker(RadComponent component) {
@@ -78,6 +79,7 @@ public class SelectionTracker extends TargetingTool {
@Override
public void keyPressed(KeyEvent event, EditableArea area) throws Exception {
+ super.keyPressed(event, area);
if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {
myToolProvider.loadDefaultTool();
}
@@ -92,7 +94,7 @@ public class SelectionTracker extends TargetingTool {
}
public static void performSelection(InputTool tool, RadComponent component) {
- if (tool.myInputEvent.isControlDown()) {
+ if ((SystemInfo.isMac ? tool.myInputEvent.isMetaDown() : tool.myInputEvent.isControlDown())) {
if (tool.myArea.isSelected(component)) {
tool.myArea.deselect(component);
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java
index 9bfdd4b1c8a0..998216cd6ffe 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java
@@ -17,11 +17,13 @@ package com.intellij.designer.designSurface.tools;
import com.intellij.designer.designSurface.ComponentTargetFilter;
import com.intellij.designer.designSurface.EditOperation;
+import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.model.RadComponent;
import com.intellij.designer.model.RadLayout;
import org.jetbrains.annotations.Nullable;
+import java.awt.event.KeyEvent;
import java.util.Collections;
/**
@@ -89,6 +91,7 @@ public abstract class TargetingTool extends InputTool {
protected void updateContext() {
myContext.setArea(myArea);
myContext.setInputEvent(myInputEvent);
+ myContext.setModifiers(myInputEvent.getModifiers());
}
protected void setTarget(@Nullable RadComponent target, @Nullable ContainerTargetFilter filter) {
@@ -102,6 +105,34 @@ public abstract class TargetingTool extends InputTool {
}
}
+ @Override
+ public void keyPressed(KeyEvent event, EditableArea area) throws Exception {
+ boolean changedModifiers = event.getModifiers() != myModifiers;
+ super.keyPressed(event, area);
+
+ if (changedModifiers) {
+ handleKeyEvent();
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent event, EditableArea area) throws Exception {
+ boolean changedModifiers = event.getModifiers() != myModifiers;
+ super.keyReleased(event, area);
+
+ if (changedModifiers) {
+ handleKeyEvent();
+ }
+ }
+
+ private void handleKeyEvent() {
+ if (myContext != null) {
+ updateContext();
+ showFeedback();
+ updateCommand();
+ }
+ }
+
protected class ContainerTargetFilter implements ComponentTargetFilter {
private EditOperation myOperation;
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ToolProvider.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ToolProvider.java
index e72dc25b3f05..bcbc4f1aebe4 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ToolProvider.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/ToolProvider.java
@@ -17,6 +17,7 @@ package com.intellij.designer.designSurface.tools;
import com.intellij.designer.designSurface.EditOperation;
import com.intellij.designer.designSurface.EditableArea;
+import com.intellij.designer.designSurface.ZoomProvider;
import com.intellij.designer.propertyTable.InplaceContext;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.NonNls;
@@ -29,7 +30,7 @@ import java.util.List;
/**
* @author Alexander Lobas
*/
-public abstract class ToolProvider {
+public abstract class ToolProvider implements ZoomProvider {
private InputTool myTool;
private EditableArea myArea;
private MouseEvent myEvent;
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/model/IComponentDeletionParticipant.java b/plugins/ui-designer-core/src/com/intellij/designer/model/IComponentDeletionParticipant.java
new file mode 100644
index 000000000000..b3b967182e74
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/model/IComponentDeletionParticipant.java
@@ -0,0 +1,22 @@
+package com.intellij.designer.model;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public interface IComponentDeletionParticipant {
+ /**
+ * Called when one or more children are about to be deleted by the user.
+ *
+ * @param parent the parent of the deleted children (which still contains
+ * the children since this method is called before the deletion
+ * is performed)
+ * @param deleted a nonempty list of children about to be deleted
+ * @return true if the children have been fully deleted by this participant; false
+ * if normal deletion should resume. Note that even though an implementation may return
+ * false from this method, that does not mean it did not perform any work. For example,
+ * a RelativeLayout handler could remove constraints pointing to now deleted components,
+ * but leave the overall deletion of the elements to the core designer.
+ */
+ boolean deleteChildren(@NotNull RadComponent parent, @NotNull List<RadComponent> deleted) throws Exception;
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java b/plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java
index e995946dae6b..453751ddd419 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/model/MetaManager.java
@@ -17,6 +17,7 @@ package com.intellij.designer.model;
import com.intellij.designer.palette.DefaultPaletteItem;
import com.intellij.designer.palette.PaletteGroup;
+import com.intellij.designer.palette.PaletteItem;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Attribute;
@@ -193,8 +194,32 @@ public abstract class MetaManager extends ModelLoader {
PaletteGroup group = new PaletteGroup(element.getAttributeValue(NAME));
for (Object child : element.getChildren(ITEM)) {
- String tag = ((Element)child).getAttributeValue(TAG);
- group.addItem(getModelByTag(tag).getPaletteItem());
+ Element itemElement = (Element)child;
+ MetaModel model = getModelByTag(itemElement.getAttributeValue(TAG));
+ PaletteItem paletteItem = model.getPaletteItem();
+
+ if (!itemElement.getChildren().isEmpty()) {
+ // Replace the palette item shown in the palette; it might provide a custom
+ // title, icon or creation logic (and this is done here rather than in the
+ // default palette item, since when loading elements back from XML, there's
+ // no variation matching. We don't want for example to call the default
+ // LinearLayout item "LinearLayout (Horizontal)", since that item would be
+ // shown in the component tree for any <LinearLayout> found in the XML, including
+ // those which set orientation="vertical". In the future, consider generalizing
+ // this such that the {@link MetaModel} can hold multiple {@link PaletteItem}
+ // instances, and perform attribute matching.
+ if (itemElement.getAttribute("title") != null) {
+ paletteItem = new VariationPaletteItem(paletteItem, model, itemElement);
+ }
+ group.addItem(paletteItem);
+
+ for (Object grandChild : itemElement.getChildren(ITEM)) {
+ group.addItem(new VariationPaletteItem(paletteItem, model, (Element)grandChild));
+ }
+ }
+ else {
+ group.addItem(paletteItem);
+ }
}
myPaletteGroups.add(group);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/model/RadComponent.java b/plugins/ui-designer-core/src/com/intellij/designer/model/RadComponent.java
index c4c6bf110c97..3fedbbe03d5e 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/model/RadComponent.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/model/RadComponent.java
@@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
+import java.awt.event.InputEvent;
import java.util.*;
import java.util.List;
@@ -120,25 +121,170 @@ public abstract class RadComponent extends PropertiesContainer {
getParent().remove(this);
}
+ /**
+ * Whether this view is considered to be the background.
+ * This can for example return true for the root layout, such that marquee
+ * selection, and Select All, will not include it in marquee selection or select
+ * all operations.
+ *
+ * @return true if this view should be considered part of the background
+ */
+ public boolean isBackground() {
+ return false;
+ }
+
+ /**
+ * Returns true if this component is of the same logical type as the given other component.
+ * This is used to for example select "Select Same Type".
+ */
+ public boolean isSameType(@NotNull RadComponent other) {
+ return other.getClass() == this.getClass();
+ }
+
//////////////////////////////////////////////////////////////////////////////////////////
//
// Visual
//
//////////////////////////////////////////////////////////////////////////////////////////
+ /**
+ * Returns the bounds of this {@linkplain RadComponent} in the model.
+ * <p/>
+ * Caller should <b>not</b> modify this rectangle.
+ *
+ * @return the bounds of this {@linkplain RadComponent} in the model coordinate system
+ * (e.g. unaffected by a view zoom for example)
+ */
public Rectangle getBounds() {
return null;
}
+ /**
+ * Returns the bounds of this {@linkplain RadComponent} in the coordinate system of
+ * the given Swing component. This will scale the coordinates if the view is zoomed
+ * (see {@link DesignerEditorPanel#zoom(com.intellij.designer.designSurface.ZoomType)})
+ * and will apply any relative position offsets of views in the hierarchy between the
+ * two components.
+ * <p/>
+ * Returns a new {@link Rectangle}, so callers are free to modify the result.
+ *
+ * @param relativeTo the component whose coordinate system the model bounds should
+ * be shifted and scaled into
+ * @return the bounds of this {@linkplain RadComponent} in the given coordinate system
+ */
public Rectangle getBounds(Component relativeTo) {
return null;
}
+ /**
+ * Converts the given rectangle (in model coordinates) to coordinates in the given
+ * target component's coordinate system. The model coordinate system refers to
+ * the same coordinate system as the bounds returned by {@link #getBounds()}.
+ * <p/>
+ * This means that calling {@link #getBounds(java.awt.Component)} is equivalent
+ * to calling this method and passing in {@link #getBounds()}.
+ * <p/>
+ * Returns a new {@link Rectangle}, so callers are free to modify the result.
+ *
+ * @param target the component whose coordinate system the rectangle should be
+ * translated into
+ * @param rectangle the model rectangle to convert
+ * @return the rectangle converted to the coordinate system of the target
+ */
+ public Rectangle fromModel(@NotNull Component target, @NotNull Rectangle rectangle) {
+ return null;
+ }
+
+ /**
+ * Converts the given rectangle (in coordinates relative to the given component)
+ * into the equivalent rectangle in model coordinates.
+ * <p/>
+ * Returns a new {@link Rectangle}, so callers are free to modify the result.
+ *
+ * @param source the component which defines the coordinate system of the rectangle
+ * @param rectangle the rectangle to be converted into model coordinates
+ * @return the rectangle converted to the model coordinate system
+ */
+ public Rectangle toModel(@NotNull Component source, @NotNull Rectangle rectangle) {
+ return null;
+ }
+
+ /**
+ * Converts the given point (in model coordinates) to coordinates in the given
+ * target component's coordinate system. The model coordinate system refers to
+ * the same coordinate system as the bounds returned by {@link #getBounds()}.
+ * <p/>
+ * Returns a new {@link Point}, so callers are free to modify the result.
+ *
+ * @param target the component whose coordinate system the point should be
+ * translated into
+ * @param point the model point to convert
+ * @return the point converted to the coordinate system of the target
+ */
+ public Point fromModel(@NotNull Component target, @NotNull Point point) {
+ return null;
+ }
+
+ /**
+ * Converts the given point (in coordinates relative to the given component)
+ * into the equivalent point in model coordinates.
+ * <p/>
+ * Returns a new {@link Point}, so callers are free to modify the result.
+ *
+ * @param source the component which defines the coordinate system of the point
+ * @param point the point to be converted into model coordinates
+ * @return the point converted to the model coordinate system
+ */
+ public Point toModel(@NotNull Component source, @NotNull Point point) {
+ return null;
+ }
+
+ /**
+ * Converts the given rectangle (in model coordinates) to coordinates in the given
+ * target component's coordinate system. The model coordinate system refers to
+ * the same coordinate system as the bounds returned by {@link #getBounds()}.
+ * <p/>
+ * Returns a new {@link Dimension}, so callers are free to modify the result.
+ *
+ * @param target the component whose coordinate system the dimension should be
+ * translated into
+ * @param size the model dimension to convert
+ * @return the size converted to the coordinate system of the target
+ */
+ public Dimension fromModel(@NotNull Component target, @NotNull Dimension size) {
+ return null;
+ }
+
+ /**
+ * Converts the given size (in coordinates relative to the given component)
+ * into the equivalent size in model coordinates.
+ * <p/>
+ * Returns a new {@link Dimension}, so callers are free to modify the result.
+ *
+ * @param source the component which defines the coordinate system of the size
+ * @param size the dimension to be converted into model coordinates
+ * @return the size converted to the model coordinate system
+ */
+ public Dimension toModel(@NotNull Component source, @NotNull Dimension size) {
+ return null;
+ }
+
+ /**
+ * Returns the point in the model coordinate space (see {@link #getBounds()}) given
+ * a coordinate {@code x, y} in the given Swing component.
+ * <p/>
+ * Returns a new {@link Point}, so callers are free to modify the result.
+ *
+ * @param relativeFrom the component whose coordinate system defines the rectangle
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ * @return a corresponding {@link Point} in the model coordinate system
+ */
public Point convertPoint(Component relativeFrom, int x, int y) {
return null;
}
- public InputTool getDragTracker(Point location, boolean isTree) {
+ public InputTool getDragTracker(Point location, InputEvent event, boolean isTree) {
return new DragTracker(this);
}
@@ -259,19 +405,23 @@ public abstract class RadComponent extends PropertiesContainer {
public void accept(RadComponentVisitor visitor, boolean forward) {
if (visitor.visit(this)) {
- List<RadComponent> children = getChildrenForAccept(visitor);
- if (forward) {
- for (RadComponent child : children) {
- child.accept(visitor, forward);
- }
+ acceptChildren(visitor, forward);
+ visitor.endVisit(this);
+ }
+ }
+
+ public void acceptChildren(RadComponentVisitor visitor, boolean forward) {
+ List<RadComponent> children = getChildrenForAccept(visitor);
+ if (forward) {
+ for (RadComponent child : children) {
+ child.accept(visitor, forward);
}
- else {
- int size = children.size();
- for (int i = size - 1; i >= 0; i--) {
- children.get(i).accept(visitor, forward);
- }
+ }
+ else {
+ int size = children.size();
+ for (int i = size - 1; i >= 0; i--) {
+ children.get(i).accept(visitor, forward);
}
- visitor.endVisit(this);
}
}
@@ -335,6 +485,41 @@ public abstract class RadComponent extends PropertiesContainer {
}, true);
}
+ /**
+ * Partitions the given list of components into a map where each value is a list of siblings,
+ * in the same order as in the original list, and where the keys are the parents (or null
+ * for the components that do not have a parent).
+ * <p/>
+ * The value lists will never be empty. The parent key will be null for components without parents.
+ *
+ * @param components the components to be grouped
+ * @return a map from parents (or null) to a list of components with the corresponding parent
+ */
+ @NotNull
+ public static Map<RadComponent, List<RadComponent>> groupSiblings(@NotNull List<? extends RadComponent> components) {
+ Map<RadComponent, List<RadComponent>> siblingLists = new HashMap<RadComponent, List<RadComponent>>();
+
+ if (components.isEmpty()) {
+ return siblingLists;
+ }
+ if (components.size() == 1) {
+ RadComponent component = components.get(0);
+ siblingLists.put(component.getParent(), Collections.singletonList(component));
+ return siblingLists;
+ }
+
+ for (RadComponent component : components) {
+ RadComponent parent = component.getParent();
+ List<RadComponent> children = siblingLists.get(parent);
+ if (children == null) {
+ children = new ArrayList<RadComponent>();
+ siblingLists.put(parent, children);
+ }
+ children.add(component);
+ }
+
+ return siblingLists;
+ }
public static Set<RadComponent> getParents(List<RadComponent> components) {
Set<RadComponent> parents = new HashSet<RadComponent>();
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/model/RadVisualComponent.java b/plugins/ui-designer-core/src/com/intellij/designer/model/RadVisualComponent.java
index e9ff52595d45..c06402bb77b1 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/model/RadVisualComponent.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/model/RadVisualComponent.java
@@ -15,6 +15,9 @@
*/
package com.intellij.designer.model;
+import com.intellij.designer.designSurface.ScalableComponent;
+import org.jetbrains.annotations.NotNull;
+
import javax.swing.*;
import java.awt.*;
@@ -32,9 +35,119 @@ public abstract class RadVisualComponent extends RadComponent {
@Override
public Rectangle getBounds(Component relativeTo) {
- return myNativeComponent == relativeTo
- ? new Rectangle(getBounds()) :
- SwingUtilities.convertRectangle(myNativeComponent, getBounds(), relativeTo);
+ return fromModel(relativeTo, getBounds());
+ }
+
+ @Override
+ public Rectangle fromModel(@NotNull Component target, @NotNull Rectangle bounds) {
+ if (target != myNativeComponent && myNativeComponent instanceof ScalableComponent) {
+ ScalableComponent scalableComponent = (ScalableComponent)myNativeComponent;
+ double zoom = scalableComponent.getScale();
+
+ if (zoom != 1) {
+ bounds = new Rectangle(bounds);
+ bounds.x *= zoom;
+ bounds.y *= zoom;
+ bounds.width *= zoom;
+ bounds.height *= zoom;
+ }
+ }
+
+ return myNativeComponent == target
+ ? new Rectangle(bounds) :
+ SwingUtilities.convertRectangle(myNativeComponent, bounds, target);
+ }
+
+ @Override
+ public Rectangle toModel(@NotNull Component source, @NotNull Rectangle rectangle) {
+ Rectangle bounds = myNativeComponent == source
+ ? new Rectangle(rectangle) : SwingUtilities.convertRectangle(source, rectangle, myNativeComponent);
+
+ if (myNativeComponent != source && myNativeComponent instanceof ScalableComponent) {
+ ScalableComponent scalableComponent = (ScalableComponent)myNativeComponent;
+ double zoom = scalableComponent.getScale();
+
+ if (zoom != 1) {
+ bounds = new Rectangle(bounds);
+ bounds.x /= zoom;
+ bounds.y /= zoom;
+ bounds.width /= zoom;
+ bounds.height /= zoom;
+ }
+ }
+
+ return bounds;
+ }
+
+ @Override
+ public Point fromModel(@NotNull Component target, @NotNull Point point) {
+ if (target != myNativeComponent && myNativeComponent instanceof ScalableComponent) {
+ ScalableComponent scalableComponent = (ScalableComponent)myNativeComponent;
+ double zoom = scalableComponent.getScale();
+
+ if (zoom != 1) {
+ point = new Point(point);
+ point.x *= zoom;
+ point.y *= zoom;
+ }
+ }
+
+ return myNativeComponent == target
+ ? new Point(point) :
+ SwingUtilities.convertPoint(myNativeComponent, point, target);
+ }
+
+ @Override
+ public Point toModel(@NotNull Component source, @NotNull Point point) {
+ Point p = myNativeComponent == source
+ ? new Point(point) : SwingUtilities.convertPoint(source, point, myNativeComponent);
+
+ if (myNativeComponent != source && myNativeComponent instanceof ScalableComponent) {
+ ScalableComponent scalableComponent = (ScalableComponent)myNativeComponent;
+ double zoom = scalableComponent.getScale();
+
+ if (zoom != 1) {
+ p = new Point(p);
+ p.x /= zoom;
+ p.y /= zoom;
+ }
+ }
+
+ return p;
+ }
+
+ @Override
+ public Dimension fromModel(@NotNull Component target, @NotNull Dimension size) {
+ size = new Dimension(size);
+
+ if (target != myNativeComponent && myNativeComponent instanceof ScalableComponent) {
+ ScalableComponent scalableComponent = (ScalableComponent)myNativeComponent;
+ double zoom = scalableComponent.getScale();
+
+ if (zoom != 1) {
+ size.width *= zoom;
+ size.height *= zoom;
+ }
+ }
+
+ return size;
+ }
+
+ @Override
+ public Dimension toModel(@NotNull Component source, @NotNull Dimension size) {
+ size = new Dimension(size);
+
+ if (myNativeComponent != source && myNativeComponent instanceof ScalableComponent) {
+ ScalableComponent scalableComponent = (ScalableComponent)myNativeComponent;
+ double zoom = scalableComponent.getScale();
+
+ if (zoom != 1) {
+ size.width /= zoom;
+ size.height /= zoom;
+ }
+ }
+
+ return size;
}
public void setBounds(int x, int y, int width, int height) {
@@ -43,9 +156,19 @@ public abstract class RadVisualComponent extends RadComponent {
@Override
public Point convertPoint(Component relativeFrom, int x, int y) {
- return myNativeComponent == relativeFrom
- ? new Point(x, y) :
- SwingUtilities.convertPoint(relativeFrom, x, y, myNativeComponent);
+ Point p = myNativeComponent == relativeFrom ? new Point(x, y) : SwingUtilities.convertPoint(relativeFrom, x, y, myNativeComponent);
+
+ if (myNativeComponent != relativeFrom && myNativeComponent instanceof ScalableComponent) {
+ ScalableComponent scalableComponent = (ScalableComponent)myNativeComponent;
+ double zoom = scalableComponent.getScale();
+
+ if (zoom != 1) {
+ p.x /= zoom;
+ p.y /= zoom;
+ }
+ }
+
+ return p;
}
public Component getNativeComponent() {
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/model/VariationPaletteItem.java b/plugins/ui-designer-core/src/com/intellij/designer/model/VariationPaletteItem.java
new file mode 100644
index 000000000000..81c761fd175c
--- /dev/null
+++ b/plugins/ui-designer-core/src/com/intellij/designer/model/VariationPaletteItem.java
@@ -0,0 +1,105 @@
+package com.intellij.designer.model;
+
+import com.intellij.designer.palette.PaletteItem;
+import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * Implementation of a {@link PaletteItem} which delegates to another {@linkplain PaletteItem}
+ * but which possibly overrides the title, icon and or creation properties.
+ */
+final class VariationPaletteItem implements PaletteItem {
+ private final PaletteItem myDefaultItem;
+ private final MetaModel myModel;
+ private final String myTitle;
+ private final String myIconPath;
+ private final String myTooltip;
+ private final String myCreation;
+ private Icon myIcon;
+
+ VariationPaletteItem(PaletteItem defaultItem, MetaModel model, Element element) {
+ myDefaultItem = defaultItem;
+ myModel = model;
+
+ String title = element.getAttributeValue("title");
+ if (StringUtil.isEmpty(title)) {
+ title = myDefaultItem.getTitle();
+ }
+ myTitle = title;
+
+ String iconPath = element.getAttributeValue("icon");
+ if (StringUtil.isEmpty(iconPath)) {
+ myIcon = myDefaultItem.getIcon();
+ }
+ myIconPath = iconPath;
+
+ String tooltip = element.getAttributeValue("tooltip");
+ if (StringUtil.isEmpty(tooltip)) {
+ tooltip = myDefaultItem.getTooltip();
+ }
+ myTooltip = tooltip;
+
+ Element creation = element.getChild("creation");
+ if (creation != null) {
+ myCreation = creation.getTextTrim();
+ }
+ else {
+ myCreation = myModel.getCreation();
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return myTitle;
+ }
+
+ @Override
+ public Icon getIcon() {
+ if (myIcon == null) {
+ assert myIconPath != null;
+ myIcon = IconLoader.findIcon(myIconPath, myModel.getModel());
+ }
+ return myIcon;
+ }
+
+ @Override
+ public String getTooltip() {
+ return myTooltip;
+ }
+
+ @Override
+ public String getVersion() {
+ return myDefaultItem.getVersion();
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return myDefaultItem.isEnabled();
+ }
+
+ @Override
+ public String getCreation() {
+ return myCreation;
+ }
+
+ @Override
+ public MetaModel getMetaModel() {
+ return myModel;
+ }
+
+ @Nullable
+ @Override
+ public String getDeprecatedIn() {
+ return myDefaultItem.getDeprecatedIn();
+ }
+
+ @Nullable
+ @Override
+ public String getDeprecatedHint() {
+ return myDefaultItem.getDeprecatedHint();
+ }
+} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/DefaultPaletteItem.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/DefaultPaletteItem.java
index 985e8625b7f6..4ae4ae9ddee9 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/palette/DefaultPaletteItem.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/DefaultPaletteItem.java
@@ -18,6 +18,7 @@ package com.intellij.designer.palette;
import com.intellij.designer.model.MetaModel;
import com.intellij.openapi.util.IconLoader;
import org.jdom.Element;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -31,6 +32,8 @@ public class DefaultPaletteItem implements PaletteItem {
private final String myTooltip;
private final String myVersion;
private boolean myEnabled = true;
+ private final String myDeprecatedVersion;
+ private final String myDeprecatedHint;
protected MetaModel myMetaModel;
@@ -38,14 +41,23 @@ public class DefaultPaletteItem implements PaletteItem {
this(palette.getAttributeValue("title"),
palette.getAttributeValue("icon"),
palette.getAttributeValue("tooltip"),
- palette.getAttributeValue("version"));
+ palette.getAttributeValue("version"),
+ palette.getAttributeValue("deprecated"),
+ palette.getAttributeValue("deprecatedHint"));
}
- public DefaultPaletteItem(String title, String iconPath, String tooltip, String version) {
+ public DefaultPaletteItem(String title,
+ String iconPath,
+ String tooltip,
+ String version,
+ String deprecatedVersion,
+ String deprecatedHint) {
myTitle = title;
myIconPath = iconPath;
myTooltip = tooltip;
myVersion = version;
+ myDeprecatedVersion = deprecatedVersion;
+ myDeprecatedHint = deprecatedHint;
}
@Override
@@ -80,6 +92,24 @@ public class DefaultPaletteItem implements PaletteItem {
myEnabled = enabled;
}
+ @Nullable
+ @Override
+ public String getDeprecatedIn() {
+ return myDeprecatedVersion;
+ }
+
+ @Nullable
+ @Override
+ public String getDeprecatedHint() {
+ return myDeprecatedHint;
+ }
+
+ @Override
+ public String getCreation() {
+ return myMetaModel.getCreation();
+ }
+
+ @Override
public MetaModel getMetaModel() {
return myMetaModel;
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItem.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItem.java
index 9c05cd1faba8..8cf9578fce75 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItem.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItem.java
@@ -15,6 +15,9 @@
*/
package com.intellij.designer.palette;
+import com.intellij.designer.model.MetaModel;
+import org.jetbrains.annotations.Nullable;
+
import javax.swing.*;
/**
@@ -30,4 +33,31 @@ public interface PaletteItem {
String getVersion();
boolean isEnabled();
+
+ /**
+ * Returns null or empty if this item is not deprecated, and otherwise returns the version
+ * the item was deprecated in.
+ *
+ * @return null or empty if the item is not deprecated, otherwise a version
+ */
+ @Nullable
+ String getDeprecatedIn();
+
+ /**
+ * Returns a hint regarding the deprecation. Can be null or empty.
+ *
+ * @return a hint describing the deprecated item.
+ */
+ @Nullable
+ String getDeprecatedHint();
+
+ /**
+ * @return the creation data to be used by {@link com.intellij.designer.model.MetaModel#getCreation()}
+ */
+ String getCreation();
+
+ /**
+ * Returns the associated {@link com.intellij.designer.model.MetaModel}, if known
+ */
+ MetaModel getMetaModel();
} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItemsComponent.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItemsComponent.java
index 2f523a681328..cecf8126b114 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItemsComponent.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteItemsComponent.java
@@ -42,6 +42,8 @@ import java.awt.event.MouseListener;
* @author Alexander Lobas
*/
public class PaletteItemsComponent extends JBList {
+ private static final SimpleTextAttributes DEPRECATED_ATTRIBUTES = new SimpleTextAttributes(SimpleTextAttributes.STYLE_STRIKEOUT, null);
+
private final PaletteGroup myGroup;
private final DesignerEditorPanel myDesigner;
private int myBeforeClickSelectedRow = -1;
@@ -81,22 +83,34 @@ public class PaletteItemsComponent extends JBList {
}
String title = item.getTitle();
- append(title, SimpleTextAttributes.REGULAR_ATTRIBUTES);
-
String tooltip = item.getTooltip();
- String version = item.getVersion();
- if (version == null) {
- version = "";
- }
- else {
+ String version = myDesigner.getVersionLabel(item.getVersion());
+ String deprecatedIn = item.getDeprecatedIn();
+ boolean deprecated = myDesigner.isDeprecated(deprecatedIn);
+
+ append(title, deprecated ? DEPRECATED_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
+
+ if (!version.isEmpty()) {
version = "<sup><i>" + version + "</i></sup>";
}
if (tooltip != null) {
+ String deprecatedMessage = "";
+ if (deprecated) {
+ deprecatedMessage =
+ String.format("<b>This item is deprecated in version \"%1$s\".<br>", myDesigner.getVersionLabel(deprecatedIn));
+ String hint = item.getDeprecatedHint();
+ if (!StringUtil.isEmpty(hint)) {
+ deprecatedMessage += hint;
+ }
+ deprecatedMessage += "</b><br><br>";
+ }
+
tooltip = "<html><body><center><b>" +
StringUtil.escapeXml(title) +
"</b>" +
version +
"</center><p style='width: 300px'>" +
+ deprecatedMessage +
tooltip +
"</p></body></html>";
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java
index 91a90c381391..a10ea8c3f048 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java
@@ -16,6 +16,7 @@
package com.intellij.designer.palette;
import com.intellij.designer.AbstractToolWindowManager;
+import com.intellij.designer.DesignerCustomizations;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -51,7 +52,10 @@ public class PaletteToolWindowManager extends AbstractToolWindowManager {
@Override
protected void initToolWindow() {
- myToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow("Palette\t", false, ToolWindowAnchor.RIGHT, myProject, true);
+ DesignerCustomizations customization = getCustomizations();
+ ToolWindowAnchor anchor = customization != null ? customization.getPaletteAnchor() : ToolWindowAnchor.RIGHT;
+
+ myToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow("Palette\t", false, anchor, myProject, true);
myToolWindow.setIcon(AllIcons.Toolwindows.ToolWindowPalette);
ContentManager contentManager = myToolWindow.getContentManager();
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/actions/RestoreDefault.java b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/actions/RestoreDefault.java
index 54303b0e6b67..fa4527a64e53 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/actions/RestoreDefault.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/actions/RestoreDefault.java
@@ -36,7 +36,7 @@ public class RestoreDefault extends AnAction implements IPropertyTableAction {
String text = DesignerBundle.message("designer.properties.restore_default");
presentation.setText(text);
presentation.setDescription(text);
- presentation.setIcon(AllIcons.Actions.Reset_to_default);
+ presentation.setIcon(AllIcons.General.Reset);
}
@Override
diff --git a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java
index 60ce10a7f051..63a1fb4aff85 100644
--- a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java
+++ b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsBindingManager.java
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.builders.java.JavaBuilderUtil;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.java.CopyResourcesUtil;
@@ -103,7 +104,7 @@ public class FormsBindingManager extends FormsBuilder {
final Map<File, ModuleBuildTarget> formsToCompile = new THashMap<File, ModuleBuildTarget>(FileUtil.FILE_HASHING_STRATEGY);
final Map<File, Collection<File>> srcToForms = new THashMap<File, Collection<File>>(FileUtil.FILE_HASHING_STRATEGY);
- if (!context.isProjectRebuild() && config.isInstrumentClasses() && FORCE_FORMS_REBUILD_FLAG.get(context, Boolean.FALSE)) {
+ if (!JavaBuilderUtil.isForcedRecompilationAllJavaModules(context) && config.isInstrumentClasses() && FORCE_FORMS_REBUILD_FLAG.get(context, Boolean.FALSE)) {
// force compilation of all forms, but only once per chunk
if (!FORMS_REBUILD_FORCED.get(context, Boolean.FALSE)) {
FORMS_REBUILD_FORCED.set(context, Boolean.TRUE);
diff --git a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
index 146354137d0e..f2d2b9a05a02 100644
--- a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
+++ b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
@@ -31,10 +31,12 @@ import org.jetbrains.asm4.ClassReader;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.ProjectPaths;
import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.java.JavaBuilderUtil;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.instrumentation.BaseInstrumentingBuilder;
+import org.jetbrains.jps.incremental.instrumentation.ClassProcessingBuilder;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
@@ -77,7 +79,7 @@ public class FormsInstrumenter extends FormsBuilder {
formsToCompile.addAll(files);
}
- if (context.isMake()) {
+ if (JavaBuilderUtil.isCompileJavaIncrementally(context)) {
final ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
if (logger.isEnabled()) {
logger.logCompiledFiles(formsToCompile, getPresentableName(), "Compiling forms:");
@@ -93,8 +95,7 @@ public class FormsInstrumenter extends FormsBuilder {
final Map<File, String> chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk);
classpath.addAll(chunkSourcePath.keySet()); // sourcepath for loading forms resources
- final InstrumentationClassFinder finder =
- BaseInstrumentingBuilder.createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
+ final InstrumentationClassFinder finder = ClassProcessingBuilder.createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
try {
final Map<File, Collection<File>> processed = instrumentForms(context, chunk, chunkSourcePath, finder, formsToCompile, outputConsumer);
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java
index 9cae19b9c707..8a2eaf255a03 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java
@@ -38,6 +38,7 @@ import com.intellij.uiDesigner.propertyInspector.editors.IntEnumEditor;
import com.intellij.uiDesigner.propertyInspector.properties.*;
import com.intellij.uiDesigner.propertyInspector.renderers.IntEnumRenderer;
import com.intellij.uiDesigner.radComponents.RadComponent;
+import com.intellij.util.containers.ContainerUtil;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
@@ -72,12 +73,12 @@ public final class Palette implements ProjectComponent, PersistentStateComponent
private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.palette.Palette");
private final MyLafManagerListener myLafManagerListener;
- private final HashMap<Class, IntrospectedProperty[]> myClass2Properties;
- private final HashMap<String, ComponentItem> myClassName2Item;
+ private final Map<Class, IntrospectedProperty[]> myClass2Properties;
+ private final Map<String, ComponentItem> myClassName2Item;
/*All groups in the palette*/
private final ArrayList<GroupItem> myGroups;
/*Listeners, etc*/
- private final ArrayList<Listener> myListeners;
+ private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private final Project myProject;
private final GroupItem mySpecialGroup = new GroupItem(true);
@@ -122,7 +123,6 @@ public final class Palette implements ProjectComponent, PersistentStateComponent
myClass2Properties = new HashMap<Class, IntrospectedProperty[]>();
myClassName2Item = new HashMap<String, ComponentItem>();
myGroups = new ArrayList<GroupItem>();
- myListeners = new ArrayList<Listener>();
if (project != null) {
mySpecialGroup.setReadOnly(true);
@@ -154,8 +154,7 @@ public final class Palette implements ProjectComponent, PersistentStateComponent
}
void fireGroupsChanged() {
- final Listener[] listeners = myListeners.toArray(new Listener[myListeners.size()]);
- for(Listener listener : listeners) {
+ for(Listener listener : myListeners) {
listener.groupsChanged(this);
}
}
@@ -614,7 +613,8 @@ public final class Palette implements ProjectComponent, PersistentStateComponent
for (final PropertyDescriptor descriptor : descriptors) {
Method readMethod = descriptor.getReadMethod();
Method writeMethod = descriptor.getWriteMethod();
- if (writeMethod == null || readMethod == null) {
+ Class propertyType = descriptor.getPropertyType();
+ if (writeMethod == null || readMethod == null || propertyType == null) {
continue;
}
@@ -631,7 +631,6 @@ public final class Palette implements ProjectComponent, PersistentStateComponent
final IntrospectedProperty property;
- final Class propertyType = descriptor.getPropertyType();
final Properties properties = (myProject == null) ? new Properties() : Properties.getInstance();
if (int.class.equals(propertyType)) { // int
IntEnumEditor.Pair[] enumPairs = properties.getEnumPairs(aClass, name);
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java
index 82bff0979708..4a4e34dae8a3 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java
@@ -39,6 +39,7 @@ import com.intellij.uiDesigner.componentTree.ComponentTree;
import com.intellij.uiDesigner.componentTree.ComponentTreeBuilder;
import com.intellij.uiDesigner.designSurface.GuiEditor;
import com.intellij.uiDesigner.editor.UIFormEditor;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import icons.UIDesignerIcons;
@@ -51,7 +52,6 @@ import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -67,7 +67,7 @@ public class UIDesignerToolWindowManager implements ProjectComponent {
private ToolWindow myToolWindow;
private boolean myToolWindowReady = false;
private boolean myToolWindowDisposed = false;
- private List<TreeSelectionListener> myPendingListeners = new ArrayList<TreeSelectionListener>();
+ private final List<TreeSelectionListener> myPendingListeners = ContainerUtil.createLockFreeCopyOnWriteList();
public UIDesignerToolWindowManager(final Project project, final FileEditorManager fileEditorManager) {
myProject = project;
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/ClientPropertiesProperty.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/ClientPropertiesProperty.java
index 3a618b96ecd0..3b775cd0a329 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/ClientPropertiesProperty.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/ClientPropertiesProperty.java
@@ -79,7 +79,7 @@ public class ClientPropertiesProperty extends ReadOnlyProperty {
myTf.setText(UIDesignerBundle.message("client.properties.configure"));
myTf.getTextField().setEditable(false);
myTf.getTextField().setBorder(null);
- myTf.getTextField().setForeground(JBColor.foreground);
+ myTf.getTextField().setForeground(JBColor.foreground());
myTf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showClientPropertiesDialog();
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/GridLayoutColumnProperties.java b/plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/GridLayoutColumnProperties.java
index 2f5f8a83f5c2..e77e15314fb3 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/GridLayoutColumnProperties.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/radComponents/GridLayoutColumnProperties.java
@@ -21,13 +21,13 @@ import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.propertyInspector.Property;
import com.intellij.uiDesigner.propertyInspector.properties.HSizePolicyProperty;
import com.intellij.uiDesigner.propertyInspector.properties.VSizePolicyProperty;
+import com.intellij.util.containers.ContainerUtil;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -40,7 +40,7 @@ public class GridLayoutColumnProperties implements CustomPropertiesPanel {
private RadContainer myContainer;
private boolean myRow;
private int mySelectedIndex;
- private final List<ChangeListener> myListeners = new ArrayList<ChangeListener>();
+ private final List<ChangeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
public GridLayoutColumnProperties() {
myWantGrowCheckBox.addActionListener(new ActionListener() {
diff --git a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java
index 0d32e004d534..f889fe6cee5e 100644
--- a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java
+++ b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java
@@ -23,6 +23,7 @@ import com.intellij.projectView.BaseProjectViewTestCase;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
+import com.intellij.testFramework.ProjectViewTestUtil;
public class FormMergerTreeStructureProviderTest extends BaseProjectViewTestCase {
@@ -32,7 +33,7 @@ public class FormMergerTreeStructureProviderTest extends BaseProjectViewTestCase
}
public void testStandardProviders() {
- final AbstractProjectViewPSIPane pane = createPane();
+ final AbstractProjectViewPSIPane pane = myStructure.createPane();
getProjectTreeStructure().setProviders(new ClassesTreeStructureProvider(myProject),
new FormMergerTreeStructureProvider(myProject));
@@ -48,11 +49,11 @@ public class FormMergerTreeStructureProviderTest extends BaseProjectViewTestCase
" PsiFile(plain text):Form1.form\n");
PsiClass psiClass = ((PsiJavaFile)getPackageDirectory().findFile("Form1.java")).getClasses()[0];
- checkNavigateFromSourceBehaviour(psiClass, psiClass.getContainingFile().getVirtualFile(), pane);
+ ProjectViewTestUtil.checkNavigateFromSourceBehaviour(psiClass, psiClass.getContainingFile().getVirtualFile(), pane);
PsiFile psiFile = getPackageDirectory().findFile("Form1.form");
VirtualFile virtualFile = psiFile.getContainingFile().getVirtualFile();
- checkNavigateFromSourceBehaviour(psiFile, virtualFile, pane);
+ ProjectViewTestUtil.checkNavigateFromSourceBehaviour(psiFile, virtualFile, pane);
}
}
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java
index e2d3277351a7..d0667a103ac8 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java
@@ -58,9 +58,9 @@ public class XsltReferenceContributor {
public static class XML extends PsiReferenceContributor {
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(
- psiElement(XmlAttributeValue.class).withParent(xmlAttribute().withLocalName(string().oneOf(
- "name", "href", "mode", "elements", "exclude-result-prefixes", "extension-element-prefixes", "stylesheet-prefix"
- )).withParent(xmlTag().withNamespace(XsltSupport.XSLT_NS))),
+ psiElement(XmlAttributeValue.class).withParent(
+ xmlAttribute().withLocalName("name", "href", "mode", "elements", "exclude-result-prefixes", "extension-element-prefixes", "stylesheet-prefix").withParent(
+ xmlTag().withNamespace(XsltSupport.XSLT_NS))),
new XsltReferenceProvider());
registrar.registerReferenceProvider(
diff --git a/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathAppComponent.java b/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathAppComponent.java
index 6d96250b90b3..cceed7925c71 100644
--- a/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathAppComponent.java
+++ b/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathAppComponent.java
@@ -195,7 +195,7 @@ public class XPathAppComponent implements ApplicationComponent, JDOMExternalizab
label.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.WHITE, Gray._128),
BorderFactory.createEmptyBorder(3, 5, 3, 5)));
- label.setForeground(JBColor.foreground);
+ label.setForeground(JBColor.foreground());
label.setBackground(HintUtil.INFORMATION_COLOR);
label.setOpaque(true);
label.setFont(label.getFont().deriveFont(Font.BOLD));
diff --git a/plugins/xslt-debugger/engine/xslt-debugger-engine.iml b/plugins/xslt-debugger/engine/xslt-debugger-engine.iml
index 7567de0d98fb..c322da283ea6 100644
--- a/plugins/xslt-debugger/engine/xslt-debugger-engine.iml
+++ b/plugins/xslt-debugger/engine/xslt-debugger-engine.iml
@@ -18,7 +18,7 @@
<SOURCES />
</library>
</orderEntry>
- <orderEntry type="library" name="Trove4j" level="project" />
+ <orderEntry type="library" exported="" name="Trove4j" level="project" />
</component>
</module>
diff --git a/plugins/xslt-debugger/xslt-debugger.iml b/plugins/xslt-debugger/xslt-debugger.iml
index 6809acd95195..973d062e5308 100644
--- a/plugins/xslt-debugger/xslt-debugger.iml
+++ b/plugins/xslt-debugger/xslt-debugger.iml
@@ -18,11 +18,11 @@
<orderEntry type="module" module-name="xdebugger-impl" />
<orderEntry type="module" module-name="xml-openapi" />
<orderEntry type="module" module-name="compiler-impl" />
- <orderEntry type="module" module-name="openapi" />
<orderEntry type="module" module-name="xml" />
<orderEntry type="module" module-name="execution-openapi" />
<orderEntry type="module" module-name="debugger-impl" />
<orderEntry type="module" module-name="platform-impl" />
+ <orderEntry type="module" module-name="vcs-api" />
</component>
</module>