From 6169cf7a3eaaef7222f6ac51b4a7fc0261dceb00 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Mon, 14 May 2012 10:43:53 +0400 Subject: [PATCH] IDEA-19061 Integrate the Rearranger-plugin into core-IDEA Initial bundling iteration. The changes to the initial version available at http://java.net/projects/rearranger/sources: * switched from log4j to IJ logging; * 'Rearranger' component is service now; * plugin descriptor is adapted to the common IJ scheme (id, vendor etc); * IJ project is configured to have new 'rearranger' module; * build script is adjusted to process 'rearranger' plugin as well; * almost all tests are commented and their refactoring is started; --- .idea/modules.xml | 1 + build/scripts/layouts.gant | 6 + community-main.iml | 1 + plugins/rearranger/rearranger.iml | 21 + plugins/rearranger/src/META-INF/plugin.xml | 46 + .../com/wrq/rearranger/ClassInitializer.png | Bin 0 -> 775 bytes .../wrq/rearranger/LiveRearrangerAction.java | 36 + .../LiveRearrangerActionHandler.java | 206 ++ .../com/wrq/rearranger/ModifierConstants.java | 59 + .../rearranger/ProjectTreeActionHandler.java | 347 +++ .../src/com/wrq/rearranger/Rearranger.java | 212 ++ .../com/wrq/rearranger/RearrangerAction.java | 34 + .../rearranger/RearrangerActionHandler.java | 227 ++ .../src/com/wrq/rearranger/RearrangerIcon.png | Bin 0 -> 2139 bytes .../src/com/wrq/rearranger/ShowComments.png | Bin 0 -> 148 bytes .../src/com/wrq/rearranger/ShowFields.png | Bin 0 -> 637 bytes .../com/wrq/rearranger/ShowMatchedRules.png | Bin 0 -> 744 bytes .../src/com/wrq/rearranger/ShowParamNames.png | Bin 0 -> 757 bytes .../src/com/wrq/rearranger/ShowParamTypes.png | Bin 0 -> 752 bytes .../src/com/wrq/rearranger/ShowRules.png | Bin 0 -> 748 bytes .../wrq/rearranger/ShowTypeAfterMethod.png | Bin 0 -> 650 bytes .../wrq/rearranger/StaticClassInitializer.png | Bin 0 -> 783 bytes .../src/com/wrq/rearranger/TestOverImpl.java | 58 + .../com/wrq/rearranger/WaitableBoolean.java | 69 + .../configuration/ChoiceObject.java | 66 + .../rearranger/configuration/ChoicePanel.java | 155 ++ .../ClassMemberSettingsPane.java | 95 + .../configuration/ClassOrderSettingsPane.java | 65 + .../configuration/ExtractedMethodsPane.java | 428 ++++ .../configuration/IListManagerObject.java | 35 + .../IListManagerObjectFactory.java | 31 + .../configuration/IntTextField.java | 94 + .../rearranger/configuration/ListManager.java | 303 +++ .../rearranger/configuration/MethodSpec.java | 227 ++ .../RearrangerSettingsPanel.java | 566 +++++ .../configuration/RelatedByNamePane.java | 217 ++ .../configuration/SettingsPane.java | 549 +++++ .../rearranger/configuration/SpacingPane.java | 145 ++ .../configuration/StringTextArea.java | 58 + .../configuration/StringTextField.java | 56 + .../rearranger/configuration/TableMap.java | 103 + .../rearranger/configuration/TableSorter.java | 341 +++ .../wrq/rearranger/defaultConfiguration.xml | 360 +++ .../rearranger/entry/ClassContentsEntry.java | 68 + .../com/wrq/rearranger/entry/ClassEntry.java | 576 +++++ .../entry/ClassInitializerEntry.java | 68 + .../com/wrq/rearranger/entry/FieldEntry.java | 116 + .../entry/IPopupTreeRangeEntry.java | 45 + .../wrq/rearranger/entry/IRelatableEntry.java | 61 + .../rearranger/entry/MemberAttributes.java | 41 + .../com/wrq/rearranger/entry/MethodEntry.java | 1288 ++++++++++ .../entry/MiscellaneousTextEntry.java | 67 + .../wrq/rearranger/entry/PsiFileEntry.java | 93 + .../com/wrq/rearranger/entry/RangeEntry.java | 306 +++ .../rearranger/popup/FileStructurePopup.java | 352 +++ .../wrq/rearranger/popup/IFilePopupEntry.java | 41 + .../wrq/rearranger/popup/IHasScrollPane.java | 32 + .../wrq/rearranger/popup/ILiveRearranger.java | 34 + .../src/com/wrq/rearranger/popup/IconBox.java | 229 ++ .../popup/LiveRearrangerDialog.java | 321 +++ .../rearranger/popup/LiveRearrangerPopup.java | 638 +++++ .../com/wrq/rearranger/popup/PopupTree.java | 283 +++ .../rearranger/popup/PopupTreeComponent.java | 361 +++ .../rearranger/popup/RearrangerTreeNode.java | 35 + .../popup/TransferableTreeNode.java | 57 + .../wrq/rearranger/popup/TreeDragSource.java | 93 + .../wrq/rearranger/popup/TreeDropTarget.java | 273 ++ .../wrq/rearranger/rearrangement/Emitter.java | 69 + .../rearrangement/GenericRearranger.java | 202 ++ .../wrq/rearranger/rearrangement/Mover.java | 66 + .../wrq/rearranger/rearrangement/Parser.java | 74 + .../wrq/rearranger/rearrangement/Spacer.java | 685 ++++++ .../ruleinstance/CommentRuleInstance.java | 187 ++ .../CommentRuleInstanceFactory.java | 47 + .../ruleinstance/CommonRuleInstance.java | 160 ++ .../ruleinstance/DefaultRuleInstance.java | 35 + .../EmitAlwaysCommentRuleInstance.java | 43 + .../HeaderTrailerRuleInstance.java | 81 + .../ruleinstance/IRuleInstance.java | 71 + .../ruleinstance/InterfaceInstance.java | 146 ++ .../ruleinstance/InterfaceRuleInstance.java | 136 + .../PrecedingCommentRuleInstance.java | 49 + .../SubsequentCommentRuleInstance.java | 50 + .../SurroundingCommentRuleInstance.java | 57 + .../settings/CommentFillString.java | 196 ++ .../wrq/rearranger/settings/CommentRule.java | 613 +++++ .../settings/ForceBlankLineSetting.java | 131 + .../settings/PrimaryMethodSetting.java | 386 +++ .../settings/RearrangerSettings.java | 683 +++++ .../RelatedByNameMethodsSettings.java | 45 + .../settings/RelatedMethodsSettings.java | 247 ++ .../settings/SecondaryMethodSetting.java | 307 +++ .../atomicAttributes/AbstractAttribute.java | 55 + .../atomicAttributes/AndNotAttribute.java | 152 ++ .../atomicAttributes/AtomicAttribute.java | 33 + .../atomicAttributes/EnumAttribute.java | 55 + .../atomicAttributes/FinalAttribute.java | 55 + .../ImplementedAttribute.java | 54 + .../ImplementingAttribute.java | 53 + .../InitToAnonClassAttribute.java | 53 + .../InitializerAttribute.java | 55 + .../atomicAttributes/IntegerAttribute.java | 172 ++ .../atomicAttributes/MaxParamsAttribute.java | 53 + .../atomicAttributes/MinParamsAttribute.java | 53 + .../atomicAttributes/NameAttribute.java | 57 + .../atomicAttributes/NativeAttribute.java | 55 + .../atomicAttributes/OverriddenAttribute.java | 54 + .../atomicAttributes/OverridingAttribute.java | 53 + .../ProtectionLevelAttributes.java | 264 ++ .../atomicAttributes/ReturnTypeAttribute.java | 57 + .../atomicAttributes/SortOptions.java | 259 ++ .../atomicAttributes/StaticAttribute.java | 55 + .../atomicAttributes/StringAttribute.java | 171 ++ .../SynchronizedAttribute.java | 55 + .../atomicAttributes/TransientAttribute.java | 55 + .../atomicAttributes/TypeAttribute.java | 58 + .../atomicAttributes/VolatileAttribute.java | 55 + .../attributeGroups/AttributeGroup.java | 36 + .../attributeGroups/ClassAttributes.java | 180 ++ .../attributeGroups/CommonAttributes.java | 184 ++ .../settings/attributeGroups/DefaultRule.java | 72 + .../attributeGroups/FieldAttributes.java | 214 ++ .../GetterSetterDefinition.java | 326 +++ .../settings/attributeGroups/HeaderRule.java | 66 + .../IHasGetterSetterDefinition.java | 30 + .../attributeGroups/IPrioritizableRule.java | 29 + .../IRestrictMethodExtraction.java | 32 + .../settings/attributeGroups/IRule.java | 63 + .../attributeGroups/InnerClassAttributes.java | 174 ++ .../attributeGroups/InterfaceAttributes.java | 459 ++++ .../attributeGroups/ItemAttributes.java | 62 + .../attributeGroups/MethodAttributes.java | 680 +++++ .../settings/attributeGroups/RegexUtil.java | 344 +++ .../settings/attributeGroups/TrailerRule.java | 66 + .../com/wrq/rearranger/util/CommentUtil.java | 244 ++ .../com/wrq/rearranger/util/Constraints.java | 321 +++ .../src/com/wrq/rearranger/util/IconUtil.java | 77 + .../com/wrq/rearranger/util/MethodUtil.java | 241 ++ .../wrq/rearranger/util/ModifierUtils.java | 52 + .../com/wrq/rearranger/InteractiveTest.java | 163 ++ .../com/wrq/rearranger/RearrangerTest.groovy | 2188 +++++++++++++++++ .../settings/CommentFillStringTest.java | 27 + .../attributeGroups/MethodAttributesTest.java | 66 + .../attributeGroups/RegexUtilTest.java | 25 + .../rearranger/testClasses/TestClass1.java | 19 + .../rearranger/testClasses/TestClass2.java | 38 + .../wrq/rearranger/testClasses/TestEnum.java | 24 + .../testClasses/TestImplementation.java | 13 + .../rearranger/testClasses/TestInterface.java | 19 + .../rearranger/testClasses/TestOverride.java | 20 + .../wrq/rearranger/util/CommentUtilTest.java | 57 + .../com/wrq/rearranger/BitFieldResult.java | 388 +++ .../com/wrq/rearranger/BitFieldTest.java | 375 +++ .../rearranger/CommentSeparatorResult1.java | 6 + .../wrq/rearranger/CommentSeparatorTest1.java | 3 + .../rearranger/CorruptRespacingResult.java | 15 + .../wrq/rearranger/CorruptRespacingTest.java | 12 + .../com/wrq/rearranger/CorruptionConfig.xml | 557 +++++ .../wrq/rearranger/DomainExpanderResult.java | 230 ++ .../wrq/rearranger/DomainExpanderTest.java | 231 ++ .../com/wrq/rearranger/Enum1Result.java | 715 ++++++ .../com/wrq/rearranger/Enum1Test.java | 696 ++++++ .../com/wrq/rearranger/Enum2AResult.java | 26 + .../com/wrq/rearranger/Enum2Result.java | 31 + .../com/wrq/rearranger/Enum2Test.java | 24 + .../com/wrq/rearranger/GenericsResult1.java | 8 + .../com/wrq/rearranger/GenericsTest1.java | 5 + .../GetFieldReturnsFieldResult.java | 33 + .../wrq/rearranger/GetFieldReturnsResult.java | 33 + .../rearranger/GetPrefixImmaterialResult.java | 32 + .../GetPrefixReturnsFieldResult.java | 33 + .../rearranger/GetPrefixReturnsResult.java | 33 + .../wrq/rearranger/GetterDefinitionTest.java | 33 + .../wrq/rearranger/IncompleteLineResult.java | 22 + .../wrq/rearranger/IncompleteLineTest.java | 20 + .../com/wrq/rearranger/InterfaceResult1.java | 8 + .../com/wrq/rearranger/InterfaceTest1.java | 9 + .../NoRearrangeInnerClassResult.java | 25 + .../rearranger/NoRearrangeInnerClassTest.java | 12 + .../NoRearrangementInnerClassCfg.xml | 185 ++ .../rearranger/NoRearrangementResult1.java | 57 + .../com/wrq/rearranger/OpsBlockingQueue.java | 70 + .../rearranger/OpsBlockingQueueIndented.java | 75 + .../OpsBlockingQueueIndentedResult.java | 71 + .../com/wrq/rearranger/OverloadedConfig.xml | 500 ++++ .../com/wrq/rearranger/OverloadedResult1.java | 11 + .../com/wrq/rearranger/OverloadedTest1.java | 11 + .../wrq/rearranger/RearrangementResult10.java | 58 + .../wrq/rearranger/RearrangementResult11.java | 8 + .../wrq/rearranger/RearrangementResult12.java | 21 + .../wrq/rearranger/RearrangementResult13.java | 28 + .../rearranger/RearrangementResult13BA.java | 28 + .../rearranger/RearrangementResult13BI.java | 28 + .../RearrangementResult13BIELC.java | 52 + .../RearrangementResult13BIEMC.java | 84 + .../RearrangementResult13BINFC.java | 32 + .../RearrangementResult13BITLC.java | 36 + .../rearranger/RearrangementResult13BO.java | 28 + .../rearranger/RearrangementResult13DA.java | 28 + .../rearranger/RearrangementResult13DI.java | 28 + .../RearrangementResult13DIELC.java | 60 + .../RearrangementResult13DIEMC.java | 84 + .../RearrangementResult13DINFC.java | 32 + .../RearrangementResult13DITLC.java | 36 + .../rearranger/RearrangementResult13DO.java | 28 + .../rearranger/RearrangementResult13Ex.java | 28 + .../wrq/rearranger/RearrangementResult14.java | 14 + .../wrq/rearranger/RearrangementResult18.java | 34 + .../rearranger/RearrangementResult18A.java | 35 + .../rearranger/RearrangementResult18B.java | 29 + .../rearranger/RearrangementResult19A.java | 24 + .../rearranger/RearrangementResult19B.java | 24 + .../rearranger/RearrangementResult19C.java | 25 + .../wrq/rearranger/RearrangementResult1A.java | 58 + .../wrq/rearranger/RearrangementResult2.java | 57 + .../wrq/rearranger/RearrangementResult20.java | 18 + .../wrq/rearranger/RearrangementResult21.java | 3 + .../wrq/rearranger/RearrangementResult22.java | 11 + .../RearrangementResult23BNNANXME.java | 39 + .../RearrangementResult23NNIANXME.java | 42 + .../RearrangementResult23NNNANXMA.java | 42 + .../RearrangementResult23NNNANXME.java | 42 + .../RearrangementResult23NNNANXMI.java | 42 + .../wrq/rearranger/RearrangementResult25.java | 24 + .../wrq/rearranger/RearrangementResult26.java | 16 + .../wrq/rearranger/RearrangementResult27.java | 45 + .../wrq/rearranger/RearrangementResult28.java | 50 + .../wrq/rearranger/RearrangementResult3.java | 57 + .../wrq/rearranger/RearrangementResult30.java | 328 +++ .../wrq/rearranger/RearrangementResult31.java | 176 ++ .../wrq/rearranger/RearrangementResult32.java | 11 + .../wrq/rearranger/RearrangementResult33.java | 7 + .../wrq/rearranger/RearrangementResult34.java | 15 + .../rearranger/RearrangementResult34B.java | 13 + .../wrq/rearranger/RearrangementResult35.java | 7 + .../wrq/rearranger/RearrangementResult37.java | 21 + .../wrq/rearranger/RearrangementResult39.java | 8 + .../rearranger/RearrangementResult39A.java | 8 + .../rearranger/RearrangementResult39B.java | 8 + .../rearranger/RearrangementResult39C.java | 8 + .../wrq/rearranger/RearrangementResult4.java | 58 + .../wrq/rearranger/RearrangementResult40.java | 31 + .../wrq/rearranger/RearrangementResult41.java | 5 + .../wrq/rearranger/RearrangementResult42.java | 5 + .../wrq/rearranger/RearrangementResult43.java | 13 + .../wrq/rearranger/RearrangementResult44.java | 6 + .../wrq/rearranger/RearrangementResult45.java | 59 + .../rearranger/RearrangementResult46A.java | 19 + .../rearranger/RearrangementResult46B.java | 19 + .../rearranger/RearrangementResult46C.java | 19 + .../rearranger/RearrangementResult46D.java | 19 + .../rearranger/RearrangementResult46E.java | 19 + .../wrq/rearranger/RearrangementResult47.java | 9 + .../wrq/rearranger/RearrangementResult5.java | 57 + .../wrq/rearranger/RearrangementResult6.java | 8 + .../wrq/rearranger/RearrangementResult7.java | 14 + .../wrq/rearranger/RearrangementResult8.java | 58 + .../wrq/rearranger/RearrangementResult8A.java | 19 + .../wrq/rearranger/RearrangementResult9.java | 58 + .../com/wrq/rearranger/RearrangementTest.java | 57 + .../wrq/rearranger/RearrangementTest11.java | 5 + .../wrq/rearranger/RearrangementTest12.java | 20 + .../wrq/rearranger/RearrangementTest13.java | 28 + .../wrq/rearranger/RearrangementTest14.java | 13 + .../wrq/rearranger/RearrangementTest15.java | 15 + .../wrq/rearranger/RearrangementTest16.java | 18 + .../wrq/rearranger/RearrangementTest17.xml | 5 + .../wrq/rearranger/RearrangementTest18.java | 34 + .../wrq/rearranger/RearrangementTest18B.java | 27 + .../wrq/rearranger/RearrangementTest19.java | 24 + .../wrq/rearranger/RearrangementTest2.java | 8 + .../wrq/rearranger/RearrangementTest20.java | 17 + .../wrq/rearranger/RearrangementTest21.java | 3 + .../wrq/rearranger/RearrangementTest22.java | 11 + .../wrq/rearranger/RearrangementTest23.java | 39 + .../wrq/rearranger/RearrangementTest24.java | 137 ++ .../wrq/rearranger/RearrangementTest25.java | 25 + .../wrq/rearranger/RearrangementTest26.java | 15 + .../wrq/rearranger/RearrangementTest27.java | 45 + .../wrq/rearranger/RearrangementTest28.java | 46 + .../wrq/rearranger/RearrangementTest29.java | 26 + .../wrq/rearranger/RearrangementTest30.java | 328 +++ .../wrq/rearranger/RearrangementTest31.java | 175 ++ .../wrq/rearranger/RearrangementTest32.java | 10 + .../wrq/rearranger/RearrangementTest33.java | 9 + .../wrq/rearranger/RearrangementTest34.java | 10 + .../wrq/rearranger/RearrangementTest35.java | 7 + .../wrq/rearranger/RearrangementTest36.java | 48 + .../wrq/rearranger/RearrangementTest37.java | 21 + .../wrq/rearranger/RearrangementTest38.java | 19 + .../wrq/rearranger/RearrangementTest38cfg.xml | 274 +++ .../wrq/rearranger/RearrangementTest39.java | 8 + .../wrq/rearranger/RearrangementTest39A.java | 8 + .../wrq/rearranger/RearrangementTest40.java | 31 + .../wrq/rearranger/RearrangementTest41.java | 7 + .../wrq/rearranger/RearrangementTest42.java | 5 + .../wrq/rearranger/RearrangementTest43.java | 13 + .../wrq/rearranger/RearrangementTest44.java | 5 + .../wrq/rearranger/RearrangementTest45.java | 45 + .../wrq/rearranger/RearrangementTest46.java | 19 + .../wrq/rearranger/RearrangementTest47.java | 9 + .../wrq/rearranger/RearrangementTest7.java | 14 + .../wrq/rearranger/RearrangementTest8.java | 19 + .../com/wrq/rearranger/SpaceResult1.java | 13 + .../com/wrq/rearranger/SpaceResult2.java | 20 + .../com/wrq/rearranger/SpaceResult3.java | 18 + .../com/wrq/rearranger/SpaceResult4.java | 335 +++ .../com/wrq/rearranger/SpaceResult5.java | 41 + .../com/wrq/rearranger/SpaceResult6.java | 37 + .../com/wrq/rearranger/SpaceResult7.java | 97 + .../com/wrq/rearranger/SpaceResult8.java | 11 + .../com/wrq/rearranger/SpaceTest1.java | 22 + .../com/wrq/rearranger/SpaceTest2.java | 16 + .../com/wrq/rearranger/SpaceTest3.java | 18 + .../com/wrq/rearranger/SpaceTest4.java | 337 +++ .../com/wrq/rearranger/SpaceTest5.java | 42 + .../com/wrq/rearranger/SpaceTest6.java | 38 + .../com/wrq/rearranger/SpaceTest7.java | 100 + .../com/wrq/rearranger/SpaceTest7cfg.xml | 325 +++ .../com/wrq/rearranger/SpaceTest8.java | 9 + .../test/testData/defaultConfiguration.xml | 262 ++ 321 files changed, 34764 insertions(+) create mode 100644 plugins/rearranger/rearranger.iml create mode 100644 plugins/rearranger/src/META-INF/plugin.xml create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ClassInitializer.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/LiveRearrangerAction.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/LiveRearrangerActionHandler.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ModifierConstants.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ProjectTreeActionHandler.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/Rearranger.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/RearrangerAction.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/RearrangerIcon.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ShowComments.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ShowFields.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ShowMatchedRules.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ShowParamNames.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ShowParamTypes.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ShowRules.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ShowTypeAfterMethod.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/StaticClassInitializer.png create mode 100644 plugins/rearranger/src/com/wrq/rearranger/TestOverImpl.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/WaitableBoolean.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/ChoiceObject.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/ChoicePanel.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/ClassMemberSettingsPane.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/ClassOrderSettingsPane.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/ExtractedMethodsPane.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/IListManagerObject.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/IListManagerObjectFactory.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/IntTextField.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/ListManager.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/MethodSpec.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/RearrangerSettingsPanel.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/RelatedByNamePane.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/SettingsPane.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/SpacingPane.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/StringTextArea.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/StringTextField.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/TableMap.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/configuration/TableSorter.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/defaultConfiguration.xml create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/MemberAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/FileStructurePopup.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/IFilePopupEntry.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/IHasScrollPane.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/ILiveRearranger.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/IconBox.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/LiveRearrangerDialog.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/LiveRearrangerPopup.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/PopupTree.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/PopupTreeComponent.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/RearrangerTreeNode.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/TransferableTreeNode.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/TreeDragSource.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/popup/TreeDropTarget.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstanceFactory.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/DefaultRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/EmitAlwaysCommentRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/IRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/CommentFillString.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/ForceBlankLineSetting.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/PrimaryMethodSetting.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/RearrangerSettings.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/RelatedByNameMethodsSettings.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/RelatedMethodsSettings.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/SecondaryMethodSetting.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AbstractAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AtomicAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/EnumAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/FinalAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ImplementedAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ImplementingAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitializerAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/IntegerAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/MaxParamsAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/MinParamsAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/NameAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/NativeAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/OverriddenAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/OverridingAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ProtectionLevelAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ReturnTypeAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/SortOptions.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/StaticAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/StringAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/SynchronizedAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/TransientAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/TypeAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/VolatileAttribute.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/GetterSetterDefinition.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IHasGetterSetterDefinition.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IPrioritizableRule.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IRestrictMethodExtraction.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IRule.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/RegexUtil.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/util/Constraints.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/util/IconUtil.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/util/MethodUtil.java create mode 100644 plugins/rearranger/src/com/wrq/rearranger/util/ModifierUtils.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/InteractiveTest.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/settings/CommentFillStringTest.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/RegexUtilTest.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestClass1.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestClass2.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestEnum.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestImplementation.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestInterface.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestOverride.java create mode 100644 plugins/rearranger/test/src/com/wrq/rearranger/util/CommentUtilTest.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/BitFieldResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/BitFieldTest.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/CommentSeparatorResult1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/CommentSeparatorTest1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/CorruptRespacingResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/CorruptRespacingTest.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/CorruptionConfig.xml create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/DomainExpanderResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/DomainExpanderTest.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/Enum1Result.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/Enum1Test.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/Enum2AResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/Enum2Result.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/Enum2Test.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/GenericsResult1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/GenericsTest1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/GetFieldReturnsFieldResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/GetFieldReturnsResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixImmaterialResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixReturnsFieldResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixReturnsResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/GetterDefinitionTest.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/IncompleteLineResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/IncompleteLineTest.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/InterfaceResult1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/InterfaceTest1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangeInnerClassResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangeInnerClassTest.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangementInnerClassCfg.xml create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangementResult1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueue.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndented.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedConfig.xml create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedResult1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedTest1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult10.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult11.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult12.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BA.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BI.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BIELC.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BIEMC.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BINFC.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BITLC.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BO.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DA.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DI.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DIELC.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DIEMC.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DINFC.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DITLC.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DO.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13Ex.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult14.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18A.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18B.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19A.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19B.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19C.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult1A.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult20.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult21.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult22.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23BNNANXME.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNIANXME.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXMA.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXME.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXMI.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult25.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult26.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult27.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult28.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult3.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult30.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult31.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult32.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult33.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult34.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult34B.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult35.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult37.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39A.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39B.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39C.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult40.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult41.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult42.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult43.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult44.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult45.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46A.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46B.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46C.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46D.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46E.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult47.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult5.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult7.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult8.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult8A.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult9.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest11.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest12.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest13.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest14.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest15.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest16.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest17.xml create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest18.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest18B.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest19.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest20.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest21.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest22.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest23.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest24.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest25.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest26.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest27.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest28.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest29.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest30.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest31.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest32.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest33.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest34.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest35.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest36.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest37.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest38.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest38cfg.xml create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest39.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest39A.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest40.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest41.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest42.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest43.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest44.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest45.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest46.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest47.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest7.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest8.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult2.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult3.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult4.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult5.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult6.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult7.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult8.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest1.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest2.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest3.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest4.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest5.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest6.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest7.java create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest7cfg.xml create mode 100644 plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest8.java create mode 100644 plugins/rearranger/test/testData/defaultConfiguration.xml diff --git a/.idea/modules.xml b/.idea/modules.xml index ed5c32e269fe..8500e622a7bf 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -91,6 +91,7 @@ + diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index f299b61a63fd..19c53fae82b7 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -226,6 +226,12 @@ public def layoutCommunityPlugins(String home) { module("gradle") } } + + layoutPlugin("rearranger") { + jar("rearranger.jar") { + module("rearranger") + } + } layoutPlugin("git4idea") { jar("git4idea-rt.jar") { diff --git a/community-main.iml b/community-main.iml index 0dbcfb09ce10..68ce7b7be166 100644 --- a/community-main.iml +++ b/community-main.iml @@ -89,6 +89,7 @@ + diff --git a/plugins/rearranger/rearranger.iml b/plugins/rearranger/rearranger.iml new file mode 100644 index 000000000000..a4214d4850e2 --- /dev/null +++ b/plugins/rearranger/rearranger.iml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/rearranger/src/META-INF/plugin.xml b/plugins/rearranger/src/META-INF/plugin.xml new file mode 100644 index 000000000000..067d2828af8a --- /dev/null +++ b/plugins/rearranger/src/META-INF/plugin.xml @@ -0,0 +1,46 @@ + + org.jetbrains.plugins.rearranger + Rearranger + + Rearranges (reorders) class and class member declarations according to a user-specified order and/or method call hierarchy; + generates section-marking comments; + provides several controls for spacing within and between methods and classes; and + permits the user to manually rearrange items. + + JetBrains Inc. + + com.intellij.modules.lang + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/rearranger/src/com/wrq/rearranger/ClassInitializer.png b/plugins/rearranger/src/com/wrq/rearranger/ClassInitializer.png new file mode 100644 index 0000000000000000000000000000000000000000..069d412ce72cc8c262df0e321c12692319edb1a3 GIT binary patch literal 775 zcmV+i1Ni)jP)PDo5ZiFtPD7~=|={7;A zh;kqiWkD+y5{66ZLL99oI88lsM-Th+dXDdV&in7@#WZ*FTz1j#>fy)peE5AHeqZ>H zN;PY?w0Ft+p)HtvfuMSq;><+?zf6`U3PB#cY&hGi0Ub~E%4=`G%PTu}kSRmK06}U)x;yfL*VL(dir0I!(SX{aG(!kDJ%u`L|Cc`eoa^iGv><6y!Y~x z&AgO)sB-M530@fLqq9|!Qwl#2s*w;S5NEI$W|S&*Zp`1|!;#)cY7Zu|0Y=|B#HN8h zI`WDqwC2y7^Bn#BB*nQB#u#>N-^%dtiv*EgfdIB^B%#JXFxP97FE8Absl`N=vrLw& zfsF3|SWb*jO0km4iOE^nw&#FM|9xA2yA{i^^LOOn_tVnVGa#$&biTcd){eELDfst< zQ@_tpD73SE>oCQt(7mpQ(Kq+9WOp!E$v`xY< outerClasses = p.parseOuterLevel(); + if (outerClasses.size() > 0) { + final Mover mover = new Mover(outerClasses, settings); + final List resultRuleInstances = mover.rearrangeOuterClasses(); + fsp.setResultRuleInstances(resultRuleInstances); + fsp.liveRearranger(); + } + LOG.debug("exit liveRearrangeDocument on thread " + Thread.currentThread().getName()); + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/ModifierConstants.java b/plugins/rearranger/src/com/wrq/rearranger/ModifierConstants.java new file mode 100644 index 000000000000..e5b02062d9e6 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ModifierConstants.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger; + +/** Additional "modifier" flags, used to identify other boolean attributes of a field, method or class. */ +public final class ModifierConstants { +// ------------------------------ FIELDS ------------------------------ + + /* + * dummy modifier values -- chosen to not conflict with other Java modifiers + */ + public static final int OVERRIDDEN = 0x2000; + public static final int CONSTRUCTOR = 0x4000; + public static final int CANONICAL = 0x200000; + public static final int OTHER_METHOD = 0x10000; + public static final int OVERRIDING = 0x20000; + public static final int IMPLEMENTING = 0x100000; + public static final int INIT_TO_ANON_CLASS = 0x40000; + public static final int INITIALIZER = 0x80000; + public static final int IMPLEMENTED = 0x400000; + public static final int ENUM = 0x800000; + + private ModifierConstants() { + } + + public static String toString(int constants) { + String result = ""; + if ((constants & OVERRIDDEN) > 0) result += "OVERRIDDEN "; + if ((constants & CONSTRUCTOR) > 0) result += "CONSTRUCTOR "; + if ((constants & CANONICAL) > 0) result += "CANONICAL "; + if ((constants & OTHER_METHOD) > 0) result += "OTHER_METHOD "; + if ((constants & OVERRIDING) > 0) result += "OVERRIDING "; + if ((constants & IMPLEMENTED) > 0) result += "IMPLEMENTED "; + if ((constants & IMPLEMENTING) > 0) result += "IMPLEMENTING "; + if ((constants & INIT_TO_ANON_CLASS) > 0) result += "INIT_TO_ANON_CLASS "; + if ((constants & INITIALIZER) > 0) result += "INITIALIZER "; + if ((constants & ENUM) > 0) result += "ENUM "; + return result.trim(); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/ProjectTreeActionHandler.java b/plugins/rearranger/src/com/wrq/rearranger/ProjectTreeActionHandler.java new file mode 100644 index 000000000000..f2f47be70cf8 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ProjectTreeActionHandler.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +/** Handles right-click in project view; applies rearrangement to a directory and its files recursively. */ +public final class ProjectTreeActionHandler + extends AnAction +{ +// ------------------------------ FIELDS ------------------------------ + + private static final Logger LOG = Logger.getInstance("#" + ProjectTreeActionHandler.class.getName()); + +// -------------------------- OTHER METHODS -------------------------- + + public final void actionPerformed(final AnActionEvent anActionEvent) { + LOG.debug("entered actionPerformed"); + // we're being called on the Swing event dispatch thread. Spin off another thread to do the + // rearranging and let Swing's thread go. + Thread t = new Thread( + new Runnable() { + public void run() { + new RearrangeIt(anActionEvent.getDataContext()).run(); + } + }, "RearrangerThread" + ); + t.start(); + } + +// -------------------------- INNER CLASSES -------------------------- + + abstract class VirtualFileVisitor { + volatile boolean cancel = false; + + final void accept(final VirtualFile f) { + if (f != null) { + visitVirtualFile(f); + } + final VirtualFile[] vfa = f.getChildren(); + if (vfa != null) { + for (VirtualFile aVfa : vfa) { + if (!cancel) { + accept(aVfa); + } + } + } + } + + abstract void visitVirtualFile(VirtualFile f); + } + + final class RearrangeIt + implements Runnable + { + final DataContext dc; + final Project project; + final JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL); + final JLabel filename = new JLabel(); + + class BoolHolder { + boolean value; + } + + public RearrangeIt(final DataContext dc) { + this.dc = dc; + if (dc != null) { + this.project = (Project)dc.getData(DataConstants.PROJECT); + } + else { + this.project = null; + } + } + + public final void run() { + final VirtualFile virtualFile = (VirtualFile)dc.getData(DataConstants.VIRTUAL_FILE); + final List files = new ArrayList(); + final IntHolder count = new IntHolder(); + final VirtualFileVisitor counter = new VirtualFileVisitor() { + void visitVirtualFile(final VirtualFile file) { + if (!file.isDirectory()) { + count.n++; + LOG.debug("" + count.n + ": file " + file.getName()); + files.add(file); + } + } + }; + + final Application application = ApplicationManager.getApplication(); + application.runReadAction( + new Runnable() { + public void run() { + counter.accept(virtualFile); + } + } + ); + + LOG.debug("counted " + count.n + " files"); + final RearrangerActionHandler rah = new RearrangerActionHandler(); + final PsiDocumentManager dm = PsiDocumentManager.getInstance(project); + final PsiManager pm = PsiManager.getInstance(project); + final BoolHolder cancelled = new BoolHolder(); + final JDialog dialog = getProgressFrame(cancelled, count.n); + dialog.setVisible(true); + for (int currentCount = 0; currentCount < files.size(); currentCount++) { + if (cancelled.value) { + LOG.debug("cancelled rearrangement"); + break; + } + final VirtualFile f = files.get(currentCount); + final int k = currentCount; + Runnable fn = new Runnable() { + public void run() { + final PsiFile psiFile = pm.findFile(f); + LOG.debug("SDT setting filename to " + psiFile.getName()); + filename.setText(psiFile.getName()); + filename.repaint(); + } + }; + Runnable r = new Runnable() { + public void run() { + final PsiFile psiFile = pm.findFile(f); + if (psiFile != null && + psiFile.getName().endsWith(".java") && + psiFile.isWritable()) + { + LOG.debug("SDT rearranging file " + psiFile.getName()); + final Document document = dm.getDocument(psiFile); + final Application application = ApplicationManager.getApplication(); + application.runWriteAction( + new Runnable() { + public void run() { + final Application application = ApplicationManager.getApplication(); + final Rearranger rearranger = application.getComponent(Rearranger.class); + RearrangerSettings settings = rearranger.getSettings(); + settings = settings.deepCopy(); + // avoid showing confirmation dialog for each file done + settings.setAskBeforeRearranging(false); + rah.runWriteActionRearrangement(project, document, psiFile, settings); + } + + ; + } + ); + } + ; + if (!cancelled.value) { + LOG.debug("SDT setting progress bar value to " + (k + 1)); + bar.setValue(k + 1); + bar.repaint(); + } + } + }; + + try { + SwingUtilities.invokeAndWait(fn); + SwingUtilities.invokeAndWait(r); + } + catch (InterruptedException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + dialog.setVisible(false); + dialog.dispose(); + } + + final JDialog getProgressFrame(final BoolHolder cancelled, final int max) { + Object parent = null; + if (project != null) { + parent = WindowManager.getInstance().suggestParentWindow(project); + } + LOG.debug("suggested parent window=" + parent); + final JDialog dialog = parent == null ? + new JDialog() : + (parent instanceof JDialog ? + new JDialog((JDialog)parent) : + new JDialog((JFrame)parent)); + final Container pane = dialog.getContentPane(); + final JLabel rearrangingLabel = new JLabel("Rearranging files, please wait..."); + final JPanel progressPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.newRow(); + constraints.insets = new Insets(15, 15, 0, 0); + progressPanel.add(rearrangingLabel, constraints.weightedLastCol()); + constraints.newRow(); + bar.setMinimum(0); + bar.setMaximum(max); + bar.setPreferredSize(new Dimension(500, 15)); + bar.setMinimumSize(new Dimension(500, 15)); + bar.setStringPainted(true); + constraints.insets = new Insets(15, 15, 5, 15); + progressPanel.add(bar, constraints.weightedFirstCol()); + constraints.insets = new Insets(9, 0, 5, 15); + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener( + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + LOG.debug("cancel button pressed"); + filename.setText("cancelling..."); + cancelled.value = true; + } + } + ); + + progressPanel.add(cancelButton, constraints.weightedLastCol()); + constraints.weightedLastRow(); + constraints.insets = new Insets(0, 15, 15, 0); + filename.setSize(500, 15); + filename.setPreferredSize(new Dimension(500, 15)); +// filename.setFont(new Font("dialog", Font.PLAIN, 12)); + progressPanel.add(filename, constraints.weightedLastCol()); + pane.add(progressPanel, BorderLayout.CENTER); + dialog.setTitle(Rearranger.COMPONENT_NAME); + dialog.addWindowListener( + new WindowListener() { + public void windowClosed(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowActivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowClosing(final WindowEvent e) { + LOG.debug("dialog closed, cancel Rearranger"); + filename.setText("cancelling..."); + cancelled.value = true; + } + + public void windowDeactivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowDeiconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowIconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowOpened(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + } + ); + + dialog.pack(); + return dialog; + } + + final class IntHolder { + public int n; + } + } + +// --------------------------- main() method --------------------------- + + /** + * Test progress bar functionality. Read 10 "filenames" from console, pausing between each to update the + * progress bar dialog. Handle cancel button and dialog window close button properly. + * + * @param args + */ + public static void main(final String[] args) { +// test the progress bar. + final BufferedReader reader; + final ProjectTreeActionHandler ptah = new ProjectTreeActionHandler(); + final RearrangeIt ri = ptah.new RearrangeIt(null); + final RearrangeIt.IntHolder cancelled = ri.new IntHolder(); + reader = new BufferedReader(new InputStreamReader(System.in)); + RearrangeIt.BoolHolder c = ri.new BoolHolder(); + + final JDialog dialog = ri.getProgressFrame(c, 10); + int count = 0; + dialog.pack(); + dialog.setVisible(true); + while (count <= 10 && cancelled.n == 0) { + String s = null; + try { + s = reader.readLine(); + } + catch (IOException e) { + e.printStackTrace(); + } + if (cancelled.n == 0) { + ri.filename.setText(s); + count++; + ri.bar.setValue(count); + } + } + dialog.setVisible(false); + dialog.dispose(); + System.exit(0); + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/Rearranger.java b/plugins/rearranger/src/com/wrq/rearranger/Rearranger.java new file mode 100644 index 000000000000..2f9b590023bd --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/Rearranger.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger; + +import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.util.JDOMExternalizable; +import com.wrq.rearranger.configuration.RearrangerSettingsPanel; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.IconUtil; +import org.jdom.Element; + +import javax.swing.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; + +/** + * The rearranger is an IntelliJ IDEA plugin that rearranges the order of class declarations and + * class member declarations within a Java file. The user configures an ordering of fields, methods, and classes. + * Subsequently, whenever the rearranger plugin is invoked on a Java file, the order of declarations is rearranged + * according to the configuration. + */ +public final class Rearranger + implements ApplicationComponent, Configurable, JDOMExternalizable +{ +// ------------------------------ FIELDS ------------------------------ + + public static final String COMPONENT_NAME = "Rearranger"; + public static final String VERSION = "5.5"; + private static final Logger LOG = Logger.getInstance("#" + Rearranger.class.getName()); + + private transient RearrangerSettingsPanel preferencesPanel; + private RearrangerSettings settings = new RearrangerSettings(); + private boolean haveReadExternalSettings; + +// --------------------------- CONSTRUCTORS --------------------------- + + public Rearranger() { +// logger.setAdditivity(false); +// logger.addAppender(new ConsoleAppender(new PatternLayout("[%7r] %6p - %30.30c - %m \n"))); +// logger.setLevel(Level.DEBUG); +// logger.setLevel(Level.INFO); + LOG.debug("constructor called for " + COMPONENT_NAME + " plugin version " + VERSION); + preferencesPanel = null; + /** + * If the Reformat plugin is present, register for a callback after code reformatting + * takes place. This allows user to optimize imports, reformat code, and rearrange all + * with one keystroke. + */ + try { + if (Class.forName("org.intellij.psi.codeStyle.ReformatManager") != null) { + /** + * Reformat plugin is available. Hook it by calling code in RearrangeUtility. + * Do this dynamically using reflection so we don't get class loading problems. + */ + LOG.debug("found ReformatManager class, attempting to hook."); + /** + * if the Reformat plugin is present, obtain a reference to our RearrangerUtility class, which will register + * for callbacks from the Reformat plugin. + */ + Class rearrangerUtilityClass = Class.forName("org.intellij.psi.codeStyle.RearrangerUtility"); + final Method hookit = rearrangerUtilityClass.getMethod("hookReformatPlugin", new Class[]{}); + hookit.invoke(null, (Object)null); + } + } + catch (ClassNotFoundException e) { + /** + * no reformat plugin available. Just continue with normal rearranger plugin behavior. + */ + LOG.debug("did not find class org.intellij.psi.codeStyle.RearrangerUtility"); + } + catch (NoSuchMethodException e) { + LOG.info(e.toString(), e); + } + catch (IllegalAccessException e) { + LOG.info(e.toString(), e); + } + catch (InvocationTargetException e) { + LOG.info(e.toString(), e); + } + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + // End Methods of Interface JDOMExternalizable + public RearrangerSettings getSettings() { + return settings; + } + + public void setSettings(RearrangerSettings settings) { + this.settings = settings; + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface BaseComponent --------------------- + + + public void initComponent() { + LOG.debug("initComponent()"); + } + + public void disposeComponent() { + LOG.debug("disposeComponent()"); + } + +// --------------------- Interface Configurable --------------------- + + public String getDisplayName() { + return COMPONENT_NAME; + } + + public Icon getIcon() { + return IconUtil.getIcon("RearrangerIcon"); + } + + public String getHelpTopic() { + return null; + } + +// --------------------- Interface JDOMExternalizable --------------------- + + public void readExternal(final Element element) //throws InvalidDataException + { + LOG.debug("rearranger.readExternal()"); + haveReadExternalSettings = true; + final List entries = element.getChildren(COMPONENT_NAME); + if (entries.size() > 0) { + LOG.debug("element 'Rearranger' seen; configuration loading"); + final Element entry = (Element)entries.get(0); + LOG.debug("element has " + entry.getChildren().size() + " children"); + settings.readExternal(entry); + } + } + + public void writeExternal(final Element element) //throws WriteExternalException + { + LOG.debug("rearranger.writeExternal()"); + final Element our_element = new Element(COMPONENT_NAME); + settings.writeExternal(our_element); + element.getChildren().clear(); + element.addContent(our_element); + } + +// --------------------- Interface NamedComponent --------------------- + + public String getComponentName() { + return COMPONENT_NAME; + } + +// --------------------- Interface UnnamedConfigurable --------------------- + + public JComponent createComponent() { + LOG.debug("createComponent: haveReadExternalSettings=" + haveReadExternalSettings); + RearrangerSettings rs; + if (!haveReadExternalSettings) { + LOG.debug("createComponent: reading default settings"); + rs = RearrangerSettings.getDefaultSettings(); + if (rs == null) { + LOG.debug("createComponent: could not find default settings"); + } + haveReadExternalSettings = true; + } + else { + rs = settings; + } + preferencesPanel = new RearrangerSettingsPanel(rs); + return preferencesPanel; + } + + public boolean isModified() { + final boolean result = !preferencesPanel.settings.equals(settings); + LOG.debug("rearranger.isModified(): returning " + result); + return result; + } + + public void apply() { + LOG.debug("rearranger.apply()"); + settings = preferencesPanel.settings.deepCopy(); + } + + public void reset() { + LOG.debug("rearranger.reset()"); + } + + public void disposeUIResources() { + preferencesPanel = null; + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/RearrangerAction.java b/plugins/rearranger/src/com/wrq/rearranger/RearrangerAction.java new file mode 100644 index 000000000000..328eefc61177 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/RearrangerAction.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger; + +import com.intellij.openapi.editor.actionSystem.EditorAction; + +public final class RearrangerAction + extends EditorAction +{ +// --------------------------- CONSTRUCTORS --------------------------- + + public RearrangerAction() { + super(new RearrangerActionHandler()); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java b/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java new file mode 100644 index 000000000000..97d333290b3b --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger; + +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.popup.FileStructurePopup; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.rearrangement.Mover; +import com.wrq.rearranger.rearrangement.Parser; +import com.wrq.rearranger.rearrangement.Spacer; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.CommentUtil; + +import java.awt.dnd.DragSource; +import java.util.List; + +/** This class performs rearrangement actions requested by the user. */ +public final class RearrangerActionHandler extends EditorActionHandler { + +// ------------------------------ FIELDS ------------------------------ + + private static final Logger LOG = Logger.getInstance("#" + RearrangerActionHandler.class.getName()); + private static int rightMargin; + private static int tabSize; + +// -------------------------- STATIC METHODS -------------------------- + + public static int getRightMargin() { + return rightMargin; + } + + public static int getTabSize() { + return tabSize; + } + + public void setTabSize(int tabSize) { + RearrangerActionHandler.tabSize = tabSize; + } +// -------------------------- OTHER METHODS -------------------------- + + public final void execute(final Editor editor, final DataContext context) { + if (editor == null) { + return; + } + LOG.debug("enter RearrangerActionHandler.execute()"); + final Project project = (Project)context.getData(DataConstants.PROJECT); + final Document document = editor.getDocument(); + final PsiFile psiFile = getFile(editor, context); + LOG.debug("suggested tool window = " + + WindowManager.getInstance().suggestParentWindow(project)); + LOG.debug("drag source image supported = " + DragSource.isDragImageSupported()); + if (!psiFile.getName().endsWith(".java")) { + LOG.debug("not a .java file -- skipping " + psiFile.getName()); + return; + } + if (!psiFile.isWritable()) { + LOG.debug("not a writable .java file -- skipping " + psiFile.getName()); + return; + } + rightMargin = editor.getSettings().getRightMargin(project); + tabSize = editor.getSettings().getTabSize(project); + LOG.debug("right margin=" + rightMargin + ", tabSize=" + tabSize); + final Application application = ApplicationManager.getApplication(); + application.runWriteAction(new Runnable() { + public void run() { + final Rearranger rearranger = ServiceManager.getService(Rearranger.class); + final RearrangerSettings settings = rearranger.getSettings(); + runWriteActionRearrangement(project, document, psiFile, settings); + } + } + ); + } + + private static PsiFile getFile(final Editor editor, + final DataContext context) + { + final Project project = (Project)context.getData(DataConstants.PROJECT); + final Document document = editor.getDocument(); + final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); + final VirtualFile virtualFile = fileDocumentManager.getFile(document); + final PsiManager psiManager = PsiManager.getInstance(project); + return psiManager.findFile(virtualFile); + } + + /** + * must be called from within an IDEA write-action thread. + * + * @param project + * @param document + * @param psiFile + */ + void runWriteActionRearrangement(final Project project, + final Document document, + final PsiFile psiFile, + final RearrangerSettings settings) + { + /** + * Per instructions from IntelliJ, we have to commit any changes to the document to the Psi + * tree. + */ + final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); + documentManager.commitDocument(document); + final WaitableBoolean wb = new WaitableBoolean(); + if (psiFile != null && + isFileWritable(psiFile) && + psiFile.getName().endsWith(".java")) + { + LOG.debug("schedule rearranger task"); + final Runnable task = new rearrangerTask(project, psiFile, settings, document, wb); + CommandProcessor.getInstance().executeCommand(project, task, "Rearrange", null); + } + try { + LOG.debug("wait for rearranger task to complete."); + wb.whenTrue(); + } + catch (InterruptedException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + LOG.debug("end execute"); + } + + public static boolean isFileWritable(PsiElement element) { + VirtualFile file = element.getContainingFile().getVirtualFile(); + return file != null && file.isWritable(); + } + + public final void rearrangeDocument(final Project project, + final PsiFile psiFile, + final RearrangerSettings settings, + final Document document) + { + LOG.debug("enter rearrangeDocument"); + new CommentUtil(settings); // create CommentUtil singleton + final Parser p = new Parser(project, settings, psiFile); + final List outerClasses = p.parseOuterLevel(); + if (outerClasses.size() > 0) { + final Mover m = new Mover(outerClasses, settings); + final List resultRuleInstances = m.rearrangeOuterClasses(); + boolean rearrange = true; + if (settings.isAskBeforeRearranging()) { + FileStructurePopup fsp = new FileStructurePopup(settings, resultRuleInstances, psiFile); + rearrange = fsp.displayRearrangement(); + } + if (rearrange) { + final Emitter e = new Emitter(psiFile, resultRuleInstances, document); + e.emitRearrangedDocument(); + } + } + LOG.debug("respacing document"); + PsiDocumentManager.getInstance(project).commitDocument(document); + Spacer spacer = new Spacer(project, psiFile, document, settings); + if (spacer.respace()) { + PsiDocumentManager.getInstance(project).commitDocument(document); + } + LOG.debug("exit rearrangeDocument"); + } + +// -------------------------- INNER CLASSES -------------------------- + + final class rearrangerTask implements Runnable { + final Project project; + final PsiFile psiFile; + final RearrangerSettings settings; + final Document document; + final WaitableBoolean wb; + + public rearrangerTask(final Project project, + final PsiFile psiFile, + final RearrangerSettings settings, + final Document document, + final WaitableBoolean wb) + { + this.project = project; + this.psiFile = psiFile; + this.settings = settings; + this.document = document; + this.wb = wb; + } + + public final void run() { + try { + rearrangeDocument(project, psiFile, settings, document); + } + finally { + wb.set(); + } + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/RearrangerIcon.png b/plugins/rearranger/src/com/wrq/rearranger/RearrangerIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..f4047ce53faab06181ef2bc0405c705732e6a450 GIT binary patch literal 2139 zcmWkwX;>477M;mJ7BWBtfeDLAaRK|egvAZi41y7~6-xVrrxu1779R>yXhm5vK?x{S zaKlg+f={ViMG+Ad$w0!sy1b%KTM`5j5s9)G$TE#T&OP7#aemx;&i%f7By8&@Yb$3f z0068*f`h`%%>4p7)m&2#9-K6jMSQ@w0RT|hy2|qCh`DE{ZH!F&J~=LJf6Py@K!7M& z7|RXW8xtQJ9vdS%kkS^r7652tAwdB@r2k)NAW6OwrQm>2h+qHpq&mtvmTH#5fh|aoKjeaLz}5EY7O@>*yg>cPC*1Owm7SY z<~#1u8_$=N7=hW}&O6B7B3BiDqaMwq36xv;%Wk3aDZY zmwbJX1NYZw#p|XW5I;UXZJ4ozSzD=5HuI<}--zMl8oF?SK;#cn^240famI;_@4Hf| z(iWon^Sp!+8a6jN+W^Vh*ld%DWd7poL34pTco964lL(`3u;J?aio|gL-}PW=LvD{b zZSI3WlpxMgYKxX-L$ikEya*pkf&0caHdL?0@=GkKL;1d|)hd%0jlF z9^B$5Rj7ki@n1~YeE398T_zl@kiZrd%P~)K#xl)g}SgTb@zzv|gUPoVx`tfdbDn&9DnM*K(0L(>sq8@2;{{=AOHsn8seO5bAW3 z9?Cyy&T#zS`97JtrXH;|(szTB1Mei~lbF_aNs;S0Qg^rbN?`mw^r& z<8wS-@RKBd_dkx+xCbg4VHS@={Y$KnjRI^iz<7InDEVw z3c~l}Sq z6>*}7F*iv*;B<<_8*Gk=_MM-!J%>-C#B^{^&Rt#PFINgX2f zrdXY6l&N&V0<@pTGNgHxeD7D_Kx(qW`<&h+)v*0NAb-9+?=M5Fu10s=uD4syGoJ%} zoi*LZU>MdGjc}BC`#H#k`b?$PV04leq0RmH(h&`#qddfCo1Ij0I(t&<>g zpOJXV1n1PENMvTpaA>;;DD&4!3O8i12beY`6`lh`5)3o zefNH{B4X>MrInY;K*>mTx?|+9W%ES4sP4G8@(O&hiteAVJh(b&@bY(;-#ASrCvQLe zUlyHqb?D)ItN0xqf~LNl9e{TSW{I-s7Xuw-6>5?c#U$PjTd8^cGU^w0+;l@{;4m}j zsO0a?=mWvgO-jc>_leJrJ3gI@sMQu6iA)$5%^v$t(?a%7^E~gP(*m!cnwswGY=zMt z@9=&OvZyhhss8Us^6Ovivwjo`*RqZ+U07{k?AbI{UXZ?b89_UtZ*q39Chsc$l1_ZR zgs&f;JVG8V2#NJvx5DaK;X!*=`2)v86HFbQJGoQa6hxfU44pm$FA?LG49^U&Kwls5 z&~K$~k$ov%Ak#&#PoivXr}V(`FrDo+SM+Bn9}qC@Z|xI;Z|qiL>_+lzS-{xxD<3EF8^8xRhP)R<@& zMy-GZn3Oc;9g&Rr^GNXkMJP9Np0jKDP)9-N4Y+Rn0P?)-w)o(b;a|+&V@|D(6bn|( z1K()Uk zzL+#jz3wZ@>(9=9_)#;eXD0X8*XiEBxYH5V!T;(dgN5q02Nm{qQ~j%dY|S}bTK<^! z6!0G8RIi?en&h=6%clN)ck=;Ceu_M!1ps~3k9Oez1YBi*Rs6thO|SVo075oy4Z67j G%lQZFbkFwy literal 0 HcmV?d00001 diff --git a/plugins/rearranger/src/com/wrq/rearranger/ShowComments.png b/plugins/rearranger/src/com/wrq/rearranger/ShowComments.png new file mode 100644 index 0000000000000000000000000000000000000000..150f22dcaa7602042943fc6e42ea4425e475e635 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|z(Vi}jAr*6y6C_xbGswDmVRMd1Pg9@)mmA|r28ICsKK-xpF2O)+7(8A5T-G@yGywo@_AlrF literal 0 HcmV?d00001 diff --git a/plugins/rearranger/src/com/wrq/rearranger/ShowFields.png b/plugins/rearranger/src/com/wrq/rearranger/ShowFields.png new file mode 100644 index 0000000000000000000000000000000000000000..d85a07398be38f4c94170578357123b1c0a5677d GIT binary patch literal 637 zcmV-@0)qXCP)(ITS7iH!k^#4Z7gh>b!T(}=+$rnCwKK{y+^#t<#U zG8?c+nFvCzNRcANHi6qBuv;A5Kpw2c?#45BXD%`2{pGyb`R0Fb-dh;zf;DoUkGyMs zdgrzWjtdrcc0-~l1bceDGXcHpe!8+a%k1R+JfdJ@u*&vslh?}u+dmustohes3h79n zCaMprY4B+QV+`N|k^zaqCSYTtDB<15Eo!SlU+ATiff&**XV<)R?fpE)jDqpOt3XM> z=}5AIDG5u@DpYP%x@zQaM=-|Na!D(mCtU@b>!zK$)d=z;5>Lna(9>cOG z1-UFeft|;W0`5te>K_<+QLE5OI#S}}JaJ9F>3X`uE*PLzY3wKYeM@p^Oxt!ek~_mO zV9F@M*01n%U{9%z)W7XyMGGfZ;iwI^BhL|}R7S+G_9H}FNzc1D*h?dlu77yJ#Jyq= z+PSmibwtYG7#jN_Q_t%}QS=``!1KJc_U17Yw@e;UaGO z+v6>gPCp!H=I$sHl`>)sl!dSf^^HAhs{yDE{+6CaQP)!aj=CB*3HsEJ4s!{KTwE+5;~M* zk>F$s4qb${AoPYpGgP>x&>Mtg2=oIF&f#)3&0X3iI*AViF7J2m^SsaZz2AHAAAcE% zL6WTDw14x41%?S8?Cd(Yt^?lLe0>R8SJM9Lrv(ZVW9^6ruK}KBYxj^RFKcXV+oy7# zT=elt#1}DoXVkBKSU@QSn1BR=G{9?u*T8j~EWg{NxK`^adLa^N;76PdTYmZNW0V>K zl?E#dNdcqdB~MUEVd+7Z?6qu!BZLu&sHoG0xhc|?1)@OGOh0b&^!1EfY8j&Z=dDr^#hUpye=@5gb>8D6|e5$TVOiGt`G*q;ZY{XP$;u zKa!EnbL_~oh*mZ~eTm|>Q>B-yQ@D}kW@8+1gHNTtgIFjy$U`N?A*rgDmx44Ra9lQn23uFTKIpQ a3%>wWsU0$F2G`~Q0000b=s6owRz|J86KOi${ zVvpOAafcGlcNL1INZKaQ3GS+015cAqO+(vZW>Rom4WiIGC?L~->B+?T2?qi*DiQASsq0S0s|~)E#QT>?hOu7a7fypp~6EwOXC(QH%AZ9DFZ> zrx8;T?9ihL2gm^JX=;Zp(o+(6&_M%*e3sOB1AXj(w~Id3U?{NS=vIf_Z%!oP&^zo= z7%RQ62Fi4^tGEk~AeCq^1hL|XD9WE5bh{P#FP^W{i1;7hER($x7D6XDfOoQvNE{4B z?a(2&RKj)LKOh8b+xClV56Iq7U5iGpDzHpM6c|FS?vPvA#yxU|#=Thc7V+oqrJ28- zAe)LKN}FM`}`#t&bMFFREb0j<%V9!dIt<3xIXvET!2Zx&_1m^Li?OJ2zki5<*P@r`Jo6}=wLTW**ni6WV!;o;e*dTgMEQmoP&g_rqf$1^ n79z5>jY`=l49mzR{t12p;Pf)`V)Z1N00000NkvXXu0mjfg@9lS literal 0 HcmV?d00001 diff --git a/plugins/rearranger/src/com/wrq/rearranger/ShowParamTypes.png b/plugins/rearranger/src/com/wrq/rearranger/ShowParamTypes.png new file mode 100644 index 0000000000000000000000000000000000000000..474a783ed31e34db34d50e035a18e1f98ac42570 GIT binary patch literal 752 zcmVXx!Q@#i1>9Fm9F((n;zfs362eLWhzr z;%Ed1mqIHD$xvv93bzz;Lm?Rg`M`s7xLi$>OOx78(*Jb4d++~$|L?u~4z6&?i2X~E zJ)ZRM-m$?j!Gp@agX=or4d*+TpnWsxzj=`(H#^gbXz&`~Y4-N(Jbztg???4a&QmXa z@M8m-n0_$rmp`telmbjZ0zn$!HNk7(x=l7d>{8e&4-~!D8)$&v=WN{eOYfecR032I z>=al6Mpu$2C`(v>k|K30)yEOS=nbd{r>iUTByAf+fh1XY`iiMZ#X-#>Zo$UdGRmj| zE@HxZF3rNrnjbaOK8GPbhfYQOxku?>L5%Pi+a$+@(%U@gRGf|XMX<97z;BqIFtNw% zNZx^h^Bsp`DU!Acw1Zi-s^DqTsVQhV%uEQ5t3ec62Mc5xFg1}FU9f*~+JQ4qLn|P4 z4iCUEsUJ5;SacRg2Zv$_a$OAM@`n3vhb?}o<>YX zP@#tl_K5-7(^LY+n+ zsfg>k7Z3z&+x81QMYzqp(#5tw+C0&x7pjv>*O0zVB2(1hhtbdZ_6CjZ@Zhi}}7=etWYJ%Pr>p z?ae~0J1>k!<@UygcF|juTg>}mtoOOMCaURf4FB-Ex(vyB-JaFpNEnnHMLcS4h`t~2 iWuRMhq#0h}BKQMVAS9@r`zU7s0000rU?#YE!v@0yA9nX#JkJIHY`${|+E+5c>!*40MJ& zo)`=uNOehK{ngV7A!B$ zq6`P{5EGX2Ii{aigQPu;IgC(_oQedK_i|x@7|}8|$qWj`H}mAOX_i-3!Ja?>e!|F* ziGA5l=#b!g8bqOWSU{!$!$SkT3&snl89MVd zG(uAMU>^*VqaQT}ELw%5!$q+KxhRQ(C-zVSW~Z3ezs0B>lUBY~ahxiw4{ABuBAd1D)AXA`l~h$xC*Ty&$Jcouu>G$O(0m08AaM}^P~6Y!765lMrg za1LB1W>)b$?+*k4+qQ$k;(f-ht5!rKmlRkgA_@$_sk%(emGBPTuDs`K-Xg)|-5gW5 z1{lkx5v3q4xJR(MQKhh60j+!QrRTxK_(%}l7L|?7zIpy}QSXwKjx+Q!f*uIRNS+*z8EveF4A(a&C eH}U`I3BLda8y-5g2a*5)0000?Co~wk~EV6bGq- z($OwL-HekNgl2HKC6EJ$+)%g&J~)TF#w|4PP5|{ALTZI@WGzLVG$NRUbcKabX?|Kr7H8XsG@0SlN6>?c3g|NC%AE zD{i#&s)A)%AQDe%Kn0*;;^0@n>ib=)Z?}dfJ=dpf%89n0J;fTgV9JS~@kv0%8;tm6 z2~@7RH6a%R)~*-9kfBJ8&OowObSuf3@3*OJY-5cH zp4Xy$x5)12@9cXm9+s|hc>)ML<{cZ`p2Tl@iIdp~RnH(tC|C7NpF+vzuqSd|HEq95 zxm2Wb+huKYo8_AYDmUhM{bmPj2hkw{%uPFkGE_a&A?O<)4khS2!w z;XZke-}Hv=G)EhVL`w?=ikI>fF2s#M1R6oe)|VR9k2|P?;B0zn9}I~^1j*)52W^yA kpicj%7-57FM)*JY15%pf$h+8>j{pDw07*qoM6N<$f{Gg?OaK4? literal 0 HcmV?d00001 diff --git a/plugins/rearranger/src/com/wrq/rearranger/StaticClassInitializer.png b/plugins/rearranger/src/com/wrq/rearranger/StaticClassInitializer.png new file mode 100644 index 0000000000000000000000000000000000000000..dad14aa70729dc3ba0aea87585229145eec6430a GIT binary patch literal 783 zcmV+q1MvKbP)Hj58<~|B4DF^V3eql`oro?35nM<_+l`2?jSC|Y zD}oB5*s9R9(Sj&GyC@aXhSvB@%p_uxNv<<@<~}|bn#ZWwx$vz1{NemK=i|UflJcR? zlG1Ydtf3Jz5+`eq(%bzP*~|+9-%}9et+VK@PX#3ARLS>ScJRg8^+Y03@~)7{3qzwe z_wU~1>hS~eM7c2u7za*GR9Uk^_MJFQU2Qd{rl2X1_k>|b$T-5wTtMH85n5Nz{!lMP z8L!g*>kXDQR8tmJ2rCMitY8;}f(LE@L%D$TSe~c-gY5pYYO>nfL^?pr_C3_sR+ES* zRH!QdJnN_Jr;GIVr7=yDwarbWQp?E})He`7H%#$xn1C5pOitc?CijOt83_Uzv9r>$ zZLgf|xFx+~zMQ?)BVTX$LAo9f$nEE@wBH$&AAjkR^2%D7+D?s>mJ?0P!uKKbO6dHv zn|QpG=B5k5{pkRBKzY?`tIoR193~m3TgOg6g+UefSluU{_s9J4^_Ok#c|lgvdiW!ly7$(VSY^w zrmmu^8fwTw6qT`28+$avm6OM~c4Y4KiN34J~P^Y`^m zZeDC-&Voj|F0CnoOe@_mB|0-HGiJ}1=**-TR;*}z3s*MFbly)#uK~&> 1; + constraints.gridwidth = (i % 2 == 1) ? + GridBagConstraints.REMAINDER : 1; + constraints.weightx = (i % 2 == 1) ? 1 : 0; + add(buttons[i], constraints); + choices[i].editingObject = choices[i].choiceObject.deepCopy(); + panels[i] = choices[i].createJPanel(); + /** + * calculate largest dimension of any of the replaceable panels. + */ + final Dimension dimension = panels[i].getPreferredSize(); + if (dimension.height > max.height) max.height = dimension.height; + if (dimension.width > max.width) max.width = dimension.width; + } + buttons[choice].setSelected(true); + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.gridwidth = 2; + constraints.weighty = 1; + constraints.gridx = 0; + constraints.gridy = (choices.length >> 1) + 1; + for (int i = 0; i < choices.length; i++) { + final int j = i; + panels[i].setPreferredSize(max); + buttons[i].addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + if (buttons[j].isSelected()) { + remove(choices.length); + add(panels[j], constraints); + panels[j].invalidate(); + panels[j].repaint(); + validate(); + choice = j; + } + } + }); + } + final JPanel beginning_panel = panels[choice]; + add(beginning_panel, constraints); + } + + void copyChoices(final ChoicePanel currentMsg) { + System.arraycopy(currentMsg.choices, 0, choices, 0, choices.length); + choice = currentMsg.choice; + } + + void acceptEdited() { + for (ChoiceObject choice1 : choices) { + choice1.acceptEdited(); + } + } + + ChoiceObject getChoice() { + return choices[choice]; + } + + public ChoiceObject[] getChoices() { + return choices; + } + + public void setChoice(int choice) { + this.choice = choice; + } + + public String getChoicePanelName() { + return choicePanelName; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/ClassMemberSettingsPane.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/ClassMemberSettingsPane.java new file mode 100644 index 000000000000..682961995469 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/ClassMemberSettingsPane.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.FieldAttributes; +import com.wrq.rearranger.settings.attributeGroups.InnerClassAttributes; +import com.wrq.rearranger.settings.attributeGroups.InterfaceAttributes; +import com.wrq.rearranger.settings.attributeGroups.MethodAttributes; + +import javax.swing.*; + +/** UI code for Class Member (field, method, inner class) dialog. */ +final class ClassMemberSettingsPane + extends SettingsPane +{ +// --------------------------- CONSTRUCTORS --------------------------- + + ClassMemberSettingsPane(final RearrangerSettings settings) { + super(settings, settings.getItemOrderAttributeList()); + } + +// -------------------------- OTHER METHODS -------------------------- + + ChoicePanel createChoicePanel() { + final ChoiceObject[] choices = new ChoiceObject[5]; + int index = 0; + choices[index++] = new ChoiceObject("Field") { + void createObject() { + choiceObject = new FieldAttributes(); + } + + JPanel createJPanel() { + return ((FieldAttributes)editingObject).getFieldAttributes(); + } + }; + choices[index++] = new ChoiceObject("Method") { + void createObject() { + choiceObject = new MethodAttributes(settings.getDefaultGSDefinition()); + } + + JPanel createJPanel() { + return ((MethodAttributes)editingObject).getMethodAttributes(); + } + }; + choices[index++] = new ChoiceObject("Interface Methods") { + void createObject() { + choiceObject = new InterfaceAttributes(); + } + + JPanel createJPanel() { + return ((InterfaceAttributes)editingObject).getInterfaceAttributes(); + } + }; + choices[index++] = new ChoiceObject("Inner Class") { + void createObject() { + choiceObject = new InnerClassAttributes(); + } + + JPanel createJPanel() { + return ((InnerClassAttributes)editingObject).getInnerClassAttributes(); + } + }; + choices[index++] = new ChoiceObject("Separator Comment") { + void createObject() { + choiceObject = new CommentRule(); + } + + JPanel createJPanel() { + return ((CommentRule)editingObject).getCommentPanel(); + } + }; + return new ChoicePanel(choices, "Class Member Order"); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/ClassOrderSettingsPane.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/ClassOrderSettingsPane.java new file mode 100644 index 000000000000..e1152f0b94a3 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/ClassOrderSettingsPane.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.ClassAttributes; + +import javax.swing.*; + +/** UI code for Outer Class order dialog. */ +final class ClassOrderSettingsPane + extends SettingsPane +{ +// --------------------------- CONSTRUCTORS --------------------------- + + public ClassOrderSettingsPane(final RearrangerSettings settings) { + super(settings, settings.getClassOrderAttributeList()); + } + +// -------------------------- OTHER METHODS -------------------------- + + ChoicePanel createChoicePanel() { + final ChoiceObject[] choices = new ChoiceObject[2]; + choices[0] = new ChoiceObject("Class") { + void createObject() { + choiceObject = new ClassAttributes(); + } + + JPanel createJPanel() { + return ((ClassAttributes)editingObject).getClassAttributesPanel(); + } + }; + choices[1] = new ChoiceObject("Separator Comment") { + void createObject() { + choiceObject = new CommentRule(); + } + + JPanel createJPanel() { + return ((CommentRule)editingObject).getCommentPanel(); + } + }; + final ChoicePanel panel = new ChoicePanel(choices, "Outer Class Order"); + return panel; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/ExtractedMethodsPane.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/ExtractedMethodsPane.java new file mode 100644 index 000000000000..f97308afec0c --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/ExtractedMethodsPane.java @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.RelatedMethodsSettings; +import com.wrq.rearranger.util.Constraints; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** Configuration settings for handling ordering of extracted methods. */ +public class ExtractedMethodsPane { +// --------------------------- main() method --------------------------- + + +// ---------- START Level 1 ---------- + + +// ---------- START Level 2 ---------- + + JPanel getExtractedMethodsPane(final RelatedMethodsSettings rms) { + final JPanel containerPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.weightedLastRow(); + final JTabbedPane pane = new JTabbedPane(); + final JPanel relatedMethodsArrangementPane = getExtractedMethodsArrangementPane(rms); + final JPanel relatedMethodsCommentsPane = getRelatedMethodsCommentsPane(rms); + pane.addTab("Arrangement", null, relatedMethodsArrangementPane, + "Options controlling arrangement of extracted methods"); + pane.addTab("Comments", null, relatedMethodsCommentsPane, + "Extracted method comments"); + pane.setSelectedIndex(0); + containerPanel.add(pane, constraints.weightedLastCol()); + return containerPanel; + } + +// ---------- START Level 3 ---------- + + + private JPanel getExtractedMethodsArrangementPane(final RelatedMethodsSettings rms) { + final JPanel pane = new JPanel(new GridBagLayout()); + final JPanel innerPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + final TitledBorder tb = new TitledBorder(border, "Options controlling arrangement of extracted methods"); + innerPanel.setBorder(tb); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + JPanel traversalOrderPanel = getTraversalOrderPanel(rms); + JPanel orderingPanel = getOrderingPanel(rms); + JPanel extractedPanel = getExtractedPanel(rms); + innerPanel.add(getMoveMethodsPanel(rms, new JPanel[]{traversalOrderPanel, orderingPanel, extractedPanel}), + constraints.weightedLastCol()); + constraints.newRow(); + constraints.insets = new Insets(0, 20, 0, 0); + innerPanel.add(traversalOrderPanel, constraints.weightedLastCol()); + constraints.newRow(); + innerPanel.add(orderingPanel, constraints.weightedLastCol()); + constraints.weightedLastRow(); + innerPanel.add(extractedPanel, constraints); + Dimension d = innerPanel.getPreferredSize(); + innerPanel.setPreferredSize(d); + innerPanel.setMaximumSize(d); + constraints.fill = GridBagConstraints.NONE; + constraints.gridx = constraints.gridy = 0; + pane.add(innerPanel, constraints); + return pane; + } + +// ---------- START Level 4 ---------- + + + JPanel getTraversalOrderPanel(final RelatedMethodsSettings rms) { + final JPanel traversalOrderPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.weightedLastRow(); + { + constraints.insets = new Insets(5, 5, 5, 0); + JLabel performLabel = new JLabel("Perform"); + traversalOrderPanel.add(performLabel, constraints.firstCol()); + } + { + final JComboBox traversalOrderBox = new JComboBox(new String[]{"depth first", "breadth first"}); + traversalOrderPanel.add(traversalOrderBox, constraints.nextCol()); + traversalOrderBox.setSelectedIndex(1); + Dimension d = traversalOrderBox.getPreferredSize(); + d.width += 3; + traversalOrderBox.setPreferredSize(d); + traversalOrderBox.setSelectedIndex(rms.isDepthFirstOrdering() ? 0 : 1); + traversalOrderBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + rms.setDepthFirstOrdering(traversalOrderBox.getSelectedIndex() == 0); + } + }); + } + { + JLabel remainderLabel = new JLabel("ordering on nested method calls"); + traversalOrderPanel.add(remainderLabel, constraints.lastCol()); + } + return traversalOrderPanel; + } + + JPanel getOrderingPanel(final RelatedMethodsSettings rms) { + final JPanel orderingPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + final TitledBorder tb = new TitledBorder(border, "Ordering options"); + orderingPanel.setBorder(tb); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + final JRadioButton invocationButton = new JRadioButton("Place in order of invocation"); + final JRadioButton originalButton = new JRadioButton("Retain original order"); + final JRadioButton alphabetizeButton = new JRadioButton("Alphabetize"); + ButtonGroup group = new ButtonGroup(); + group.add(invocationButton); + group.add(originalButton); + group.add(alphabetizeButton); + orderingPanel.add(invocationButton, constraints.weightedLastCol()); + constraints.newRow(); + orderingPanel.add(originalButton, constraints.weightedLastCol()); + constraints.weightedLastRow(); + orderingPanel.add(alphabetizeButton, constraints.weightedLastCol()); + switch (rms.getOrdering()) { + case RelatedMethodsSettings.INVOCATION_ORDER: + invocationButton.setSelected(true); + break; + case RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER: + originalButton.setSelected(true); + break; + case RelatedMethodsSettings.ALPHABETICAL_ORDER: + alphabetizeButton.setSelected(true); + break; + } + + invocationButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (invocationButton.isSelected()) { + rms.setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); + } + } + }); + + originalButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (originalButton.isSelected()) { + rms.setOrdering(RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER); + } + } + }); + + alphabetizeButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (alphabetizeButton.isSelected()) { + rms.setOrdering(RelatedMethodsSettings.ALPHABETICAL_ORDER); + } + } + }); + return orderingPanel; + } + + JPanel getExtractedPanel(final RelatedMethodsSettings rms) { + final JPanel extractedPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.insets = new Insets(5, 5, 5, 0); + JLabel label = new JLabel("Consider a non-private method as an extracted method:"); + extractedPanel.add(label, constraints.weightedLastCol()); + constraints.insets = new Insets(0, 15, 0, 0); + final JRadioButton neverButton = new JRadioButton("never"); + constraints.newRow(); + extractedPanel.add(neverButton, constraints.weightedLastCol()); + final JRadioButton oneButton = new JRadioButton("when it is called by only one method in the class"); + constraints.newRow(); + extractedPanel.add(oneButton, constraints.weightedLastCol()); + final JRadioButton moreButton = new JRadioButton("when it has one or more callers in the class"); + constraints.weightedLastRow(); + extractedPanel.add(moreButton, constraints.weightedLastCol()); + ButtonGroup g = new ButtonGroup(); + g.add(neverButton); + g.add(oneButton); + g.add(moreButton); + switch (rms.getNonPrivateTreatment()) { + case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_NEVER: + neverButton.setSelected(true); + break; + case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ONE_CALLER: + oneButton.setSelected(true); + break; + case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ANY_CALLERS: + moreButton.setSelected(true); + break; + } + neverButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (neverButton.isSelected()) { + rms.setNonPrivateTreatment(RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_NEVER); + } + } + }); + oneButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (oneButton.isSelected()) { + rms.setNonPrivateTreatment(RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ONE_CALLER); + } + } + }); + moreButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (moreButton.isSelected()) { + rms.setNonPrivateTreatment(RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ANY_CALLERS); + } + } + }); + return extractedPanel; + } + + JPanel getMoveMethodsPanel(final RelatedMethodsSettings rms, final JPanel[] dependentPanels) { + final JPanel moveMethodsPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.weightedLastRow(); + { + constraints.insets = new Insets(5, 5, 5, 0); + final JCheckBox moveBox = new JCheckBox("Move extracted methods below"); + moveBox.setSelected(rms.isMoveExtractedMethods()); + moveBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + rms.setMoveExtractedMethods(moveBox.isSelected()); + enableComponents(moveMethodsPanel, moveBox.isSelected()); + enableOtherComponents(dependentPanels, moveBox.isSelected()); + } + }); + moveMethodsPanel.add(moveBox, constraints.firstCol()); + } + { + final JComboBox firstLastBox = new JComboBox(new String[]{"first", "last"}); + firstLastBox.setSelectedIndex(0); + Dimension d = firstLastBox.getPreferredSize(); + d.width += 3; + firstLastBox.setPreferredSize(d); + firstLastBox.setSelectedIndex(rms.isBelowFirstCaller() ? 0 : 1); + firstLastBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + rms.setBelowFirstCaller(firstLastBox.getSelectedIndex() == 0); + } + }); + moveMethodsPanel.add(firstLastBox, constraints.nextCol()); + } + { + constraints.insets = new Insets(8, 5, 5, 0); + JLabel usageLabel = new JLabel("usage"); + moveMethodsPanel.add(usageLabel, constraints.weightedLastCol()); + } + enableComponents(moveMethodsPanel, rms.isMoveExtractedMethods()); + enableOtherComponents(dependentPanels, rms.isMoveExtractedMethods()); + return moveMethodsPanel; + } + +// ---------- START Level 5 ---------- + + + private void enableComponents(JPanel pane, boolean selected) { + for (int i = 1; i < pane.getComponents().length; i++) { + pane.getComponents()[i].setEnabled(selected); + } + } + + private void enableOtherComponents(JPanel[] otherPanels, boolean selected) { + for (JPanel otherPanel : otherPanels) { + enablePanel(otherPanel, selected); + } + } + +// ---------- START Level 6 ---------- + + + private void enablePanel(JPanel otherPanel, boolean selected) { + for (int i = 0; i < otherPanel.getComponents().length; i++) { + Component c = otherPanel.getComponents()[i]; + if (c instanceof JPanel) { + enablePanel((JPanel)c, selected); + } + else { + c.setEnabled(selected); + } + } + } + +// ---------- END Level 6 ---------- + + +// ---------- END Level 5 ---------- + + +// ---------- END Level 4 ---------- + + + private JPanel getRelatedMethodsCommentsPane(final RelatedMethodsSettings rms) { + JPanel rmcPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.gridwidth = 1; + constraints.gridheight = 1; + constraints.weightx = 0.0d; + constraints.weighty = 0.0d; + JLabel commentTypeLabel = new JLabel("Emit comment at"); + final JComboBox commentType = new JComboBox(new String[]{ + "top level", + "each level", + "each method", + "family change (up level, or next sibling has children)" + }); + commentType.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + rms.setCommentType(commentType.getSelectedIndex()); + } + }); + commentType.setSelectedIndex(rms.getCommentType()); + JLabel legendLabel = new JLabel("Comment Substitutions: use"); + JLabel legendLabel_1 = new JLabel("%TL% for top level method"); + JLabel legendLabel_2 = new JLabel("%MN% for method name"); + JLabel legendLabel_4 = new JLabel("%LV% for level number"); + JLabel legendLabel_3 = new JLabel("%AM% for all method names"); + JLabel precedingCommentLabel = new JLabel("Preceding Comment:"); + JLabel trailingCommentLabel = new JLabel("Trailing Comment:"); + JPanel precedingCommentPanel = getCommentAreaPanel(rms.getPrecedingComment()); + JPanel trailingCommentPanel = getCommentAreaPanel(rms.getTrailingComment()); + constraints.insets = new Insets(3, 5, 0, 0); + rmcPanel.add(commentTypeLabel, constraints.firstCol()); + rmcPanel.add(commentType, constraints.lastCol()); + JPanel legendPanel = new JPanel(new GridBagLayout()); + { + final Border border = BorderFactory.createEtchedBorder(); + legendPanel.setBorder(border); + final Constraints legendConstraints = new Constraints(GridBagConstraints.NORTHWEST); + legendConstraints.fill = GridBagConstraints.BOTH; + + legendConstraints.insets = new Insets(5, 5, 0, 0); + legendPanel.add(legendLabel, legendConstraints.firstCol()); + legendConstraints.insets = new Insets(5, 5, 0, 5); + legendPanel.add(legendLabel_1, legendConstraints.nextCol()); + legendPanel.add(legendLabel_2, legendConstraints.lastCol()); + legendConstraints.newRow(); + legendConstraints.firstCol(); // skip first column + legendConstraints.insets = new Insets(5, 5, 5, 5); + legendPanel.add(legendLabel_3, legendConstraints.nextCol()); + legendPanel.add(legendLabel_4, legendConstraints.lastCol()); + } + constraints.newRow(); + constraints.insets = new Insets(5, 5, 0, 5); + rmcPanel.add(legendPanel, constraints.weightedLastCol()); + constraints.newRow(); + rmcPanel.add(precedingCommentLabel, constraints.weightedLastCol()); + constraints.weightedNewRow(0.50d); + rmcPanel.add(precedingCommentPanel, constraints.weightedLastCol()); + constraints.newRow(); + rmcPanel.add(trailingCommentLabel, constraints.weightedLastCol()); + constraints.weightedNewRow(0.50d); + constraints.insets = new Insets(5, 5, 5, 5); + rmcPanel.add(trailingCommentPanel, constraints.weightedLastCol()); + constraints.lastRow(); + rmcPanel.add(rms.getCommentFillString().getCommentFillStringPanel(), constraints.weightedLastCol()); + return rmcPanel; + } + +// ---------- START Level 4 ---------- + + + private JPanel getCommentAreaPanel(final CommentRule comment) { + JPanel commentPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.weightedLastRow(); + final JTextArea commentArea = new JTextArea(4, 40); + commentArea.setText(comment.getCommentText()); + final JScrollPane scrollPane = new JScrollPane(commentArea); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + commentPanel.add(scrollPane, constraints.weightedFirstCol()); + commentArea.getDocument().addDocumentListener(new DocumentListener() { + public void changedUpdate(final DocumentEvent e) { + comment.setCommentText(commentArea.getText()); + } + + public void insertUpdate(final DocumentEvent e) { + comment.setCommentText(commentArea.getText()); + } + + public void removeUpdate(final DocumentEvent e) { + comment.setCommentText(commentArea.getText()); + } + }); + return commentPanel; + } + +// ---------- END Level 4 ---------- + + +// ---------- END Level 3 ---------- + + +// ---------- END Level 2 ---------- + + +// ---------- END Level 1 ---------- +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/IListManagerObject.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/IListManagerObject.java new file mode 100644 index 000000000000..2b2b56bd288b --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/IListManagerObject.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import javax.swing.*; + +/** Describes objects that can be handled by ListManager. */ +public interface IListManagerObject { + String getDescription(); + + void setDescription(String description); + + JPanel getPanel(); + + IListManagerObject deepcopy(); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/IListManagerObjectFactory.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/IListManagerObjectFactory.java new file mode 100644 index 000000000000..1324f3f2611d --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/IListManagerObjectFactory.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import java.util.List; + +/** Handles creation and removal of list manager objects. */ +public interface IListManagerObjectFactory { + IListManagerObject create(String name); + + List getObjectList(); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/IntTextField.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/IntTextField.java new file mode 100644 index 000000000000..82eabd895268 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/IntTextField.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.DefaultFormatterFactory; +import javax.swing.text.NumberFormatter; +import java.awt.*; +import java.text.NumberFormat; + +/** + * A JTextField tied to a numeric field. Initialize the JTextField from the field and update + * the field whenever the JTextField's text changes. + */ +public class IntTextField + extends JFormattedTextField +{ + public interface IGetSet { + public int get(); + + public void set(int value); + } + + public IntTextField(final IGetSet getset, final Integer minimum, final Integer maximum) { + final NumberFormat integerInstance = NumberFormat.getIntegerInstance(); + int maxDigits = 2; + if (maximum != null && (maximum) > 99) { + maxDigits = maximum.toString().length(); + } + integerInstance.setMaximumIntegerDigits(maxDigits); + integerInstance.setMinimumIntegerDigits(1); + setFormatterFactory(new DefaultFormatterFactory(new NumberFormatter(integerInstance))); + setValue(maximum != null ? maximum : new Integer("88")); + final Dimension d = getPreferredSize(); + d.width += 3; + setPreferredSize(d); + setValue(getset.get()); + setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT); + setText("" + getValue()); + getDocument().addDocumentListener(new DocumentListener() { + private void setit() { + try { + // allow empty string, else must be valid number + if (getText().length() != 0) { + int value = Integer.parseInt(getText()); + if (minimum != null) { + if (value < (minimum)) value = (minimum); + } + if (maximum != null) { + if (value > (maximum)) value = (maximum); + } + getset.set(value); + } + } + catch (NumberFormatException e) { + // leave value alone + } + } + + public void insertUpdate(DocumentEvent e) { + setit(); + } + + public void removeUpdate(DocumentEvent e) { + setit(); + } + + public void changedUpdate(DocumentEvent e) { + setit(); + } + }); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/ListManager.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/ListManager.java new file mode 100644 index 000000000000..9ea313d9a573 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/ListManager.java @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.wrq.rearranger.util.IconUtil; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Generic manager for a panel with a list combo box, add/delete/copy buttons, + * a name field, and a subpanel to get contents of current item. + */ +public class ListManager + extends JPanel +{ + JLabel nameLabel; + JTextField name; + JButton addButton; + JButton removeButton; + JButton copyButton; + JList list; + GridBagConstraints constraints; + final IListManagerObjectFactory factory; + IListManagerObject currentObject; + boolean buttonPressInProgress; + + private JButton makeButton(String iconName) { + Icon icon = IconUtil.getIcon(iconName); + JButton result = new JButton(icon); + result.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); + return result; + } + + public ListManager(final IListManagerObjectFactory factory, String nameLabelText) { + super(new GridBagLayout()); + this.factory = factory; + currentObject = null; + nameLabel = new JLabel(nameLabelText); + name = new JTextField(3); + addButton = makeButton("general/add"); + removeButton = makeButton("general/remove"); + copyButton = makeButton("general/copy"); + list = new JList(new DefaultListModel()); + /** + * declare callback handlers for buttons. + */ + addButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + buttonPressInProgress = true; + currentObject = factory.create(getUniqueName("unnamed")); + factory.getObjectList().add(currentObject); + ((DefaultListModel)list.getModel()).addElement(currentObject); + list.setSelectedIndex(list.getModel().getSize() - 1); + updateListSelection(); + buttonPressInProgress = false; + } + } + ); + removeButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + buttonPressInProgress = true; + DefaultListModel dlm = ((DefaultListModel)list.getModel()); + int selectedIndex = list.getSelectedIndex(); + IListManagerObject lmo = (IListManagerObject)dlm.getElementAt(selectedIndex); + factory.getObjectList().remove(lmo); + dlm.remove(selectedIndex); + if (selectedIndex >= dlm.getSize()) { + selectedIndex = dlm.getSize() - 1; + } + list.setSelectedIndex(selectedIndex); + currentObject = + (IListManagerObject)(selectedIndex < 0 ? null : dlm.getElementAt(selectedIndex)); + updateListSelection(); + buttonPressInProgress = false; + } + } + ); + copyButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + buttonPressInProgress = true; + DefaultListModel dlm = ((DefaultListModel)list.getModel()); + int selectedIndex = list.getSelectedIndex(); + IListManagerObject lmo = (IListManagerObject)dlm.getElementAt(selectedIndex); + currentObject = lmo.deepcopy(); + currentObject.setDescription(getUniqueName(lmo.getDescription())); + dlm.addElement(currentObject); + list.setSelectedIndex(list.getModel().getSize() - 1); + updateListSelection(); + buttonPressInProgress = false; + } + } + ); + name.getDocument().addDocumentListener( + new DocumentListener() { + private void updateList() { + if (buttonPressInProgress) { + return; + } + String newText = name.getText(); + final IListManagerObject listObject = (IListManagerObject)list.getSelectedValue(); + if (listObject != null) { + listObject.setDescription(newText); + } + int index = list.getSelectedIndex(); + DefaultListModel dlm = ((DefaultListModel)list.getModel()); + dlm.setElementAt(listObject, index); + validate(); + } + + public void changedUpdate(DocumentEvent e) { + updateList(); + } + + public void insertUpdate(DocumentEvent e) { + updateList(); + } + + public void removeUpdate(DocumentEvent e) { + updateList(); + } + } + ); + list.addListSelectionListener( + new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + if (buttonPressInProgress) { + return; // list selection changes due to add/remove/copy button handled elsewhere + } + buttonPressInProgress = true; + int selectedIndex = list.getSelectedIndex(); + DefaultListModel dlm = ((DefaultListModel)list.getModel()); + currentObject = + (IListManagerObject)(selectedIndex < 0 ? null : ((java.lang.Object)dlm.getElementAt(selectedIndex))); + updateListSelection(); + buttonPressInProgress = false; + } + } + ); + } + + public final JPanel getPane() { + constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = 1; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.weightx = 0.0d; + constraints.weighty = 0.0d; + constraints.gridy = constraints.gridx = 0; + constraints.insets = new Insets(0, 0, 0, 5); + JPanel buttonPanel = new JPanel(new GridBagLayout()); + buttonPanel.setBorder(BorderFactory.createEtchedBorder()); // todo remove + addButton.setBorderPainted(false); + removeButton.setBorderPainted(false); + copyButton.setBorderPainted(false); + buttonPanel.add(addButton, constraints); + constraints.gridx++; + buttonPanel.add(removeButton, constraints); + constraints.gridx++; +// constraints.gridwidth = GridBagConstraints.REMAINDER; +// constraints.weightx = 1; + buttonPanel.add(copyButton, constraints); + + constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = 1; + constraints.gridheight = 1; + constraints.weightx = 0.0d; + constraints.weighty = 0.0d; + constraints.gridy = constraints.gridx = 0; + constraints.insets = new Insets(3, 3, 3, 3); + add(buttonPanel, constraints); + buttonPanel.setPreferredSize(buttonPanel.getPreferredSize()); // todo determine effect if any + constraints.gridx++; + add(nameLabel, constraints); + constraints.gridx++; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1; + constraints.fill = GridBagConstraints.HORIZONTAL; + add(name, constraints); + + + list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); +// addButton.setEnabled(true); + JScrollPane scrollPane = new JScrollPane(list); + Dimension d = buttonPanel.getPreferredSize(); + d.width = d.width * 5 / 3; + scrollPane.setPreferredSize(d); + scrollPane.setMinimumSize(d); + for (Object object : factory.getObjectList()) { + ((DefaultListModel)list.getModel()).addElement(object); + } + list.setSelectedIndex(list.getModel().getSize() - 1); + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.gridwidth = 1; + constraints.gridx = 0; + constraints.gridy++; + constraints.weightx = 0; + constraints.weighty = 0; + constraints.fill = GridBagConstraints.VERTICAL; + add(scrollPane, constraints); + constraints.gridx++; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1; + constraints.weighty = 1; + final JPanel contents = new JPanel(); + contents.setBorder(BorderFactory.createEtchedBorder()); // todo remove + add(contents, constraints); + updateListSelection(); + validate(); + return this; + } + + /** + * Enable add/remove/copy buttons and fill in name of selected list item. Called whenever + * the list selection changes. + */ + private void updateListSelection() { + if (list.getModel().getSize() > 0) { + name.setEnabled(true); + nameLabel.setEnabled(true); + name.setText(((IListManagerObject)list.getSelectedValue()).getDescription()); + removeButton.setEnabled(true); + copyButton.setEnabled(true); + } + else { + name.setEnabled(false); + nameLabel.setEnabled(false); + removeButton.setEnabled(false); + copyButton.setEnabled(false); + name.setText(""); + } + remove(getComponentCount() - 1); + final JPanel contents = new JPanel(); + contents.setBorder(BorderFactory.createEtchedBorder()); // todo remove + add(currentObject == null ? contents : ((javax.swing.JPanel)currentObject.getPanel()), constraints); + validate(); + } + + public String getUniqueName(String name) { + String result; + if (name != null) { + // test initially supplied name; if not duplicate, return it. + if (!dupName(name)) { + return name; + } + } + result = (name == null) ? "unnamed" : name; + int suffix = 0; + String testName; + do { + suffix++; + testName = result + "_" + suffix; + } + while (dupName(testName)); + return testName; + } + + /** + * @param name + * @return true if the supplied name is identical to any other primary method name. + */ + public boolean dupName(String name) { + for (int i = 0; i < list.getModel().getSize(); i++) { + IListManagerObject lmo = (IListManagerObject)list.getModel().getElementAt(i); + if (lmo.getDescription().equals(name)) { + return true; + } + } + return false; //To change body of created methods use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/MethodSpec.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/MethodSpec.java new file mode 100644 index 000000000000..6ed83ca6a999 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/MethodSpec.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.intellij.ui.DocumentAdapter; +import com.wrq.rearranger.util.Constraints; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import java.awt.*; +import java.text.NumberFormat; + +/** + * Getters and setters are defined by their method names (eg., beginning with "get"), number of parameters, + * return type, and body contents. This class provides support for these common rule attributes. + * Other attributes, like number of parameters or return type, are already specified in MethodAttributes. + */ +public class MethodSpec { + /** + * pattern for property name. Must contain one or more regular expression groups, one of which will be + * regarded as the property. Will be matched against the candidate method's name. + */ + String propertyPattern; + /** Group number which identifies which regex group contains the pattern. */ + int propertyGroup; + /** true if first letter of property should be lowercased. */ + boolean lowercaseFirstLetterOfProperty; + /** if true, the property name must match a field in the class, else the method will not match. */ + boolean propertyMustMatchField; + /** + * pattern of method body (excluding comments and newline characters). Substitutions will be performed + * in this pattern before matching against the method's body as follows: + *
+   * %PATTERN%        this method's pattern
+   * %TYPE%           this method's type
+   * %PARAMNAME%   name of parameter ,  = 1, 2, 3, ...
+   * $PARAMTYPE%   type of parameter ,  = 1, 2, 3, ...
+   * $PARENT%         parent's property
+   * 
+ */ + String body; + /** true if body matching should be done against method body stripped of comments. */ + boolean ignoreComments; + /** + * value of "parent property", which is the property of the field or method executing this rule. + * If this is the top level rule (not being called by another rule to associate methods matching this + * rule with the parent), then there is no parent property. + */ + final String parentProperty; + + public MethodSpec(String parentProperty) { + this.parentProperty = parentProperty; + } + + public String getPropertyPattern() { + return propertyPattern; + } + + public void setPropertyPattern(String propertyPattern) { + this.propertyPattern = propertyPattern; + } + + public int getPropertyGroup() { + return propertyGroup; + } + + public void setPropertyGroup(int propertyGroup) { + this.propertyGroup = propertyGroup; + } + + public boolean isLowercaseFirstLetterOfProperty() { + return lowercaseFirstLetterOfProperty; + } + + public void setLowercaseFirstLetterOfProperty(boolean lowercaseFirstLetterOfProperty) { + this.lowercaseFirstLetterOfProperty = lowercaseFirstLetterOfProperty; + } + + public boolean isPropertyMustMatchField() { + return propertyMustMatchField; + } + + public void setPropertyMustMatchField(boolean propertyMustMatchField) { + this.propertyMustMatchField = propertyMustMatchField; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public boolean isIgnoreComments() { + return ignoreComments; + } + + public void setIgnoreComments(boolean ignoreComments) { + this.ignoreComments = ignoreComments; + } + + boolean isMatch() { + return false; // todo + } + + private JFormattedTextField getIntField(int initialValue) { + final NumberFormat integerInstance = NumberFormat.getIntegerInstance(); + integerInstance.setMaximumIntegerDigits(2); + integerInstance.setMinimumIntegerDigits(1); + final JFormattedTextField intField = new JFormattedTextField(integerInstance); + intField.setValue(new Integer("88")); + final Dimension d = intField.getPreferredSize(); + d.width += 3; + intField.setPreferredSize(d); + intField.setValue(initialValue); + intField.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT); + return intField; + } + + public JPanel getPanel() { + JPanel panel = new JPanel(new GridBagLayout()); + Constraints constraints = new Constraints(); + constraints.insets = new Insets(3, 3, 3, 3); + JLabel propertyPatternLabel = new JLabel("Property pattern:"); + propertyPatternLabel.setToolTipText("Regex pattern which method name must match; " + + "parenthesize portion which will be regarded as the method's property" + + ", e.g. \"(get|is|has)([A-Z]\\w*)\""); + panel.add(propertyPatternLabel, constraints.firstCol()); + constraints.fill = GridBagConstraints.HORIZONTAL; + final JTextField propertyPatternField = new JTextField(this.propertyPattern); + propertyPatternField.getDocument().addDocumentListener( + new DocumentAdapter() { + protected void textChanged(DocumentEvent event) { + propertyPattern = propertyPatternField.getText(); + } + } + ); + panel.add(propertyPatternField, constraints.weightedLastCol(0.5)); + constraints.newRow(); + constraints.fill = GridBagConstraints.NONE; + final JLabel propertyGroupLabel = new JLabel("Property group number:"); + propertyGroupLabel.setToolTipText("Regular expression parenthesized group corresponding to the property name"); + panel.add(propertyGroupLabel, constraints.firstCol()); + final JFormattedTextField propertyGroupField = getIntField(propertyGroup); + panel.add(propertyGroupField, constraints.nextCol()); + constraints.newRow(); + JCheckBox lowerCase = new JCheckBox("Lowercase first letter of property"); + lowerCase.setToolTipText("If selected, lower cases the first letter of the property found in the regular expression"); + panel.add(lowerCase, constraints.lastCol()); + constraints.newRow(); + JCheckBox mustMatch = new JCheckBox("Property must match field name"); + mustMatch.setToolTipText("If selected, the property name derived from the regular expression must match the " + + "name of a field in the same class as the method; if no such field exists, the " + + "method will not match the rule"); + panel.add(mustMatch, constraints.lastCol()); +// propertyGroupField.get + constraints.newRow(); + JLabel bodyLabel = new JLabel("Body:"); + bodyLabel.setToolTipText("Regex pattern for method body (excluding comments);\n" + + "use \"%FN%\" for field name, \"%P1%\" for param 1, etc."); + constraints.fill = GridBagConstraints.NONE; + panel.add(bodyLabel, constraints.firstCol()); + JCheckBox stripComments = new JCheckBox("Strip comments"); + stripComments.setToolTipText("If selected, comments will be stripped from the method body before attempting" + + " to match the supplied expression"); + panel.add(stripComments, constraints.lastCol()); + constraints.weightedLastRow(); + constraints.fill = GridBagConstraints.BOTH; + JTextArea body = new JTextArea(4, 40); + JScrollPane sp = new JScrollPane(body); + panel.add(sp, constraints.weightedLastCol()); + + return panel; + } + + public MethodSpec deepcopy() { + MethodSpec result = new MethodSpec(parentProperty); + result.body = body; + result.ignoreComments = ignoreComments; + result.lowercaseFirstLetterOfProperty = lowercaseFirstLetterOfProperty; + result.propertyGroup = propertyGroup; + result.propertyMustMatchField = propertyMustMatchField; + result.propertyPattern = propertyPattern; + result.body = body; + return result; + } + + public static void main(String[] args) { + MethodSpec ms = new MethodSpec(null); + final JDialog frame = new JDialog((Frame)null, "SwingApplication"); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1.0d; + constraints.weighty = 1.0d; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 0; + constraints.gridy = 0; + frame.getContentPane().setLayout(new GridBagLayout()); + frame.getContentPane().add(ms.getPanel(), constraints); + //Finish setting up the frame, and show it. + frame.pack(); + frame.setResizable(true); + frame.setModal(true); + frame.setVisible(true); + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/RearrangerSettingsPanel.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/RearrangerSettingsPanel.java new file mode 100644 index 000000000000..75a340fa150f --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/RearrangerSettingsPanel.java @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.wrq.rearranger.Rearranger; +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.AttributeGroup; +import com.wrq.rearranger.settings.attributeGroups.RegexUtil; +import com.wrq.rearranger.util.CommentUtil; +import com.wrq.rearranger.util.Constraints; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.PatternSyntaxException; + +/** Code for top level configuration panel. */ +public final class RearrangerSettingsPanel + extends JPanel +{ +// ------------------------------ FIELDS ------------------------------ + + public RearrangerSettings settings; + +// --------------------------- CONSTRUCTORS --------------------------- + + // ---------- START Level 1 ---------- + public RearrangerSettingsPanel(final RearrangerSettings externalSettings) { + RearrangerSettings settings = externalSettings.deepCopy(); + setLayout(new GridBagLayout()); + createSettingsPanel(settings); + } + +// ---------- START Level 2 ---------- + + private void createSettingsPanel(RearrangerSettings settings) { + this.settings = settings; + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.weightedLastRow(); + while (getComponents().length > 0) { + remove(0); + } + add(getSettingsPanel(), constraints.weightedLastCol()); + validate(); + } + +// ---------- START Level 3 ---------- + + private JPanel getSettingsPanel() { + final JPanel containerPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.weightedLastRow(); + final JTabbedPane pane = new JTabbedPane(); + final SettingsPane classMemberSettingsPane = new ClassMemberSettingsPane(settings); + final SettingsPane classOrderSettingsPane = new ClassOrderSettingsPane(settings); + final SpacingPane spacingPane = new SpacingPane(settings); + final ExtractedMethodsPane extractedMethodsSettings = new ExtractedMethodsPane(); + final JPanel generalSettingsPane = getGeneralSettingsPane(); + final RelatedByNamePane rbnp = new RelatedByNamePane(settings.getExtractedMethodsSettings().getRbnms()); + pane.addTab( + "Class Member Order", + null, + classMemberSettingsPane.getPane(), + "Options controlling arrangement of fields, methods and inner classes" + ); + pane.addTab( + "Outer Class Order", + null, + classOrderSettingsPane.getPane(), + "Options controlling arrangement of outer classes" + ); + pane.addTab( + "Extracted Methods", + null, + extractedMethodsSettings.getExtractedMethodsPane(settings.getExtractedMethodsSettings()), + "Options controlling arrangement of extracted methods" + ); + pane.addTab( + "General", + null, + generalSettingsPane, + "General options" + ); + pane.addTab( + "Spacing", + null, + spacingPane.getPane(), + "Options controlling number of blank lines before and after braces" + ); + pane.addTab( + "Configuration", + null, + getConfigurationPane(), + "Load, save, clear configuration, or set to default" + ); +// pane.addTab("Related By Name", null, // todo - add when ready; replace "Extracted Methods" pane above +// rbnp.getPane(), "Global definitions for methods related by name (\"getters/setters\")"); + pane.setSelectedIndex(0); + containerPanel.add(pane, constraints.weightedLastCol()); + return containerPanel; + } + +// ---------- START Level 4 ---------- + + private JPanel getGeneralSettingsPane() { + final JPanel gsPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + gsPanel.setBorder(border); + final GridBagConstraints constraints = new GridBagConstraints(); + + constraints.fill = GridBagConstraints.BOTH; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridwidth = 1; + constraints.gridheight = 1; + constraints.weightx = 0; + constraints.weighty = 0; + constraints.gridx = constraints.gridy = 0; + constraints.insets = new Insets(5, 5, 0, 0); + final JCheckBox getterSetterBox = new JCheckBox("Keep getters/setters together"); + getterSetterBox.setSelected(settings.isKeepGettersSettersTogether()); + final JCheckBox gettersSettersWithPropertyBox = new JCheckBox("Keep getters/setters with property"); + gettersSettersWithPropertyBox.setSelected(settings.isKeepGettersSettersWithProperty()); + gettersSettersWithPropertyBox.setEnabled(settings.isKeepGettersSettersTogether()); + final JCheckBox overloadedMethodsBox = new JCheckBox("Keep overloaded methods/constructors together"); + overloadedMethodsBox.setSelected(settings.isKeepOverloadedMethodsTogether()); + final JLabel overloadOrderLabel = new JLabel("Ordering of constructors and overloaded methods:"); + final JComboBox overloadOrderBox = new JComboBox( + new String[]{ + "Retain original order", + "Order by number of parameters (ascending)", + "Order by number of parameters (descending)" + } + ); + overloadOrderLabel.setEnabled(settings.isKeepOverloadedMethodsTogether()); + overloadOrderBox.setEnabled(settings.isKeepOverloadedMethodsTogether()); + overloadOrderBox.setSelectedIndex(settings.getOverloadedOrder()); + overloadedMethodsBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + settings.setKeepOverloadedMethodsTogether(overloadedMethodsBox.isSelected()); + overloadOrderLabel.setEnabled(settings.isKeepOverloadedMethodsTogether()); + overloadOrderBox.setEnabled(settings.isKeepOverloadedMethodsTogether()); + } + } + ); + final JCheckBox confirmBox = new JCheckBox("Confirm before rearranging"); + confirmBox.setSelected(settings.isAskBeforeRearranging()); + confirmBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + settings.setAskBeforeRearranging(confirmBox.isSelected()); + } + } + ); + + final JCheckBox rearrangeInnerClasses = new JCheckBox("Rearrange contents of inner classes"); + rearrangeInnerClasses.setSelected(settings.isRearrangeInnerClasses()); + rearrangeInnerClasses.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + settings.setRearrangeInnerClasses(rearrangeInnerClasses.isSelected()); + } + }); + gsPanel.add(getterSetterBox, constraints); + constraints.gridy++; + gsPanel.add(gettersSettersWithPropertyBox, constraints); + constraints.gridy++; +// constraints.insets = new Insets(0, 0, 0, 0); + gsPanel.add(overloadedMethodsBox, constraints); + constraints.gridy++; + constraints.insets = new Insets(0, 30, 3, 0); + gsPanel.add(overloadOrderLabel, constraints); + constraints.gridy++; + constraints.insets = new Insets(0, 30, 10, 0); + constraints.fill = GridBagConstraints.NONE; + gsPanel.add(overloadOrderBox, constraints); + constraints.fill = GridBagConstraints.BOTH; + constraints.gridy++; + constraints.insets = new Insets(5, 5, 0, 0); + gsPanel.add(confirmBox, constraints); + constraints.gridy++; + gsPanel.add(rearrangeInnerClasses, constraints); + constraints.gridy++; + // + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1.0d; + constraints.weighty = 0.0d; + final JPanel gsDefaultPane = settings.getDefaultGSDefinition().getGSDefinitionPanel(); + constraints.insets = new Insets(5, 5, 0, 5); + constraints.gridx = 1; + int oldGridy = constraints.gridy; + constraints.gridheight = constraints.gridy; + constraints.gridy = 0; + Border b = gsDefaultPane.getBorder(); + TitledBorder tb = BorderFactory.createTitledBorder(b, "Default Getter/Setter Definition"); + gsDefaultPane.setBorder(tb); + gsPanel.add(gsDefaultPane, constraints); + constraints.gridy = oldGridy; + // + constraints.gridx = 0; + constraints.gridwidth = 1; + constraints.gridheight = 1; + constraints.gridy++; + constraints.weightx = 0; // was 1 + constraints.insets = new Insets(5, 5, 0, 0); + final JLabel commentLabel = new JLabel("Comment pattern:"); + final JButton createPatternButton = new JButton("Generate pattern"); + final JButton verifyCommentsButton = new JButton("Verify comments against pattern"); + gsPanel.add(commentLabel, constraints); + constraints.gridx++; + constraints.anchor = GridBagConstraints.NORTH; + gsPanel.add(createPatternButton, constraints); + constraints.anchor = GridBagConstraints.NORTHEAST; + constraints.gridx++; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1; // was 0 + constraints.insets = new Insets(5, 0, 0, 5); + constraints.fill = GridBagConstraints.NONE; // new line + gsPanel.add(verifyCommentsButton, constraints); + constraints.fill = GridBagConstraints.BOTH; + constraints.gridx = 0; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.insets = new Insets(5, 5, 5, 5); + constraints.gridy++; + constraints.weighty = 1.0d; + constraints.gridheight = GridBagConstraints.REMAINDER; + final JTextArea commentArea = new JTextArea(4, 40); + commentArea.setText(settings.getGlobalCommentPattern()); + constraints.gridheight = GridBagConstraints.REMAINDER; + final JScrollPane scrollPane = new JScrollPane(commentArea); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + gsPanel.add(scrollPane, constraints); + + getterSetterBox.addActionListener( + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + settings.setKeepGettersSettersTogether(getterSetterBox.isSelected()); + gettersSettersWithPropertyBox.setEnabled(settings.isKeepGettersSettersTogether()); + } + } + ); + + gettersSettersWithPropertyBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + settings.setKeepGettersSettersWithProperty(gettersSettersWithPropertyBox.isSelected()); + } + }); + + overloadOrderBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + settings.setOverloadedOrder(overloadOrderBox.getSelectedIndex()); + } + } + ); + + commentArea.getDocument().addDocumentListener( + new DocumentListener() { + public void changedUpdate(final DocumentEvent e) { + settings.setGlobalCommentPattern(commentArea.getText()); + } + + public void insertUpdate(final DocumentEvent e) { + settings.setGlobalCommentPattern(commentArea.getText()); + } + + public void removeUpdate(final DocumentEvent e) { + settings.setGlobalCommentPattern(commentArea.getText()); + } + } + ); + + createPatternButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + String t = commentArea.getText(); + if (t.length() > 0) { + int result = JOptionPane.showConfirmDialog( + null, "This will replace the existing comment pattern with the generated pattern." + + " Are you sure?", + "Replace existing pattern", + JOptionPane.YES_NO_CANCEL_OPTION + ); + if (result != 0) return; + } + String s = generateCommentPattern(settings); + commentArea.setText(s); + } + } + ); + + verifyCommentsButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + checkCommentsAgainstGlobalPattern(settings); + } + } + ); + return gsPanel; + } + +// ---------- START Level 5 ---------- + + private String generateCommentPattern(RearrangerSettings settings) { + new CommentUtil(settings); + String result = RegexUtil.combineExpressions(CommentUtil.getCommentStrings()); + return result; + } + + /** + * Compare all comments specified by the user against the global comment pattern. If all match, then + * the global pattern will catch all the user's comments and remove them before rearranging and inserting + * new ones. If any don't match, bring up a dialog box listing them. + * + * @param settings current Rearranger settings. + */ + public void checkCommentsAgainstGlobalPattern(RearrangerSettings settings) { + String pattern = settings.getGlobalCommentPattern(); + if (pattern == null || pattern.trim().length() == 0) { + JOptionPane.showMessageDialog( + null, "No global comment pattern exists!" + , "Verify Comments Against Pattern", + JOptionPane.WARNING_MESSAGE + ); + return; + } + try { + " ".matches(pattern); + } + catch (PatternSyntaxException pse) { + JOptionPane.showMessageDialog( + null, + "Invalid global pattern:" + pse.toString(), + "Verify Comments Against Pattern", + JOptionPane.ERROR_MESSAGE + ); + return; + } + int nCommentsSeen = 0; + List mismatches = new ArrayList(); + // first check all rules in the class order settings panes. + nCommentsSeen = + checkAttributeListForErrors(settings.getClassOrderAttributeList(), nCommentsSeen, pattern, mismatches); + // now check all the class member attributes. + nCommentsSeen = + checkAttributeListForErrors(settings.getItemOrderAttributeList(), nCommentsSeen, pattern, mismatches); + + // now check all comments for extracted methods. Expand keywords to make the match realistic. + CommentRule rule = settings.getExtractedMethodsSettings().getPrecedingComment(); + String preceding = rule.getCommentText(); + if (preceding != null && preceding.trim().length() > 0) { + nCommentsSeen++; + checkExtractedComment(rule, "Preceding", pattern, mismatches); + } + rule = settings.getExtractedMethodsSettings().getTrailingComment(); + String trailing = rule.getCommentText(); + if (preceding != null && preceding.trim().length() > 0) { + nCommentsSeen++; + checkExtractedComment(rule, "Trailing", pattern, mismatches); + } + /** + * if any strings mismatch, display a dialog showing them; otherwise display a dialog indicating that + * everything is ok. + */ + if (nCommentsSeen == 0) { + JOptionPane.showMessageDialog( + null, "No user-defined comments have been configured" + , "Verify Comments Against Pattern", + JOptionPane.PLAIN_MESSAGE + ); + } + else if (mismatches.size() == 0) { + JOptionPane.showMessageDialog( + null, + nCommentsSeen + + " user-defined comments seen; " + + "all match the global comment pattern", + "Verify Comments Against Pattern", + JOptionPane.PLAIN_MESSAGE + ); + } + else { + mismatches.add(0, nCommentsSeen + " user-defined comments seen; following comments did not match:"); + JOptionPane.showMessageDialog( + null, mismatches.toArray(), + "Verify Comments Against Pattern", JOptionPane.WARNING_MESSAGE + ); + } + } + +// ---------- START Level 6 ---------- + + private int checkAttributeListForErrors(List list, + int nCommentsSeen, + String pattern, + List mismatches) + { + int index = 0; + for (AttributeGroup group : list) { + index++; + nCommentsSeen += group.getCommentCount(); + if (!group.commentsMatchGlobalPattern(pattern)) { + List badComments = group.getOffendingPatterns(pattern); + for (Object badComment : badComments) { + mismatches.add("Class Member item #" + index + ": \"" + badComment + "\""); + } + } + } + return nCommentsSeen; + } + + private void checkExtractedComment(final CommentRule commentRule, + final String which, + String pattern, + List mismatches) + { + String comment = commentRule.getCommentText(); + if (comment.length() == 0) return; + // make some 'typical' substitutions for wildcard expansion to check against pattern. + // hand-expand the %FS% (fill string) because the fill string could contain special characters that + // replaceAll interprets and changes. + String expanded = comment.replaceAll("%LV%", "12"); + expanded = expanded.replaceAll("%TL%", "topLevelMethod()"); + expanded = expanded.replaceAll("%MN%", "methodName()"); + expanded = expanded.replaceAll("%AM%", "method1().[method1A(),method1B()]"); + expanded = expanded.replaceAll("%IF%", "Interface_ExampleName0"); + expanded = RegexUtil.replaceAllFS(expanded, commentRule.getCommentFillString().getFillString()); + if (!expanded.matches(pattern)) { + mismatches.add(which + " comment for extracted methods: \"" + comment + "\""); + } + } + +// ---------- END Level 6 ---------- + + +// ---------- END Level 5 ---------- + + private JPanel getConfigurationPane() { + final JPanel gcPanel = new JPanel(new GridBagLayout()); + Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.insets = new Insets(5, 5, 0, 5); + final JButton clearConfig = new JButton("Clear configuration"); + final JButton loadDefaultConfig = new JButton("Load default configuration"); + final JButton readConfig = new JButton("Read configuration from file..."); + final JButton writeConfig = new JButton("Write configuration to file..."); + clearConfig.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + createSettingsPanel(new RearrangerSettings()); + } + }); + loadDefaultConfig.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + RearrangerSettings defaultSettings = RearrangerSettings.getDefaultSettings(); + if (defaultSettings == null) { + JOptionPane.showMessageDialog(null, "Could not obtain default configuration.", + "No default configuration available", JOptionPane.WARNING_MESSAGE); + } + else { + createSettingsPanel(defaultSettings); + } + } + }); + readConfig.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JFileChooser fc = new JFileChooser(); + int returnVal = fc.showOpenDialog(null); + + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + RearrangerSettings fileSettings = RearrangerSettings.getSettingsFromFile(file); + if (fileSettings == null) { + JOptionPane.showMessageDialog(null, "Could not read configuration.", + "File or file contents invalid", JOptionPane.WARNING_MESSAGE); + } + else { + createSettingsPanel(fileSettings); + } + } + } + }); + writeConfig.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JFileChooser fc = new JFileChooser(); + int returnVal = fc.showSaveDialog(null); + + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + settings.writeSettingsToFile(file); + } + } + }); + gcPanel.add(clearConfig, constraints.weightedLastCol()); + constraints.newRow(); + gcPanel.add(loadDefaultConfig, constraints.weightedLastCol()); + constraints.newRow(); + gcPanel.add(readConfig, constraints.weightedLastCol()); + constraints.newRow(); + gcPanel.add(writeConfig, constraints.weightedLastCol()); + + // now create outer panel so that buttons aren't stretched across creation. + JPanel outerPanel = new JPanel(new GridBagLayout()); + constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.weightedLastRow(); + outerPanel.add(gcPanel, constraints.weightedLastCol()); + JPanel extraPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + extraPanel.setBorder(border); + constraints = new Constraints(GridBagConstraints.SOUTHEAST); + extraPanel.add(outerPanel, constraints.firstCol()); + constraints.weightedNewRow(); + constraints.firstCol(); // skip first column + extraPanel.add(new JLabel(), constraints.weightedNextCol()); + constraints.lastRow(); + constraints.firstCol(); // skip first column + constraints.nextCol(); // skip second column + constraints.weightx = constraints.weighty = 0; + constraints.insets = new Insets(5, 5, 5, 5); + JLabel version = new JLabel("Rearranger plugin, version " + Rearranger.VERSION); + extraPanel.add(version, constraints.lastCol()); + return extraPanel; + } + +// --------------------------- main() method --------------------------- + +// ---------- END Level 4 ---------- +// ---------- END Level 3 ---------- + + +// ---------- END Level 2 ---------- + + +// ---------- END Level 1 ---------- +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/RelatedByNamePane.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/RelatedByNamePane.java new file mode 100644 index 000000000000..16eb362ec6ba --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/RelatedByNamePane.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.wrq.rearranger.settings.PrimaryMethodSetting; +import com.wrq.rearranger.settings.RelatedByNameMethodsSettings; + +import javax.swing.*; +import java.util.List; + +/** Configuration settings for handling ordering of extracted methods. */ +public class RelatedByNamePane { + RelatedByNameMethodsSettings rbnms; + + public RelatedByNamePane(RelatedByNameMethodsSettings rbnms) { + this.rbnms = rbnms; + } + + public final JPanel getPane() { + IListManagerObjectFactory lmof = new IListManagerObjectFactory() { + public IListManagerObject create(String name) { + PrimaryMethodSetting pms = new PrimaryMethodSetting(); + pms.setDescription(name); + return pms; + } + + public List getObjectList() { + return rbnms.getMethodList(); + } + }; + ListManager result = new ListManager(lmof, "Primary method name:"); +// constraints = new GridBagConstraints(); +// constraints.anchor = GridBagConstraints.NORTHWEST; +// constraints.fill = GridBagConstraints.NONE; +// constraints.gridwidth = 1; +// constraints.gridheight = 1; +// constraints.weightx = 0.0d; +// constraints.weighty = 0.0d; +// constraints.gridy = constraints.gridx = 0; +// constraints.insets = new Insets(3, 3, 3, 3); +// addButton.setBorderPainted(false); +// removeButton.setBorderPainted(false); +// copyButton.setBorderPainted(false); +// containerPanel.add(addButton, constraints); +// constraints.gridx++; +// containerPanel.add(removeButton, constraints); +// constraints.gridx++; +// containerPanel.add(copyButton, constraints); +// constraints.gridx++; +// containerPanel.add(nameLabel, constraints); +// constraints.gridx++; +// constraints.gridwidth = GridBagConstraints.REMAINDER; +// constraints.weightx = 1; +// constraints.fill = GridBagConstraints.HORIZONTAL; +// containerPanel.add(name, constraints); +// /** +// * declare callback handlers for buttons. +// */ +// addButton.addActionListener(new ActionListener() +// { +// public void actionPerformed(ActionEvent e) +// { +// PrimaryMethodSetting pms = new PrimaryMethodSetting(); +// pms.setName("unnamed"); +// ((DefaultListModel)rbnmlist.getModel()).addElement(pms); +// rbnmlist.setSelectedIndex(rbnmlist.getModel().getSize() - 1); +// updateListSelection(); +// } +// }); +// removeButton.addActionListener(new ActionListener() +// { +// public void actionPerformed(ActionEvent e) +// { +// DefaultListModel dlm = ((DefaultListModel)rbnmlist.getModel()); +// int selectedIndex = rbnmlist.getSelectedIndex(); +// PrimaryMethodSetting pms = (PrimaryMethodSetting) dlm.getElementAt(selectedIndex); +// rbnms.getMethodList().remove(pms); +// dlm.remove(selectedIndex); +// if (selectedIndex >= dlm.getSize()) { +// selectedIndex = dlm.getSize() - 1; +// } +// rbnmlist.setSelectedIndex(selectedIndex); +// updateListSelection(); +// } +// }); +// copyButton.addActionListener(new ActionListener() +// { +// public void actionPerformed(ActionEvent e) +// { +// DefaultListModel dlm = ((DefaultListModel)rbnmlist.getModel()); +// int selectedIndex = rbnmlist.getSelectedIndex(); +// PrimaryMethodSetting pms = (PrimaryMethodSetting) dlm.getElementAt(selectedIndex); +// dlm.addElement(pms.deepcopy()); +// rbnmlist.setSelectedIndex(rbnmlist.getModel().getSize() - 1); +// updateListSelection(); +// } +// }); +// rbnmlist.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); +// addButton.setEnabled(true); +// name.getDocument().addDocumentListener(new DocumentListener() +// { +// private void updateList() +// { +// String newText = name.getText(); +// final PrimaryMethodSetting primaryMethodSetting = (PrimaryMethodSetting)rbnmlist.getSelectedValue(); +// primaryMethodSetting.setName(newText); +// int index = rbnmlist.getSelectedIndex(); +// DefaultListModel dlm = ((DefaultListModel)rbnmlist.getModel()); +// dlm.remove(index); +// dlm.add(index, primaryMethodSetting); +// rbnmlist.setSelectedIndex(index); +// } +// public void changedUpdate(DocumentEvent e) +// { +// updateList(); +// } +// +// public void insertUpdate(DocumentEvent e) +// { +// updateList(); +// } +// +// public void removeUpdate(DocumentEvent e) +// { +// updateList(); +// } +// }); +// JScrollPane scrollPane = new JScrollPane(rbnmlist); +// scrollPane.setPreferredSize(new Dimension(80, 300)); +// ListIterator li = rbnms.getMethodList().listIterator(); +// while (li.hasNext()) +// { +// PrimaryMethodSetting pms = (PrimaryMethodSetting) li.next(); +// ((DefaultListModel)rbnmlist.getModel()).addElement(pms); +// } +// rbnmlist.setSelectedIndex(rbnmlist.getModel().getSize() - 1); +// constraints.gridheight = GridBagConstraints.REMAINDER; +// constraints.gridx = 0; +// constraints.gridy++; +// constraints.gridwidth = 3; +// constraints.weightx = .2; +// constraints.weighty = 1; +// constraints.fill = GridBagConstraints.BOTH; +// containerPanel.add(scrollPane, constraints); +// constraints.gridx += 3; +// constraints.gridwidth = GridBagConstraints.REMAINDER; +// constraints.fill = GridBagConstraints.BOTH; +// constraints.weightx = .8; +// containerPanel.add(getPrimaryMethodPanel(), constraints); +// updateListSelection(); + return result.getPane(); + } + + /** + * Enable add/remove/copy buttons and fill in name of selected list item. Called whenever + * the list selection changes. + */ +// private void updateListSelection() +// { +// if (rbnmlist.getModel().getSize() > 0) +// { +// rbnmlist.setSelectedIndex(0); +// name.setEnabled(true); +// nameLabel.setEnabled(true); +// name.setText(((PrimaryMethodSetting) rbnmlist.getSelectedValue()).getName()); +// removeButton.setEnabled(true); +// copyButton.setEnabled(true); +// } +// else +// { +// name.setEnabled(false); +// nameLabel.setEnabled(false); +// removeButton.setEnabled(false); +// copyButton.setEnabled(false); +// name.setText(""); +// } +// containerPanel.remove(containerPanel.getComponentCount() - 1); +// containerPanel.add(getPrimaryMethodPanel(), constraints); +// containerPanel.validate(); +// } + + /** + * Get a primary method panel based on values for the currently selected primary item. + * @return + */ +// private JPanel getPrimaryMethodPanel() +// { +// PrimaryMethodSetting pms = (PrimaryMethodSetting) rbnmlist.getSelectedValue(); +// if (pms == null) { +// return new JPanel(); // empty +// } +// else { +// return pms.getPanel(); +// } +// } + +// ---------- START Level 4 ---------- +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/SettingsPane.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/SettingsPane.java new file mode 100644 index 000000000000..358a2312e225 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/SettingsPane.java @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.AttributeGroup; +import com.wrq.rearranger.settings.attributeGroups.IPrioritizableRule; +import com.wrq.rearranger.settings.attributeGroups.IRule; +import com.wrq.rearranger.util.Constraints; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.*; +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; +import java.util.List; + +/** Code common to dialog managing creation and maintenance of a list of rules. */ +public abstract class SettingsPane { +// ------------------------------ FIELDS ------------------------------ + + public static final int SEQUENCE_COLUMN = 0; + public static final int PRIORITY_COLUMN = 1; + public static final int DESCRIPTION_COLUMN = 2; + public static final int NUM_COLUMNS = 3; + protected final RearrangerSettings settings; + + private final List list; + private List modelData; + private JTable jTable; + private AbstractTableModel model; + private JPanel pane; + +// --------------------------- CONSTRUCTORS --------------------------- + + SettingsPane(final RearrangerSettings settings, List list) { + this.settings = settings; + this.list = list; + modelData = new ArrayList(list.size()); + createConfigurationPane(); + } + + private void createConfigurationPane() { + pane = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEmptyBorder(); + pane.setBorder(border); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.weightedNewRow(); + constraints.fill = GridBagConstraints.BOTH; + constraints.insets = new Insets(10, 10, 10, 10); + pane.add(createScrollableTablePanel(), constraints.weightedFirstCol()); + pane.add(createAddRemovePanel(), constraints.nextCol()); + } + + private JPanel createScrollableTablePanel() { + final JPanel cmlPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.weightedLastRow(); + constraints.fill = GridBagConstraints.BOTH; + final JTextField priorityField = new JTextField(); + priorityField.setHorizontalAlignment(JTextField.RIGHT); + TableCellEditor priorityEditor = new DefaultCellEditor(priorityField); + model = new AbstractTableModel() { + public int getColumnCount() { + return NUM_COLUMNS; // sequence, priority, rule description + } + + public int getRowCount() { + return list.size(); + } + + public Object getValueAt(int rowIndex, int columnIndex) { + switch (columnIndex) { + case SEQUENCE_COLUMN: + return rowIndex + 1; + + case PRIORITY_COLUMN: + ChoicePanel cp = (modelData.get(rowIndex)); + IRule rule = cp.getChoice().getChoiceObject(); + return new Priority(rule.getPriority()); + + case DESCRIPTION_COLUMN: + return list.get(rowIndex).toString(); + } + return null; + } + + public String getColumnName(int column) { + switch (column) { + case SEQUENCE_COLUMN: + return "Seq"; + + case PRIORITY_COLUMN: + return "Pri"; + + case DESCRIPTION_COLUMN: + return "Rule"; + } + return null; + } + + public Class getColumnClass(int columnIndex) { + switch (columnIndex) { + case SEQUENCE_COLUMN: + return Integer.class; + + case PRIORITY_COLUMN: + return Priority.class; + + case DESCRIPTION_COLUMN: + return String.class; + } + return Object.class; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + if (columnIndex == PRIORITY_COLUMN && rowIndex >= 0) { + ChoicePanel cp = (modelData.get(rowIndex)); + IRule rule = cp.getChoice().getChoiceObject(); + if (rule instanceof IPrioritizableRule) { + return true; + } + } + return false; + } + + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if (columnIndex == PRIORITY_COLUMN) { + ChoicePanel cp = (modelData.get(rowIndex)); + IRule rule = cp.getChoice().getChoiceObject(); + if (rule instanceof IPrioritizableRule) { + int priority; + try { + priority = (new Integer((String)aValue)); + } + catch (NumberFormatException nfe) { + return; + } + if (priority > 0 && priority < 100) { + rule.setPriority(priority); + fireTableCellUpdated(rowIndex, columnIndex); + } + } + } + } + }; + TableCellRenderer priorityRenderer = new DefaultTableCellRenderer() { + protected void setValue(Object value) { + Priority p = (Priority)value; + if (p.priority <= 0) { + setText("n/a"); + setHorizontalAlignment(JLabel.CENTER); + } + else { + setText("" + p.priority + " "); + setHorizontalAlignment(JLabel.RIGHT); + } + } + }; + TableSorter sorter = new TableSorter(model) { + public void sortByColumn(int column, boolean ascending) { + if (column == SEQUENCE_COLUMN || + column == PRIORITY_COLUMN) + { + super.sortByColumn(column, ascending); + } + } + + public boolean defaultSortOrderAscending(int column) { + switch (column) { + case SEQUENCE_COLUMN: + return true; + case PRIORITY_COLUMN: + return false; + } + return true; + } + }; + jTable = new JTable(sorter); + sorter.addMouseListenerToHeaderInTable(jTable); + jTable.setShowHorizontalLines(false); + jTable.setShowVerticalLines(true); + jTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + jTable.setDragEnabled(false); + jTable.setRowSelectionAllowed(true); + jTable.setColumnSelectionAllowed(false); + jTable.setPreferredScrollableViewportSize(jTable.getPreferredSize()); + jTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + + TableColumnModel tcm = jTable.getColumnModel(); + tcm.getColumn(0).setPreferredWidth(new JLabel("SEQ").getWidth() * 3); + tcm.getColumn(1).setPreferredWidth(new JLabel("MMM").getWidth() * 3); + tcm.getColumn(1).setCellRenderer(priorityRenderer); + tcm.getColumn(1).setCellEditor(priorityEditor); + final JScrollPane scrollPane = new JScrollPane(jTable); + for (AttributeGroup ca : list) { + modelData.add(createOptionsPaneMsg(ca)); + } + if (list.size() > 0) { + jTable.getSelectionModel().setSelectionInterval(0, 0); + } + cmlPanel.add(scrollPane, constraints.weightedLastCol()); + setTableColumnWidths(); + return cmlPanel; + } + + /** + * @param ca FieldAttributes, MethodAttributes, InnerClassAttributes, or CommentRule object + * @return ItemPanel corresponding to the value of param. + */ + private ChoicePanel createOptionsPaneMsg(final AttributeGroup ca) { + final ChoicePanel result = createChoicePanel(); + for (int i = 0; i < result.getChoices().length; i++) { + final AttributeGroup choiceObject = result.getChoices()[i].getChoiceObject(); + if (ca.getClass() == choiceObject.getClass()) { + result.setChoice(i); + result.getChoice().choiceObject = ca; + break; + } + } + return result; + } + + abstract ChoicePanel createChoicePanel(); + + private void setTableColumnWidths() { + int columnCount = jTable.getColumnCount(); + TableColumnModel tcm = jTable.getColumnModel(); + final int SPARE = 24; + + for (int i = 0; i < columnCount; i++) { + int width = calculateColumnWidth(i); + width += SPARE; + TableColumn column = tcm.getColumn(i); + column.setMinWidth(width); + if (i < columnCount - 1) { + column.setMaxWidth(width); + } + } + } + + private int calculateColumnWidth(int columnIndex) { + int result = 0; + int rowCount = jTable.getRowCount(); + for (int i = 0; i < rowCount; i++) { + TableCellRenderer tcr = jTable.getCellRenderer(i, columnIndex); + Component comp = tcr.getTableCellRendererComponent( + jTable, + jTable.getValueAt(i, columnIndex), + true, true, i, columnIndex + ); + int compWidth = comp.getPreferredSize().width; + if (compWidth > result) { + result = compWidth; + } + } + TableCellRenderer tcr = jTable.getColumnModel().getColumn(columnIndex).getHeaderRenderer(); + if (tcr == null) { + tcr = jTable.getDefaultRenderer(String.class); + } + Component comp = tcr.getTableCellRendererComponent( + jTable, + model.getColumnName(columnIndex), true, true, -1, columnIndex + ); + int compWidth = comp.getPreferredSize().width; + if (compWidth > result) { + result = compWidth; + } + if (columnIndex == DESCRIPTION_COLUMN) { + if (result < 400) result = 400; + } + return result; + } + + private JPanel createAddRemovePanel() { + final JPanel addRemovePanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTH); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.insets = new Insets(0, 0, 10, 0); + final JButton addButton = new JButton("Add"); + final JButton editButton = new JButton("Edit"); + final JButton removeButton = new JButton("Remove"); + final JButton duplicateButton = new JButton("Duplicate"); + final JButton moveUpButton = new JButton("Move up"); + final JButton moveDownButton = new JButton("Move down"); + addRemovePanel.add(addButton, constraints.firstCol()); + constraints.newRow(); + addRemovePanel.add(editButton, constraints.firstCol()); + constraints.newRow(); + addRemovePanel.add(duplicateButton, constraints.firstCol()); + constraints.newRow(); + addRemovePanel.add(removeButton, constraints.firstCol()); + constraints.newRow(); + addRemovePanel.add(moveUpButton, constraints.firstCol()); + constraints.weightedNewRow(); + constraints.insets = new Insets(0, 0, 0, 0); + addRemovePanel.add(moveDownButton, constraints.firstCol()); + if (jTable.getSelectedRow() < 0) { + editButton.setEnabled(false); + duplicateButton.setEnabled(false); + removeButton.setEnabled(false); + moveUpButton.setEnabled(false); + moveDownButton.setEnabled(false); + } + if (jTable.getSelectedRow() == 0) { + moveUpButton.setEnabled(false); + } + if (jTable.getSelectedRowCount() > 0 && + jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1] == jTable.getModel().getRowCount() - 1) + { + moveDownButton.setEnabled(false); + } + jTable.getSelectionModel().addListSelectionListener( + new ListSelectionListener() { + public void valueChanged(final ListSelectionEvent e) { + if (e.getValueIsAdjusting() || (e.getFirstIndex() < 0)) { + return; + } + final int index = jTable.getSelectedRow(); + final boolean selectionExists = index >= 0; + editButton.setEnabled(selectionExists); + duplicateButton.setEnabled(selectionExists); + removeButton.setEnabled(selectionExists); + moveUpButton.setEnabled(selectionExists && index > 0); + int lastSelectedRow = 0; + if (selectionExists) { + lastSelectedRow = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1]; + } + moveDownButton.setEnabled(selectionExists && + lastSelectedRow < jTable.getModel().getRowCount() - 1); + } + } + ); + jTable.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + int index = jTable.getSelectedRow(); + editRow(addRemovePanel); + jTable.getSelectionModel().setLeadSelectionIndex(index); + } + } + }); + addButton.addActionListener( + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + // add new rule after last selected rule + final int currentIndex; + if (jTable.getSelectedRowCount() <= 0) { + currentIndex = 0; + } + else { + currentIndex = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1] + 1; + } + final ChoicePanel choicePanel = getOptionsPaneMsg(null); + final JOptionPane op = new JOptionPane( + choicePanel, + JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, + null, null, null + ); + final JDialog jd = op.createDialog(addRemovePanel, choicePanel.getChoicePanelName()); + jd.setVisible(true); + final Object result = op.getValue(); + if (result != null && + ((Integer)result) == JOptionPane.OK_OPTION) + { + final ChoicePanel value = (ChoicePanel)op.getMessage(); + value.acceptEdited(); + modelData.add(currentIndex, value); + list.add(currentIndex, ((com.wrq.rearranger.settings.attributeGroups.AttributeGroup)value.getChoice().getChoiceObject())); + model.fireTableRowsInserted(currentIndex, currentIndex); + jTable.getSelectionModel().setSelectionInterval(currentIndex, currentIndex); + } + setTableColumnWidths(); + } + } + ); + editButton.addActionListener( + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + editRow(addRemovePanel); + } + } + ); + jTable.addMouseListener( + new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() >= 2) { + editRow(addRemovePanel); + } + } + } + ); + + duplicateButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + // duplicate all selected rows as a block + AttributeGroup[] newRules = new AttributeGroup[jTable.getSelectedRowCount()]; + for (int row = 0; row < jTable.getSelectedRowCount(); row++) { + final int currentIndex = jTable.getSelectedRows()[row]; + final ChoicePanel choicePanel = (modelData.get(currentIndex)); + AttributeGroup rule = choicePanel.getChoice().getChoiceObject(); + AttributeGroup newRule = rule.deepCopy(); + newRules[row] = newRule; + } + // now insert the new rows at the correct place + final int offset = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1] + 1; + for (int row = 0; row < newRules.length; row++) { + final AttributeGroup newRule = newRules[row]; + modelData.add(row + offset, createOptionsPaneMsg(newRule)); + list.add(row + offset, newRule); + model.fireTableRowsInserted(row + offset, row + offset); + } + } + } + ); + removeButton.addActionListener( + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + // remove a block of rules. + final int currentIndex = jTable.getSelectedRow(); + if (currentIndex >= 0) { + final int first = jTable.getSelectedRows()[0]; + final int last = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1]; + for (int i = first; i <= last; i++) { + list.remove(currentIndex); + modelData.remove(currentIndex); + } + model.fireTableRowsDeleted(currentIndex, currentIndex); + int newSelIndex = (currentIndex >= model.getRowCount()) + ? model.getRowCount() - 1 + : currentIndex; + jTable.getSelectionModel().setSelectionInterval(newSelIndex, newSelIndex); + setTableColumnWidths(); + } + } + } + ); + moveUpButton.addActionListener( + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final int first = jTable.getSelectedRows()[0]; + if (first <= 0) return; + final int last = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1]; + for (int i = first; i <= last; i++) { + list.add(i - 1, list.remove(i)); + modelData.add(i - 1, modelData.remove(i)); + model.fireTableRowsUpdated(i - 1, i); + } + jTable.getSelectionModel().setSelectionInterval(first - 1, last - 1); + } + } + ); + moveDownButton.addActionListener( + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final int first = jTable.getSelectedRows()[0]; + final int last = jTable.getSelectedRows()[jTable.getSelectedRowCount() - 1]; + if (last + 1 >= jTable.getModel().getRowCount()) return; + for (int i = last; i >= first; i--) { + list.add(i + 1, (list.remove(i))); + modelData.add(i + 1, (modelData.remove(i))); + model.fireTableRowsUpdated(i, i + 1); + } + jTable.getSelectionModel().setSelectionInterval(first + 1, last + 1); + } + } + ); + return addRemovePanel; + } + + private ChoicePanel getOptionsPaneMsg(final ChoicePanel currentMsg) { + final ChoicePanel result = createChoicePanel(); + if (currentMsg != null) { + result.copyChoices(currentMsg); + } + result.configurePanel(); + return result; + } + + private void editRow(final JPanel addRemovePanel) { + // edit first row of all rows selected + final int currentIndex = jTable.getSelectedRow(); + final ChoicePanel o = modelData.get(currentIndex); + final ChoicePanel choicePanel = getOptionsPaneMsg(o); + final JOptionPane op = new JOptionPane( + choicePanel, + JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, + null, null, null + ); + final JDialog jd = op.createDialog(addRemovePanel, choicePanel.getChoicePanelName()); + jd.setVisible(true); + final Object result = op.getValue(); + if (result != null && + ((Integer)result) == JOptionPane.OK_OPTION) + { + final ChoicePanel value = (ChoicePanel)op.getMessage(); + value.acceptEdited(); + modelData.set(currentIndex, value); + list.set(currentIndex, ((com.wrq.rearranger.settings.attributeGroups.AttributeGroup)value.getChoice().getChoiceObject())); + model.fireTableRowsUpdated(currentIndex, currentIndex); + } + setTableColumnWidths(); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public final JPanel getPane() { + return pane; + } + +// -------------------------- INNER CLASSES -------------------------- + + class Priority { + int priority; + + public Priority(int priority) { + this.priority = priority; + } + + public String toString() { + return "" + priority; + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/SpacingPane.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/SpacingPane.java new file mode 100644 index 000000000000..1e92633e5ec5 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/SpacingPane.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import com.wrq.rearranger.settings.ForceBlankLineSetting; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.text.NumberFormat; + +/** UI code for Spacing rules dialog. */ +public class SpacingPane { +// ------------------------------ FIELDS ------------------------------ + + private final RearrangerSettings settings; + +// --------------------------- CONSTRUCTORS --------------------------- + + public SpacingPane(RearrangerSettings settings) { + this.settings = settings; + } + +// -------------------------- OTHER METHODS -------------------------- + + public JPanel getPane() { + final JPanel panel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + panel.setBorder(border); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1.0d; + constraints.insets = new Insets(3, 3, 0, 0); + panel.add(getForceBlankLinePanel(settings.getAfterClassLBrace()), constraints.weightedLastCol()); + constraints.newRow(); + panel.add(getForceBlankLinePanel(settings.getBeforeClassRBrace()), constraints.weightedLastCol()); + constraints.newRow(); + panel.add(getForceBlankLinePanel(settings.getAfterClassRBrace()), constraints.weightedLastCol()); + constraints.newRow(); + panel.add(getForceBlankLinePanel(settings.getBeforeMethodLBrace()), constraints.weightedLastCol()); + constraints.newRow(); + panel.add(getForceBlankLinePanel(settings.getAfterMethodLBrace()), constraints.weightedLastCol()); + constraints.newRow(); + panel.add(getForceBlankLinePanel(settings.getBeforeMethodRBrace()), constraints.weightedLastCol()); + constraints.newRow(); + panel.add(getForceBlankLinePanel(settings.getAfterMethodRBrace()), constraints.weightedLastCol()); + constraints.newRow(); + panel.add(getForceBlankLinePanel(settings.getNewlinesAtEOF()), constraints.weightedLastCol()); + constraints.weightedLastRow(); + final JCheckBox insideBlockBox = new JCheckBox("Remove initial and final blank lines inside code block"); + insideBlockBox.setSelected(settings.isRemoveBlanksInsideCodeBlocks()); + panel.add(insideBlockBox, constraints.weightedLastCol()); + insideBlockBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + settings.setRemoveBlanksInsideCodeBlocks(insideBlockBox.isSelected()); + } + }); + return panel; + } + + private JPanel getForceBlankLinePanel(final ForceBlankLineSetting fbl) { + final JPanel panel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(); + constraints.fill = GridBagConstraints.BOTH; + constraints.lastRow(); + + final JCheckBox forceBox = new JCheckBox("Force"); + forceBox.setSelected(fbl.isForce()); + panel.add(forceBox, constraints.weightedFirstCol()); + final NumberFormat integerInstance = NumberFormat.getIntegerInstance(); + integerInstance.setMaximumIntegerDigits(2); + integerInstance.setMinimumIntegerDigits(1); + final JFormattedTextField nBlankLines = new JFormattedTextField(integerInstance); + nBlankLines.setValue(new Integer("88")); + Dimension d = nBlankLines.getPreferredSize(); + d.width += 3; + nBlankLines.setPreferredSize(d); + nBlankLines.setValue(fbl.getnBlankLines()); + nBlankLines.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT); + constraints.insets = new Insets(0, 3, 0, 0); + panel.add(nBlankLines, constraints.weightedNextCol()); + nBlankLines.addPropertyChangeListener("value", new PropertyChangeListener() { + public void propertyChange(final PropertyChangeEvent evt) { + int n = ((Number)nBlankLines.getValue()).intValue(); + if (n < 0) { + n = 0; + nBlankLines.setValue(n); + } + fbl.setnBlankLines(n); + } + }); + String labelText = "blank lines " + + (fbl.isBefore() ? "before" : "after"); + switch (fbl.getObject()) { + case ForceBlankLineSetting.CLASS_OBJECT: + labelText += " class "; + break; + case ForceBlankLineSetting.METHOD_OBJECT: + labelText += " method "; + break; + } + labelText += fbl.isOpenBrace() ? "open brace \"{\"" + : "close brace \"}\""; + if (fbl.getObject() == ForceBlankLineSetting.EOF_OBJECT) { + labelText = "newline characters at end of file"; + } + final JLabel blankLineLabel = new JLabel(labelText); + panel.add(blankLineLabel, constraints.lastCol()); + nBlankLines.setEnabled(forceBox.isSelected()); + blankLineLabel.setEnabled(forceBox.isSelected()); + forceBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + fbl.setForce(forceBox.isSelected()); + nBlankLines.setEnabled(forceBox.isSelected()); + blankLineLabel.setEnabled(forceBox.isSelected()); + } + }); + return panel; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/StringTextArea.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/StringTextArea.java new file mode 100644 index 000000000000..5e5b815e8a8c --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/StringTextArea.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + + +/** + * A JTextArea tied to a String field of this class. Initialize the JTextField from the field and update + * the field whenever the JTextField's text changes. + */ +public abstract class StringTextArea + extends JTextArea +{ + + abstract public void setValue(String value); + + abstract public String getValue(); + + public StringTextArea() { + super(); + setText(getValue()); + getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { + setValue(getText()); + } + + public void removeUpdate(DocumentEvent e) { + setValue(getText()); + } + + public void changedUpdate(DocumentEvent e) { + setValue(getText()); + } + }); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/StringTextField.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/StringTextField.java new file mode 100644 index 000000000000..4170141255b9 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/StringTextField.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +/** + * A JTextField tied to a String field of this class. Initialize the JTextField from the field and update + * the field whenever the JTextField's text changes. + */ +public abstract class StringTextField + extends JTextField +{ + abstract public void setValue(String value); + + abstract public String getValue(); + + public StringTextField() { + super(); + setText(getValue()); + getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { + setValue(getText()); + } + + public void removeUpdate(DocumentEvent e) { + setValue(getText()); + } + + public void changedUpdate(DocumentEvent e) { + setValue(getText()); + } + }); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/TableMap.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/TableMap.java new file mode 100644 index 000000000000..df6f86f1ac44 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/TableMap.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +/** + * In a chain of data manipulators some behaviour is common. TableMap + * provides most of this behaviour and can be subclassed by filters + * that only need to override a handful of specific methods. TableMap + * implements TableModel by routing all requests to its model, and + * TableModelListener by routing all events to its listeners. Inserting + * a TableMap which has not been subclassed into a chain of table filters + * should have no effect. + * + * @version 1.4 12/17/97 + * @author Philip Milne + */ + +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableModel; + +public class TableMap + extends AbstractTableModel + implements TableModelListener +{ +// ------------------------------ FIELDS ------------------------------ + + protected TableModel model; + +// --------------------- GETTER / SETTER METHODS --------------------- + + public void setModel(TableModel model) { + this.model = model; + model.addTableModelListener(this); + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface TableModel --------------------- + + + public int getColumnCount() { + return (model == null) ? 0 : model.getColumnCount(); + } + + public int getRowCount() { + return (model == null) ? 0 : model.getRowCount(); + } + + public boolean isCellEditable(int row, int column) { + return model.isCellEditable(row, column); + } + + public Class getColumnClass(int aColumn) { + return model.getColumnClass(aColumn); + } + + // By default, implement TableModel by forwarding all messages + // to the model. + + public Object getValueAt(int aRow, int aColumn) { + return model.getValueAt(aRow, aColumn); + } + + public void setValueAt(Object aValue, int aRow, int aColumn) { + model.setValueAt(aValue, aRow, aColumn); + } + + public String getColumnName(int aColumn) { + return model.getColumnName(aColumn); + } + +// --------------------- Interface TableModelListener --------------------- + + // +// Implementation of the TableModelListener interface, +// + // By default forward all events to all the listeners. + public void tableChanged(TableModelEvent e) { + fireTableChanged(e); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/configuration/TableSorter.java b/plugins/rearranger/src/com/wrq/rearranger/configuration/TableSorter.java new file mode 100644 index 000000000000..1b4a48c96dd2 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/configuration/TableSorter.java @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.configuration; + +/** + * A sorter for TableModels. The sorter has a model (conforming to TableModel) + * and itself implements TableModel. TableSorter does not store or copy + * the data in the TableModel, instead it maintains an array of + * integers which it keeps the same size as the number of rows in its + * model. When the model changes it notifies the sorter that something + * has changed eg. "rowsAdded" so that its internal array of integers + * can be reallocated. As requests are made of the sorter (like + * getValueAt(row, col) it redirects them to its model via the mapping + * array. That way the TableSorter appears to hold another copy of the table + * with the rows in a different order. The sorting algorthm used is stable + * which means that it does not move around rows when its comparison + * function returns 0 to denote that they are equivalent. + * + * @version 1.5 12/17/97 + * @author Philip Milne + */ + +import javax.swing.*; +import javax.swing.event.TableModelEvent; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Date; +import java.util.List; +import java.util.Vector; + +public class TableSorter extends TableMap { +// ------------------------------ FIELDS ------------------------------ + + int[] indexes; + List sortingColumns = new Vector(); + boolean ascending = true; + int compares; + +// --------------------------- CONSTRUCTORS --------------------------- + + public TableSorter() { + indexes = new int[0]; // for consistency + } + + public TableSorter(TableModel model) { + setModel(model); + } + + public void setModel(TableModel model) { + super.setModel(model); + reallocateIndexes(); + } + + public void reallocateIndexes() { + int rowCount = model.getRowCount(); + + // Set up a new array of indexes with the right number of elements + // for the new data model. + indexes = new int[rowCount]; + + // Initialise with the identity mapping. + for (int row = 0; row < rowCount; row++) { + indexes[row] = row; + } + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface TableModel --------------------- + + + // The mapping only affects the contents of the data rows. + // Pass all requests to these rows through the mapping array: "indexes". + + public Object getValueAt(int aRow, int aColumn) { + checkModel(); + return model.getValueAt(indexes[aRow], aColumn); + } + + public void setValueAt(Object aValue, int aRow, int aColumn) { + checkModel(); + model.setValueAt(aValue, indexes[aRow], aColumn); + } + +// --------------------- Interface TableModelListener --------------------- + + public void tableChanged(TableModelEvent e) { + reallocateIndexes(); + super.tableChanged(e); + } + +// -------------------------- OTHER METHODS -------------------------- + + // There is nowhere else to put this. + // Add a mouse listener to the Table to trigger a table sort + // when a column heading is clicked in the JTable. + public void addMouseListenerToHeaderInTable(JTable table) { + final TableSorter sorter = this; + final JTable tableView = table; + tableView.setColumnSelectionAllowed(false); + MouseAdapter listMouseListener = new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + TableColumnModel columnModel = tableView.getColumnModel(); + int viewColumn = columnModel.getColumnIndexAtX(e.getX()); + int column = tableView.convertColumnIndexToModel(viewColumn); + if (e.getClickCount() == 1 && column != -1) { + int shiftPressed = e.getModifiers() & InputEvent.SHIFT_MASK; + boolean ascending = defaultSortOrderAscending(column) ^ (shiftPressed != 0); + sorter.sortByColumn(column, ascending); + } + } + }; + JTableHeader th = tableView.getTableHeader(); + th.addMouseListener(listMouseListener); + } + + public boolean defaultSortOrderAscending(int column) { + return true; + } + + public void sortByColumn(int column, boolean ascending) { + this.ascending = ascending; + sortingColumns.clear(); + sortingColumns.add(column); + sort(this); + super.tableChanged(new TableModelEvent(this)); + } + + public void sort(TableSorter sender) { + checkModel(); + + compares = 0; + // n2sort(); + // qsort(0, indexes.length-1); + shuttlesort(indexes.clone(), indexes, 0, indexes.length); + } + + public void checkModel() { + if (indexes.length != model.getRowCount()) { + throw new RuntimeException("Sorter not informed of a change in model."); + } + } + + // This is a home-grown implementation which we have not had time + // to research - it may perform poorly in some circumstances. It + // requires twice the space of an in-place algorithm and makes + // NlogN assigments shuttling the values between the two + // arrays. The number of compares appears to vary between N-1 and + // NlogN depending on the initial order but the main reason for + // using it here is that, unlike qsort, it is stable. + public void shuttlesort(int[] from, int[] to, int low, int high) { + if (high - low < 2) { + return; + } + int middle = (low + high) / 2; + shuttlesort(to, from, low, middle); + shuttlesort(to, from, middle, high); + + int p = low; + int q = middle; + + /* This is an optional short-cut; at each recursive call, +check to see if the elements in this subset are already +ordered. If so, no further comparisons are needed; the +sub-array can just be copied. The array must be copied rather +than assigned otherwise sister calls in the recursion might +get out of sinc. When the number of elements is three they +are partitioned so that the first set, [low, mid), has one +element and and the second, [mid, high), has two. We skip the +optimisation when the number of elements is three or less as +the first compare in the normal merge will produce the same +sequence of steps. This optimisation seems to be worthwhile +for partially ordered lists but some analysis is needed to +find out how the performance drops to Nlog(N) as the initial +order diminishes - it may drop very quickly. */ + + if (high - low >= 4 && compare(from[middle - 1], from[middle]) <= 0) { + for (int i = low; i < high; i++) { + to[i] = from[i]; + } + return; + } + + // A normal merge. + + for (int i = low; i < high; i++) { + if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) { + to[i] = from[p++]; + } + else { + to[i] = from[q++]; + } + } + } + + public int compare(int row1, int row2) { + compares++; + for (Integer column : sortingColumns) { + int result = compareRowsByColumn(row1, row2, column); + if (result != 0) { + return ascending ? result : -result; + } + } + return 0; + } + + public int compareRowsByColumn(int row1, int row2, int column) { + Class type = model.getColumnClass(column); + TableModel data = model; + + // Check for nulls. + + Object o1 = data.getValueAt(row1, column); + Object o2 = data.getValueAt(row2, column); + + // If both values are null, return 0. + if (o1 == null && o2 == null) { + return 0; + } + else if (o1 == null) { // Define null less than everything. + return -1; + } + else if (o2 == null) { + return 1; + } + + /* + * We copy all returned values from the getValue call in case + * an optimised model is reusing one object to return many + * values. The Number subclasses in the JDK are immutable and + * so will not be used in this way but other subclasses of + * Number might want to do this to save space and avoid + * unnecessary heap allocation. + */ + + if (type.getSuperclass() == java.lang.Number.class) { + Number n1 = (Number)data.getValueAt(row1, column); + double d1 = n1.doubleValue(); + Number n2 = (Number)data.getValueAt(row2, column); + double d2 = n2.doubleValue(); + + if (d1 < d2) { + return -1; + } + else if (d1 > d2) { + return 1; + } + else { + return 0; + } + } + else if (type == java.util.Date.class) { + Date d1 = (Date)data.getValueAt(row1, column); + long n1 = d1.getTime(); + Date d2 = (Date)data.getValueAt(row2, column); + long n2 = d2.getTime(); + + if (n1 < n2) { + return -1; + } + else if (n1 > n2) { + return 1; + } + else { + return 0; + } + } + else if (type == String.class) { + String s1 = (String)data.getValueAt(row1, column); + String s2 = (String)data.getValueAt(row2, column); + int result = s1.compareTo(s2); + + if (result < 0) { + return -1; + } + else if (result > 0) { + return 1; + } + else { + return 0; + } + } + else if (type == Boolean.class) { + Boolean bool1 = (Boolean)data.getValueAt(row1, column); + boolean b1 = bool1; + Boolean bool2 = (Boolean)data.getValueAt(row2, column); + boolean b2 = bool2; + + if (b1 == b2) { + return 0; + } + else if (b1) { // Define false < true + return 1; + } + else { + return -1; + } + } + else { + Object v1 = data.getValueAt(row1, column); + String s1 = v1.toString(); + Object v2 = data.getValueAt(row2, column); + String s2 = v2.toString(); + int result = s1.compareTo(s2); + + if (result < 0) { + return -1; + } + else if (result > 0) { + return 1; + } + else { + return 0; + } + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/defaultConfiguration.xml b/plugins/rearranger/src/com/wrq/rearranger/defaultConfiguration.xml new file mode 100644 index 000000000000..ff91276bbcac --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/defaultConfiguration.xml @@ -0,0 +1,360 @@ + + + + + + \n//\ ------------------------------\ FIELDS\ + ------------------------------\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n//\ --------------------------\ STATIC\ METHODS\ + --------------------------\n + + + + + + + + + + + + + + + + + + + + + + \n//\ ---------------------------\ CONSTRUCTORS\ + ---------------------------\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n//\ ---------------------\ GETTER\ /\ SETTER\ METHODS\ + ---------------------\n + + + + + + + + + + + + + + + + + + + + + + \n//\ ------------------------\ CANONICAL\ METHODS\ + ------------------------\n + + + + + + + + + + + + + + + + + + + + + + \n//\ ------------------------\ INTERFACE\ METHODS\ + ------------------------\n + + + + + \n//\ ---------------------\ Interface\ %IF%\ + ---------------------\n + + + + + + + \n//\ --------------------------\ OTHER\ METHODS\ + --------------------------\n + + + + + + + + + + + + + + + + + + + + + + \n//\ --------------------------\ ENUMERATIONS\ + --------------------------\n + + + + + + + + + + + \n//\ --------------------------\ INNER\ CLASSES\ + --------------------------\n + + + + + + + + + + + \n//\ ---------------------------\ main()\ method\ + ---------------------------\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java new file mode 100644 index 000000000000..1739647d8bc6 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiField; +import com.wrq.rearranger.popup.IFilePopupEntry; +import com.wrq.rearranger.popup.RearrangerTreeNode; +import com.wrq.rearranger.settings.RearrangerSettings; + +import javax.swing.tree.DefaultMutableTreeNode; + +/** + * Describes the fields, methods, and inner class declarations of a class. This information is used to reorder + * these declarations within an outer class. + */ +public abstract class ClassContentsEntry + extends RangeEntry + implements IFilePopupEntry +{ + public ClassContentsEntry(final PsiElement start, + final PsiElement end, + final int modifiers, + final String modifierString, + final String name, + final String type) + { + super(start, end, modifiers, modifierString, name, type); + } + + public ClassContentsEntry(final PsiElement start, + final PsiElement end, + final boolean fixedHeader, + final boolean fixedTrailer) + { + super(start, end, fixedHeader, fixedTrailer); + } + + public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { + DefaultMutableTreeNode node = null; + if ((end instanceof PsiField && settings.isShowFields()) || + (this instanceof ClassEntry)) + { + node = new RearrangerTreeNode(this, name); + parent.add(node); + } + return node; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java new file mode 100644 index 000000000000..028f08352cd7 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.search.PsiSearchHelper; +import com.intellij.psi.search.SearchScope; +import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.util.Query; +import com.wrq.rearranger.ModifierConstants; +import com.wrq.rearranger.popup.IFilePopupEntry; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.rearrangement.GenericRearranger; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.ModifierUtils; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Describes an entire class's range and type. + * This information is used when reordering outer classes. + */ +public class ClassEntry + extends ClassContentsEntry + implements IFilePopupEntry +{ + private static final Logger LOG = Logger.getInstance("#" + ClassEntry.class.getName()); + + protected final List contents; + private List resultRuleInstances; + private final RearrangerSettings settings; + private final int nestingLevel; + + public ClassEntry(PsiElement start, + PsiElement end, + int modifiers, + String modifierString, + String name, + int nestingLevel, + RearrangerSettings settings) + { + super(start, end, modifiers, modifierString, name, ""); + contents = new ArrayList(); + resultRuleInstances = null; + this.settings = settings; + this.nestingLevel = nestingLevel; + } + + public String getTypeIconName() { + String result = "nodes/class"; + if (end.getParent() instanceof PsiClass) { + PsiClass psiClass = (PsiClass)end.getParent(); + if (psiClass.isEnum()) { + result = "nodes/enum"; + } + else if (psiClass.isInterface()) { + result = "nodes/interface"; + } + } + return result; + } + + public String[] getAdditionalIconNames() { + if (end instanceof PsiJavaToken && end.getText().equals("{")) { + PsiClass psiClass = (PsiClass)end.getParent(); + if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) { + return new String[]{"nodes/c_public"}; + } + if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PROTECTED)) { + return new String[]{"nodes/c_protected"}; + } + if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) { + return new String[]{"nodes/c_private"}; + } + return new String[]{"nodes/c_plocal"}; + } + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + return new JLabel(name); + } + + protected void parseRemainingClassContents(final Project project, + int startingIndex, + final PsiElement psiClass + ) + { + final PsiSearchHelper psh = PsiSearchHelper.SERVICE.getInstance(project); + int lastIndex = startingIndex; + /** + * if option indicates, don't parse inner class contents; leave them unchanged. + */ + if (settings.isRearrangeInnerClasses() || nestingLevel <= 1) { + for (int i = startingIndex; i < psiClass.getChildren().length; i++) { + PsiElement child = psiClass.getChildren()[i]; + if (child instanceof PsiJavaToken && child.getText().equals("{")) { + lastIndex = i + 1; // first item of a class starts immediately after the class left brace. + } + LOG.debug(psiClass.toString() + " child " + i + ":" + child.toString()); + if (child instanceof PsiField || + child instanceof PsiMethod || + child instanceof PsiClass || + child instanceof PsiClassInitializer) + { + MemberAttributes attributes = new MemberAttributes(); + PsiElement startElement = psiClass.getChildren()[lastIndex]; + + ClassContentsEntry classContentsEntry = null; + if (child instanceof PsiField) { + i = parseField(child, attributes, i, (PsiClass)psiClass); + // a field declaration with multiple fields like "int x, y;" must advance child to "y;" + // to prevent splitting. + child = psiClass.getChildren()[i]; + classContentsEntry = new FieldEntry( + startElement, + child, + attributes.modifiers, + attributes.modifierString, + attributes.name, + attributes.type + ); + } + if (child instanceof PsiMethod) { + parseMethod(child, attributes, psh); + classContentsEntry = new MethodEntry( + startElement, + child, + attributes.modifiers, + attributes.modifierString, + attributes.name, + attributes.type, + attributes.nParameters, + attributes.interfaceName + ); + } + if (child instanceof PsiClass) { + parseClassAttributes(child, attributes); + // + // if child is an enum, set the last entry past the LBrace to the final enumeration or the + // semicolon thereafter, if any. + // + PsiClass clazz = (PsiClass)child; + PsiElement clazzEnd; + int startElementIndex = 0; + if (clazz.isEnum()) { + // we want to skip all the enumeration fields, including terminating semicolon if present. + // class parsing begins after these. + startElementIndex = findLastEnumTerminator(clazz); + clazzEnd = clazz.getChildren()[startElementIndex]; + startElementIndex++; + } + else { + // normal class: parse everything after the left brace. + clazzEnd = clazz.getLBrace(); + startElementIndex = Arrays.asList(clazz.getChildren()).indexOf(clazzEnd) + 1; + } + ClassEntry entry = new ClassEntry( + startElement, + clazzEnd, + attributes.modifiers, + attributes.modifierString, + attributes.name, + nestingLevel + 1, + settings + ); + classContentsEntry = entry; + entry.parseRemainingClassContents( + project, + startElementIndex, + child); + } + if (child instanceof PsiClassInitializer) { + parseClassInitializer(child, attributes); + classContentsEntry = new ClassInitializerEntry(startElement, + child, + attributes.modifiers, + attributes.modifierString, + attributes.name); + } + contents.add(classContentsEntry); + classContentsEntry.checkForComment(); + lastIndex = i + 1; // next class includes everything since the end of the prior class. + } + } + } + if (lastIndex < psiClass.getChildren().length) { + if (lastIndex < 0) { + lastIndex = 0; + } + // create a dummy trailer entry to cover anything after the last class. + final MiscellaneousTextEntry miscellaneousTextEntry = new MiscellaneousTextEntry( + psiClass.getChildren()[lastIndex], + psiClass.getChildren()[psiClass.getChildren().length - 1], + false, true + ); + contents.add(miscellaneousTextEntry); + miscellaneousTextEntry.checkForComment(); + } + } + + /** + * Search for the end of the enumeration's fields. It may be terminated with a semicolon, in which case we want + * to point to the next item. If no semicolon is found, we want to point to the enum's right brace. + * + * @param clazz + * @return starting element index for the portion of the enumeration class following its enum declarations. + */ + private int findLastEnumTerminator(PsiClass clazz) { + int startElementIndex = 0; + // go until we hit RBrace (non-inclusive), or semicolon (inclusive) + boolean foundLBrace = false; + for (int j = 0; j < clazz.getChildren().length; j++) { + PsiElement psiElement = clazz.getChildren()[j]; + if (!foundLBrace) { + if (psiElement == clazz.getLBrace()) { + foundLBrace = true; + } + } + else { + startElementIndex = j; + if (psiElement == clazz.getRBrace()) { + break; + } + if (psiElement instanceof PsiJavaToken && + ((PsiJavaToken)psiElement).getTokenType() == JavaTokenType.SEMICOLON) + { + break; + } + } + } + return startElementIndex; + } + + private int parseField(PsiElement child, MemberAttributes attributes, int i, final PsiClass psiClass) { + attributes.field = (PsiField)child; + LOG.debug("enter parseField: child=" + + (child == null ? "null" : child.toString())); + attributes.name = attributes.field.getName(); + if (attributes.field.getTypeElement() == null) { + attributes.type = attributes.field.getContainingClass().getName(); // if enum, use class as type + } + else { + attributes.type = attributes.field.getTypeElement().getText(); + } + attributes.modifierString = attributes.field.getModifierList().getText(); + attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString); + if (attributes.field.getContainingClass().isInterface()) { + // all fields in an interface are constants, hence "public static final" + attributes.modifiers |= Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; + } + if (attributes.field.getInitializer() instanceof PsiNewExpression) { + final PsiElement lc = attributes.field.getInitializer().getLastChild(); + if (lc instanceof PsiAnonymousClass) { + attributes.modifiers |= ModifierConstants.INIT_TO_ANON_CLASS; + } + } + LOG.debug( + "parseField: name=" + + attributes.name + + ", modifiers=" + + Integer.toHexString(attributes.modifiers) + ); + /** + * handle multiple declarations here. While this field declaration does not end + * in a semicolon, skip whitespace and intervening comma; move child ahead to + * next field. This prevents declarations like "int b, a;" from being split. + */ + PsiElement myChild = child; + boolean done = false; + while (!done) { + PsiElement lastElement = myChild.getLastChild(); + LOG.debug("parseField: getLastChild=" + + (lastElement == null ? "null" : lastElement.toString())); + if (lastElement == null) break; + if (lastElement instanceof PsiErrorElement) break; + if (lastElement instanceof PsiJavaToken && + ((PsiJavaToken)lastElement).getTokenType() == JavaTokenType.SEMICOLON) + { + break; + } + if (lastElement instanceof PsiComment) { + break; + } + // skip to next field + LOG.debug( + "parseField:skipping to next field, i=" + + i + + ", psiClass=" + psiClass.getName() + ); + LOG.debug( + "parseField: psiClass children array length=" + + psiClass.getChildren().length + ); + while (++i < psiClass.getChildren().length) { + myChild = psiClass.getChildren()[i]; + LOG.debug("parseField: myChild=" + myChild.toString()); + if (myChild instanceof PsiField) { + done = true; + break; + } + } + } + return i; + } + + private void parseMethod(PsiElement child, MemberAttributes attributes, final PsiSearchHelper psh) { + attributes.method = (PsiMethod)child; + attributes.name = attributes.method.getName(); + if (attributes.method.getReturnTypeElement() == null) { + attributes.type = "null"; + } + else { + attributes.type = attributes.method.getReturnTypeElement().getText(); + } + attributes.modifierString = attributes.method.getModifierList().getText(); + attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString); + attributes.nParameters = attributes.method.getParameterList().getParameters().length; + if (attributes.method.getContainingClass().isInterface()) { + // methods in an interface are always considered public + attributes.modifiers |= Modifier.PUBLIC; + } + // set any additional "modifier" flags. +// final Query sm2 = SuperMethodsSearch.search(attributes.method, +// attributes.method.getContainingClass(), false, false); +// for (MethodSignatureBackedByPsiMethod msb : sm2) { +// System.out.println(msb.getMethod().getName()); +// } // seems to be no different than method.findSuperMethods() + + attributes.modifiers |= isCanonicalOrInterface(attributes.method, attributes); + final SearchScope ss = psh.getUseScope(child); + final Query query = OverridingMethodsSearch.search(attributes.method, ss, true); + final PsiMethod method = query.findFirst(); + if (method != null) { + final Collection overridersCollection = query.findAll(); + final PsiMethod[] overriders = overridersCollection.toArray(new PsiMethod[overridersCollection.size()]); + LOG.debug( + "method " + + attributes.method.toString() + + " is overridden; has " + + overriders.length + " overriding methods:" + ); + dumpMethodNames(overriders); + if (attributes.method.getBody() == null) { + attributes.modifiers |= ModifierConstants.IMPLEMENTED; + } + else { + attributes.modifiers |= ModifierConstants.OVERRIDDEN; + } + } + // determine if this method overrides another. + final PsiMethod[] superMethods = attributes.method.findSuperMethods(false); + LOG.debug("method " + attributes.method.toString() + " has " + superMethods.length + " supermethods"); + dumpMethodNames(superMethods); + if (superMethods.length > 0) { + // determine if supermethod is abstract or interface; if so, assign IMPLEMENTING attribute. + PsiMethod superMethod = superMethods[0]; + boolean abztract = superMethod.getModifierList().hasModifierProperty(PsiModifier.ABSTRACT); + PsiClass superclass = superMethod.getContainingClass(); + if (abztract || ( + superclass != null && superclass.isInterface())) + { + attributes.modifiers |= ModifierConstants.IMPLEMENTING; + } + else { + attributes.modifiers |= ModifierConstants.OVERRIDING; + } + } + if (attributes.method.isConstructor()) { + attributes.modifiers |= ModifierConstants.CONSTRUCTOR; + } + /** getter/setter cannot be determined here because definition of what a getter/setter + * is can vary from rule to rule. Do it at the time of rule matching. + */ + else if ((attributes.modifiers & ModifierConstants.CANONICAL) == 0) { + attributes.modifiers |= ModifierConstants.OTHER_METHOD; + } + LOG.debug( + "method " + + attributes.name + + " attributes: " + + ModifierConstants.toString(attributes.modifiers) + ); + } + + private int isCanonicalOrInterface(PsiMethod method, MemberAttributes attributes) { + PsiElement methodParent = method.getParent(); + LOG.debug("checking to see if " + method.getName() + " of " + methodParent + " is canonical"); + PsiMethod[] superMethods = method.findSuperMethods(); + LOG.debug("result of findSuperMethods for " + method.getName() + ": size=" + superMethods.length); + // check to see if this method is canonical (inherited from Object). + for (PsiMethod m : superMethods) { + PsiElement parent = m.getParent(); + LOG.debug( + "supermethod " + + m.getName() + + " belongs to " + + parent + ); + if (parent instanceof PsiClass) { + final PsiClass psiClass = ((PsiClass)parent); + if (psiClass.isInterface()) { + LOG.debug("method " + method.toString() + " implements interface"); + attributes.interfaceName = psiClass.getName(); + } + PsiElement superclass = psiClass.getSuperClass(); + if (superclass == null) { + // m's class must be java.lang.Object; it's the only class with a null + // superclass. + LOG.debug("method " + method.toString() + " is canonical"); + return ModifierConstants.CANONICAL; + } + else { + int result = isCanonicalOrInterface(m, attributes); +// int result = 0; +// if (!superclass.toString().equalsIgnoreCase("psiclass:object")) +// { +// result = isCanonicalOrInterface(m, attributes); +// } + if (result > 0) { + LOG.debug("Returning result from canonical check as " + result); + return result; + } + } + } + } + return 0; + } + + private void dumpMethodNames(PsiMethod[] methods) { + for (int j = 0; j < methods.length; j++) { + LOG.debug( + j + + ":" + + methods[j].toString() + + " of class " + + methods[j].getParent().toString() + ); + } + } + + private void parseClassAttributes(PsiElement child, MemberAttributes attributes) { + attributes.childClass = (PsiClass)child; + attributes.name = attributes.childClass.getName(); + if (attributes.name == null) { + attributes.name = ""; + } + attributes.modifierString = attributes.childClass.getModifierList().getText(); + attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString); + attributes.type = attributes.childClass.isEnum() ? "enum" : "class"; + if (attributes.childClass.isEnum()) { + attributes.modifiers |= ModifierConstants.ENUM; + } + } + + private void parseClassInitializer(PsiElement child, MemberAttributes attributes) { + attributes.classInitializer = (PsiClassInitializer)child; + attributes.classInitializer.getModifierList(); + attributes.name = ""; + attributes.modifierString = attributes.classInitializer.getModifierList().getText(); + attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString) | + ModifierConstants.INITIALIZER; + } + + public void emit(Emitter emitter) { + // first emit the text up to and including the left brace. + super.emit(emitter); + // now emit all children. + emitter.emitRuleInstances(getResultRuleInstances()); + } + + public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { + DefaultMutableTreeNode result = super.addToPopupTree(parent, settings); + // now add class contents, if any + if (getResultRuleInstances() != null) { + for (IRuleInstance instance : getResultRuleInstances()) { + instance.addRuleInstanceToPopupTree(result, settings); + } + } + return result; + } + + /** rearranges the contents of this PsiClass according to supplied rules. */ + public void rearrangeContents() { + buildMethodCallGraph(); + + LOG.debug("identifying setters and extracted (related) methods"); + for (ClassContentsEntry contentsEntry : getContents()) { + if (contentsEntry instanceof IRelatableEntry) { + ((IRelatableEntry)contentsEntry).determineSettersAndMethodCalls(settings, getContents()); + } + } + LOG.debug("relating extracted methods"); + for (ClassContentsEntry contentsEntry : getContents()) { + if (contentsEntry instanceof IRelatableEntry) { + ((IRelatableEntry)contentsEntry).determineExtractedMethod(settings.getExtractedMethodsSettings()); + } + } + /** + * remove any cycles in the related method graph. + */ + MethodEntry.eliminateCycles(getContents()); + /** + * check for overloaded extracted methods; if configured to be kept together, attach subsequent + * methods to the first and remove them from consideration for other alignment. + */ + MethodEntry.handleOverloadedMethods(getContents(), settings); + final GenericRearranger classContentsRearranger = + new GenericRearranger(settings.getItemOrderAttributeList(), + contents, + nestingLevel, + settings) + { + public void rearrangeRelatedItems(List entries, + List ruleInstanceList) + { + for (IRuleInstance ruleInstance : ruleInstanceList) { + ruleInstance.rearrangeRuleItems(entries, settings); + } + } + }; + resultRuleInstances = classContentsRearranger.rearrangeEntries(); + } + + private void buildMethodCallGraph() { + if (settings.getExtractedMethodsSettings().isMoveExtractedMethods() || + settings.isKeepGettersSettersTogether()) + { + LOG.debug("building method call & getter-setter graph"); + for (ClassContentsEntry contentsEntry : getContents()) { + if (contentsEntry instanceof IRelatableEntry) { + ((IRelatableEntry)contentsEntry).determineGetterSetterAndExtractedMethodStatus(settings); + } + } + } + } + +// End Methods of Interface IFilePopupEntry + + public final List getContents() { + return contents; + } + + public List getResultRuleInstances() { + return resultRuleInstances; + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java new file mode 100644 index 000000000000..f15a3b75c5e4 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.PsiElement; +import com.wrq.rearranger.popup.RearrangerTreeNode; +import com.wrq.rearranger.settings.RearrangerSettings; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import java.lang.reflect.Modifier; + +/** Represents a class initializer. */ +public class ClassInitializerEntry + extends ClassContentsEntry +{ + private static final Logger LOG = Logger.getInstance("#" + ClassInitializerEntry.class.getName()); + + public ClassInitializerEntry(final PsiElement start, + final PsiElement end, + final int modifiers, + final String modifierString, + final String name) + { + super(start, end, modifiers, modifierString, name, ""); + } + + + public String getTypeIconName() { + final String name = Modifier.isStatic(getModifiers()) ? "nodes/StaticClassInitializer" : "nodes/ClassInitializer"; + return name; + } + + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + return new JLabel(Modifier.isStatic(getModifiers()) ? "" : ""); + } + + public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { + LOG.debug("add class initializer to popup tree"); + DefaultMutableTreeNode node = new RearrangerTreeNode(this, name); + parent.add(node); + return node; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java new file mode 100644 index 000000000000..92b96ab24473 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiModifierList; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.settings.RearrangerSettings; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; + +/** Represents a member field of a class. */ +public class FieldEntry + extends ClassContentsEntry +{ + /** + * If Keep Getters/Setters With Property is true, and if this field is a property, then a reference to the + * property's getter (primary) method is stored here. That method is removed from the list of entries considered + * for rule matching. This field is responsible for emitting that method. + */ + MethodEntry getterMethod; + + public FieldEntry(final PsiElement start, + final PsiElement end, + final int modifiers, + final String modifierString, + final String name, + final String type) + { + super(start, end, modifiers, modifierString, name, type); + getterMethod = null; + } + + public String getTypeIconName() { + if (end instanceof PsiField) { + PsiField f = (PsiField)end; + return ((PsiModifierList)f.getModifierList()).hasModifierProperty(PsiModifier.STATIC) ? "nodes/staticField" : "nodes/field"; + } + return null; + } + + public String[] getAdditionalIconNames() { + if (end instanceof PsiField) { + PsiField f = (PsiField)end; + if (f.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) return new String[]{"nodes/c_public"}; + if (f.getModifierList().hasModifierProperty(PsiModifier.PROTECTED)) return new String[]{"nodes/c_protected"}; + if (f.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) return new String[]{"nodes/c_private"}; + return new String[]{"nodes/c_plocal"}; + } + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + StringBuffer name = new StringBuffer(80); + PsiField f = (PsiField)end; + name.append(f.getName()); + name.append(": "); + name.append(f.getTypeElement().getText()); + if (f.getInitializer() != null && f.getInitializer().getText().indexOf('\n') < 0) { + name.append(" = "); + name.append(f.getInitializer().getText()); + } + return new JLabel(name.toString()); + } + + public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { + DefaultMutableTreeNode node = super.addToPopupTree(parent, settings); + if (node != null && getterMethod != null) { + getterMethod.addToPopupTree(node, settings); + for (MethodEntry me : getterMethod.correspondingGetterSetters) { + me.addToPopupTree(node, settings); + } + } + return node; + } + + public void emit(Emitter emitter) { + super.emit(emitter); + /** + * emit setters/getters if they are kept with the property. + */ + if (getterMethod != null) { + getterMethod.emit(emitter); + } + } + + public MethodEntry getGetterMethod() { + return getterMethod; + } + + public void setGetterMethod(MethodEntry getterMethod) { + this.getterMethod = getterMethod; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java new file mode 100644 index 000000000000..eb4e7636443f --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.wrq.rearranger.settings.RearrangerSettings; + +import javax.swing.tree.DefaultMutableTreeNode; + +/** + * Created by IntelliJ IDEA. + * User: davek + * Date: Feb 18, 2004 + * Time: 9:17:56 AM + * To change this template use File | Settings | File Templates. + */ +public interface IPopupTreeRangeEntry { + + /** + * Gives individual entries control over their appearance, depending on settings. + * + * @param parent DefaultMutableTreeNode to which this entry will be appended as a child. + * @param settings current Rearranger settings + * @return new DefaultMutableTreeNode + */ + DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java new file mode 100644 index 000000000000..317360a1a093 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.RelatedMethodsSettings; + +import java.util.List; + +/** + * Defines methods implemented by entries which may be related to others, i.e. getters and setters, + * method entries which call other methods, and overloaded method entries. + */ +public interface IRelatableEntry { + /** + * Determine if the entry is a getter/setter or is excluded from extracted method consideration by an + * overriding rule. + */ + void determineGetterSetterAndExtractedMethodStatus(RearrangerSettings settings); + + /** + * Determine corresponding setters for getters and identify related methods. + * + * @param settings current settings, containing extracted/related method options. + * @param contents contents of class, containing potentially related methods. + */ + void determineSettersAndMethodCalls(RearrangerSettings settings, + List contents); + + /** + * Decide if a method is an extracted method. It is an extracted method if: + * - it is called by at least one other method, and + * - it is private, or passes the "never / 1 / >1" caller test. + */ + void determineExtractedMethod(RelatedMethodsSettings settings); + + /** @return true if the method is related to another. In this case, the method is exempt from rule matching. */ + boolean isRelatedMethod(); + + /** @return true if the method is a setter and will be emitted below a corresponding getter. */ + boolean isEmittableSetter(); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/MemberAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/entry/MemberAttributes.java new file mode 100644 index 000000000000..662c5d59e0a3 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/MemberAttributes.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiClassInitializer; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiMethod; + +/** Temporary structure to accumulate attributes during parsing, before final RangeEntry is created. */ +public class MemberAttributes { + String name = ""; + String type = ""; + String interfaceName = null; + PsiField field = null; + PsiMethod method = null; + PsiClass childClass = null; + PsiClassInitializer classInitializer = null; + int modifiers = 0; + String modifierString = ""; + int nParameters = 0; +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java new file mode 100644 index 000000000000..0c4780ef24c4 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java @@ -0,0 +1,1288 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.psi.*; +import com.wrq.rearranger.ModifierConstants; +import com.wrq.rearranger.popup.RearrangerTreeNode; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.RelatedMethodsSettings; +import com.wrq.rearranger.settings.attributeGroups.IHasGetterSetterDefinition; +import com.wrq.rearranger.settings.attributeGroups.IRestrictMethodExtraction; +import com.wrq.rearranger.settings.attributeGroups.IRule; +import com.wrq.rearranger.util.CommentUtil; +import com.wrq.rearranger.util.MethodUtil; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import java.util.*; + +/** + * Corresponds to a method in the source file. + * Contains structures and logic to handle related method rearrangement. + */ +public class MethodEntry + extends ClassContentsEntry + implements IRelatableEntry +{ +// ------------------------------ FIELDS ------------------------------ + + private static final Logger LOG = Logger.getInstance("#" + MethodEntry.class.getName()); + + /** + * Contains a list of methods called by this method. One exception: if this method is a getter, then + * the corresponding setter will be placed in calledMethods. This allows the same code to rearrange both + * types of related methods. + */ + List calledMethods = new ArrayList(); + List calledByMethods = new ArrayList(); + List overloadedMethods = new ArrayList(); + // MethodEntry correspondingSetter = null; // TODO - avoid wrong level for setters + List correspondingGetterSetters = new ArrayList(); + private boolean keptWithProperty; + private boolean relatedMethod; + + /** @return true if the method is related to another. In this case, the method is exempt from rule matching. */ + public boolean isRelatedMethod() { + return relatedMethod; + } + + /** @return true if the method is a setter and will be emitted below a corresponding getter. */ + public boolean isEmittableSetter() { + return setter && correspondingGetterSetters.size() > 0; + } + + private boolean isOverloadedMethod; + private final int nParameters; + private String customizedPrecedingComment = ""; + + public String getCustomizedPrecedingComment() { + if (customizedPrecedingComment == null) { + return ""; + } + return customizedPrecedingComment; + } + + private String customizedTrailingComment = ""; + + public String getCustomizedTrailingComment() { + if (customizedTrailingComment == null) { + return ""; + } + return customizedTrailingComment; + } + + private boolean noExtractedMethods; + + public boolean isNoExtractedMethods() { + return noExtractedMethods; + } + + public void setNoExtractedMethods(boolean noExtractedMethods) { + this.noExtractedMethods = noExtractedMethods; + } + + private boolean getter; + + public boolean isGetter() { + return getter; + } + + public void setGetter(boolean getter) { + this.getter = getter; + } + + private boolean setter; + + public boolean isSetter() { + return setter; + } + + public void setSetter(boolean setter) { + this.setter = setter; + } + + /** name of interface, if this method implements an interface method. */ + private final String interfaceName; + + public String getInterfaceName() { + return interfaceName; + } + + private List sortedMethods = new LinkedList(); + +// -------------------------- STATIC METHODS -------------------------- + + /** + * Called after top level methods (and other items) have been moved from entries to ruleInstanceList. Task now + * is to scan ruleInstanceList looking for MethodEntry objects with dependent (related, extracted) methods. Move + * these from the entries list to the correct place in the ruleInstanceList list. + * + * @param entries Remaining (unarranged) items, including all dependent (extracted) methods. + * @param ruleInstance Rule containing parents (callers) of potentially related methods + */ + public static void rearrangeRelatedItems(List entries, + IRuleInstance ruleInstance, + RelatedMethodsSettings rms) + { + List parentEntries = new ArrayList(ruleInstance.getMatches()); + for (RangeEntry o : parentEntries) { + if (o instanceof IRelatableEntry) { + MethodEntry me = (MethodEntry)o; + if (me.isGetter()) { + if (me.keptWithProperty) { + if (me.getMatchedRule() != null && me.getMatchedRule().getMatches() != null) { + // prevent the getter from appearing under a rule it matches; it will be placed under the property + me.getMatchedRule().getMatches().remove(me); + } + } + for (MethodEntry theSetter : me.correspondingGetterSetters) { + final IRuleInstance theRule = theSetter.getMatchedRule(); + LOG.debug( + "rearrangeRelatedItems: for getter method " + + me + + ", corresponding setter is " + + theSetter + ); + if (theRule != null && + theRule.getMatches() != null) + { + LOG.debug( + "remove entry " + + theSetter.end + + " from matched rule" + + theRule + + "; matches = " + + ((java.util.List)theRule.getMatches()) == null ? "null" : "" + ); + theRule.getMatches().remove(theSetter); + } + } + } + if (me.calledMethods.size() > 0) { + List parents = new LinkedList(); + parents.add(me); + moveRelatedItems( + entries, + parents, + rms, + ((PsiMethod)me.end).getName(), + ((PsiMethod)me.end).getName() + "()", + 1 + ); + if (LOG.isDebugEnabled()) { + // dump sorted children recursively + me.dumpChild(0); + } + me.assignComments(rms); + } + } + } + } + + /** + * Move methods related to this one underneath it (beginning at the index specified.) Do so in depth-first or + * breadth-first order, as configured. At each level, do alphabetical, original order, or call order sorting. + * + * @param entries list of global (all rule) unmatched items including dependent methods + * @param parents contains a list of items to be handled; order is depth or breadth-first. + */ + private static void moveRelatedItems(List entries, + List parents, + RelatedMethodsSettings rms, + String topLevelMethodName, + String allMethodNames, + int level) + { + allMethodNames = buildAllMethodNamesString(allMethodNames, parents); + /** + * First, identify all dependent methods. Move them to parents in the specified order. + */ + List children = ((MethodEntry)parents.get(parents.size() - 1)).sortedMethods; +// if (rms.isDepthFirstOrdering()) +// { + switch (rms.getOrdering()) { + case RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER: { + /** + * iterate through entries looking for those that are called by method(s) in the set of parent methods. + * Add these to the list of children in order seen in entries. + */ + ListIterator li = entries.listIterator(); + while (li.hasNext()) { + Object o = li.next(); + if (o instanceof IRelatableEntry) { + MethodEntry me = (MethodEntry)o; + for (MethodEntry entry : parents) { + if (me.calledByMethods.contains(entry)) { + children.add(me); + li.remove(); + break; + } + } + } + } + } + break; + case RelatedMethodsSettings.ALPHABETICAL_ORDER: { + /** + * iterate through entries looking for those that are called by method(s) in the set of parent methods. + * Add these to the list of children alphabetically. + */ + ListIterator li = entries.listIterator(); + while (li.hasNext()) { + Object o = li.next(); + if (o instanceof IRelatableEntry) { + MethodEntry me = (MethodEntry)o; + for (MethodEntry entry : parents) { + if (me.calledByMethods.contains(entry)) { + me.insertAlphabetically(children); + li.remove(); + break; + } + } + } + } + } + break; + case RelatedMethodsSettings.INVOCATION_ORDER: + /** + * iterate through calling methods, looking for remaining unmatched methods (in 'entries' list). + * Add these to the list of children in order of invocation. + */ + for (MethodEntry me : parents) { + for (MethodEntry child : me.calledMethods) { + if (entries.contains(child)) { + children.add(child); + entries.remove(child); + } + } + } + break; + } + /** + * now children contains all the children of the parents for this level, and all these children have been + * removed from "entries". Move these to the rearranged list. Then: + * If depth-first, recurse setting the parent list to each of the children in turn. + * If breadth first, recurse setting the parent list to all of the children. + */ + if (children.size() > 0) { + if (rms.isDepthFirstOrdering()) { + for (MethodEntry entry : children) { + if (entry.calledMethods.size() == 0) { + continue; + } + List parent = new LinkedList(); + parent.add(entry); + moveRelatedItems( + entries, + parent, + rms, + topLevelMethodName, + allMethodNames + "." + ((PsiMethod)entry.end).getName() + "()", + level + 1 + ); + } + } + else { + moveRelatedItems( + entries, + children, + rms, + topLevelMethodName, + allMethodNames + ".Depth " + level, + level + 1 + ); + } + } + } + + private static String buildAllMethodNamesString(String allMethodNames, List parents) { + StringBuffer allMN = new StringBuffer(120); + allMN.append(allMethodNames); + if (allMN.length() > 0) { + allMN.append("."); + } + if (parents.size() > 1) { + allMN.append("["); + } + { + boolean first = true; + for (MethodEntry entry : parents) { + if (!first) { + allMN.append(","); + } + first = false; + allMN.append(((PsiMethod)entry.end).getName()); + } + } + if (parents.size() > 1) { + allMN.append("]"); + } + return allMN.toString(); + } + + public void insertAlphabetically(final List list) { + Comparator comparator = new Comparator() { + public int compare(MethodEntry me, MethodEntry me2) { + String s = ((PsiMethod)me.end).getName(); + if (me.isGetter()) { + s = MethodUtil.getPropertyName((PsiMethod)me.end); + } + return s.compareTo(((PsiMethod)me2.end).getName()); + } + }; + insertInList(list, comparator); + } + + void insertInList(final List list, Comparator comparator) { + boolean inserted = false; + ListIterator li = list.listIterator(); + while (li.hasNext() && !inserted) { + MethodEntry entry = ((MethodEntry)li.next()); + if (comparator.compare(this, entry) < 0) { + LOG.debug( + "insertInList dependent method: add " + end.toString() + " at index " + (li.nextIndex() - 1) + ); + list.add(li.nextIndex() - 1, this); + inserted = true; + } + } + if (!inserted) { + list.add(this); + } + } + + void dumpChild(int level) { + LOG.debug(level + ": " + ((PsiMethod)end).getName()); + for (MethodEntry methodEntry : sortedMethods) { + methodEntry.dumpChild(level + 1); + } + } + + private void assignComments(RelatedMethodsSettings rms) { + List callingMethod = new ArrayList(); + callingMethod.add(this); + assignComments(rms, callingMethod, "", 1); + } + + /** + * Eliminate cycles of method calls so that the related method tree is a tree, not a cycle (or directed graph). + * If method A calls method B, B calls C, and C calls A, eliminate the final call to prevent cycling. + * + * @param contents + */ + public static void eliminateCycles(List contents) { + for (ClassContentsEntry entry : contents) { + if (entry instanceof IRelatableEntry) { + MethodEntry current = (MethodEntry)entry; + List set = new LinkedList(); + set.add(current); + test(current, set); + } + } + } + + private static void test(MethodEntry current, List set) { + Iterator it = current.calledMethods.iterator(); + while (it.hasNext()) { + MethodEntry callee = it.next(); + if (set.contains(callee)) { + callee.calledByMethods.remove(current); + if (callee.calledByMethods.size() == 0) { + callee.relatedMethod = false; + } + it.remove(); + } + else { + set.add(callee); + test(callee, set); + } + } + } + + /** + * If setting indicates, move all overloaded methods (of the same name) + * adjacent with the first encountered. Sort in the configured order + * (original order, or by number of parameters). + */ + public static void handleOverloadedMethods(List contents, + RearrangerSettings settings) + { + if (!settings.isKeepOverloadedMethodsTogether()) return; + /** + * first, detect overloaded methods and move them to the first method's list of overloaded methods. + * Make two passes, first for extracted methods, then for non-extracted methods. This will organize any + * overloaded methods for extracted methods with them (as opposed to whichever was seen first.) + */ + cullOverloadedMethods(contents, true); + LOG.debug("entered handleOverloadedMethods(): move overloaded methods together"); + cullOverloadedMethods(contents, false); + List copy = new ArrayList(contents); + for (ClassContentsEntry rangeEntry : copy) { + if (rangeEntry instanceof IRelatableEntry) { + MethodEntry current = (MethodEntry)rangeEntry; + if (current.overloadedMethods.size() > 0) { + List newList = new ArrayList(current.overloadedMethods.size() + 1); + newList.add(current); + /** + * we are looking at the head of a list of overloaded methods. We need to sort the list + * if necessary and, if the head of the list has changed, replace it in the contents array. + */ + switch (settings.getOverloadedOrder()) { + case RearrangerSettings.OVERLOADED_ORDER_RETAIN_ORIGINAL: + // list is already in original order, except perhaps that the top-most extracted method + // comes first (if there is one). + newList.addAll(current.overloadedMethods); + break; + case RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS: + case RearrangerSettings.OVERLOADED_ORDER_DESCENDING_PARAMETERS: + for (MethodEntry entry : current.overloadedMethods) { + boolean inserted = false; + for (int index = 0; index < newList.size(); index++) { + MethodEntry me = newList.get(index); + if (settings.getOverloadedOrder() == RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS + ? me.getnParameters() > entry.getnParameters() + : me.getnParameters() < entry.getnParameters()) + { + newList.add(index, entry); + inserted = true; + break; + } + } + if (!inserted) { + newList.add(entry); + } + } + break; + } + current.overloadedMethods.clear(); + /** + * if the head of the arraylist is not the same as "current", then the sort operation moved + * another method to the head of the list. Replace that in the contents array. Then assign + * a new ordered list. + */ + int index = contents.indexOf(current); + if (newList.get(0) != current) { + contents.set(index, ((MethodEntry)newList.get(0))); + } + /** + * insert the remaining overloaded methods after the current entry. + */ + newList.remove(0); + for (int j = 0; j < newList.size(); j++) { + contents.add(index + j + 1, ((MethodEntry)newList.get(j))); + } + } + } + } + } + + /** + * Removes overloaded methods from the contents list and adds them to the overloadedMethods list of the first + * overloaded method encountered. + * + * @param contents + * @param doExtractedMethods + */ + private static void cullOverloadedMethods(List contents, + boolean doExtractedMethods) + { + List copy = new ArrayList(contents); + for (ClassContentsEntry o : copy) { + if (o instanceof IRelatableEntry) { + MethodEntry me = (MethodEntry)o; + if ((me.isRelatedMethod() == doExtractedMethods) && !me.isOverloadedMethod) { + String meName = me.end.toString(); + // search contents list for methods with identical name, and attach them as overloaded methods. + ListIterator contentIterator = contents.listIterator(); + while (contentIterator.hasNext()) { + Object o1 = contentIterator.next(); + if (o1 instanceof IRelatableEntry) { + MethodEntry me2 = (MethodEntry)o1; + if (me2 == me) { + continue; + } + String me2Name = me2.end.toString(); + if (meName.equals(me2Name)) { + contentIterator.remove(); + me.overloadedMethods.add(me2); + me2.isOverloadedMethod = true; // set flag so array copy will skip this entry. + } + } + } + } + } + } + } + + public int getnParameters() { + return nParameters; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public MethodEntry(final PsiElement start, + final PsiElement end, + final int modifiers, + final String modifierString, + final String name, + final String type, + int nParameters, + final String interfaceName) + { + super(start, end, modifiers, modifierString, name, type); + this.nParameters = nParameters; + this.interfaceName = interfaceName; + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public String[] getAdditionalIconNames() { + ArrayList result = new ArrayList(); + String[] sa = new String[0]; + if (end instanceof PsiMethod) { + PsiMethod m = (PsiMethod)end; + if (m.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) { + result.add("nodes/c_public"); + } + else if (m.getModifierList().hasModifierProperty(PsiModifier.PROTECTED)) { + result.add("nodes/c_protected"); + } + else if (m.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) { + result.add("nodes/c_private"); + } + else { + result.add("nodes/c_plocal"); + } + if ((getModifiers() & ModifierConstants.IMPLEMENTING) != 0) { + result.add("gutter/implementingMethod"); + } + if ((getModifiers() & ModifierConstants.IMPLEMENTED) != 0) { + result.add("gutter/implementedMethod"); + } + if ((getModifiers() & ModifierConstants.OVERRIDING) != 0) { + result.add("gutter/overridingMethod"); + } + if ((getModifiers() & ModifierConstants.OVERRIDDEN) != 0) { + result.add("gutter/overridenMethod"); + } + } + return result.toArray(sa); + } + + public String getTypeIconName() { + if (end instanceof PsiMethod) { + PsiMethod m = (PsiMethod)end; + return (((PsiModifierList)m.getModifierList()).hasModifierProperty(PsiModifier.STATIC)) ? "nodes/staticMethod" : "nodes/method"; + } + return null; + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface IFilePopupEntry --------------------- + + public JLabel getPopupEntryText(RearrangerSettings settings) { + StringBuffer name = new StringBuffer(80); + + PsiMethod m = (PsiMethod)end; + if (m.getReturnTypeElement() != null && !settings.isShowTypeAfterMethod()) { + name.append(m.getReturnTypeElement().getText()); + name.append(' '); + } + name.append(m.getName()); + PsiParameterList plist = m.getParameterList(); + if (settings.isShowParameterNames() || + settings.isShowParameterTypes()) + { + if (plist != null) { + name.append("("); + for (int i = 0; i < plist.getParameters().length; i++) { + if (i > 0) { + name.append(", "); + } + if (settings.isShowParameterTypes()) { + String modifiers = plist.getParameters()[i].getModifierList().getText(); + if (modifiers.length() > 0) { + name.append(modifiers); + name.append(' '); + } + name.append(plist.getParameters()[i].getTypeElement().getText()); + if (settings.isShowParameterNames()) { + name.append(' '); + } + } + if (settings.isShowParameterNames()) { + name.append(plist.getParameters()[i].getName()); + } + } + name.append(")"); + } + } + if (m.getReturnTypeElement() != null && settings.isShowTypeAfterMethod()) { + name.append(": "); + name.append(m.getReturnTypeElement().getText()); + } + return new JLabel(name.toString()); + } + +// --------------------- Interface IRelatableEntry --------------------- + + public void determineGetterSetterAndExtractedMethodStatus(RearrangerSettings settings) { + LOG.debug("building method call & getter-setter graph for " + getName()); + /** + * check all rules to find first that this method matches. If that rule specifies + * that matching methods are excluded from extracted method treatment, then skip this + * step. If this method is a getter (according to that rule's definition) then + * determine its setter (according to that rule's definition) at this point also. + */ + setNoExtractedMethods(false); + /** + * The following code determines whether the method is a getter/setter based on default definition. + * This is necessary in case there are no rules, but "Keep Getters/Setters Together" is set. + * If the method matches an individual rule with its own getter/setter definition, the values of + * getter and setter will be changed to match that rule's definition. + */ + setGetter( + MethodUtil.isGetter( + (PsiMethod)end, + settings.getDefaultGSDefinition() + ) + ); + setSetter( + MethodUtil.isSetter( + (PsiMethod)end, + settings.getDefaultGSDefinition() + ) + ); + for (IRule rule : settings.getItemOrderAttributeList()) { + if (rule instanceof IRestrictMethodExtraction) { + if (rule.isMatch(this)) { + if (((IRestrictMethodExtraction)rule).isNoExtractedMethods()) { + LOG.debug( + "excluding " + + end.toString() + + " from extracted method consideration" + ); + setNoExtractedMethods(true); + } + setGetter(false); + if (rule instanceof IHasGetterSetterDefinition) { + if (MethodUtil.isGetter( + (PsiMethod)getEnd(), + ((IHasGetterSetterDefinition)rule).getGetterSetterDefinition() + )) + { + if (settings.isKeepGettersSettersTogether()) { + setGetter(true); + } + } + setSetter( + MethodUtil.isSetter( + (PsiMethod)getEnd(), + ((IHasGetterSetterDefinition)rule).getGetterSetterDefinition() + ) + ); + } + break; + } + } + } + } + + public void determineSettersAndMethodCalls(RearrangerSettings settings, + List contents) + { + if (isGetter()) { + if (settings.isKeepGettersSettersTogether()) { + determineSetter(contents, settings); // link getters/setters via correspondingGetterSetter entries + } + } + if (!isNoExtractedMethods() && + settings.getExtractedMethodsSettings().isMoveExtractedMethods()) + { + determineMethodCalls(contents, settings); + } + } + + /** + * Decide if a method is an extracted method. It is an extracted method if: + * - it is called by at least one other method, and + * - it is private, or passes the "never / 1 / >1" caller test. + *

+ * (It is not considered an extracted method if it is a setter, there is a corresponding getter, and the + * option to keep getters and setters together is set. This is a special case.) + */ + public void determineExtractedMethod(RelatedMethodsSettings settings) { + relatedMethod = false; + if (!isGetter() && !isSetter()) { + if (calledByMethods.size() > 0) { + PsiMethod m = (PsiMethod)end; + if (!m.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) { + switch (settings.getNonPrivateTreatment()) { + case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_NEVER: + break; + case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ONE_CALLER: + if (calledByMethods.size() == 1) { + relatedMethod = true; + } + break; + case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ANY_CALLERS: + relatedMethod = true; + break; + } + } + else { + relatedMethod = true; + } + } + } + else { + if (isSetter() && calledByMethods.size() > 0 && correspondingGetterSetters.size() == 0) { + relatedMethod = true; + LOG.debug(end.toString() + " is setter but has no getter, treated as extracted method"); + } + else { + LOG.debug(end.toString() + " is getter/setter, not treated as extracted method"); + } + } + LOG.debug("determined " + end.toString() + " is extracted method? " + relatedMethod); + /** + * If this is not an extracted method, remove it from any callers so that it won't be moved. + */ + if (!relatedMethod) { + ListIterator li = calledByMethods.listIterator(); + while (li.hasNext()) { + MethodEntry entry = (li.next()); + entry.calledMethods.remove(this); + li.remove(); + } + } + /** + * Remaining entries are only extracted methods at this point. Using first/last rule, keep only the call by + * the calling method that this child method will be grouped with, and discard the rest. + */ + if (calledByMethods.size() > 1) { + ListIterator li; + if (settings.isBelowFirstCaller()) { + li = calledByMethods.listIterator(1); + while (li.hasNext()) { + MethodEntry entry = (li.next()); + entry.calledMethods.remove(this); + li.remove(); + } + } + else { + li = calledByMethods.listIterator(calledByMethods.size() - 1); + while (li.hasPrevious()) { + MethodEntry entry = (li.previous()); + entry.calledMethods.remove(this); + li.remove(); + } + } + } + if (relatedMethod) { + LOG.debug( + "extracted method " + + toString() + + " will be arranged under " + + calledByMethods.get(0).toString() + ); + } + } + +// -------------------------- OTHER METHODS -------------------------- + + public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { + DefaultMutableTreeNode node = new RearrangerTreeNode(this, name); + parent.add(node); + ListIterator li; + for (MethodEntry methodEntry : sortedMethods) { + if (methodEntry.isSetter() && methodEntry.calledByMethods.size() > 0) { + // setters are arranged with getters when "keep getters/setters together" option is checked. + // but setters are not really called by getters. So attach them to the upper level. + methodEntry.addToPopupTree(parent, settings); + } + else { + methodEntry.addToPopupTree(node, settings); + } + } + for (MethodEntry methodEntry : overloadedMethods) { + methodEntry.addToPopupTree(node, settings); + } + return node; + } + + /** + * Set preceding and/or trailing comments on the appropriate methods, based on the comment type. + * + * @param rms + * @param allMethodNames contains a list of methods invoked to reach this point. Top level is empty string. + * @param level current nesting level; top level is 1. + */ + private void assignComments(RelatedMethodsSettings rms, + List allCallingMethods, + String allMethodNames, + int level) + { + final String currentMethodName = ((PsiMethod)end).getName(); + String[] callingNames = new String[allCallingMethods.size()]; + for (int i = 0; i < allCallingMethods.size(); i++) { + MethodEntry me = allCallingMethods.get(i); + callingNames[i] = ((PsiMethod)me.end).getName(); + } + MethodEntry topLevel = this; + while (topLevel.calledByMethods.size() > 0) { + topLevel = (topLevel.calledByMethods.get(0)); + } + switch (rms.getCommentType()) { + case RelatedMethodsSettings.COMMENT_TYPE_TOP_LEVEL: + customizedPrecedingComment = expandComment( + rms.getPrecedingComment(), + currentMethodName, + allMethodNames, + currentMethodName, + level + ); + MethodEntry last = this; + while (last.sortedMethods.size() > 0) { + last = (last.sortedMethods.get(last.sortedMethods.size() - 1)); + } + last.customizedTrailingComment = expandComment( + rms.getTrailingComment(), + currentMethodName, + allMethodNames, + currentMethodName, + level + ); + break; + case RelatedMethodsSettings.COMMENT_TYPE_EACH_METHOD: + customizedPrecedingComment = expandComment( + rms.getPrecedingComment(), + currentMethodName, + allMethodNames, + ((PsiMethod)topLevel.end).getName(), + level + ); + customizedTrailingComment = expandComment( + rms.getTrailingComment(), + currentMethodName, + allMethodNames, + ((PsiMethod)topLevel.end).getName(), + level + ); + // recursively assign comments. + for (MethodEntry methodEntry : sortedMethods) { + String newAllMethodNames = appendMN( + allMethodNames, + callingNames, + allCallingMethods, + this, + rms + ); + methodEntry.assignComments(rms, sortedMethods, newAllMethodNames, level + 1); + } + break; + case RelatedMethodsSettings.COMMENT_TYPE_NEW_FAMILY: { + /** + * Specialized routine to assign comments to "families" of + * methods. Insert a preceding comment before every sibling + * except: when it is the first, and when the prior sibling + * had no children and this sibling has no children. + */ + MethodEntry firstEntry = null; + MethodEntry previousEntry = null; + for (MethodEntry methodEntry : allCallingMethods) { + if (firstEntry == null) { + firstEntry = methodEntry; + } + else if (methodEntry.sortedMethods.size() != 0 || + previousEntry.sortedMethods.size() != 0) + { + methodEntry.customizedPrecedingComment = + expandComment( + rms.getPrecedingComment(), + currentMethodName, + allMethodNames, + ((PsiMethod)topLevel.end).getName(), + level + ); + } + previousEntry = methodEntry; + if (methodEntry.sortedMethods.size() != 0) { + String newAllMethodNames = appendMN( + allMethodNames, + callingNames, + allCallingMethods, + methodEntry, + rms + ); + methodEntry.assignComments(rms, methodEntry.sortedMethods, newAllMethodNames, level + 1); + } + } + } + break; + case RelatedMethodsSettings.COMMENT_TYPE_EACH_LEVEL: { + MethodEntry beginLevel = allCallingMethods.get(0); + MethodEntry endLevel = allCallingMethods.get(allCallingMethods.size() - 1); + beginLevel.customizedPrecedingComment = expandComment( + rms.getPrecedingComment(), + currentMethodName, + allMethodNames, + ((PsiMethod)topLevel.end).getName(), + level + ); + // recursively assign comments for each level. + for (MethodEntry methodEntry : allCallingMethods) { + if (methodEntry.sortedMethods.size() > 0) { + String newAllMethodNames = appendMN( + allMethodNames, + callingNames, + allCallingMethods, + methodEntry, + rms + ); + methodEntry.assignComments(rms, methodEntry.sortedMethods, newAllMethodNames, level + 1); + } + } + while (endLevel.sortedMethods.size() > 0) { + endLevel = endLevel.sortedMethods.get(endLevel.sortedMethods.size() - 1); + } + if (endLevel.customizedTrailingComment.length() > 0) { + endLevel.customizedTrailingComment += "\n"; + } + endLevel.customizedTrailingComment += expandComment( + rms.getTrailingComment(), + currentMethodName, + allMethodNames, + ((PsiMethod)topLevel.end).getName(), + level + ); + } + break; + } + } + + /** + * Build a string representing a sequence of method calls needed to reach a particular child method. + * + * @param allMethods previous method call sequence + * @param newMethods names of each of the methods in callingMethods + * @param callingMethods MethodEntry objects for each method + * @param currentMethod current method being handled + * @param rms contains setting determining if depth-first or breadth-first traversal has taken place. + * @return + */ + private String appendMN(String allMethods, + String[] newMethods, + List callingMethods, + MethodEntry currentMethod, + RelatedMethodsSettings rms) + { + StringBuffer result = new StringBuffer(allMethods.length() + 80); + result.append(allMethods); + if (rms.isDepthFirstOrdering()) { + if (newMethods.length > 0) { + if (result.length() > 0) result.append('.'); + } + int index = callingMethods.indexOf(currentMethod); + result.append(newMethods[index]); + result.append("()"); + } + else { + if (newMethods.length > 0) { + if (result.length() > 0) result.append('.'); + if (newMethods.length > 1) { + result.append('['); + } + for (int i = 0; i < newMethods.length; i++) { + if (i > 0) result.append(','); + result.append(newMethods[i]); + result.append("()"); + } + if (newMethods.length > 1) { + result.append(']'); + } + } + } + return result.toString(); + } + + private static String expandComment(CommentRule comment, + String methodName, + String methodNames, + String topLevelMethodName, + int level) + { + if (comment == null) return ""; + String result = comment.getCommentText(); + if (result == null) return ""; + result = result.replaceAll("%TL%", topLevelMethodName); + result = result.replaceAll("%MN%", methodName); + result = result.replaceAll("%AM%", methodNames); + result = result.replaceAll("%LV%", String.valueOf(level)); + return result; + } + + public void checkForComment() { + if (CommentUtil.getCommentMatchers().size() == 0) { + return; + } + createAlternateValueString(); + /** + * we don't want to check for comments in the body of the method. So reduce the alternate value string + * to only that text up to and including the open brace. Temporarily remove the rest of the text; append + * it again after checking for comments. + */ + int brace = alternateValue.indexOf('{'); + String temp = ""; + if (brace >= 0) { + // every method should have an open brace -- unless it is abstract. + temp = alternateValue.substring(brace + 1, alternateValue.length()); + alternateValue = alternateValue.substring(0, brace + 1); + } + super.checkForComment(); + alternateValue += temp; + } + + /** + * Analyzes the method calls made by this method and creates a "call graph," linking caller and callee by + * references in the calledMethods and calledByMethods lists, respectively. Only method calls to methods in + * this class are entered into the call graph, because only methods in this class can be moved underneath + * their caller. + * + * @param possibleMethods list of methods in this class; call graph is limited to these methods + * @param settings current configuration + */ + public void determineMethodCalls(final List possibleMethods, + final RearrangerSettings settings) + { + /** + * recursively walk the method's code block looking for method calls. + */ + final PsiMethod thisMethod = (PsiMethod)end; + final MethodEntry thisMethodEntry = this; + + JavaRecursiveElementVisitor rev = new JavaRecursiveElementVisitor() { + public void visitMethodCallExpression(PsiMethodCallExpression psiMethodCallExpression) { +// logger.debug("visitMethodCallExpression:" + psiMethodCallExpression.toString()); + PsiElement c = psiMethodCallExpression.getMethodExpression().getReference().resolve(); + /** + * if the called method is already in our list, don't add it again. + */ + if (c != null && !calledMethods.contains(c)) { + for (ClassContentsEntry o : possibleMethods) { + if (o instanceof IRelatableEntry) { + MethodEntry me = (MethodEntry)o; + PsiMethod m = (PsiMethod)me.end; + if (c == m) { + if (settings.isKeepOverloadedMethodsTogether() && + m.getName().equals(thisMethod.getName())) + { + LOG.debug("method " + me + " is overload, not inserted in call graph"); + } + else { + LOG.debug("method " + thisMethod.toString() + " calls " + m.toString()); + calledMethods.add(me); + me.calledByMethods.add(thisMethodEntry); + } + break; + } + } + } + } + // now parse the expression list; it also may contain method calls. + super.visitExpressionList(psiMethodCallExpression.getArgumentList()); + } + }; + + thisMethod.accept(rev); + } + + /** + * Called when getters and setters are to be kept together in pairs. Searches the list of entries for + * any getter/setter methods that matches this getter method. Normally there is only one setter per getter, + * but one could have a "getXXX", "isXXX" and "setXXX" trio which need to be related. In this case, the first + * getter encountered finds the other getter and setter and the three will be emitted in that order. + * + * @param possibleMethods entry list, possibly containing the corresponding setter for this getter. + * @param settings + */ + public void determineSetter(final List possibleMethods, RearrangerSettings settings) { + if (!isGetter()) // wasted assertion, already checked before calling + { + return; + } + final PsiMethod thisMethod = (PsiMethod)end; + String thisProperty = MethodUtil.getPropertyName(thisMethod); + if (isGetter() && !keptWithProperty) { + if (settings.isKeepGettersSettersWithProperty()) { + hookGetterToProperty(possibleMethods); + } + } + for (ClassContentsEntry o : possibleMethods) { + if (o instanceof IRelatableEntry) { + MethodEntry me = (MethodEntry)o; + // don't use a setter twice (could be two methods which both look like getters; assign the setter + // to only one of them.) Also, associate all getter/setter methods for the same property with the + // first one encountered. + if ((me.isSetter() || + me.isGetter()) && + me.correspondingGetterSetters.size() == 0 && + me != this) + { + PsiMethod m = (PsiMethod)me.end; + String otherProperty = MethodUtil.getPropertyName(m); + if (thisProperty.equals(otherProperty)) { + LOG.debug("method " + thisMethod.toString() + " is getter; its setter is " + m.toString()); + // place getters ahead of setters + if (me.isGetter()) { + correspondingGetterSetters.add(0, me); + // clear the getter flag and set the setter flag; this causes the method to be emitted + // under the first getter encountered. + me.setGetter(false); + me.setSetter(true); + } + else { + correspondingGetterSetters.add(me); + } + me.correspondingGetterSetters.add(this); + } + } + } + } + } + + /** + * Getters/Setters are supposed to be kept with their associated property. Search the list of entries to find + * the property and attach the setter. + * + * @param entries list of all items (methods, fields) in the class. + */ + private void hookGetterToProperty(List entries) { + ListIterator li = entries.listIterator(); + String property = MethodUtil.getPropertyName((PsiMethod)end); + while (li.hasNext()) { + Object o = li.next(); + if (o instanceof FieldEntry) { + FieldEntry fe = (FieldEntry)o; + StringBuffer sb = new StringBuffer(fe.getName()); + sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); + if (fe.getGetterMethod() == null && property.equals(sb.toString())) { + fe.setGetterMethod(this); + keptWithProperty = true; + break; + } + } + } + } + + public void emit(Emitter emitter) { + StringBuffer sb = emitter.getStringBuffer(); + if (getCustomizedPrecedingComment().length() > 0) { + sb.append("\n"); + sb.append(getCustomizedPrecedingComment()); + } + emitAllElements(sb, emitter.getDocument()); + if (getCustomizedTrailingComment().length() > 0) { + sb.append("\n"); + sb.append(getCustomizedTrailingComment()); + } + /** + * emit corresponding setter, overloaded methods, and related methods, if any. + */ + ListIterator li; + if (isGetter()) { + for (MethodEntry entry : correspondingGetterSetters) { + entry.emit(emitter); + } + } + for (MethodEntry me : overloadedMethods) { + me.emit(emitter); + } + for (MethodEntry me : sortedMethods) { + me.emit(emitter); + } + } + + protected void emitAllElements(StringBuffer sb, Document document) { + if (alternateValue != null) { + /** + * protect body of method from removing newlines. + */ + int brace = alternateValue.indexOf('{'); + String temp = ""; + if (brace >= 0) { + // every method should have an open brace -- unless it is abstract. + temp = alternateValue.substring(brace + 1, alternateValue.length()); + alternateValue = alternateValue.substring(0, brace + 1); + } + super.emitAllElements(sb, document); + sb.append(temp); + } + else { + super.emitAllElements(sb, document); + } + } + + public void insertInterfaceOrder(List list) { + Comparator comparator = new Comparator() { + public int compare(MethodEntry o1, MethodEntry o2) { + final int offset1 = getMethodOffsetInInterface((PsiMethod)o1.end); + final int offset2 = getMethodOffsetInInterface((PsiMethod)o2.end); + if (offset1 < offset2) return -1; + if (offset1 == offset2) return 0; + return 1; + } + }; + insertInList(list, comparator); + } + + private int getMethodOffsetInInterface(PsiMethod method) { + final PsiMethod[] superMethods = method.findSuperMethods(); +// final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method); // todo - for IDEA 5.0 + if (superMethods.length == 0) return 0; + PsiMethod m = superMethods[0]; + PsiElement parent = m.getParent(); + if (parent instanceof PsiClass && ((PsiClass)parent).isInterface()) { + return m.getTextOffset(); + } + return getMethodOffsetInInterface(m); + } + + public String toString() { + return "MethodEntry " + + end.toString() + + "; calls " + + calledMethods.size() + + ", called by " + + calledByMethods.size() + + ", nParameters=" + nParameters; + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java new file mode 100644 index 000000000000..4d3da310a052 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.psi.PsiElement; +import com.wrq.rearranger.settings.RearrangerSettings; + +import javax.swing.*; + +/** Corresponds to comments and whitespace that surround Java syntactic items like classes and methods. */ +public class MiscellaneousTextEntry + extends ClassContentsEntry +{ + public MiscellaneousTextEntry(final PsiElement start, + final PsiElement end, + final boolean fixedHeader, + final boolean fixedTrailer) + { + super(start, end, fixedHeader, fixedTrailer); + } + + public String getTypeIconName() { + // do not show headers and trailers in the file structure popup. + return null; + } + + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + return null; + } + + public String toString() { + String result; + if (isFixedHeader()) { + result = "Header"; + } + else { + result = "Trailer"; + } + if (alternateValue != null) { + result += "; comments removed"; + } + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java new file mode 100644 index 000000000000..11ac5ba48afe --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; +import com.wrq.rearranger.settings.RearrangerSettings; + +import java.util.List; + +/** + * Dummy "outer class" which actually corresponds to the PsiFile. Since classes contain + * header text (text from the beginning of the class until the first recognized member), one or more + * members, and trailing text, we can create a dummy "class" which will parse the file. Header text + * will include the package and import statements, and outer classes will be its members. + */ +public class PsiFileEntry + extends ClassEntry +{ + public PsiFileEntry(RearrangerSettings settings) { + super(null, null, 0, "", null, 0, settings); + } + + /** + * Strip off leading elements which do not belong to the first class, and place them in + * a MiscellaneousText entry. + * + * @param project + * @param psiFile + * @param commentList + * @return + */ + public List parseFile(Project project, + PsiElement psiFile, + List commentList) + { + int startingIndex = 0; + for (int i = 0; i < psiFile.getChildren().length; i++) { + PsiElement child = psiFile.getChildren()[i]; + if (child instanceof PsiClass) { + do { + startingIndex = i; + i--; + if (i >= 0) { + child = psiFile.getChildren()[i]; + } + else { + break; + } + } + while (child instanceof PsiWhiteSpace || + child instanceof PsiComment || + child.getText().length() == 0); + break; + } + } + MiscellaneousTextEntry miscellaneousTextEntry = null; + if (startingIndex > 0) { + miscellaneousTextEntry = new MiscellaneousTextEntry( + psiFile.getChildren()[0], + psiFile.getChildren()[startingIndex - 1], + true, false + ); + } + parseRemainingClassContents(project, startingIndex, psiFile); + if (miscellaneousTextEntry != null) { + contents.add(0, miscellaneousTextEntry); + } + return contents; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java new file mode 100644 index 000000000000..5f41b963e9d2 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.entry; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.psi.PsiElement; +import com.wrq.rearranger.popup.RearrangerTreeNode; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.CommentUtil; + +import javax.swing.tree.DefaultMutableTreeNode; +import java.util.regex.Matcher; + +/** + * Corresponds to Java syntactic items ("entries") like classes, fields, and methods. A range entry + * contains start and end Psi elements for each item (which could be identical), as well as modifier + * flags and special flags to mark any miscellaneous text or comments that precede or follow the item. + */ +abstract public class RangeEntry implements IPopupTreeRangeEntry { +// ------------------------------ FIELDS ------------------------------ + + private static final Logger LOG = Logger.getInstance("#" + RangeEntry.class.getName()); + String alternateValue; + final String name; + protected final PsiElement start; + protected final PsiElement end; + private final int modifiers; + private final String modifierString; + private final boolean fixedHeader; + private final boolean fixedTrailer; + private final String type; + private IRuleInstance matchedRule; + private boolean separatorCommentPrecedes; + +// --------------------------- CONSTRUCTORS --------------------------- + + public RangeEntry(final PsiElement start, + final PsiElement end, + final boolean fixedHeader, + final boolean fixedTrailer) + { + this(start, end, 0, "", "", "", fixedHeader, fixedTrailer); + } + + RangeEntry(final PsiElement start, + final PsiElement end, + final int modifiers, + final String modifierString, + final String name, + final String type) + { + this(start, end, modifiers, modifierString, name, type, false, false); + } + + private RangeEntry(final PsiElement start, + final PsiElement end, + final int modifiers, + final String modifierString, + final String name, + final String type, + final boolean fixedHeader, + final boolean fixedTrailer) + { + this.start = start; + this.end = end; + this.modifiers = modifiers; + this.modifierString = modifierString; + this.fixedHeader = fixedHeader; + this.fixedTrailer = fixedTrailer; + this.name = name; + this.type = type; + alternateValue = null; + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public PsiElement getEnd() { + return end; + } + + public IRuleInstance getMatchedRule() { + return matchedRule; + } + + public void setMatchedRule(IRuleInstance matchedRule) { + this.matchedRule = matchedRule; + } + + public int getModifiers() { + return modifiers; + } + + public String getModifierString() { + return modifierString; + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public PsiElement getStart() { + return start; + } + + public boolean isFixedHeader() { + return fixedHeader; + } + + public boolean isFixedTrailer() { + return fixedTrailer; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public String toString() { + String result = (name == null ? "" : name); + if (start != null && end != null) { + result += "; range from " + + start.toString() + + " [" + + start.getTextRange().getStartOffset() + + "] to " + + end.toString() + + " [" + + end.getTextRange().getEndOffset() + + "]; modifiers=0x" + + Integer.toHexString(modifiers); + } + else { + result += "; no start/end specified"; + } + if (fixedHeader) { + result = "Header: " + result; + } + if (fixedTrailer) { + result = "Trailer: " + result; + } + if (alternateValue != null) { + result += "; comments removed"; + } + return result; + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface IPopupTreeRangeEntry --------------------- + + public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { + DefaultMutableTreeNode myNode = new RearrangerTreeNode(this, name); + parent.add(myNode); + return myNode; + } + +// -------------------------- OTHER METHODS -------------------------- + + public void checkForComment() { + if (CommentUtil.getCommentMatchers().size() == 0) { + return; + } + createAlternateValueString(); + /** + * for each separator comment specified by the user, check to see if this comment matches. + */ + for (Matcher matcher : CommentUtil.getCommentMatchers()) { + matcher.reset(alternateValue); + boolean foundMatch = matcher.find(); + if (foundMatch) { + LOG.debug("found comment pattern '" + + matcher.pattern().pattern().replaceAll("\n", "#") + + "' in '" + + alternateValue.replaceAll("\n", "#") + + "'"); + StringBuffer sb = new StringBuffer(alternateValue.length()); + do { + boolean leadingNewlines = start.getTextRange().getStartOffset() > 0; + matcher.appendReplacement(sb, + leadingNewlines ? "\n" : ""); + foundMatch = matcher.find(); + } + while (foundMatch); + matcher.appendTail(sb); + alternateValue = sb.toString(); + LOG.debug("RangeEntry alternateValue=" + alternateValue.replaceAll("\n", "#")); + } + } + } + + protected void createAlternateValueString() { + if (alternateValue != null) { + return; + } + final StringBuffer sb = new StringBuffer( + end.getTextRange().getEndOffset() - + start.getTextRange().getStartOffset() + ); + PsiElement e = start; + while (e != null && e != end) { + if (e == end.getParent()) { + e = e.getFirstChild(); + } + else { + sb.append(e.getText()); + e = e.getNextSibling(); + } + } + if (e == end) { + sb.append(end.getText()); + } + alternateValue = sb.toString(); + } + + public void emit(Emitter emitter) { + emitAllElements(emitter.getStringBuffer(), emitter.getDocument()); + } + + protected void emitAllElements(StringBuffer sb, Document document) { + if (alternateValue != null) { + String result = alternateValue; + if (separatorCommentPrecedes) { + // remove all leading blank lines. The only blank lines we want are the ones explicitly appended + // to the preceding separator comment. + LOG.debug("emitAllElements: separator comment precedes " + + name + "; original value=" + + alternateValue.replaceAll("\n", "#")); + result = alternateValue.replaceFirst("\n[ \t\n]*\n", "\n"); + LOG.debug("emitAllElements: resulting value=" + + alternateValue.replaceAll("\n", "#")); + } + sb.append(result); + } + else { + PsiElement curr = start; + while (curr != null && curr != end) { + if (curr == end.getParent()) { + curr = curr.getFirstChild(); + } + else { + emitElement(curr, sb, document); + curr = curr.getNextSibling(); + } + } + if (curr == end) { + emitElement(end, sb, document); + } + } + } + + private void emitElement(final PsiElement curr, + final StringBuffer sb, + final Document document) + { + try { + sb.append( + document.getCharsSequence().toString().toCharArray(), // for Irida (builds 3185 etc). + curr.getTextRange().getStartOffset(), + curr.getTextRange().getEndOffset() - curr.getTextRange().getStartOffset() + ); + } + catch (ArrayIndexOutOfBoundsException oob) { + LOG.error("internal error attempting to append text to document"); + LOG.error("document.getCharsSequence.length=" + document.getCharsSequence().length()); + LOG.error("document.getCharsSequence.toString().length=" + document.getCharsSequence().toString().length()); + LOG.error("document...toCharArray.length=" + document.getCharsSequence().toString().toCharArray().length); + LOG.error("current PSI element=" + curr.toString()); + LOG.error("current PSI element text=" + curr.getText()); + LOG.error("current PSI element text range, start offset=" + curr.getTextRange().getStartOffset()); + LOG.error("current PSI element text range, end offset=" + curr.getTextRange().getEndOffset()); + LOG.error("current PSI element text range, length=" + curr.getTextRange().getLength()); + LOG.error(oob); + throw oob; + } + } + + public void setSeparatorCommentPrecedes(boolean precedes) { + this.separatorCommentPrecedes = precedes; + LOG.debug("emitAllElements: set separator comment precedes " + name); + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/FileStructurePopup.java b/plugins/rearranger/src/com/wrq/rearranger/popup/FileStructurePopup.java new file mode 100644 index 000000000000..5b6b4cad46e5 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/FileStructurePopup.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.intellij.psi.PsiFile; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import com.wrq.rearranger.util.IconUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; +import java.util.List; + +/** Contains code to pop up a file structure dialog, showing proposed rearrangement. */ +public class FileStructurePopup + implements IHasScrollPane +{ + final RearrangerSettings settings; + final PopupTreeComponent treeComponent; + + public FileStructurePopup(RearrangerSettings settings, + List resultRuleInstances, + final IFilePopupEntry psiFileEntry) + { + this.settings = settings; + treeComponent = new PopupTreeComponent(settings, resultRuleInstances, psiFileEntry); + } + + public FileStructurePopup(RearrangerSettings settings, + List resultRuleInstances, + final PsiFile psiFile) + { + this.settings = settings; + IFilePopupEntry psiFileEntry = new IFilePopupEntry() { + public String getTypeIconName() { + return "ppFile"; + } + + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + return new JLabel(psiFile.getName()); + } + }; + treeComponent = new PopupTreeComponent(settings, resultRuleInstances, psiFileEntry); + } + + /** + * Display a pane showing the rearrangement. + * + * @return true if rearrangement should take place + */ + public boolean displayRearrangement() { + JPanel containerPanel = getContainerPanel(); + JOptionPane pane = new JOptionPane( + containerPanel, + JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION + ); + JDialog dialog = pane.createDialog(null, "Rearrangement Results"); + dialog.setResizable(true); + dialog.setVisible(true); + Object selectedValue = pane.getValue(); + return ((Integer)selectedValue) == JOptionPane.OK_OPTION; + } + +// Level 2 methods + + private JPanel getContainerPanel() { + final JPanel containerPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints scrollPaneConstraints = new GridBagConstraints(); + Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + + final JScrollPane treeView = getScrollPane(); + final JComponent showTypesBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowParameterTypes(); + } + + void setSetting(boolean value) { + settings.setShowParameterTypes(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowParamTypes"); + } + + String getToolTipText() { + return "Show parameter types"; + } + + int getShortcut() { + return KeyEvent.VK_T; + } + }.getIconBox(); + final JComponent showNamesBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowParameterNames(); + } + + void setSetting(boolean value) { + settings.setShowParameterNames(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowParamNames"); + } + + String getToolTipText() { + return "Show parameter names"; + } + + int getShortcut() { + return KeyEvent.VK_N; + } + }.getIconBox(); + + final JComponent showFieldsBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowFields(); + } + + void setSetting(boolean value) { + settings.setShowFields(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowFields"); + } + + String getToolTipText() { + return "Show fields"; + } + + int getShortcut() { + return KeyEvent.VK_F; + } + }.getIconBox(); + final JComponent showTypeAfterMethodBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowTypeAfterMethod(); + } + + void setSetting(boolean value) { + settings.setShowTypeAfterMethod(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowTypeAfterMethod"); + } + + String getToolTipText() { + return "Show type after method"; + } + + int getShortcut() { + return KeyEvent.VK_A; + } + }.getIconBox(); + final JComponent showRulesBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowRules(); + } + + void setSetting(boolean value) { + settings.setShowRules(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowRules"); + } + + String getToolTipText() { + return "Show rules"; + } + + int getShortcut() { + return KeyEvent.VK_R; + } + }.getIconBox(); + final JComponent showMatchedRulesBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowMatchedRules(); + } + + void setSetting(boolean value) { + settings.setShowMatchedRules(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowMatchedRules"); + } + + String getToolTipText() { + return "Show matched rules only"; + } + + int getShortcut() { + return KeyEvent.VK_M; + } + }.getIconBox(); + final JComponent showCommentsBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowComments(); + } + + void setSetting(boolean value) { + settings.setShowComments(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowComments"); + } + + String getToolTipText() { + return "Show generated separator comments"; + } + + int getShortcut() { + return KeyEvent.VK_C; + } + }.getIconBox(); + ((JCheckBox)showRulesBox.getComponent(0)).addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + showMatchedRulesBox.setEnabled(((JCheckBox)showRulesBox.getComponent(0)).isSelected()); + } + } + ); + showMatchedRulesBox.setEnabled(((JCheckBox)showRulesBox.getComponent(0)).isSelected()); + scrollPaneConstraints.insets = new Insets(3, 3, 3, 3); + scrollPaneConstraints.fill = GridBagConstraints.BOTH; + scrollPaneConstraints.gridwidth = GridBagConstraints.REMAINDER; + scrollPaneConstraints.gridheight = GridBagConstraints.REMAINDER; + scrollPaneConstraints.weightx = 1; + scrollPaneConstraints.weighty = 1; + scrollPaneConstraints.gridx = 0; + scrollPaneConstraints.gridy = 1; + + constraints.insets = new Insets(5, 5, 5, 5); + + containerPanel.add(showTypesBox, constraints.firstCol()); + containerPanel.add(showNamesBox, constraints.nextCol()); + containerPanel.add(showFieldsBox, constraints.nextCol()); + containerPanel.add(showTypeAfterMethodBox, constraints.nextCol()); + containerPanel.add(showCommentsBox, constraints.nextCol()); + containerPanel.add(showRulesBox, constraints.nextCol()); + containerPanel.add(showMatchedRulesBox, constraints.lastCol()); + containerPanel.add(treeView, scrollPaneConstraints); + return containerPanel; + } + + /** + * build a JTree containing classes, fields and methods, in accordance with settings. + * + * @return + */ + public JScrollPane getScrollPane() { + // Create the nodes. + JTree tree = treeComponent.createTree(); + /** expand all nodes. */ + for (int i = 0; i < tree.getRowCount(); i++) { + tree.expandRow(i); + } + JScrollPane treeView = new JScrollPane(tree); + treeView.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + treeView.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + Dimension d = treeView.getPreferredSize(); + if (d.width < 400) d.width = 400; + if (d.height < 300) d.height = 300; + treeView.setPreferredSize(d); + return treeView; + } + + public static void main(String[] args) { + final RearrangerSettings settings = new RearrangerSettings(); + IFilePopupEntry pf = new IFilePopupEntry() { + public String getTypeIconName() { + return "nodes/ppFile"; + } + + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + return new JLabel("FileName.java"); + } + }; + FileStructurePopup fsp = new FileStructurePopup(settings, new ArrayList(), pf); + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch (Exception e) { + } + + final JFrame frame = new JFrame("SwingApplication"); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1.0d; + constraints.weighty = 1.0d; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 0; + constraints.gridy = 0; + final JPanel object = fsp.getContainerPanel(); + frame.getContentPane().setLayout(new GridBagLayout()); + frame.getContentPane().add(object, constraints); + + //Finish setting up the frame, and show it. + frame.addWindowListener( + new WindowAdapter() { + public void windowClosing(final WindowEvent e) { + System.exit(0); + } + } + ); + frame.pack(); + frame.setVisible(true); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/IFilePopupEntry.java b/plugins/rearranger/src/com/wrq/rearranger/popup/IFilePopupEntry.java new file mode 100644 index 000000000000..bd0550870935 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/IFilePopupEntry.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.wrq.rearranger.settings.RearrangerSettings; + +import javax.swing.*; + +/** Interface implemented by objects which can appear as entries in the file structure popup. */ +public interface IFilePopupEntry { + /** @return the name of the icon representing the popup entry's type of Java object (method, class, etc.) */ + String getTypeIconName(); + + /** + * @return the names of the icon representing the protection level of the popup entry, and any other + * icons (overrides/overriding/implements/implmenting). + */ + String[] getAdditionalIconNames(); + + /** @return a JLabel containing the text of the popup tree entry. */ + JLabel getPopupEntryText(RearrangerSettings settings); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/IHasScrollPane.java b/plugins/rearranger/src/com/wrq/rearranger/popup/IHasScrollPane.java new file mode 100644 index 000000000000..b352fbb39a49 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/IHasScrollPane.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import javax.swing.*; + +/** + * Interface implemented by popups (LiveRearrangerPopup, FileStructurePopup) to (re)create the scrollpane when + * the underlying tree changes. + */ +public interface IHasScrollPane { + public JScrollPane getScrollPane(); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/ILiveRearranger.java b/plugins/rearranger/src/com/wrq/rearranger/popup/ILiveRearranger.java new file mode 100644 index 000000000000..dc1543023256 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/ILiveRearranger.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.wrq.rearranger.ruleinstance.IRuleInstance; + +import java.util.List; + +public interface ILiveRearranger { + void setRearrangementOccurred(boolean rearrangementOccurred); + + void setResultRuleInstances(List resultRuleInstances); + + void liveRearranger(); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/IconBox.java b/plugins/rearranger/src/com/wrq/rearranger/popup/IconBox.java new file mode 100644 index 000000000000..cc0ff8c03c3b --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/IconBox.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import com.wrq.rearranger.util.IconUtil; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; +import java.awt.event.*; + +/** + * Contains enough information to construct a checkbox with the given icon and tooltip + * text, related to a setting. + */ +abstract class IconBox { + + static final Color mouseoverColor = new Color(181, 190, 214); + static final Color selectedColor = new Color(132, 146, 189); + static final Color outlineColor = new Color(8, 36, 107); + + final JPanel containerPanel; + final GridBagConstraints constraints; + final IHasScrollPane scrollPaneComponent; + + protected IconBox(JPanel containerPanel, + GridBagConstraints constraints, + IHasScrollPane scrollPaneComponent) + { + this.containerPanel = containerPanel; + this.constraints = constraints; + this.scrollPaneComponent = scrollPaneComponent; + } + + abstract boolean getSetting(); + + abstract void setSetting(boolean value); + + abstract Icon getIcon(); + + abstract String getToolTipText(); + + abstract int getShortcut(); + + class MouseBox + extends JCheckBox + { + boolean mouseOver; + + public MouseBox(Icon icon) { + super(icon); + } + } + + class MyAction + extends AbstractAction + { + final MouseBox box; + + public MyAction(String name, MouseBox box) { + super(name); + this.box = box; + } + + public void actionPerformed(ActionEvent e) { + //To change body of implemented methods use File | Settings | File Templates. + box.getActionMap().get("pressed").actionPerformed(e); + box.getActionMap().get("released").actionPerformed(e); + } + } + + public JPanel getIconBox() { + final JPanel result = new JPanel(new GridBagLayout()); + + final Icon icon = getIcon(); + final MouseBox box = new MouseBox(icon); + box.setToolTipText(getToolTipText()); + box.setSelected(getSetting()); + box.setBackground(box.isSelected() ? selectedColor : null); + setOutline(result, box.isSelected()); + final MyAction myAction = new MyAction("toggleButton", box); + box.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + setAction(box, (JPanel)box.getParent()); + } + } + ); + box.setFocusable(false); + box.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke( + getShortcut(), + InputEvent.ALT_DOWN_MASK + ), + "toggleButton" + ); + + box.getActionMap().put("toggleButton", myAction); + box.addMouseListener( + new MouseAdapter() { + public void mouseEntered(MouseEvent e) { + box.mouseOver = true; + if (!box.isSelected()) { + box.setBackground(mouseoverColor); + setOutline(result, true); + } + } + + public void mouseExited(MouseEvent e) { + box.mouseOver = false; + if (!box.isSelected()) { + box.setBackground(null); + setOutline(result, false); + } + } + } + ); + result.add(box); + return result; + } + + private void setAction(final MouseBox box, final JPanel result) { + setSetting(box.isSelected()); + box.setBackground(box.isSelected() ? selectedColor : box.mouseOver ? mouseoverColor : null); + setOutline(result, box.mouseOver); + int lastIndex = containerPanel.getComponentCount() - 1; + containerPanel.remove(lastIndex); + final JScrollPane scrollPane = scrollPaneComponent.getScrollPane(); + containerPanel.add(scrollPane, constraints, lastIndex); + scrollPane.invalidate(); + containerPanel.validate(); + } + + /** + * draws a nearly-black outline border around the button (or removes such border). + * + * @param panel JPanel which contains the button. + * @param outline if true, draw the outline. + */ + private void setOutline(JPanel panel, boolean outline) { + Color borderColor = outline ? outlineColor : ((java.awt.Color)panel.getBackground()); + Border b = BorderFactory.createLineBorder(borderColor); + panel.setBorder(b); + } + + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch (Exception e) { + } + + final JFrame frame = new JFrame("IconBox test"); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.weightedLastRow(); + frame.getContentPane().setLayout(new GridBagLayout()); + JPanel panel = new JPanel(new GridBagLayout()); + frame.getContentPane().add(panel, constraints.weightedLastCol()); + constraints.fill = GridBagConstraints.NONE; + constraints.gridheight = 1; + constraints.weighty = 0; + IHasScrollPane scroll = new IHasScrollPane() { + public JScrollPane getScrollPane() { + return new JScrollPane(new JLabel("scroll pane contents")); + } + }; + final RearrangerSettings settings = new RearrangerSettings(); + IconBox box = new IconBox(panel, constraints, scroll) { + boolean getSetting() { + return settings.isShowComments(); + } + + void setSetting(boolean value) { + settings.setShowComments(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowComments"); + } + + String getToolTipText() { + return "Show comments (Alt+C)"; + } + + int getShortcut() { + return KeyEvent.VK_C; + } + }; + panel.add(box.getIconBox(), constraints); + constraints.weightedLastRow(); + constraints.fill = GridBagConstraints.BOTH; + JScrollPane firstPane = new JScrollPane(new JLabel("first scrollpane")); + panel.add(firstPane, constraints); + + //Finish setting up the frame, and show it. + frame.addWindowListener( + new WindowAdapter() { + public void windowClosing(final WindowEvent e) { + System.exit(0); + } + } + ); + frame.pack(); + frame.setVisible(true); + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/LiveRearrangerDialog.java b/plugins/rearranger/src/com/wrq/rearranger/popup/LiveRearrangerDialog.java new file mode 100644 index 000000000000..33204f9f285e --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/LiveRearrangerDialog.java @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.psi.PsiFile; +import com.wrq.rearranger.LiveRearrangerActionHandler; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import com.wrq.rearranger.util.IconUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.dnd.DnDConstants; +import java.awt.event.KeyEvent; +import java.util.List; + +/** + * Contains logic to display a rearrangement dialog, allow user to perform drag&drop rearrangement, and + * rearrange the code accordingly. + */ +public class LiveRearrangerDialog + implements IHasScrollPane, + ILiveRearranger +{ + private static final Logger LOG = Logger.getInstance("#" + LiveRearrangerDialog.class.getName()); + final RearrangerSettings settings; + PopupTreeComponent treeComponent; + List resultRuleInstances; + final Window outerPanel; + final Document document; + final PsiFile psiFile; + IFilePopupEntry psiFileEntry; + TreeDragSource tds; + TreeDropTarget tdt; + boolean rearrangementOccurred = false; + private JPanel containerPanel; + int cursorOffset; + private PopupTree popupTree; + + private void createFilePopupEntry(final PsiFile psiFile) { + psiFileEntry = new IFilePopupEntry() { + public String getTypeIconName() { + return "nodes/ppFile"; + } + + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + return new JLabel(psiFile.getName()); + } + }; + } + + public LiveRearrangerDialog(RearrangerSettings settings, PsiFile psiFile, Document document, + final Window outerPanel, int cursorOffset) + { + this.settings = settings; + this.document = document; + this.psiFile = psiFile; + createFilePopupEntry(psiFile); + this.outerPanel = outerPanel; + this.cursorOffset = cursorOffset; + } + + public void setRearrangementOccurred(boolean rearrangementOccurred) { + this.rearrangementOccurred = rearrangementOccurred; + } + + public void setResultRuleInstances(List resultRuleInstances) { + this.resultRuleInstances = resultRuleInstances; + treeComponent = new PopupTreeComponent(settings, resultRuleInstances, psiFileEntry); + } + + /** Display a live rearrangement window. */ + public void liveRearranger() { + containerPanel = getContainerPanel(); + JOptionPane pane = new JOptionPane( + containerPanel, + JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION + ); + JDialog dialog = pane.createDialog(null, "Live Rearranger"); + dialog.setResizable(true); + dialog.setVisible(true); + Object selectedValue = pane.getValue(); + rearrangementOccurred = + treeComponent.isRearrangementOccurred() && + (popupTree.isExitedWithEnterKey() || + (selectedValue != null && + (((Integer)selectedValue) == JOptionPane.OK_OPTION))); + finish(); + LOG.debug("exit liveRearranger"); + } + + public void finish() { + LOG.debug("entered finish() on thread " + Thread.currentThread().getName()); + if (!rearrangementOccurred) { + LOG.debug("no rearrangement occurred, not rearranging document"); + return; + } + LOG.debug("rearranging document"); + if (document != null) { + final Emitter e = new Emitter(psiFile, resultRuleInstances, document); + e.emitRearrangedDocument(); + } + + LiveRearrangerActionHandler.setInProgress(false); + LOG.debug("exit finish() on thread " + Thread.currentThread().getName()); + } + + private JPanel getContainerPanel() { + final JPanel containerPanel = new JPanel(new GridBagLayout()); + + final GridBagConstraints scrollPaneConstraints = new GridBagConstraints(); + scrollPaneConstraints.insets = new Insets(3, 3, 3, 3); + scrollPaneConstraints.fill = GridBagConstraints.BOTH; + scrollPaneConstraints.gridwidth = GridBagConstraints.REMAINDER; + scrollPaneConstraints.gridheight = GridBagConstraints.REMAINDER; + scrollPaneConstraints.weightx = 1; + scrollPaneConstraints.weighty = 1; + scrollPaneConstraints.gridx = 0; + scrollPaneConstraints.gridy = 1; + + final JScrollPane treeView = getScrollPane(); + final JComponent showTypesBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowParameterTypes(); + } + + void setSetting(boolean value) { + settings.setShowParameterTypes(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowParamTypes"); + } + + String getToolTipText() { + return "Show parameter types"; + } + + int getShortcut() { + return KeyEvent.VK_T; + } + }.getIconBox(); + final JComponent showNamesBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowParameterNames(); + } + + void setSetting(boolean value) { + settings.setShowParameterNames(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowParamNames"); + } + + String getToolTipText() { + return "Show parameter names"; + } + + int getShortcut() { + return KeyEvent.VK_N; + } + }.getIconBox(); + final JComponent showFieldsBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowFields(); + } + + void setSetting(boolean value) { + settings.setShowFields(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowFields"); + } + + String getToolTipText() { + return "Show fields"; + } + + int getShortcut() { + return KeyEvent.VK_F; + } + }.getIconBox(); + final JComponent showTypeAfterMethodBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowTypeAfterMethod(); + } + + void setSetting(boolean value) { + settings.setShowTypeAfterMethod(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowTypeAfterMethod"); + } + + String getToolTipText() { + return "Show type after method"; + } + + int getShortcut() { + return KeyEvent.VK_A; + } + }.getIconBox(); + Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.insets = new Insets(5, 5, 5, 5); + containerPanel.add(showTypesBox, constraints.firstCol()); + containerPanel.add(showNamesBox, constraints.nextCol()); + containerPanel.add(showFieldsBox, constraints.nextCol()); + containerPanel.add(showTypeAfterMethodBox, constraints.lastCol()); + containerPanel.add(treeView, scrollPaneConstraints); + return containerPanel; + } + + /** + * build a JTree containing classes, fields and methods, in accordance with settings. + * + * @return + */ + public JScrollPane getScrollPane() { + // Create the nodes. + popupTree = treeComponent.createLiveRearrangerTree(); + +// /** only expand node where cursor is located. Inspect all rows; deepest node that covers +// * cursor location is the best to expand. (Parent node like a class contains a method where +// * the cursor is; we want to expand the method, not just the class. +// */ +// int expandRow = -1; +// for (int i = 0; i < tree.getRowCount(); i++) +// { +// DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getPathForRow(i).getLastPathComponent(); +// if (node.getUserObject() instanceof RangeEntry) +// { +// RangeEntry re = (RangeEntry) node.getUserObject(); +// if (re.getStart().getTextRange().getStartOffset() <= cursorOffset && +// re.getEnd().getTextRange().getEndOffset() >= cursorOffset) +// { +// logger.debug( +// "node " + +// i + +// " contained cursor (offset=" + +// cursorOffset + +// "): " + re +// ); +// expandRow = i; +// } +// } +// else +// { +// logger.debug("expand node candidate not RangeEntry; node=" + node); +// } +// } +// if (expandRow >= 0) +// { +// logger.debug("expand row " + expandRow); +// tree.expandRow(expandRow); +// } + /** simply expand all nodes. */ + for (int i = 0; i < popupTree.getRowCount(); i++) { + popupTree.expandRow(i); + } + JScrollPane treeView = new JScrollPane(popupTree); + treeView.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + treeView.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + treeView.getVerticalScrollBar().setFocusable(false); + treeView.getHorizontalScrollBar().setFocusable(false); + Dimension d = treeView.getPreferredSize(); + if (d.width < 400) d.width = 400; + if (d.height < 300) d.height = 300; + treeView.setPreferredSize(d); + tdt = new TreeDropTarget(popupTree, this); + tds = new TreeDragSource(popupTree, DnDConstants.ACTION_MOVE, tdt); + return treeView; + } + +// class RearrangerTest +// extends LightCodeInsightTestCase +// { +// private RearrangerSettings rs; +// +// protected final void setUp() throws Exception +// { +// super.setUp(); +// } +// +// +// +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/LiveRearrangerPopup.java b/plugins/rearranger/src/com/wrq/rearranger/popup/LiveRearrangerPopup.java new file mode 100644 index 000000000000..700ee7527917 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/LiveRearrangerPopup.java @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.wrq.rearranger.LiveRearrangerActionHandler; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.IconUtil; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import javax.swing.tree.DefaultMutableTreeNode; +import java.awt.*; +import java.awt.dnd.DnDConstants; +import java.awt.event.*; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +/** + * Contains logic to display a rearrangement popup, allow user to perform drag&drop rearrangement, and (when + * a keystroke is seen or a mouse click outside the popup occurs) rearrange the code accordingly. + */ +public class LiveRearrangerPopup + implements IHasScrollPane, ILiveRearranger +{ + private static final Logger LOG = Logger.getInstance("#" + LiveRearrangerPopup.class.getName()); + final RearrangerSettings settings; + PopupTreeComponent treeComponent; + List resultRuleInstances; + final Window outerPanel; + final Document document; + final PsiFile psiFile; + IFilePopupEntry psiFileEntry; + private WindowFocusListener windowFocusListener; + private WindowAdapter windowAdapter; + private MouseAdapter mouseAdapter; + private KeyEventDispatcher keyEventDispatcher; + private Popup popup; + // private JWindow popup; + TreeDragSource tds; + TreeDropTarget tdt; + boolean rearrangementOccurred = false; + private FocusAdapter focusAdapter; + private JPanel containerPanel; + private final Project project; + private Cursor oldCursor; + private MouseAdapter ma2; + int cursorOffset; + private Component outerPanelFocusOwner; + boolean sawKeyPressed = false; + + public LiveRearrangerPopup(RearrangerSettings settings, + final IFilePopupEntry psiFileEntry, + Window outerPanel, + Document document, + Project project) + { + LOG.debug("entered LiveRearrangerPopup constructor"); + this.settings = settings; + this.outerPanel = outerPanel; + this.psiFileEntry = psiFileEntry; + this.document = document; + this.psiFile = null; + this.project = project; + } + + private void createFilePopupEntry(final PsiFile psiFile) { + psiFileEntry = new IFilePopupEntry() { + public String getTypeIconName() { + return "nodes/ppFile"; + } + + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + return new JLabel(psiFile.getName()); + } + }; + } + + public LiveRearrangerPopup(RearrangerSettings settings, PsiFile psiFile, Document document, Project project, + final Window outerPanel, int cursorOffset) + { + this.settings = settings; + this.document = document; + this.psiFile = psiFile; + createFilePopupEntry(psiFile); + this.project = project; + this.outerPanel = outerPanel; + this.cursorOffset = cursorOffset; + try { + SwingUtilities.invokeAndWait( + new Runnable() { + public void run() { +// popup = new JWindow(); + JPanel tempPanel = new JPanel(new GridBagLayout()); + JLabel label = new JLabel("Live Rearranger parsing file..."); + Border b = BorderFactory.createRaisedBevelBorder(); + tempPanel.setBorder(b); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.insets = new Insets(5, 5, 5, 5); + tempPanel.add(label, constraints); + Dimension d = outerPanel.getSize(); + Dimension c = tempPanel.getPreferredSize(); + int x = (d.width - c.width) / 2; + int y = (d.height - c.height) / 2; + if (x < 0) x = 0; + if (y < 0) y = 0; + popup = PopupFactory.getSharedInstance().getPopup(outerPanel, tempPanel, x, y); +// popup.getContentPane().add(tempPanel); +// popup.setLocation(x, y); + LOG.debug("initial outerPanel size=" + d + ", tempPanel preferred size=" + c); + LOG.debug("Constructing initial Popup at x,y=" + x + "," + y); +// popup.pack(); +// popup.setVisible(true); +// popup.requestFocusInWindow(); + popup.show(); + Cursor cu = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + oldCursor = outerPanel.getCursor(); + LOG.debug("setCursor (WAIT)" + cu + " on " + outerPanel); + outerPanel.setCursor(cu); + } + } + ); + } + catch (InterruptedException ie) { + throw new RuntimeException(ie); + } + catch (InvocationTargetException ite) { + throw new RuntimeException(ite); + } + } + + public void setRearrangementOccurred(boolean rearrangementOccurred) { + this.rearrangementOccurred = rearrangementOccurred; + } + + public void setResultRuleInstances(List resultRuleInstances) { + this.resultRuleInstances = resultRuleInstances; + treeComponent = new PopupTreeComponent(settings, resultRuleInstances, psiFileEntry); + } + + /** Display a live rearrangement window. */ + public void liveRearranger() { + try { + SwingUtilities.invokeAndWait( + new Runnable() { + public void run() { + containerPanel = getContainerPanel(); + LOG.debug("containerPanel.isFocusable=" + containerPanel.isFocusable()); + Border b = BorderFactory.createRaisedBevelBorder(); + containerPanel.setBorder(b); + Dimension d = outerPanel.getSize(); + Dimension c = containerPanel.getPreferredSize(); + int x = (d.width - c.width) / 2; + int y = (d.height - c.height) / 2; + if (x < 0) x = 0; + if (y < 0) y = 0; + popup.hide(); // destroy initial (interim) popup + popup = PopupFactory.getSharedInstance().getPopup(outerPanel, containerPanel, x, y); +// popup = new JFrame(); +// final Container contentPane = popup.getContentPane(); +// contentPane.remove(0); +// contentPane.add(containerPanel); +// contentPane.validate(); +// popup.setLocation(x, y); + LOG.debug("setCursor (original)" + oldCursor + " on " + outerPanel); + outerPanel.setCursor(oldCursor); +// logger.debug("set default cursor on " + popup); +// popup.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); +// popup.repaint(); + LOG.debug("outerPanel size=" + d + ", containerPanel preferred size=" + c); + LOG.debug("Constructing Popup at x,y=" + x + "," + y); + LiveRearrangerActionHandler.setInProgress(true); + +// popup.addWindowFocusListener(windowFocusListener); +// popup.addWindowListener(windowAdapter); +// popup.addMouseListener(mouseAdapter); +// popup.addFocusListener(focusAdapter); +// contentPane.addFocusListener(focusAdapter); + outerPanel.addWindowFocusListener( + windowFocusListener = getWindowFocusListener("outerPanel") + ); + outerPanel.addWindowListener(windowAdapter = getWindowAdapter("outerPanel")); + outerPanel.addMouseListener(mouseAdapter = getMouseAdapter("outerPanel")); + ma2 = getMouseAdapter("focus owner"); + outerPanelFocusOwner = outerPanel.getFocusOwner(); + if (outerPanelFocusOwner != null) { + outerPanelFocusOwner.addMouseListener(ma2); + } + outerPanel.addFocusListener(focusAdapter = getFocusAdapter("outerPanel")); + containerPanel.addFocusListener(getFocusAdapter("containerPanel")); + + keyEventDispatcher = new KeyEventDispatcher() { + public boolean dispatchKeyEvent(KeyEvent e) { + LOG.debug( + "key event dispatcher: outerPanel isFocused=" + + outerPanel.isFocused() + + ", rearrangementOccurred=" + + rearrangementOccurred + + " keyEvent=" + + e + ); + if (e.getID() == KeyEvent.KEY_RELEASED && + (rearrangementOccurred || sawKeyPressed)) + { + LOG.debug("key event dispatcher: disposing popup, saw keyEvent " + e); + finish(); + } + if (e.getID() == KeyEvent.KEY_PRESSED) { + sawKeyPressed = true; + } + return true; + } + }; + KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher( + keyEventDispatcher + ); +// wasLightWeight = ToolTipManager.sharedInstance().isLightWeightPopupEnabled(); +// ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false); + popup.show(); +// popup.setVisible(true); + } + } + ); + } + catch (InterruptedException ie) { + throw new RuntimeException(ie); + } + catch (InvocationTargetException ite) { + throw new RuntimeException(ite); + } + LOG.debug("exit liveRearranger"); + } + + private MouseAdapter getMouseAdapter(final String component) { + return new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + LOG.debug( + component + + ": mouse clicked at " + + e.getX() + + "," + + e.getY() + + "; window size/position is " + + outerPanel.getBounds() + ); + LOG.debug("close popup and finish"); + finish(); + super.mouseClicked(e); + } + }; + } + + private FocusAdapter getFocusAdapter(final String component) { + return new FocusAdapter() { + public void focusGained(FocusEvent e) { + LOG.debug(component + ": focus gained"); + } + + public void focusLost(FocusEvent e) { + LOG.debug(component + ": focus lost, close popup & finish"); + finish(); + } + }; + } + + private WindowAdapter getWindowAdapter(final String component) { + return new WindowAdapter() { + public void windowLostFocus(WindowEvent e) { + LOG.debug(component + ": lost focus"); + LOG.debug("close popup and finish"); + finish(); + } + + public void windowClosing(WindowEvent e) { + LOG.debug(component + ": window closing"); + } + }; + } + + private WindowFocusListener getWindowFocusListener(final String component) { + return new WindowFocusListener() { + public void windowGainedFocus(WindowEvent e) { + LOG.debug(component + ": gained window focus"); + } + + public void windowLostFocus(WindowEvent e) { + LOG.debug(component + ": lost window focus"); + LOG.debug("close popup and finish"); + finish(); + } + }; + } + + public void finish() { + LOG.debug("entered finish() on thread " + Thread.currentThread().getName()); +// popup.setVisible(false); +// popup.dispose(); +// popup.removeWindowFocusListener(windowFocusListener); +// popup.removeWindowListener(windowAdapter); +// popup.removeMouseListener(mouseAdapter); +// popup.removeFocusListener(focusAdapter); +// popup.getContentPane().removeFocusListener(focusAdapter); + outerPanel.removeWindowFocusListener(windowFocusListener); + if (outerPanelFocusOwner != null) { + outerPanelFocusOwner.removeMouseListener(ma2); + } + outerPanel.removeWindowListener(windowAdapter); + outerPanel.removeMouseListener(mouseAdapter); + outerPanel.removeFocusListener(focusAdapter); +// containerPanel.removeFocusListener(containerPanel.getFocusListeners()[0]); + popup.hide(); +// popup.dispose(); + + KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(keyEventDispatcher); +// ToolTipManager.sharedInstance().setLightWeightPopupEnabled(wasLightWeight); + if (!rearrangementOccurred) { + LOG.debug("no rearrangement occurred, not rearranging document"); + LiveRearrangerActionHandler.setInProgress(false); + return; + } + LOG.debug("rearranging document"); + final Runnable task = new Runnable() { + public void run() { + if (document != null) { + final Emitter e = new Emitter(psiFile, resultRuleInstances, document); + e.emitRearrangedDocument(); + } + } + }; + final Application application = ApplicationManager.getApplication(); + + application.runWriteAction( + new Runnable() { + public void run() { + CommandProcessor.getInstance().executeCommand(project, task, "Rearrange", null); + } + } + ); + + LiveRearrangerActionHandler.setInProgress(false); + LOG.debug("exit finish() on thread " + Thread.currentThread().getName()); + } + + private JPanel getContainerPanel() { + final JPanel containerPanel = new JPanel(new GridBagLayout()); + Border etched = BorderFactory.createTitledBorder( + BorderFactory.createEtchedBorder(), "Live Rearranger", TitledBorder.CENTER, + TitledBorder.TOP + ); + containerPanel.setBorder(etched); + final GridBagConstraints scrollPaneConstraints = new GridBagConstraints(); + scrollPaneConstraints.insets = new Insets(3, 3, 3, 3); + scrollPaneConstraints.fill = GridBagConstraints.BOTH; + scrollPaneConstraints.gridwidth = GridBagConstraints.REMAINDER; + scrollPaneConstraints.gridheight = GridBagConstraints.REMAINDER; + scrollPaneConstraints.weightx = 1; + scrollPaneConstraints.weighty = 1; + scrollPaneConstraints.gridx = 0; + scrollPaneConstraints.gridy = 1; + + final JScrollPane treeView = getScrollPane(); + final JComponent showTypesBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowParameterTypes(); + } + + void setSetting(boolean value) { + settings.setShowParameterTypes(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowParamTypes"); + } + + String getToolTipText() { + return "Show parameter types"; + } + + int getShortcut() { + return KeyEvent.VK_T; + } + }.getIconBox(); + final JComponent showNamesBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowParameterNames(); + } + + void setSetting(boolean value) { + settings.setShowParameterNames(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowParamNames"); + } + + String getToolTipText() { + return "Show parameter names"; + } + + int getShortcut() { + return KeyEvent.VK_N; + } + }.getIconBox(); + final JComponent showFieldsBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowFields(); + } + + void setSetting(boolean value) { + settings.setShowFields(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowFields"); + } + + String getToolTipText() { + return "Show fields"; + } + + int getShortcut() { + return KeyEvent.VK_F; + } + }.getIconBox(); + final JComponent showTypeAfterMethodBox = + new IconBox(containerPanel, scrollPaneConstraints, this) { + boolean getSetting() { + return settings.isShowTypeAfterMethod(); + } + + void setSetting(boolean value) { + settings.setShowTypeAfterMethod(value); + } + + Icon getIcon() { + return IconUtil.getIcon("ShowTypeAfterMethod"); + } + + String getToolTipText() { + return "Show type after method"; + } + + int getShortcut() { + return KeyEvent.VK_A; + } + }.getIconBox(); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = 1; + constraints.gridheight = 1; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.weightx = 0; + constraints.weighty = 0; + constraints.insets = new Insets(5, 5, 5, 5); + containerPanel.add(showTypesBox, constraints); + constraints.gridx++; + containerPanel.add(showNamesBox, constraints); + constraints.gridx++; + containerPanel.add(showFieldsBox, constraints); + constraints.gridx++; + constraints.gridwidth = GridBagConstraints.REMAINDER; + containerPanel.add(showTypeAfterMethodBox, constraints); + containerPanel.add(treeView, scrollPaneConstraints); + return containerPanel; + } + + /** + * build a JTree containing classes, fields and methods, in accordance with settings. + * + * @return + */ + public JScrollPane getScrollPane() { + // Create the nodes. + PopupTree tree = treeComponent.createLiveRearrangerTree(); + + /** only expand node where cursor is located. Inspect all rows; deepest node that covers + * cursor location is the best to expand. (Parent node like a class contains a method where + * the cursor is; we want to expand the method, not just the class. + */ + int expandRow = -1; + for (int i = 0; i < tree.getRowCount(); i++) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getPathForRow(i).getLastPathComponent(); + if (node.getUserObject() instanceof RangeEntry) { + RangeEntry re = (RangeEntry)node.getUserObject(); + if (re.getStart().getTextRange().getStartOffset() <= cursorOffset && + re.getEnd().getTextRange().getEndOffset() >= cursorOffset) + { + LOG.debug( + "node " + + i + + " contained cursor (offset=" + + cursorOffset + + "): " + re + ); + expandRow = i; + } + } + else { + LOG.debug("expand node candidate not RangeEntry; node=" + node); + } + } + if (expandRow >= 0) { + LOG.debug("expand row " + expandRow); + tree.expandRow(expandRow); + } + JScrollPane treeView = new JScrollPane(tree); + treeView.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + treeView.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + Dimension d = treeView.getPreferredSize(); + if (d.width < 400) d.width = 400; + if (d.height < 300) d.height = 300; + treeView.setPreferredSize(d); + tdt = new TreeDropTarget(tree, this); + tds = new TreeDragSource(tree, DnDConstants.ACTION_MOVE, tdt); + return treeView; + } + + // class RearrangerTest +// extends LightCodeInsightTestCase +// { +// private RearrangerSettings rs; +// +// protected final void setUp() throws Exception +// { +// super.setUp(); +// } +// +// +// + public static void main(String[] args) { +// RearrangerTest t = new RearrangerTest(); +// t.testIt(); +// void testIt() +// { + final RearrangerSettings settings = new RearrangerSettings(); + IFilePopupEntry pf = new IFilePopupEntry() { + public String getTypeIconName() { + return "nodes/ppFile"; + } + + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + return new JLabel("FileName.java"); + } + }; + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch (Exception e) { + } + +// logger.setAdditivity(false); +// logger.addAppender(new ConsoleAppender(new PatternLayout("[%7r] %6p - %30.30c - %m \n"))); +// logger.setLevel(Level.DEBUG); +// logger.debug("Testing LiveRearrangerPopup"); + + final JFrame frame = new JFrame("SwingApplication"); +// Window window = new Window(frame); + JPanel panel = new JPanel(); + panel.setSize(800, 600); + frame.setSize(800, 600); + frame.getRootPane().add(panel); +// window.setSize(800, 600); +// window.getRootPane().add(panel); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1.0d; + constraints.weighty = 1.0d; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 0; + constraints.gridy = 0; + LiveRearrangerPopup lrp = new LiveRearrangerPopup( + // getProject(), + settings, pf, frame, null, + null + ); +// final JPanel object = lrp.getContainerPanel(); +// frame.getContentPane().setLayout(new GridBagLayout()); +// frame.getContentPane().add(object, constraints); + + //Finish setting up the frame, and show it. + frame.addWindowListener( + new WindowAdapter() { + public void windowClosing(final WindowEvent e) { + System.exit(0); + } + } + ); +// frame.pack(); + frame.setVisible(true); + lrp.liveRearranger(); + } +} + +// +//} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/PopupTree.java b/plugins/rearranger/src/com/wrq/rearranger/popup/PopupTree.java new file mode 100644 index 000000000000..de925315e1fa --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/PopupTree.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.intellij.openapi.diagnostic.Logger; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.ruleinstance.IRuleInstance; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.awt.*; +import java.awt.dnd.Autoscroll; +import java.util.LinkedList; + +/** Handles vertical autoscrolling of the tree inside the live rearranger popup/dialog. */ +public class PopupTree + extends JTree + implements Autoscroll +{ + private static final Logger LOG = Logger.getInstance("#" + PopupTree.class.getName()); + private static final int margin = 12; + private TreeDropTarget treeDropTarget; + private boolean exitedWithEnterKey; + private final PopupTreeComponent owner; + + public PopupTree(TreeNode root, PopupTreeComponent owner) { + super(root); + this.owner = owner; + } + + public void setTreeDropTarget(TreeDropTarget dropTarget) { + treeDropTarget = dropTarget; + } + + public boolean isExitedWithEnterKey() { + return exitedWithEnterKey; + } + + public void setExitedWithEnterKey(boolean exitedWithEnterKey) { + this.exitedWithEnterKey = exitedWithEnterKey; + } + + // scroll because mouse cursor is in the scroll zone. + public void autoscroll(Point p) { + // determine row. Set y value to that of current row left edge; this allows scrolling to occur + int realrow = getRowForLocation(p.x, p.y); + if (treeDropTarget != null) { + treeDropTarget.clearInsertionPoint(); + // Set y value to that of current row left edge; this allows scrolling to occur even when cursor is + // to the right or left of the smallest rectangle enclosing the row. + int row = treeDropTarget.getSrcRow(); + Rectangle r = getRowBounds(row); + if (realrow < 0) { + LOG.debug("autscroll: realrow < 0 for [" + p.x + "," + p.y + "], trying x=" + r.x); + p.x = r.x; + realrow = getRowForLocation(p.x, p.y); + } + } + if (realrow < 0) { + LOG.debug("autoscroll point=[" + p.x + "," + p.y + "] realrow=" + realrow); + return; + } + Rectangle outer = getBounds(); + + // now determine if the row is at the top or bottom of the screen. + // Make the previous or next row visible accordingly. + int newRow = + p.y + outer.y <= margin + ? realrow < 1 ? 0 : realrow - 1 + : realrow < getRowCount() - 1 + ? realrow + 1 + : realrow; +// logger.setLevel(Level.DEBUG); -- following code doesn't work for horizontal scrolling; something interferes +// int newCol = p.x; +// if (this.getParent() instanceof JViewport) +// { +// JViewport parent = (JViewport) getParent(); +// logger.debug( +// "autoscroll horizontal TEST: p.x=" + +// p.x + +// ", bounds.x=" + +// outer.x + +// ", viewport x=" + +// parent.getBounds().x + +// ", width=" + parent.getBounds().width); +// if (p.x + outer.x <= margin) +// { +// newCol = p.x - margin; +// logger.debug( +// "autoscroll horizontal LEFT: new x=" + newCol +// ); +// logger.debug("this=" + this.toString()); +// logger.debug("this.parent=" + this.getParent().toString()); +// Rectangle r = parent.getViewRect(); +// r.x -= margin; +// parent.scrollRectToVisible(r); +// } +// else +// { +// if (p.x + outer.x + margin >= parent.getBounds().x + parent.getBounds().width) +// { +// newCol = p.x + margin; +// logger.debug( +// "autoscroll horizontal RIGHT: new x=" + newCol +// ); +//// logger.debug("this=" + this.toString()); +//// logger.debug("this.parent=" + parent.toString()); +// Rectangle r = parent.getViewRect(); +// r.x += margin; +// parent.scrollRectToVisible(r); +// } +// } +// } + LOG.debug("autoscroll point=[" + p.x + "," + p.y + "] realrow=" + realrow + ", newRow=" + newRow); + scrollRowToVisible(newRow); + if (treeDropTarget != null) { + treeDropTarget.computeInsertionPoint(); + treeDropTarget.drawInsertionPoint(); + } + } + + /** + * Calculate insets for the JTree, not the viewport the tree is in. + * this makes it a bit messy. + * + * @return + */ + public Insets getAutoscrollInsets() { + Rectangle outer = getBounds(); + Rectangle inner = getParent().getBounds(); + return new Insets( + inner.y - outer.y + margin, + inner.x - outer.x + margin, + outer.height - inner.height - inner.y + outer.y + margin, + outer.width - inner.width - inner.x + outer.x + margin + ); + } + + // Use this method to see the boundaries of the autoscroll active region. +// public void paintComponent(Graphics g) +// { +// super.paintComponent(g); +// Rectangle outer = getBounds(); +// Rectangle inner = getParent().getBounds(); +// g.setColor(Color.RED); +// g.drawRect(-outer.x + margin, -outer.y + margin, +// inner.width - 2*margin, inner.height - 2*margin); +// } + + /** + * Move the tree's selection to the destination row indicated. The selection may contain multiple + * discontiguous rows, but all rows must have the same parent node. + * + * @param dstIndex child index of common parent before which selection is to be inserted. If null, insert at end of parent. + */ + public void moveSelection(int dstIndex, boolean before) { + /** + * First, remove all mutable tree nodes from the tree's model and the rule instance. Place them in a list. + * If any are removed before the destination row, decrement the dstIndex so that the insertion still + * happens in the correct place. + */ + TreePath[] paths = getSelectionPaths(); + LinkedList nodeList = new LinkedList(); + LinkedList ruleList = new LinkedList(); + if (paths == null || paths.length == 0) { + return; // nothing selected + } + owner.setRearrangementOccurred(true); + final DefaultMutableTreeNode peerNode = (DefaultMutableTreeNode)paths[0].getLastPathComponent(); + RangeEntry entry = (RangeEntry)peerNode.getUserObject(); + DefaultMutableTreeNode peerParent = (DefaultMutableTreeNode)peerNode.getParent(); + DefaultMutableTreeNode dstNode = (DefaultMutableTreeNode)peerParent.getChildAt(dstIndex); + if (!before && dstIndex < peerParent.getChildCount()) { + dstIndex++; + } + IRuleInstance ruleInstance = entry.getMatchedRule(); + DefaultTreeModel model = (DefaultTreeModel)getModel(); + + for (TreePath path : paths) { + DefaultMutableTreeNode srcNode = (DefaultMutableTreeNode)path.getLastPathComponent(); + DefaultMutableTreeNode srcParent = (DefaultMutableTreeNode)srcNode.getParent(); + int srcRow = srcParent.getIndex(srcNode); + if (srcRow < dstIndex) { + dstIndex--; + } + nodeList.add(srcNode); + model.removeNodeFromParent(srcNode); + RangeEntry match = (RangeEntry)srcNode.getUserObject(); + ruleInstance.getMatches().remove(match); + ruleList.add(match); + } + /** + * now insert all the nodes in the list at the appropriate spots in the model and rule instance. + */ + clearSelection(); + TreePath visiblePath = null; + /** + * calculate the offset between the destination row in the model and its location in the ruleInstance's + * list of matching items. This is non-zero when fields exist but are not shown in the tree. + */ + int dstOffset = (ruleInstance.getMatches().indexOf(dstNode.getUserObject())) - peerParent.getIndex(dstNode); + while (!nodeList.isEmpty()) { + DefaultMutableTreeNode srcNode = nodeList.removeFirst(); + model.insertNodeInto(srcNode, peerParent, dstIndex); + final TreePath treePath = new TreePath(srcNode.getPath()); + addSelectionPath(treePath); + if (before) { + if (visiblePath == null) visiblePath = treePath; + } + else { + visiblePath = treePath; + } + final RangeEntry match = ruleList.removeFirst(); + ruleInstance.getMatches().add(dstIndex + dstOffset, match); + dstIndex++; + } + if (visiblePath != null) { + scrollPathToVisible(visiblePath); + } + } + + /** + * returns true if src and dst have common parent. Since src has been created from serialized data, + * the actual parents are different objects. So compare by name up to the root. Ignore any plain + * DefaultMutableTreeNodes in the path (these correspond to rules) -- just compare names of + * RearrangerTreeNodes. + * + * @param src RearrangerTreeNode reconstituted from serialized data + * @param dst RearrangerTreeNode next to which src is to be dropped + * @return -1 if src and dst do not have common parent; >= 0 to indicate position of src in children list + */ + int haveCommonAncestors(DefaultMutableTreeNode src, DefaultMutableTreeNode dst) { + if (src == null || dst == null) { + return -1; + } + DefaultMutableTreeNode p = (DefaultMutableTreeNode)src.getParent(); + int result = p.getIndex(src); + src = (DefaultMutableTreeNode)src.getParent(); + dst = (DefaultMutableTreeNode)dst.getParent(); + while (src != null && dst != null) { + if (src instanceof RearrangerTreeNode) { + if (dst instanceof RearrangerTreeNode) { + RearrangerTreeNode s = (RearrangerTreeNode)src; + RearrangerTreeNode d = (RearrangerTreeNode)dst; + if (!s.name.equals(d.name)) { + return -1; + } + } + else { + return -1; + } + } + else if (dst instanceof RearrangerTreeNode) { + return -1; + } + src = (DefaultMutableTreeNode)src.getParent(); + dst = (DefaultMutableTreeNode)dst.getParent(); + } + return src == null && dst == null ? result : -1; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/PopupTreeComponent.java b/plugins/rearranger/src/com/wrq/rearranger/popup/PopupTreeComponent.java new file mode 100644 index 000000000000..fa825b548a75 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/PopupTreeComponent.java @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.intellij.openapi.diagnostic.Logger; +import com.wrq.rearranger.Rearranger; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import com.wrq.rearranger.util.IconUtil; + +import javax.swing.*; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.net.URL; +import java.util.List; + +/** Builds a JTree that can be used in a file structure popup or live rearranger popup. */ +public class PopupTreeComponent { + private static final Logger LOG = Logger.getInstance("#" + PopupTreeComponent.class.getName()); + private final IFilePopupEntry psiFileEntry; + private final List resultRuleInstances; + private final RearrangerSettings settings; + private boolean rearrangementOccurred; + + public PopupTreeComponent(RearrangerSettings settings, + List resultRuleInstances, + final IFilePopupEntry psiFileEntry) + { + this.settings = settings; + this.resultRuleInstances = resultRuleInstances; + this.psiFileEntry = psiFileEntry; + } + + public boolean isRearrangementOccurred() { + return rearrangementOccurred; + } + + public void setRearrangementOccurred(boolean rearrangementOccurred) { + this.rearrangementOccurred = rearrangementOccurred; + } + + public JTree createTree() { + DefaultMutableTreeNode top = createAllNodes(); + final JTree tree = new JTree(top); + tree.putClientProperty("JTree.lineStyle", "Angled"); + tree.setRootVisible(true); + tree.setShowsRootHandles(true); + tree.setRowHeight(0); + tree.setCellRenderer(new JavaObjectRenderer()); + tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + tree.setEditable(false); + return tree; + } + + public PopupTree createLiveRearrangerTree() { + DefaultMutableTreeNode top = createAllNodes(); + // discard top nodes if only one child +// while (top.getChildCount() == 1) { // TODO - enable +// // remove that child, make its child(ren) top's child(ren). +// DefaultMutableTreeNode child = (DefaultMutableTreeNode) top.getChildAt(0); +// child.removeFromParent(); +// for (int i = 0; i < child.getChildCount(); i++) { +// DefaultMutableTreeNode grandchild = (DefaultMutableTreeNode) child.getChildAt(i); +// top.add(grandchild); +// } +// } + final PopupTree tree = new PopupTree(top, this); + tree.putClientProperty("JTree.lineStyle", "Angled"); + tree.setRootVisible(true); + tree.setShowsRootHandles(true); + tree.setRowHeight(0); + tree.setCellRenderer(new JavaObjectRenderer()); + tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + tree.setEditable(false); + tree.getSelectionModel().addTreeSelectionListener( + new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + LOG.debug("selection changed as follows (" + e.getPaths().length + " path(s)):"); + TreePath lastPathAdded = null; + int i = 0; + + for (TreePath path : e.getPaths()) { + if (e.isAddedPath(path)) { + lastPathAdded = path; + } + LOG.debug( + "path " + + i + + (e.isAddedPath(path) ? " added:" : " removed:") + + path + ); + i++; + } + if (lastPathAdded == null) { + // nothing added, so all selected paths still have same parent. + return; + } + /** + * ensure that all selection rows have the same parent. If not, take the last added + * path, and remove any rows with a different parent. (So simply start with the last + * added path and remove any rows with a different parent.) + */ + DefaultMutableTreeNode lastNodeAdded = null; + lastNodeAdded = (DefaultMutableTreeNode)lastPathAdded.getLastPathComponent(); + boolean haveSameParent = true; + for (TreePath path : tree.getSelectionPaths()) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + if (lastNodeAdded == null) { + lastNodeAdded = node; + } + if (node != lastNodeAdded) { + if (tree.haveCommonAncestors(lastNodeAdded, node) < 0) { + // parents not identical, so remove node from selection. + haveSameParent = false; + break; + } + } + } + if (!haveSameParent) { + // to avoid reentry into this listener, temporarily remove it + tree.getSelectionModel().removeTreeSelectionListener(this); + tree.clearSelection(); + tree.addSelectionPath(lastPathAdded); + tree.getSelectionModel().addTreeSelectionListener(this); + } + } + } + ); + + AbstractAction moveUpAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + LOG.debug("moveUpAction, " + tree.getSelectionPaths().length + " paths in selection"); + if (tree.getSelectionPaths().length == 0) { + return; + } + /** + * find first selection row. + */ + int selectionRow = Integer.MAX_VALUE; + for (TreePath path : tree.getSelectionPaths()) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + int nodeIndex = node.getParent().getIndex(node); + if (selectionRow > nodeIndex) { + selectionRow = nodeIndex; + } + } + if (selectionRow > 0) { + selectionRow--; + } + tree.moveSelection(selectionRow, true); + } + }; + AbstractAction moveDownAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + LOG.debug("moveDownAction, " + tree.getSelectionPaths().length + " paths in selection"); + if (tree.getSelectionPaths().length == 0) { + return; + } + /** + * find last selection row. + */ + int selectionRow = -1; + for (TreePath path : tree.getSelectionPaths()) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + final DefaultMutableTreeNode parent = ((DefaultMutableTreeNode)node.getParent()); + int nodeIndex = parent.getIndex(node); + if (selectionRow < nodeIndex) { + selectionRow = nodeIndex; + } + } + selectionRow++; + tree.moveSelection(selectionRow, false); + } + }; + AbstractAction enterKeyAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + LOG.debug("exit with enter key"); + tree.setExitedWithEnterKey(true); + for (Container p = tree.getParent(); p != null; p = p.getParent()) { + if (p instanceof JDialog) { + p.setVisible(false); + } + } + } + }; + tree.getInputMap().put( + KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), + "enterKeyAction" + ); + tree.getActionMap().put("enterKeyAction", enterKeyAction); + tree.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke( + KeyEvent.VK_UP, + InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK + ), + "moveUpAction" + ); + + tree.getActionMap().put("moveUpAction", moveUpAction); + tree.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke( + KeyEvent.VK_DOWN, + InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK + ), + "moveDownAction" + ); + + tree.getActionMap().put("moveDownAction", moveDownAction); + tree.setSelectionPath(tree.getPathForRow(0)); + return tree; + } + + public DefaultMutableTreeNode createAllNodes() { + DefaultMutableTreeNode top = new RearrangerTreeNode(psiFileEntry, "root"); + createNodes(top); + return top; + } + + private void createNodes(DefaultMutableTreeNode top) { + for (IRuleInstance ruleInstance : resultRuleInstances) { + ruleInstance.addRuleInstanceToPopupTree(top, settings); + } + } + + class JavaObjectRenderer + extends DefaultTreeCellRenderer + { + Icon findIcon(String iconName) { + if (iconName == null) { + return null; + } + URL iconURL = this.getClass().getClassLoader().getResource(iconName + ".png"); + if (iconURL == null) { + return IconUtil.getIcon(iconName); + } + else { + return new ImageIcon(iconURL, Rearranger.COMPONENT_NAME); + } + } + + public Component getTreeCellRendererComponent(final JTree tree, + final Object value, + final boolean sel, + final boolean expanded, + final boolean leaf, + final int row, + final boolean hasFocus) + { + Object userObject = null; + if (value instanceof DefaultMutableTreeNode) { + userObject = ((DefaultMutableTreeNode)value).getUserObject(); + } + // obtain a component that will render the appropriate item. + if (userObject instanceof IFilePopupEntry) { + IFilePopupEntry entry = (IFilePopupEntry)userObject; + final String iconTypeName = entry.getTypeIconName(); + final String[] iconNames = entry.getAdditionalIconNames(); + final JLabel textLabel = entry.getPopupEntryText(settings); + JPanel panel = new JPanel(new GridBagLayout()) { + public void paint(Graphics g) { +// System.out.println("paint " + textLabel.getText() + ", sel=" + sel + +// ", hasFocus=" + hasFocus + +// ", selected=" + selected + +// ", bg=" + getBackground().toString().replaceFirst(".*\\[", "[") + +// ", bg sel=" + getBackgroundSelectionColor().toString().replaceFirst(".*\\[", "[") + +// ", border=" + getBorderSelectionColor().toString().replaceFirst(".*\\[", "[") +// ); + if (sel && !hasFocus) { + Color bgColor = getBackground(); + setBackground(Color.WHITE); + super.paint(g); + setBackground(bgColor); + Color bsColor = getBorderSelectionColor(); + + if (bsColor != null) { + g.setColor(bsColor); + if (getComponentOrientation().isLeftToRight()) { + g.drawRect( + 0, 0, getWidth() - 1, + getHeight() - 1 + ); + } + else { + g.drawRect( + 0, 0, getWidth() - 1, + getHeight() - 1 + ); + } + } + } + else { + super.paint(g); + } + } + }; + Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.weightedLastRow(); + Icon typeIcon = findIcon(iconTypeName == null ? "fileTypes/unknown" : iconTypeName); + panel.setBackground(Color.WHITE); + if (sel) { +// Color fg = textLabel.getForeground(); +// Color bg = textLabel.getBackground(); +// textLabel.setForeground(bg); +// textLabel.setBackground(new Color(181, 190, 214)); +// Color fg = panel.getForeground(); +// Color bg = panel.getBackground(); +// panel.setForeground(bg); + panel.setBackground(new Color(181, 190, 214)); + } + else { + textLabel.setBackground(Color.WHITE); + } + if (typeIcon != null) { + JLabel typeLabel = new JLabel(typeIcon); + panel.add(typeLabel, constraints.nextCol()); + } + if (iconNames != null) { + for (String iconName : iconNames) { + Icon addlIcon = findIcon(iconName); + JLabel plLabel = new JLabel(addlIcon); + panel.add(plLabel, constraints.nextCol()); + } + } + constraints.insets = new Insets(0, 3, 0, 0); + panel.add(textLabel, constraints.lastCol()); + panel.repaint(); + return panel; + } + LOG.debug("getTreeCellRendererComponent: userObject not IFilePopupEntry;" + userObject); + return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/RearrangerTreeNode.java b/plugins/rearranger/src/com/wrq/rearranger/popup/RearrangerTreeNode.java new file mode 100644 index 000000000000..0a5b1afb09a5 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/RearrangerTreeNode.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import javax.swing.tree.DefaultMutableTreeNode; + +public class RearrangerTreeNode + extends DefaultMutableTreeNode +{ + String name; + + public RearrangerTreeNode(Object userObject, String name) { + super(userObject); + this.name = name; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/TransferableTreeNode.java b/plugins/rearranger/src/com/wrq/rearranger/popup/TransferableTreeNode.java new file mode 100644 index 000000000000..4f9b3660f836 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/TransferableTreeNode.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import javax.swing.tree.TreePath; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + +public class TransferableTreeNode + implements Transferable +{ + public static DataFlavor treePathFlavor = new DataFlavor(TreePath.class, "Tree Path Flavor"); + DataFlavor[] flavors = {treePathFlavor}; + TreePath[] paths; + + public TransferableTreeNode(TreePath[] paths) { + this.paths = paths; + } + + public DataFlavor[] getTransferDataFlavors() { + return flavors; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return (flavor.getRepresentationClass() == TreePath.class); + } + + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + if (isDataFlavorSupported(flavor)) { + return paths; + } + else { + throw new UnsupportedFlavorException(flavor); + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/TreeDragSource.java b/plugins/rearranger/src/com/wrq/rearranger/popup/TreeDragSource.java new file mode 100644 index 000000000000..77aa88279732 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/TreeDragSource.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.intellij.openapi.diagnostic.Logger; + +import javax.swing.*; +import java.awt.*; +import java.awt.dnd.*; + +/** Contains logic to start a drag from the popup file structure tree. */ +public class TreeDragSource + implements DragSourceListener, + DragGestureListener +{ + private static final Logger LOG = Logger.getInstance("#" + TreeDragSource.class.getName()); + DragSource source; + DragGestureRecognizer recognizer; + TransferableTreeNode transferable; + JTree sourceTree; + TreeDropTarget tdt; + + public TreeDragSource(JTree sourceTree, int actions, TreeDropTarget tdt) { + LOG.debug("construct TreeDragSource, actions=" + actions); + this.sourceTree = sourceTree; + this.tdt = tdt; + source = DragSource.getDefaultDragSource(); + recognizer = source.createDefaultDragGestureRecognizer( + sourceTree, actions, this); + } + + public void dragEnter(DragSourceDragEvent dsde) { + LOG.debug("src dragEnter, calling dragOver"); + dragOver(dsde); + } + + public void dragOver(DragSourceDragEvent dsde) { +// logger.debug("src dragOver; drop action=" + dsde.getDropAction() + +// ", target actions=" + dsde.getTargetActions()); +// dsde.getDragSourceContext().setCursor(dsde.getDropAction() > 0 +// ? DragSource.DefaultMoveDrop +// : DragSource.DefaultMoveNoDrop); + } + + public void dropActionChanged(DragSourceDragEvent dsde) { + LOG.debug("src dropActionChanged: action=" + dsde.getDropAction()); + } + + public void dragDropEnd(DragSourceDropEvent dsde) { + LOG.debug("src dragDropEnd, success=" + dsde.getDropSuccess()); + } + + public void dragExit(DragSourceEvent dse) { +// logger.debug("src dragExit"); + } + + public void dragGestureRecognized(DragGestureEvent dge) { + LOG.debug("src dragGestureRecognized, action=" + dge.getDragAction() + + ", n paths in selection=" + sourceTree.getSelectionPaths().length); + final Point point = dge.getDragOrigin(); +// TreePath path = sourceTree.getSelectionPath(); +// if (path == null || +// path.getPathCount() <= 1) +// { +// // can't move the root node or an empty selection +// System.out.println("can't drag root node or empty selection"); +// return; +// } + // Make a version of the node that we can use for DnD. + tdt.setSrcRow(sourceTree.getClosestRowForLocation(point.x, point.y)); + transferable = new TransferableTreeNode(sourceTree.getSelectionPaths()); + dge.startDrag(null, transferable, this); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/TreeDropTarget.java b/plugins/rearranger/src/com/wrq/rearranger/popup/TreeDropTarget.java new file mode 100644 index 000000000000..08be5c72ab6d --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/TreeDropTarget.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.popup; + +import com.intellij.openapi.diagnostic.Logger; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreePath; +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.*; +import java.io.IOException; + +/** Handles drop actions associated with manual rearrangement. */ +public class TreeDropTarget + implements DropTargetListener +{ + private static final Logger LOG = Logger.getInstance("#" + TreeDropTarget.class.getName()); + private static final Color xorBackgroundColor = new Color(255 - 8, 255 - 36, 255 - 107); + DropTarget target; + PopupTree targetTree; + ILiveRearranger lrp; + /** Cached information about the location of the last insertion row to be drawn. */ + private transient Rectangle lastRowRect; + + /** cached value of last row to be drawn. */ + private int lastRow; + /** + * Cached information about whether insertion was possible at the last + * insertion point. + */ + private transient boolean canInsert; + + /** true if rectangle has been drawn. */ + private boolean rectangleDrawn; + /** row being dragged. */ + private int srcRow; + + public TreeDropTarget(PopupTree tree, + ILiveRearranger lrp) + { + this.lrp = lrp; + this.targetTree = tree; + target = new DropTarget(targetTree, DnDConstants.ACTION_MOVE, this); + this.lastRowRect = new Rectangle(); + this.canInsert = false; + rectangleDrawn = false; + srcRow = -1; + tree.setTreeDropTarget(this); + } + + public void dragEnter(DropTargetDragEvent dtde) { +// logger.debug("tgt dragEnter calling dragOver logic"); + dragOver(dtde); + } + + public int getSrcRow() { + return srcRow; + } + + public void setSrcRow(int srcRow) { + this.srcRow = srcRow; + } + + public void dragOver(DropTargetDragEvent dtde) { +// logger.debug("target dragOver: src drop actions=" + dtde.getSourceActions() + +// ", src drop action=" + dtde.getDropAction()); + clearInsertionPoint(); + Point pt = dtde.getLocation(); + lastRow = targetTree.getClosestRowForLocation(pt.x, pt.y); + + computeInsertionPoint(lastRow); + TreePath path = targetTree.getClosestPathForLocation(pt.x, pt.y); + final DefaultMutableTreeNode tgtNode; + tgtNode = (DefaultMutableTreeNode)path.getLastPathComponent(); +// logger.debug("tgt dragOver, closest node=" + tgtNode); + // compare selected node(s) to see if it has same parent as tgtNode. + final DefaultMutableTreeNode srcNode; + final TreePath srcPath = targetTree.getSelectionPath(); + if (srcPath != null) { + srcNode = (DefaultMutableTreeNode)srcPath.getLastPathComponent(); +// logger.debug("tgt dragOver, selected node=" + srcNode); + if (srcNode.getParent() == tgtNode.getParent() && + srcNode != tgtNode) + { +// logger.debug("tgt dragOver: accept drag"); + canInsert = true; + drawInsertionPoint(); + dtde.acceptDrag(DnDConstants.ACTION_MOVE); + return; + } + } +// logger.debug("tgt dragOver: reject drag"); + canInsert = false; + dtde.rejectDrag(); + } + + public void dropActionChanged(DropTargetDragEvent dtde) { +// logger.debug("tgt:dropActionChanged, action=" + dtde.getDropAction()); + } + + public void drop(DropTargetDropEvent dtde) { + clearInsertionPoint(); + canInsert = false; + // figure out where the drop occurred. + Point pt = dtde.getLocation(); + TreePath path = targetTree.getClosestPathForLocation(pt.x, pt.y); + Transferable t = dtde.getTransferable(); + DataFlavor[] flavors = t.getTransferDataFlavors(); + for (DataFlavor flavor : flavors) { + if (t.isDataFlavorSupported(flavor)) { + DefaultMutableTreeNode dstNode = (DefaultMutableTreeNode)path.getLastPathComponent(); + Transferable tx = dtde.getTransferable(); + TreePath[] tr = null; + try { + Object o = tx.getTransferData(TransferableTreeNode.treePathFlavor); + tr = (TreePath[])o; + } + catch (UnsupportedFlavorException e) { + e.printStackTrace(); + dtde.rejectDrop(); + return; + } + catch (IOException e) { + e.printStackTrace(); + dtde.rejectDrop(); + return; + } + if (tr == null) { + dtde.rejectDrop(); + return; + } + final DefaultMutableTreeNode srcNode = (DefaultMutableTreeNode)tr[0].getLastPathComponent(); + int srcIndex = targetTree.haveCommonAncestors(srcNode, dstNode); + if (srcIndex < 0) { + LOG.debug( + "reject drop onto " + + dstNode + + "; parent of " + + srcNode + " is different" + ); + dtde.rejectDrop(); + return; + } + else { + DefaultMutableTreeNode parent = (DefaultMutableTreeNode)dstNode.getParent(); + DefaultMutableTreeNode srcInCurrentTree = (DefaultMutableTreeNode)parent.getChildAt(srcIndex); + int dstRow = parent.getIndex(dstNode); + boolean before = true; + if (srcIndex < dstRow) { + LOG.debug( + "drop: move " + + srcIndex + + ":" + + srcInCurrentTree + + " after " + dstRow + ":" + dstNode + ); + before = false; + } + else if (srcIndex == dstRow) { + LOG.debug("reject drop: item onto itself"); + dtde.rejectDrop(); + return; + } + else { + LOG.debug( + "drop: move " + + srcIndex + + ":" + + srcInCurrentTree + + " before " + dstRow + ":" + dstNode + ); + } + targetTree.moveSelection(dstRow, before); + lrp.setRearrangementOccurred(true); + dtde.acceptDrop(dtde.getDropAction()); + dtde.dropComplete(true); + return; + } + } + } + dtde.rejectDrop(); + } + + public void dragExit(DropTargetEvent dte) { + LOG.debug("tgt dragExit"); + clearInsertionPoint(); + canInsert = false; + } + + public void clearInsertionPoint() { + if (rectangleDrawn) { + // Erase the old insertion point by drawing over it. + drawInsertionPoint(); + } + } + + /** + * Draw or erase the current insertion point indicator. This draws in XOR + * mode, so drawing the indicator once will display it and drawing it again + * in the same location will erase it. + */ + public void drawInsertionPoint() { + if (canInsert) { + Graphics g = this.targetTree.getGraphics(); + g.setXORMode(xorBackgroundColor); + g.drawRect( + this.lastRowRect.x, this.lastRowRect.y, + this.lastRowRect.width, this.lastRowRect.height + ); + rectangleDrawn = !rectangleDrawn; + } + } + + public void computeInsertionPoint() { + computeInsertionPoint(lastRow); + } + + /** + * Given a particular point over the associated tree component, determine + * the corresponding insertion point in the tree for dropped data. The tree + * path that the insertion will be relative to can be found using the + * JTree method getClosestPathForLocation. The + * insertion itself will either be before, after, or in the node at the end + * of the path. This method also calculates the rectangle which can be used + * to draw the appropriate indicator for the insertion point. + * + * @param row the row number of the tree corresponding to the drop target. + */ + public void computeInsertionPoint(int row) { + JTree tree = targetTree; + + Rectangle rowBounds = tree.getRowBounds(row); + if (row < srcRow) { + // Insertion point is immediately before the node. + this.lastRowRect.setBounds(rowBounds.x, rowBounds.y, rowBounds.width, 0); + } + else if (row > srcRow) { + // Insertion point is immediately after the node. + this.lastRowRect.setBounds( + rowBounds.x, rowBounds.y + rowBounds.height - 1, + rowBounds.width, 0 + ); + } + else { + // Insertion point is on the node - dropped data will be appended to the + // nodes child list. Draw nothing in this case. + this.lastRowRect.setBounds(rowBounds.x, rowBounds.y, 0, 0); + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java new file mode 100644 index 000000000000..20e750b47ec9 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.rearrangement; + +import com.intellij.openapi.editor.Document; +import com.intellij.psi.PsiFile; +import com.wrq.rearranger.ruleinstance.IRuleInstance; + +import java.util.List; + +/** Emits a new document from the rearranged entries. */ +public final class Emitter { + private final PsiFile psiFile; + private final List resultRuleInstances; + private final Document document; + private StringBuffer stringBuffer; + + public Emitter(final PsiFile psiFile, final List resultRuleInstances, final Document document) { + this.psiFile = psiFile; + this.resultRuleInstances = resultRuleInstances; + this.document = document; + stringBuffer = new StringBuffer(psiFile.getText().length() + 100); // room for inserted blank lines + } + + public Document getDocument() { + return document; + } + + public StringBuffer getStringBuffer() { + return stringBuffer; + } + + public void emitRearrangedDocument() { + emitRuleInstances(resultRuleInstances); + document.replaceString( + psiFile.getTextRange().getStartOffset(), + psiFile.getTextRange().getEndOffset(), + stringBuffer.toString() + ); + } + + public void emitRuleInstances(List resultRuleInstances) { + if (resultRuleInstances == null) { + return; + } + for (IRuleInstance ruleInstance : resultRuleInstances) { + ruleInstance.emit(this); + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java new file mode 100644 index 000000000000..4289bba83c51 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.rearrangement; + +import com.intellij.openapi.diagnostic.Logger; +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.entry.ClassEntry; +import com.wrq.rearranger.entry.IRelatableEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.ruleinstance.CommentRuleInstance; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +/** Template for generic rearrangement of items in a class or in a Java file. */ +public abstract class GenericRearranger { + private static final Logger LOG = Logger.getInstance("#" + GenericRearranger.class.getName()); + private final List rules; + private final List entries; + private final List resultRuleInstances; + private final int nestingLevel; + private final RearrangerSettings settings; + + @SuppressWarnings({"AssignmentToCollectionOrArrayFieldFromParameter"}) + protected GenericRearranger(final List rules, + final List outerClasses, + final int nestingLevel, + final RearrangerSettings settings) + { + this.rules = rules; + entries = outerClasses; + this.nestingLevel = nestingLevel; + this.settings = settings; + resultRuleInstances = new ArrayList(rules.size() + 4); + } + + /** + * Rearranges the RangeEntry objects contained in entries according to rules specified by the user. + * Inserts comments as directed. + * + * @return rearranged list of RangeEntry and CommentRuleInstance objects. + */ + public final List rearrangeEntries() { + final List prioritizedRuleInstances = new ArrayList(); + buildRuleInstanceLists(prioritizedRuleInstances); + /** + * recursively reorder contents of every nested ClassEntry. + */ + for (ClassContentsEntry entry : entries) { + if (entry instanceof ClassEntry) { + ((ClassEntry)entry).rearrangeContents(); + } + } + matchPrioritizedRules(prioritizedRuleInstances); + + /** + * Move related methods together. Extracted methods and setters (emitted with getters) + * were not moved by the rearrangement code ("MatchPrioritizedRules()") just above. + */ + rearrangeRelatedItems(entries, resultRuleInstances); + /** + * Now go back and determine which comments are going to be emitted, based on their criteria and the + * state of the immediately surrounding rules. Ignore inner classes if no rearrangement of inner + * classes is taking place. + */ + if (nestingLevel <= 1 || settings.isRearrangeInnerClasses()) { + determineEmittedComments(); + } + return resultRuleInstances; + } + + /** For each comment rule instance, test its "emit" condition and set its emit flag appropriately. */ + private void determineEmittedComments() { + for (int i = 0; i < resultRuleInstances.size(); i++) { + if (resultRuleInstances.get(i) instanceof CommentRuleInstance) { + final CommentRuleInstance ce = (CommentRuleInstance)resultRuleInstances.get(i); + ce.determineEmit(resultRuleInstances, i); + if (ce.isEmit()) { + // set the "separator comment preceding" flag on the next matching RangeEntry. + for (int j = i + 1; j < resultRuleInstances.size(); j++) { + IRuleInstance instance = resultRuleInstances.get(j); + if (instance.hasMatches()) { + RangeEntry entry = (instance.getMatches().get(0)); + entry.setSeparatorCommentPrecedes(true); + break; + } + } + } + } + } + } + + /** + * For each rule (in prioritized order), test all remaining entries to identify those that match. + * Exclude any extracted (i.e. related) methods and any setter methods that will be emitted with + * a corresponding getter. If an entry matches the rule, add it to the list of entries matching the + * rule and remove it from the list of remaining entries. + * + * @param prioritizedRules prioritized list of rules + */ + @SuppressWarnings({"StringContatenationInLoop"}) + private void matchPrioritizedRules(List prioritizedRules) { + for (IRuleInstance ruleInstance : prioritizedRules) { + final IRule rule = ruleInstance.getRule(); + final ListIterator entryIterator = entries.listIterator(); + while (entryIterator.hasNext()) { + final RangeEntry entry = (RangeEntry)entryIterator.next(); + if (entry instanceof IRelatableEntry) { + // if this is an extracted (i.e. related) method, or + // if this is a setter that will be emitted under the corresponding getter, + // don't test it for match against the rule. + final IRelatableEntry relatableEntry = ((IRelatableEntry)entry); + if (relatableEntry.isRelatedMethod() || relatableEntry.isEmittableSetter()) { + continue; + } + } + if (rule.isMatch(entry)) { + LOG.debug("rule:" + rule.toString() + "; entry matched:" + entry.getEnd().toString()); + ruleInstance.addEntry(entry); + entry.setMatchedRule(ruleInstance); + entryIterator.remove(); + } + } + } + } + + /** + * Build two rule instance lists, one in order of emission ("resultRuleInstances") and one + * in order of matching ("prioritizedRuleInstances"). + * + * @param prioritizedRuleInstances + */ + private void buildRuleInstanceLists(final List prioritizedRuleInstances) { + /** + * add a HeaderTrailerRuleInstance to pick up any headers that might exist. + */ + IRuleInstance hri = new HeaderRule().createRuleInstance(); + resultRuleInstances.add(hri); + prioritizedRuleInstances.add(hri); + for (IRule rule : rules) { + IRuleInstance instance = rule.createRuleInstance(); + resultRuleInstances.add(instance); + /** + * now insert the rule instance into the prioritized list; highest priority first; stable insertion. + */ + boolean inserted = false; + for (int i = prioritizedRuleInstances.size() - 1; i >= 0; i--) { + IRuleInstance entry = (prioritizedRuleInstances.get(i)); + if (rule.getPriority() <= entry.getRule().getPriority()) { + prioritizedRuleInstances.add(i + 1, instance); + inserted = true; + break; + } + } + if (!inserted) { + prioritizedRuleInstances.add(0, instance); + } + } + // now add a default rule to pick up all unmatched items. + IRuleInstance defaultRuleInstance = new DefaultRule().createRuleInstance(); + resultRuleInstances.add(defaultRuleInstance); + prioritizedRuleInstances.add(defaultRuleInstance); + // finally, add a TrailerRuleInstance to pick up any leftover text. + IRuleInstance tri = new TrailerRule().createRuleInstance(); + resultRuleInstances.add(tri); + prioritizedRuleInstances.add(tri); + } + + /** + * Move any related items (e.g., extracted methods) remaining in 'entries' into the correct position in + * rearrangedEntries. + * + * @param entries + * @param rearrangedEntries + */ + public abstract void rearrangeRelatedItems(List entries, + List rearrangedEntries); +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java new file mode 100644 index 000000000000..745099c43398 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.rearrangement; + +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; + +import java.util.ArrayList; +import java.util.List; + +/** Moves (rearranges) classes and class members according to rules specified by the user. */ +public final class Mover { + private final List outerClasses; + private final RearrangerSettings settings; + + public Mover(final List outerClasses, + final RearrangerSettings settings) + { + this.outerClasses = new ArrayList(outerClasses); + this.settings = settings; + } + + public List rearrangeOuterClasses() { + final GenericRearranger outerClassRearranger = new GenericRearranger( + settings.getClassOrderAttributeList(), + outerClasses, + 0, + settings) + { + /** + * There are no items related to outer classes -- outer classes are completely disjoint + * and independent. Hence this routine does nothing. + * @param entries + + + @param rearrangedEntries + */ + public void rearrangeRelatedItems(List entries, + List rearrangedEntries) + { + } + }; + + return outerClassRearranger.rearrangeEntries(); + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java new file mode 100644 index 000000000000..53033b2d264f --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.rearrangement; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.entry.ClassEntry; +import com.wrq.rearranger.entry.PsiFileEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.settings.RearrangerSettings; + +import java.util.List; + +/** Creates a list of entries for classes and class members by parsing the Java file. */ +public final class Parser { + private static final Logger LOG = Logger.getInstance("#" + Parser.class.getName()); + private final Project project; + private final RearrangerSettings settings; + private final PsiFile psiFile; + + public Parser(final Project project, + final RearrangerSettings settings, + final PsiFile psiFile) + { + this.project = project; + this.settings = settings; + this.psiFile = psiFile; + } + + public List parseOuterLevel() { + /** + * Parse the top level contents of the PsiFile here. + */ + PsiFileEntry fileEntry = new PsiFileEntry(settings); + return fileEntry.parseFile(project, psiFile, settings.getClassOrderAttributeList()); + } + + private void dumpOuterClasses(final List outerClasses) { + LOG.debug("Outer class entries:"); + for (ClassEntry classEntry : outerClasses) { + LOG.debug(classEntry.toString()); + if (classEntry.getContents() == null) { + // this is a header or trailer, and isn't really a class. + continue; + } + LOG.debug(" === class contents:"); + for (RangeEntry rangeEntry : classEntry.getContents()) { + LOG.debug(rangeEntry.toString()); + } + LOG.debug(" === end class contents:"); + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java new file mode 100644 index 000000000000..b8d5c0f11872 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java @@ -0,0 +1,685 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.rearrangement; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.wrq.rearranger.settings.ForceBlankLineSetting; +import com.wrq.rearranger.settings.RearrangerSettings; + +import javax.swing.*; +import java.util.HashMap; +import java.util.Map; + +/** Responsible for adjusting the number of blank lines at strategic places in the source file. */ +public class Spacer { + private static final Logger LOG = Logger.getInstance("#" + Spacer.class.getName()); + private final Project project; + private final PsiFile psiFile; + private final Document document; + private final PsiElementFactory factory; + private final RearrangerSettings settings; + private final char[] newlineChars; + private boolean changesMade; + private StringBuffer sb; + private Map virtualElements = new HashMap(); + + public Spacer(Project project, PsiFile psiFile, Document document, RearrangerSettings settings) { + this.project = project; + this.psiFile = psiFile; + this.document = document; + this.settings = settings; + changesMade = false; + factory = JavaPsiFacade.getInstance(project).getElementFactory(); + int size = 0; + size += settings.getAfterClassLBrace().getnBlankLines() + 1; + size += settings.getBeforeMethodLBrace().getnBlankLines() + 1; + size += settings.getAfterMethodLBrace().getnBlankLines() + 1; + size += settings.getBeforeMethodRBrace().getnBlankLines() + 1; + size += settings.getAfterMethodRBrace().getnBlankLines() + 1; + size += settings.getBeforeClassRBrace().getnBlankLines() + 1; + size += settings.getAfterClassRBrace().getnBlankLines() + 1; + LOG.debug("constructor allocating " + size + " newline chars for max insertion"); + newlineChars = new char[size]; + while (size > 0) { + newlineChars[--size] = '\n'; + } + LOG.debug(settings.getAfterClassLBrace().toString()); + LOG.debug(settings.getBeforeMethodLBrace().toString()); + LOG.debug(settings.getAfterMethodLBrace().toString()); + LOG.debug(settings.getBeforeMethodRBrace().toString()); + LOG.debug(settings.getAfterMethodRBrace().toString()); + LOG.debug(settings.getBeforeClassRBrace().toString()); + LOG.debug(settings.getAfterClassRBrace().toString()); + final int ROOM_FOR_EXPANSION = 100; + int maxSize = document.getTextLength() + ROOM_FOR_EXPANSION; + sb = new StringBuffer(maxSize); + } + + private class AbortRespacing extends RuntimeException { + } + + private class BadPsiElement extends Exception { + BadPsiElement(String string) { + super(string); + } + } + + private void handleBadPsiElementException(BadPsiElement bpe, String desc, PsiElement element) + throws AbortRespacing + { + JOptionPane.showMessageDialog(null, + "Spacing could not be performed due to a syntax error:\n" + + desc + element.getText(), "Spacing Error", JOptionPane.ERROR_MESSAGE); + throw new AbortRespacing(); + } + + public boolean respace() { + sb.append(document.getText()); + + JavaElementVisitor visitor = new JavaRecursiveElementVisitor() { + private int bias = 0; + + public void visitReferenceExpression(PsiReferenceExpression referenceExpression) { + } + + public void visitFile(PsiFile psiFile) { + super.visitFile(psiFile); + if (settings.getNewlinesAtEOF().isForce()) { + // remove all newlines at end of file, then append as many as are declared in configuration. + while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '\n') { + sb.setLength(sb.length() - 1); + } + for (int count = 0; count < settings.getNewlinesAtEOF().getnBlankLines(); count++) { + sb.append('\n'); + } + } + } + + public void visitAnonymousClass(PsiAnonymousClass psiAnonymousClass) { + super.visitAnonymousClass(psiAnonymousClass); + } + + public void visitClass(PsiClass psiClass) { + if (psiClass instanceof PsiTypeParameter) { + return; + } + boolean anonymous = psiClass.getName() == null; + int oldbias = bias; + try { + bias += adjustSpacing( + psiClass.getLBrace(), + psiClass.getRBrace(), + settings.getAfterClassLBrace(), + bias + ); + } + catch (BadPsiElement badPsiElement) { + handleBadPsiElementException(badPsiElement, + "class " + psiClass.getName() + " missing left brace. Body follows:", + psiClass); + } + log(settings.getAfterClassLBrace(), psiClass.getName(), oldbias, bias); + super.visitClass(psiClass); + oldbias = bias; + try { + bias += adjustSpacing( + psiClass.getRBrace(), + psiClass.getLBrace(), + settings.getBeforeClassRBrace(), + bias + ); + } + catch (BadPsiElement badPsiElement) { + handleBadPsiElementException(badPsiElement, + "class " + psiClass.getName() + " missing right brace. Body follows:", + psiClass); + } + log(settings.getBeforeClassRBrace(), psiClass.getName(), oldbias, bias); + + if (anonymous) { + return; + } + + /** + * if this is the last class in a file, don't adjust spacing after right brace. + * The setting for number of newline characters at end of file overrides it. + */ + boolean lastClass = false; + if (psiClass.getParent() instanceof PsiJavaFile) { + lastClass = isLastMeaningfulElement(psiClass.getParent(), psiClass); + } + if (!lastClass) { + oldbias = bias; + try { + bias += adjustSpacing( + psiClass.getRBrace(), + psiClass.getLBrace(), + settings.getAfterClassRBrace(), + bias + ); + } + catch (BadPsiElement badPsiElement) { + handleBadPsiElementException(badPsiElement, + "class " + psiClass.getName() + " missing left brace. Body follows:", + psiClass); + } + log(settings.getAfterClassRBrace(), psiClass.getName(), oldbias, bias); + } + else { + LOG.debug( + "class " + + psiClass.getName() + + " is last in file, no 'after right brace' adjustment" + ); + } + } + + public void visitMethod(PsiMethod psiMethod) { + int oldbias; + /** + * if method has no body, make no spacing adjustments - there are no braces. It must be an interface + * or abstract method declaration. + */ + if (psiMethod.getBody() == null) { + LOG.debug("skipping interface or abstract method " + psiMethod.getName()); + super.visitMethod(psiMethod); + return; + } + /** + * if method has an empty body, do only the spacing before the opening brace and after the closing + * brace. + */ + boolean methodIsEmpty = true; + { + PsiElement element = psiMethod.getBody().getLBrace().getNextSibling(); + while (element != null) { + if (!(element instanceof PsiWhiteSpace) && + element != psiMethod.getBody().getRBrace()) + { + methodIsEmpty = false; + break; + } + element = element.getNextSibling(); + } + } + if (!methodIsEmpty) { + oldbias = bias; + try { + bias += adjustSpacing( + psiMethod.getBody().getLBrace(), + psiMethod.getBody().getRBrace(), + settings.getBeforeMethodLBrace(), + bias + ); + bias += adjustSpacing( + psiMethod.getBody().getLBrace(), + psiMethod.getBody().getRBrace(), + settings.getAfterMethodLBrace(), + bias + ); + } + catch (BadPsiElement badPsiElement) { + handleBadPsiElementException(badPsiElement, + "body of method " + psiMethod.getName() + " missing left brace. Body follows:", + psiMethod); + } + log(settings.getAfterMethodLBrace(), psiMethod.getName(), oldbias, bias); + super.visitMethod(psiMethod); + oldbias = bias; + try { + bias += adjustSpacing( + psiMethod.getBody().getRBrace(), + psiMethod.getBody().getLBrace(), + settings.getBeforeMethodRBrace(), + bias + ); + } + catch (BadPsiElement badPsiElement) { + handleBadPsiElementException(badPsiElement, + "body of method " + psiMethod.getName() + " missing right brace. Body follows:", + psiMethod); + } + log(settings.getBeforeMethodRBrace(), psiMethod.getName(), oldbias, bias); + } + else { + LOG.debug("method " + psiMethod.getName() + " is empty, no internal spacing changes"); + } + /** + * if this is the last method in a class, don't adjust spacing after right brace. + * The class setting for number of spaces before closing right brace overrides it. + * Normally this would make no difference, as the 2nd would cancel out the first; + * but in the case where the method ends with "}});" (anonymous inner class as + * parameter), an inserted blank line actually causes two newline characters to be + * inserted; but the class rule only removes one of those. + */ + boolean lastMethod = false; + PsiClass owner = psiMethod.getContainingClass(); + if (owner == psiMethod.getParent()) { + lastMethod = isLastMeaningfulElement(owner, psiMethod); + } + if (!lastMethod) { + oldbias = bias; + try { + bias += adjustSpacing( + psiMethod.getBody().getRBrace(), + psiMethod.getBody().getLBrace(), + settings.getAfterMethodRBrace(), + bias + ); + } + catch (BadPsiElement badPsiElement) { + handleBadPsiElementException(badPsiElement, + "body of method " + psiMethod.getName() + " missing right brace. Body follows:", + psiMethod); + } + log(settings.getAfterMethodRBrace(), psiMethod.getName(), oldbias, bias); + } + else { + LOG.debug( + "method " + + psiMethod.getName() + + " is last in class, no 'after right brace' adjustment" + ); + } + } + + public void visitCodeBlock(PsiCodeBlock psiCodeBlock) { + int oldbias; + if (!(psiCodeBlock.getParent() instanceof PsiMethod) && + settings.isRemoveBlanksInsideCodeBlocks()) + { + oldbias = bias; + try { + bias += adjustSpacing(psiCodeBlock.getLBrace(), + psiCodeBlock.getRBrace(), false, 0, bias); + } + catch (BadPsiElement badPsiElement) { + handleBadPsiElementException(badPsiElement, + "code block missing left brace. Content follows:\n", psiCodeBlock); + } + log("code block left brace", oldbias, bias); + } + super.visitCodeBlock(psiCodeBlock); + if (!(psiCodeBlock.getParent() instanceof PsiMethod) && + settings.isRemoveBlanksInsideCodeBlocks()) + { + oldbias = bias; + try { + bias += adjustSpacing(psiCodeBlock.getRBrace(), psiCodeBlock.getLBrace(), true, 0, bias); + } + catch (BadPsiElement badPsiElement) { + handleBadPsiElementException(badPsiElement, + "code block missing right brace. Content follows:\n", psiCodeBlock); + } + log("code block right brace", oldbias, bias); + } + } + }; + try { + psiFile.accept(visitor); + } + catch (AbortRespacing ar) { + return false; + } + if (changesMade) { + LOG.debug( + "changes made to document; old length=" + + document.getTextLength() + ", new=" + sb.length() + ); + LOG.debug("old document is:\n" + document.getText()); + LOG.debug("new document is:\n" + sb.toString()); + document.replaceString(0, document.getTextLength(), sb.toString()); + } + return changesMade; + } + + /** + * Determines if the psiElement (method or class) is last syntactic item in the owner class. + * If so, we don't want to change spacing after right brace of psiElement; this spacing is + * overridden by the parent class's spacing before right brace. + * + * @param owner class element to which psiElement belongs. + * @param psiElement method or inner class to be tested. + * @return true if the psiElement is the last syntactic item (i.e., not including comments and whitespace) + * of the owner. + */ + private boolean isLastMeaningfulElement(PsiElement owner, PsiElement psiElement) { + boolean lastMethod; + // class is immediate parent + PsiElement[] elements = owner.getChildren(); + boolean sawThisMethod = false; + boolean sawSomethingElseLater = false; + for (PsiElement element : elements) { + if (!sawThisMethod && element == psiElement) { + sawThisMethod = true; + } + else if (sawThisMethod && + !(element instanceof PsiWhiteSpace) && + !(element instanceof PsiJavaToken && + element.getText().equals("}"))) +// ((PsiJavaToken) elements[i]).getTokenType() == PsiJavaToken.RBRACE)) + { + sawSomethingElseLater = true; + break; + } + } + lastMethod = sawThisMethod && !sawSomethingElseLater; + return lastMethod; + } + + private void log(ForceBlankLineSetting fbls, String name, int oldbias, int bias) { + if (oldbias != bias) { + LOG.debug( + fbls.getObjectName() + + " " + + name + + (fbls.isBefore() ? " before" : " after") + + (fbls.isOpenBrace() ? " left brace:" : " right brace:") + + (oldbias < bias ? " inserted " + (bias - oldbias) + : " removed " + (oldbias - bias)) + " newlines" + ); + } + } + + private void log(String name, int oldbias, int bias) { + if (oldbias != bias) { + LOG.debug( + name + + (oldbias < bias ? " inserted " + (bias - oldbias) + : " removed " + (oldbias - bias)) + " newlines" + ); + } + } + + private int adjustSpacing(PsiElement brace, PsiElement matchingBrace, ForceBlankLineSetting fbls, int bias) + throws BadPsiElement + { + if (fbls.isForce()) { + return adjustSpacing(brace, matchingBrace, fbls.isBefore(), fbls.getnBlankLines(), bias); + } + else { + return 0; + } + } + + /** + * When whiteSpace is changed based on contents of a PsiWhiteSpace element, we need to keep track of that + * so that if a subsequent adjustment in spacing is based on that same element, we use the new whitespace value. + */ + private class VirtualElement { + private String textValue; + private final int textOffset; + + VirtualElement(PsiWhiteSpace whiteSpace, int bias) { + textValue = whiteSpace.getText(); + textOffset = whiteSpace.getTextOffset() + bias; + virtualElements.put(whiteSpace, this); + } + + String getText() { + return textValue; + } + + public void setTextValue(String textValue) { + this.textValue = textValue; + } + + public int getTextOffset() { + return textOffset; + } + } + + /** + * Determine the number of blank lines actually occurring before or after the brace. If this is not + * the desired number, alter the whitespace before or after the brace to contain the desired number + * of blank lines. + * + * @param brace + * @param before + * @param nBlankLines + * @param bias + * @return bias adjustment corresponding to number of newlines inserted or deleted + */ + private int adjustSpacing(PsiElement brace, PsiElement matchingBrace, boolean before, int nBlankLines, int bias) + throws BadPsiElement + { + int result = 0; + if (brace == null) { + throw new BadPsiElement( + "adjustSpacing: illegal syntax (mismatched braces); PsiElement for brace is null" + ); + } + /* + * ensure that character at offset indicated by brace element is in fact a brace. + */ + int offset = brace.getTextRange().getStartOffset() + bias; + int direction = before ? -1 : +1; + int count = 0; + { + char braceChar = sb.charAt(offset); + if (braceChar != '{' && braceChar != '}') { + int L = offset - 50; + int R = offset + 50; + if (L < 0) { + L = 0; + } + if (R > sb.length()) { + R = sb.length(); + } + String context = sb.toString().substring(L, R); + throw new RuntimeException( + "adjustSpacing: char at offset " + + offset + + " is not a brace, ='" + + braceChar + "'" + "; context is " + context + ); + } + } + /* + * Locate the whitespace that precedes or follows this brace and which contains newline characters. + * Intervening text, such as comments and other syntactic items, could be skipped. + */ + PsiElement whiteSpace = brace; + do { + whiteSpace = getNextElement(whiteSpace, before); + if (whiteSpace == matchingBrace) { + /** + * Don't parse past the matching brace. This could occur if a class or method body is empty and + * the left and right braces are on the same line with no intervening whitespace. + */ + return result; + } + } + while (whiteSpace != null && + (!(whiteSpace instanceof PsiWhiteSpace) || + whiteSpace.getText().indexOf('\n') < 0)); + + VirtualElement virtualWhiteSpace = null; + if (whiteSpace != null) { + virtualWhiteSpace = (virtualElements.get(whiteSpace)); + if (virtualWhiteSpace == null) { + virtualWhiteSpace = new VirtualElement((PsiWhiteSpace)whiteSpace, bias); + } + else { + LOG.debug("reusing virtualWhiteSpace, offset=" + virtualWhiteSpace.textOffset); + } + /* + * now count the number of newlines. + */ + String s = virtualWhiteSpace.getText(); + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '\n') { + count++; + } + } + } + + /** + * first count the number of existing blank lines. + */ + if (offset + direction >= sb.length()) { + LOG.debug("at EOF, don't append any extra blank lines"); + // we're at end of file. Don't append any extra blank lines. + nBlankLines = 0; + } + /** + * Count of one means there was a single newline character next to the brace. + * This can be counted as the one that belongs on the brace's line. So the real number + * of consecutive newline characters desired is nBlankLines + 1. + */ + int desiredNewlineChars = nBlankLines + 1; + if (desiredNewlineChars == 1 && count == 0 && before) { + // no blank lines to precede this text; in fact, there's prior text and no newline character at all. + // this is acceptable. + desiredNewlineChars = 0; + } + { + PsiElement element = brace.getParent(); + if (element instanceof PsiCodeBlock && + element.getParent() instanceof PsiMethod) + { + element = element.getParent(); + } + LOG.debug( + "adjustSpacing: " + + (before ? "before " : "after ") + + element.toString() + + " " + + brace.getText() + + ", desire " + desiredNewlineChars + " newlines, have " + count + ); + } + if (desiredNewlineChars == count) { + return 0; + } + /* + * determine end index of whitespace to be replaced. + * keep trailing spaces/tabs. + */ + int endIndex; +// if (whiteSpace != null) // todo - try modifying the PSI tree +// { +// try +// { +// StringBuilder sbr = new StringBuilder(whiteSpace.getText()); +// if (desiredNewlineChars > count) sbr.append(newlineChars, 0, desiredNewlineChars - count); +// else sbr.setLength(sbr.length() + desiredNewlineChars - count); +// PsiElement codeblk = factory.createCodeBlockFromText(sbr.toString(), element); +// whiteSpace.replace(codeblk.getFirstChild()); +// } +// catch (IncorrectOperationException e) +// { +// e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. +// } +// } + if (virtualWhiteSpace != null) { + String s = virtualWhiteSpace.getText(); + for (endIndex = s.length() - 1; endIndex >= 0; endIndex--) { + if (s.charAt(endIndex) != ' ' && + s.charAt(endIndex) != '\t') + { + break; + } + } // now endIndex points to the last newline character in the whitespace. + offset = virtualWhiteSpace.getTextOffset(); + endIndex += offset + 1; + } + else { + offset = endIndex = sb.length(); + } + try { + changesMade = true; + LOG.debug( + "sb.replace(" + + offset + + "," + + endIndex + ") with " + desiredNewlineChars + " newline characters" + ); + sb.replace(offset, endIndex, new String(newlineChars, 0, desiredNewlineChars)); + result = desiredNewlineChars - (endIndex - offset); + // now update virtualWhiteSpace accordingly. + if (virtualWhiteSpace != null) { + offset -= virtualWhiteSpace.getTextOffset(); + endIndex -= virtualWhiteSpace.getTextOffset(); + StringBuffer vsb = new StringBuffer(virtualWhiteSpace.getText()); + vsb.replace(offset, endIndex, new String(newlineChars, 0, desiredNewlineChars)); + virtualWhiteSpace.setTextValue(vsb.toString()); + } + } + catch (StringIndexOutOfBoundsException si) { + throw new RuntimeException( + "sb.length()=" + + sb.length() + + ", offset=" + + offset + + ", before=" + + before + + ", count=" + + count + + ", desiredNewlineChars=" + + desiredNewlineChars + + ", charAt offset=" + (offset < sb.length() ? "" + sb.charAt(offset) : "OOB"), si + ); + } + return result; + } + + /** + * Returns the leaf psiElement before or after the given element. + * + * @param element original element. + * @param before if true, return prior leaf element; else return next left element. + * @return adjacent leaf element. + */ + private PsiElement getNextElement(PsiElement element, boolean before) { + PsiElement result; + while (true) { + result = before ? element.getPrevSibling() : element.getNextSibling(); + if (result == null) { + // first/last sibling; go to parent's previous/next item. + result = element.getParent(); + if (result instanceof PsiFile) { + // don't go beyond this document! + result = null; + } + // if we started at the first/last leaf node, we run out of parents; there is no previous/next leaf element. + if (result == null) { + break; + } + else { + element = result; + } + } + else { + break; + } + } + while (result != null && result.getChildren().length != 0) { + // previous/next sibling is parent of others; find last/first leaf node. + result = result.getChildren()[before ? result.getChildren().length - 1 : 0]; + } + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java new file mode 100644 index 000000000000..2e30b45d3161 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.popup.IFilePopupEntry; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.IRule; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** Used to store a generated comment, and to determine if it should be emitted. */ +public abstract class CommentRuleInstance + implements IRuleInstance, + IFilePopupEntry +{ + protected final CommentRule commentRule; + protected boolean emit; + + public CommentRuleInstance(final CommentRule commentRule) { + this.commentRule = commentRule; + emit = false; + } + + public boolean isEmit() { + return emit; + } + + public void setEmit(final boolean emit) { + this.emit = emit; + } + + public IRule getRule() { + return commentRule; + } + + /** Determine if this comment, in this instance, should be emitted. */ + public abstract void determineEmit(List resultRuleInstances, int startIndex); + + public boolean hasMatches() { + return false; // a generated comment never matches any object + } + + public void emit(Emitter emitter) { + StringBuffer sb = emitter.getStringBuffer(); + if (emit) { + // emit a comment. Precede with a newline unless this is the first line of the file. + if (sb.length() > 0) { + sb.append('\n'); + sb.append(commentRule.getExpandedCommentText()); + } + else { + sb.append(commentRule.getExpandedCommentText()); + sb.append('\n'); + } + } + } + + public void addEntry(RangeEntry entry) // adds entry to list of matching entries, in correct order + { + // comment rules don't match anything in the existing file; they conditionally generate comments. + // So this method will never be called. + throw new RuntimeException("cannot add entry to comment rule instance"); + } + + public List getMatches() { + return new ArrayList(); + } + + public void rearrangeRuleItems(List entries, + RearrangerSettings settings) + { + } + + public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) { + /** + * if we are supposed to show comment rules, create a node for the rule and put its contents below. + * Otherwise, just add comments. + */ + if (!settings.isShowComments()) return; + DefaultMutableTreeNode top = node; + if (settings.isShowRules()) { + // if "show matched rules only" is set, only display if comment will be emitted + if ((!settings.isShowMatchedRules()) || isEmit()) { + top = new DefaultMutableTreeNode(this); + node.add(top); + } + } + /** + * append the comment if generated and if showComments is set. + */ + if (isEmit()) { + commentRule.addToPopupTree(top, settings); + } + } + + public String getTypeIconName() { + return null; + } + + @Nullable + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + JLabel label = new JLabel(commentRule.toString()); + Font font = label.getFont().deriveFont(Font.ITALIC); + label.setFont(font); + return label; + } + + public String toString() { + return "instance of:" + commentRule.toString(); + } + + /** + * beginning at the index of ruleStatistics (which is a comment entry), find nRules in the direction indicated, + * and test to see if all or any of them had entries that matched. + * + * @param nRules number of rules to consider for matching algorithm. + * @param direction 1 = subsequent, -1 = previous. + * @param startIndex comment entry index, sandwiched between rules. + * @param ANDing if true, all rules must be matched; if false, any rule that matches returns a result of true. + * @return true if the match condition is met. + */ + @SuppressWarnings({"MethodParameterNamingConvention"}) + protected boolean match(final List resultRuleInstances, + final int nRules, + final int direction, + final int startIndex, + final boolean ANDing) + { + int index = startIndex + direction; + int nRulesSeen = 0; + while (index >= 0 && + index < resultRuleInstances.size() && + nRulesSeen < nRules) + { + if (!(resultRuleInstances.get(index) instanceof CommentRuleInstance)) { + // this is a rule entry, not a comment. + nRulesSeen++; + final IRuleInstance ruleInstance = resultRuleInstances.get(index); + if (ruleInstance.hasMatches()) { + if (!ANDing) { + return true; // OR condition (any matching rule) met + } + } + else { + if (ANDing) { + return false; // AND condition not met + } + } + } + index += direction; + } + return ANDing; + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstanceFactory.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstanceFactory.java new file mode 100644 index 000000000000..0c2f3a49cd01 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstanceFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.settings.CommentRule; + +/** Creates appropriate subtype of CommentRuleInstance from a CommentRule. */ +@SuppressWarnings({"UtilityClass"}) +public class CommentRuleInstanceFactory { + private CommentRuleInstanceFactory() { + } + + @SuppressWarnings({"MethodWithMultipleReturnPoints"}) + public static CommentRuleInstance buildCommentRuleInstance(CommentRule rule) { + switch (rule.getEmitCondition()) { + case CommentRule.EMIT_ALWAYS: + return new EmitAlwaysCommentRuleInstance(rule); + case CommentRule.EMIT_IF_ITEMS_MATCH_SURROUNDING_RULES: + return new SurroundingCommentRuleInstance(rule); + case CommentRule.EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE: + return new SubsequentCommentRuleInstance(rule); + case CommentRule.EMIT_IF_ITEMS_MATCH_PRECEDING_RULE: + return new PrecedingCommentRuleInstance(rule); + default: + throw new IllegalStateException("unknown emit condition type=" + rule.getEmitCondition()); + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java new file mode 100644 index 000000000000..4fa75c6bc511 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.intellij.openapi.diagnostic.Logger; +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.entry.IPopupTreeRangeEntry; +import com.wrq.rearranger.entry.MethodEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.popup.IFilePopupEntry; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.atomicAttributes.SortOptions; +import com.wrq.rearranger.settings.attributeGroups.CommonAttributes; +import com.wrq.rearranger.settings.attributeGroups.IRule; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** Handles basic Rule functions. */ +public abstract class CommonRuleInstance + implements IRuleInstance, + IFilePopupEntry +{ + private static final Logger LOG = Logger.getInstance("#" + CommonRuleInstance.class.getName()); + protected final IRule rule; + protected final List matchedItems; + + public CommonRuleInstance(IRule rule) { + this.rule = rule; + matchedItems = new ArrayList(); + } + + public IRule getRule() { + return rule; + } + + /** + * adds entry to list of matching entries, in correct order (order encountered, or alphabetically) + * + * @param entry + */ + public void addEntry(RangeEntry entry) { + if (rule instanceof CommonAttributes) { + SortOptions sortOptions = ((CommonAttributes)rule).getSortAttr(); + insertionSort(entry, sortOptions); + } + else { + matchedItems.add(entry); + } + } + + public List getMatches() { + return matchedItems; + } + + private void insertionSort(final RangeEntry newEntry, final SortOptions sortOptions) { + boolean inserted = false; + final String s = sortOptions.generateSortString(newEntry); + LOG.debug("insertionSort: new entry=" + s); + int index = 0; + while (index < matchedItems.size()) { + final RangeEntry re = matchedItems.get(index); + final String res = sortOptions.generateSortString(re); + LOG.debug("insertionSort: compare to " + res); + if (s.compareTo(res) < 0) { + LOG.debug("insertionSort: insert at " + index); + matchedItems.add(index, newEntry); + inserted = true; + break; + } + index++; + } + if (!inserted) { + LOG.debug("insertionSort: add " + s + " to end"); + matchedItems.add(newEntry); + } + } + + public boolean hasMatches() { + return matchedItems.size() > 0; + } + + public void emit(Emitter emitter) { + for (RangeEntry rangeEntry : matchedItems) { + rangeEntry.emit(emitter); + } + } + + public void rearrangeRuleItems(List entries, + RearrangerSettings settings) + { + MethodEntry.rearrangeRelatedItems( + entries, + this, + settings.getExtractedMethodsSettings() + ); + } + + public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) { + /** + * if we are supposed to show rules, create a node for the rule and put its contents below. + * Otherwise, delegate to each of the matches. + */ + DefaultMutableTreeNode top = node; + if (settings.isShowRules() && + (!settings.isShowMatchedRules() || hasMatches())) + { + top = new DefaultMutableTreeNode(this); + node.add(top); + } + /** + * append each of the matches to the top level. + */ + for (IPopupTreeRangeEntry entry : getMatches()) { + entry.addToPopupTree(top, settings); + } + } + + public String getTypeIconName() { + return "general/templateGroup"; + } + + public String[] getAdditionalIconNames() { + return null; + } + + public JLabel getPopupEntryText(RearrangerSettings settings) { + JLabel label = new JLabel(toString()); + Font font = label.getFont().deriveFont(Font.ITALIC); + label.setFont(font); + return label; + } + + public String toString() { + return getRule().toString(); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/DefaultRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/DefaultRuleInstance.java new file mode 100644 index 000000000000..deda68b4c640 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/DefaultRuleInstance.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.settings.attributeGroups.IRule; + +/** Collects any remaining RangeEntries after all explicit rule matching is done. */ +public class DefaultRuleInstance extends CommonRuleInstance { + public DefaultRuleInstance(IRule defaultRule) { + super(defaultRule); + } + + public String toString() { + return getRule().toString(); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/EmitAlwaysCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/EmitAlwaysCommentRuleInstance.java new file mode 100644 index 000000000000..77f53e911e07 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/EmitAlwaysCommentRuleInstance.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.settings.CommentRule; + +import java.util.List; + +/** Used to store a generated comment which is always emitted. */ +public class EmitAlwaysCommentRuleInstance + extends CommentRuleInstance +{ + public EmitAlwaysCommentRuleInstance(final CommentRule commentRule) { + super(commentRule); + } + + /** + * Determine if this comment, in this instance, should be emitted. + * For an "Emit Always" type of comment, it should always be emitted. + */ + public void determineEmit(List resultRuleInstances, int startIndex) { + setEmit(true); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java new file mode 100644 index 000000000000..098215166840 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.IRule; + +import javax.swing.tree.DefaultMutableTreeNode; +import java.util.ArrayList; +import java.util.List; + +/** Instance to pick up header text. */ +public class HeaderTrailerRuleInstance + implements IRuleInstance +{ + private final IRule rule; + private RangeEntry entry; + + public HeaderTrailerRuleInstance(IRule rule) { + this.rule = rule; + } + + public boolean hasMatches() { + return false; // comments are never emitted based on whether header text is emitted, so false is fine. + } + + public List getMatches() { + List list = null; + if (entry != null) { + list = new ArrayList(); + list.add(entry); + } + return list; + } + + public IRule getRule() { + return rule; + } + + public void addEntry(RangeEntry entry) { + this.entry = entry; // a header only has one entry + } + + public void emit(Emitter emitter) { + if (entry != null) { + entry.emit(emitter); + } + } + + public void rearrangeRuleItems(List entries, + RearrangerSettings settings) + { + return; + } + + public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) { + return; // don't show header/trailer junk in popup tree + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/IRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/IRuleInstance.java new file mode 100644 index 000000000000..fd681e3cb13f --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/IRuleInstance.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.IRule; + +import javax.swing.tree.DefaultMutableTreeNode; +import java.util.List; + +/** + * One RuleInstance exists for every execution of every rule. An execution of a rule is the process by which + * items are matched to a rule. + */ +public interface IRuleInstance { + /** @return true if one or more items matched the rule in this instance. */ + boolean hasMatches(); + + /** @return list of items matching the rule in this instance. */ + List getMatches(); + + /** + * Causes the text representation of this item to be emitted to a buffer, and from there into the final Document. + * + * @param emitter Emitter target object with buffer and Document. + */ + void emit(Emitter emitter); + + /** @return the rule associated with this instance. */ + IRule getRule(); + + /** + * Adds an item to the list of items matching the rule in this instance. Order is preserved. + * + * @param entry matching item + */ + void addEntry(RangeEntry entry); + + /** + * Perform any rearranging based on rule or item relationships indicated by the settings. + * + * @param entries list of items (fields, methods, etc.) + * @param settings + */ + void rearrangeRuleItems(List entries, RearrangerSettings settings); + + /** add the contents of this rule to the file structure popup tree. */ + void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java new file mode 100644 index 000000000000..c227c5829fcd --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.entry.MethodEntry; +import com.wrq.rearranger.popup.IFilePopupEntry; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.InterfaceAttributes; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** Corresponds to a single interface with one or more implementing methods. */ +public class InterfaceInstance + implements IFilePopupEntry +{ +// ------------------------------------------------------- FIELDS ------------------------------------------------------ + + private String interfaceName; + + public String getInterfaceName() { + return interfaceName; + } + + private List methods; + private InterfaceAttributes rule; + +// ---------------------------------------------------- CONSTRUCTORS --------------------------------------------------- + + public InterfaceInstance(String interfaceName, InterfaceAttributes rule) { + this.interfaceName = interfaceName; + methods = new ArrayList(); + this.rule = rule; + } + +// ---------------------------------------------- GETTER / SETTER METHODS ---------------------------------------------- + + public String[] getAdditionalIconNames() { + return null; + } + + public String getTypeIconName() { + return null; + } + +// ------------------------------------------------- INTERFACE METHODS ------------------------------------------------- + +// --------------------------------------------- Interface IFilePopupEntry --------------------------------------------- + + public JLabel getPopupEntryText(RearrangerSettings settings) { + JLabel label = new JLabel("methods of interface " + interfaceName); + Font font = label.getFont().deriveFont(Font.ITALIC); + label.setFont(font); + return label; + } + +// --------------------------------------------------- OTHER METHODS --------------------------------------------------- + + /** + * add the method to the list of methods, in the order specified by the configuration settings (alphabetical, + * in order declared in the interface, or in order encountered). + * + * @param entry method to add. + */ + void addMethod(MethodEntry entry) { + switch (rule.getMethodOrder()) { + case InterfaceAttributes.METHOD_ORDER_ALPHABETICAL: + entry.insertAlphabetically(methods); + break; + case InterfaceAttributes.METHOD_ORDER_ENCOUNTERED: + methods.add(entry); + break; + case InterfaceAttributes.METHOD_ORDER_INTERFACE_ORDER: + entry.insertInterfaceOrder(methods); + break; + } + } + + public void addToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) { + /** + * if we are supposed to show rules, create a node for the rule and put its contents below. + * Otherwise, delegate to each of the matches. + */ + DefaultMutableTreeNode top = node; + if (settings.isShowRules()) { + top = new DefaultMutableTreeNode(this); + node.add(top); + } + /** + * append each of the matches to the top level. + */ + for (MethodEntry entry : methods) { + entry.addToPopupTree(top, settings); + } + } + + void emit(Emitter emitter) { + StringBuffer sb = emitter.getStringBuffer(); + String commentString = expandComment(rule.getPrecedingComment()); + if (commentString.length() > 0) { + sb.append("\n"); + sb.append(commentString); + } + for (MethodEntry rangeEntry : methods) { + rangeEntry.emit(emitter); + } + commentString = expandComment(rule.getTrailingComment()); + if (commentString.length() > 0) { + sb.append("\n"); + sb.append(commentString); + } + } + + private String expandComment(CommentRule comment) { + if (comment == null || comment.getCommentText() == null) return ""; + comment.setCommentFillString(rule.getCommentFillString()); + String result = comment.getCommentText().replaceAll("%IF%", interfaceName); + result = rule.getCommentFillString().getExpandedCommentText(result); + return result; + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceRuleInstance.java new file mode 100644 index 000000000000..db5ee379cdd2 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceRuleInstance.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.entry.ClassContentsEntry; +import com.wrq.rearranger.entry.MethodEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.rearrangement.Emitter; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.IRule; +import com.wrq.rearranger.settings.attributeGroups.InterfaceAttributes; + +import javax.swing.tree.DefaultMutableTreeNode; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +/** Handles interface rule processing. */ +public class InterfaceRuleInstance + extends CommonRuleInstance +{ +// ------------------------------ FIELDS ------------------------------ + + List interfaceInstances; + +// --------------------------- CONSTRUCTORS --------------------------- + + public InterfaceRuleInstance(IRule rule) { + super(rule); + interfaceInstances = new ArrayList(); + } + +// -------------------------- OTHER METHODS -------------------------- + + /** + * override the supermethod because we never want to alphabetize methods based on the "alphabetize" flag; that + * flag controls whether interfaces are alphabetized or not. Just add the methods to the list in order encountered. + * + * @param entry + */ + public void addEntry(RangeEntry entry) { + matchedItems.add((MethodEntry)entry); + } + + public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) { + /** + * if we are supposed to show rules, create a node for the rule and put its contents below. + * Otherwise, delegate to each of the matches. + */ + DefaultMutableTreeNode top = node; + if (settings.isShowRules()) { + top = new DefaultMutableTreeNode(this); + node.add(top); + } + /** + * An InterfaceRuleInstance has a list of InterfaceInstances, which in turn list the methods which matched + * the name of the interface. Build the tree accordingly. + */ + for (InterfaceInstance instance : interfaceInstances) { + instance.addToPopupTree(top, settings); + } + } + + public void emit(Emitter emitter) { + for (Object interfaceInstance : interfaceInstances) { + InterfaceInstance instance = (InterfaceInstance)interfaceInstance; + instance.emit(emitter); + } + } + + public void rearrangeRuleItems(List entries, + RearrangerSettings settings) + { + /** + * create a list of interface instances, one for each interface specified by any of the matched methods. + * Alphabetize this list if specified. + */ + for (RangeEntry re : matchedItems) { + MethodEntry me = (MethodEntry)re; + InterfaceInstance instance = null; + for (InterfaceInstance interfaceInstance : interfaceInstances) { + if (interfaceInstance.getInterfaceName().equals(me.getInterfaceName())) { + instance = interfaceInstance; + } + } + if (instance == null) { + final InterfaceAttributes interfaceRule = (InterfaceAttributes)getRule(); + instance = new InterfaceInstance(me.getInterfaceName(), interfaceRule); + if (interfaceRule.isAlphabetize()) { + boolean inserted = false; + String s = instance.getInterfaceName(); + ListIterator lii = interfaceInstances.listIterator(); + while (lii.hasNext()) { + InterfaceInstance entry = (lii.next()); + final String ename = entry.getInterfaceName(); + if (s.compareTo(ename) < 0) { + interfaceInstances.add(lii.nextIndex() - 1, instance); + inserted = true; + break; + } + } + if (!inserted) { + interfaceInstances.add(instance); + } + } + else { + interfaceInstances.add(instance); + } + } + instance.addMethod(me); + } + MethodEntry.rearrangeRelatedItems(entries, + this, + settings.getExtractedMethodsSettings()); + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java new file mode 100644 index 000000000000..ba31eaf0c85a --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.settings.CommentRule; + +import java.util.List; + +/** Used to store a generated comment which is emitted based on whether it matches preceding rules. */ +public class PrecedingCommentRuleInstance + extends CommentRuleInstance +{ + + public PrecedingCommentRuleInstance(final CommentRule commentRule) { + super(commentRule); + } + + /** Determine if this comment, in this instance, should be emitted. */ + public void determineEmit(List resultRuleInstances, int startIndex) { + if (match( + resultRuleInstances, + commentRule.getnPrecedingRulesToMatch(), + -1, + startIndex, + commentRule.isAllPrecedingRules())) + { + setEmit(true); + } + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java new file mode 100644 index 000000000000..89ddb0e99e3a --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.settings.CommentRule; + +import java.util.List; + +/** Used to store a generated comment which is emitted based on whether it matches subsequent rules. */ +public class SubsequentCommentRuleInstance + extends CommentRuleInstance +{ + + public SubsequentCommentRuleInstance(final CommentRule commentRule) { + super(commentRule); + } + + /** Determine if this comment, in this instance, should be emitted. */ + public void determineEmit(List resultRuleInstances, int startIndex) { + if (match( + resultRuleInstances, + commentRule.getnSubsequentRulesToMatch(), + +1, + startIndex, + commentRule.isAllSubsequentRules() + )) + { + setEmit(true); + } + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java new file mode 100644 index 000000000000..b5e379b9a3f6 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.ruleinstance; + +import com.wrq.rearranger.settings.CommentRule; + +import java.util.List; + +/** Used to store a generated comment which is emitted based on whether it matches surrounding rules. */ +public class SurroundingCommentRuleInstance + extends CommentRuleInstance +{ + + public SurroundingCommentRuleInstance(final CommentRule commentRule) { + super(commentRule); + } + + /** Determine if this comment, in this instance, should be emitted. */ + public void determineEmit(List resultRuleInstances, int startIndex) { + if (match( + resultRuleInstances, + commentRule.getnPrecedingRulesToMatch(), + -1, + startIndex, + commentRule.isAllPrecedingRules() + ) && + match( + resultRuleInstances, + commentRule.getnSubsequentRulesToMatch(), + +1, + startIndex, + commentRule.isAllSubsequentRules() + )) + { + setEmit(true); + } + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/CommentFillString.java b/plugins/rearranger/src/com/wrq/rearranger/settings/CommentFillString.java new file mode 100644 index 000000000000..f1992695517a --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/CommentFillString.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings; + +import com.wrq.rearranger.RearrangerActionHandler; +import com.wrq.rearranger.configuration.IntTextField; +import com.wrq.rearranger.settings.attributeGroups.RegexUtil; +import com.wrq.rearranger.util.CommentUtil; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Attribute; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** Implements routines for handling comment fill string expansion. */ +public class CommentFillString { + private String fillString; // replicate in place of %FS% + private boolean useProjectWidthForFill; + private int fillWidth; + + public CommentFillString() { + fillString = ""; + useProjectWidthForFill = true; + fillWidth = 0; + } + + public final String getExpandedCommentText(String commentText) { + int width = useProjectWidthForFill ? RearrangerActionHandler.getRightMargin() : fillWidth; + int tabSize = RearrangerActionHandler.getTabSize(); + return CommentUtil.expandFill(commentText, width, tabSize, fillString); + } + + public String getFillString() { + return fillString; + } + + public void setFillString(String fillString) { + this.fillString = fillString; + } + + public boolean isUseProjectWidthForFill() { + return useProjectWidthForFill; + } + + public void setUseProjectWidthForFill(boolean useProjectWidthForFill) { + this.useProjectWidthForFill = useProjectWidthForFill; + } + + public int getFillWidth() { + return fillWidth; + } + + public void setFillWidth(int fillWidth) { + this.fillWidth = fillWidth; + } + + public final boolean equals(final Object object) { + if (!(object instanceof CommentFillString)) return false; + final CommentFillString c = (CommentFillString)object; + return fillString.equals(c.fillString) && + useProjectWidthForFill == c.useProjectWidthForFill && + fillWidth == c.fillWidth; + } + + public final CommentFillString deepCopy() { + final CommentFillString comment = new CommentFillString(); + comment.fillString = fillString; + comment.useProjectWidthForFill = useProjectWidthForFill; + comment.fillWidth = fillWidth; + return comment; + } + + public static CommentFillString readExternal(final Element item) { + final CommentFillString result = new CommentFillString(); + Attribute fillAttr = RearrangerSettings.getAttribute(item, "fillString"); + if (fillAttr == null) { + result.fillString = ""; + } + else { + String fill = fillAttr.getValue(); + result.fillString = CommentRule.unescape(fill); + } + result.useProjectWidthForFill = RearrangerSettings.getBooleanAttribute(item, "useProjectWidthForFill", true); + result.fillWidth = RearrangerSettings.getIntAttribute(item, "fillWidth", 0); + return result; + } + + public final void writeExternal(final Element me) { + me.setAttribute("fillString", CommentRule.escape(fillString)); + me.setAttribute("useProjectWidthForFill", "" + useProjectWidthForFill); + me.setAttribute("fillWidth", "" + fillWidth); + } + + public final JPanel getCommentFillStringPanel() { + final JPanel cfsPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.insets = new Insets(4, 4, 4, 0); + constraints.newRow(); + final JLabel fillStringLabel = new JLabel("Fill string:"); + fillStringLabel.setToolTipText("Occurrences of %FS% in the comment separator text will be replaced with equal \n" + + "amounts of the fill string, replicated to make the comment end at the specified column"); + cfsPanel.add(fillStringLabel, constraints.firstCol()); + final JTextField fillString = new JTextField(this.fillString); + cfsPanel.add(fillString, constraints.weightedLastCol()); + constraints.newRow(); + final JCheckBox useProjectWidthBox = new JCheckBox("Use project right margin as fill width"); + useProjectWidthBox.setSelected(useProjectWidthForFill); + cfsPanel.add(useProjectWidthBox, constraints.weightedLastCol()); + constraints.lastRow(); + constraints.insets = new Insets(4, 15, 4, 4); + final JLabel fillWidthLabel = new JLabel("Fill width:"); + cfsPanel.add(fillWidthLabel, constraints.firstCol()); + final IntTextField fillWidthField = new IntTextField( + new IntTextField.IGetSet() { + public int get() { + return fillWidth; + } + + public void set(int value) { + fillWidth = value; + } + }, + 0, + 999 + ); + cfsPanel.add(fillWidthField, constraints.nextCol()); + cfsPanel.add(new JLabel(), constraints.weightedLastCol()); + fillWidthLabel.setEnabled(!useProjectWidthForFill); + fillWidthField.setEnabled(!useProjectWidthForFill); + fillString.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { + setFillString(fillString.getText()); + } + + public void removeUpdate(DocumentEvent e) { + setFillString(fillString.getText()); + } + + public void changedUpdate(DocumentEvent e) { + setFillString(fillString.getText()); + } + }); + useProjectWidthBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + useProjectWidthForFill = useProjectWidthBox.isSelected(); + fillWidthLabel.setEnabled(!useProjectWidthForFill); + fillWidthField.setEnabled(!useProjectWidthForFill); + } + }); + return cfsPanel; + } + + /** Returns a regular expression that will match the fill string. */ + public String getFillStringPattern() { + String fs = fillString; + if (fs.length() == 0) fs = " "; + final int length = fs.length(); + StringBuffer sb = new StringBuffer(length * (length + 1) / 2 + length * 3); + sb.append('('); + sb.append(RegexUtil.escape(fs)); + sb.append(")*"); + if (length > 1) { + sb.append('('); + for (int i = length - 1; i > 0; i--) { + sb.append(RegexUtil.escape(fs.substring(0, i))); + sb.append(i <= 1 ? ")?" : "|"); + } + } + return sb.toString(); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java new file mode 100644 index 000000000000..dd871c0c69b7 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings; + +import com.wrq.rearranger.entry.IPopupTreeRangeEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.popup.IFilePopupEntry; +import com.wrq.rearranger.popup.RearrangerTreeNode; +import com.wrq.rearranger.ruleinstance.CommentRuleInstanceFactory; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.attributeGroups.AttributeGroup; +import com.wrq.rearranger.settings.attributeGroups.RegexUtil; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Attribute; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.tree.DefaultMutableTreeNode; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; + +/** Handles insertion of comment separators between sections of the rearranged file. */ +public final class CommentRule + implements AttributeGroup, + IPopupTreeRangeEntry, + IFilePopupEntry +{ +// ------------------------------------------------------- FIELDS ------------------------------------------------------ + + public static final int EMIT_ALWAYS = 0; + public static final int EMIT_IF_ITEMS_MATCH_PRECEDING_RULE = 1; + public static final int EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE = 2; + public static final int EMIT_IF_ITEMS_MATCH_SURROUNDING_RULES = 3; + + private String commentText; + + public final String getCommentText() { + return commentText; + } + + public final void setCommentText(final String commentText) { + StringBuffer sb = new StringBuffer(commentText); + while (sb.length() > 0 && + Character.isWhitespace(sb.charAt(sb.length() - 1)) && + sb.charAt(sb.length() - 1) != '\n') + { + sb.setLength(sb.length() - 1); + } + this.commentText = sb.toString(); + } + + private int emitCondition; + + public final int getEmitCondition() { + return emitCondition; + } + + public final void setEmitCondition(final int emitCondition) { + this.emitCondition = emitCondition; + } + + private int nPrecedingRulesToMatch; // default 1 + private int nSubsequentRulesToMatch; // default 1 + private boolean allPrecedingRules; // if false, ANY preceding rules + + public final boolean isAllPrecedingRules() { + return allPrecedingRules; + } + + public final void setAllPrecedingRules(final boolean allPrecedingRules) { + this.allPrecedingRules = allPrecedingRules; + } + + private boolean allSubsequentRules; // if false, ANY subsequent rules + + public final boolean isAllSubsequentRules() { + return allSubsequentRules; + } + + public final void setAllSubsequentRules(final boolean allSubsequentRules) { + this.allSubsequentRules = allSubsequentRules; + } + + private CommentFillString commentFillString; + + public CommentFillString getCommentFillString() { + return commentFillString; + } + + public void setCommentFillString(CommentFillString commentFillString) { + this.commentFillString = commentFillString; + } + +// --------------------------------------------------- STATIC METHODS -------------------------------------------------- + + public static CommentRule readExternal(final Element item) { + final CommentRule result = new CommentRule(); + + final Attribute attr = RearrangerSettings.getAttribute(item, "commentText"); + // backward compatibility. Comment text was formerly saved as an attribute. + // Newline characters were lost this way. Now comment text is saved as element text. + // If there's no text but there is an attribute, load the old format. It will be + // saved as element text next time IDEA is exited. + // Turns out that IDEA strips newlines in the element text. Maybe it's due to document + // formatting options. In any case, we have to escape newline characters. + String text = item.getText(); + if (text == null || text.length() == 0) { + result.commentText = (attr == null ? "" : ((java.lang.String)attr.getValue())); + } + else { + result.commentText = unescape(text); + } + result.emitCondition = RearrangerSettings.getIntAttribute(item, "condition", 0); + result.nPrecedingRulesToMatch = RearrangerSettings.getIntAttribute(item, "nPrecedingRulesToMatch", 1); + result.nSubsequentRulesToMatch = RearrangerSettings.getIntAttribute(item, "nSubsequentRulesToMatch", 1); + result.allPrecedingRules = RearrangerSettings.getBooleanAttribute(item, "allPrecedingRules", true); + result.allSubsequentRules = RearrangerSettings.getBooleanAttribute(item, "allSubsequentRules", true); + result.commentFillString = CommentFillString.readExternal(item); + return result; + } + + public static String unescape(String text) { + StringBuffer s = new StringBuffer(text); + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '\\' && (i + 1 < s.length())) { + switch (s.charAt(i + 1)) { + case 'n': + s.setCharAt(i, '\n'); + s.deleteCharAt(i + 1); + break; + case '\\': + s.deleteCharAt(i + 1); + break; + case 't': + s.setCharAt(i, '\t'); + s.deleteCharAt(i + 1); + break; + case ' ': + s.deleteCharAt(i); + break; + } + } + } + return s.toString(); + } + + public static String escape(String s) { + StringBuffer sb = new StringBuffer(s); + // for reasons given in readExternal(), escape certain characters in the comment text. + for (int i = 0; i < sb.length(); i++) { + switch (sb.charAt(i)) { + case '\\': + case ' ': + sb.insert(i, '\\'); + i++; + break; + case '\n': + sb.replace(i, i + 1, "\\n"); + i++; + break; + case '\t': + sb.replace(i, i + 1, "\\t"); + i++; + break; + } + } + return sb.toString(); + } + +// ---------------------------------------------------- CONSTRUCTORS --------------------------------------------------- + + public CommentRule() { + commentText = ""; + emitCondition = EMIT_ALWAYS; + nPrecedingRulesToMatch = 1; + nSubsequentRulesToMatch = 1; + allPrecedingRules = true; + allSubsequentRules = true; + commentFillString = new CommentFillString(); + } + +// ---------------------------------------------- GETTER / SETTER METHODS ---------------------------------------------- + + public String[] getAdditionalIconNames() { + return null; + } + + public int getCommentCount() { + return (commentText != null && commentText.length() > 0) ? 1 : 0; + } + + public final JPanel getCommentPanel() { + final JPanel commentPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + commentPanel.setBorder(border); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.insets = new Insets(4, 4, 4, 0); + final JLabel emitLabel = new JLabel("Emit comment:"); + final JRadioButton alwaysButton = new JRadioButton("Always"), + whenButton = new JRadioButton("When"); + final ButtonGroup group = new ButtonGroup(); + group.add(alwaysButton); + group.add(whenButton); + if (emitCondition == 0) { + alwaysButton.setSelected(true); + } + else { + whenButton.setSelected(true); + } + commentPanel.add(emitLabel, constraints.weightedLastCol()); + constraints.newRow(); + constraints.insets = new Insets(0, 14, 0, 0); + commentPanel.add(alwaysButton, constraints.weightedLastCol()); + constraints.newRow(); + commentPanel.add(whenButton, constraints.weightedLastCol()); + constraints.insets = new Insets(0, 24, 0, 4); + constraints.newRow(); + final JPanel anyAllPreviousPanel = new AnyAllPanel(true); + commentPanel.add(anyAllPreviousPanel, constraints.weightedLastCol()); + constraints.newRow(); + constraints.insets = new Insets(0, 24, 10, 4); + final JPanel anyAllSubsequentPanel = new AnyAllPanel(false); + commentPanel.add(anyAllSubsequentPanel, constraints.weightedLastCol()); + anyAllPreviousPanel.setEnabled(emitCondition > 0); + anyAllSubsequentPanel.setEnabled(emitCondition > 0); + final JLabel commentLabel = new JLabel("Comment separator text:"); + constraints.insets = new Insets(4, 4, 4, 4); + constraints.newRow(); + commentPanel.add(commentLabel, constraints.weightedLastCol()); + final JTextArea commentArea = new JTextArea(4, 40); + commentArea.setText(getCommentText()); + constraints.weightedNewRow(); + final JScrollPane scrollPane = new JScrollPane(commentArea); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + commentPanel.add(scrollPane, constraints.weightedLastCol()); + constraints.newRow(); + final JPanel cfsPanel = commentFillString.getCommentFillStringPanel(); + final JLabel fillStringLabel = new JLabel("Fill string:"); + fillStringLabel.setToolTipText("Occurrences of %FS% in the comment separator text will be replaced with equal \n" + + "amounts of the fill string, replicated to make the comment end at the specified column"); + commentPanel.add(cfsPanel, constraints.weightedLastCol()); + + alwaysButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + if (alwaysButton.isSelected()) { + emitCondition = EMIT_ALWAYS; + anyAllPreviousPanel.setEnabled(false); + anyAllSubsequentPanel.setEnabled(false); + } + } + }); + whenButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + if (whenButton.isSelected()) { + anyAllPreviousPanel.setEnabled(true); + anyAllSubsequentPanel.setEnabled(true); + } + } + }); + commentArea.getDocument().addDocumentListener(new DocumentListener() { + public void changedUpdate(final DocumentEvent e) { + setCommentText(commentArea.getText()); + } + + public void insertUpdate(final DocumentEvent e) { + setCommentText(commentArea.getText()); + } + + public void removeUpdate(final DocumentEvent e) { + setCommentText(commentArea.getText()); + } + }); + return commentPanel; + } + + public String getDescriptiveString() { + final StringBuffer sb = new StringBuffer(commentText.trim()); + if (sb.length() > 60) { + // attempt to shorten by removing duplicate (well, quadruplicate) characters. + for (int i = 0; i < sb.length() - 4; i++) { + if (sb.charAt(i) == sb.charAt(i + 1) && + sb.charAt(i + 1) == sb.charAt(i + 2) && + sb.charAt(i + 2) == sb.charAt(i + 3)) + { + // we have at least 4 characters in a row. Shorten the entire sequence to + // a length of 4 characters and append the length. + int j = 0; + while (i + 4 < sb.length() && sb.charAt(i) == sb.charAt(i + 4)) { + j++; + sb.deleteCharAt(i + 4); + } + if (j > 3) { + sb.insert(i + 4, "<" + j + ">"); + } + else { + // compression is quite small, so just output the actual characters. + while (j-- > 0) { + sb.insert(i + 4, sb.charAt(i)); + } + } + } + } + } + if (sb.length() > 60) { + sb.delete(60, sb.length()); + sb.append("..."); + } + String condition = ""; + switch (emitCondition) { + case EMIT_ALWAYS: + break; + case EMIT_IF_ITEMS_MATCH_PRECEDING_RULE: + condition = " when " + precedingRuleString(); + break; + case EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE: + condition = " when " + subsequentRuleString(); + break; + case EMIT_IF_ITEMS_MATCH_SURROUNDING_RULES: + condition = " when " + precedingRuleString() + ", and " + subsequentRuleString(); + } + return ("Comment (" + sb.toString() + ")" + condition); + } + + private String precedingRuleString() { + return (nPrecedingRulesToMatch == 1) ? "preceding rule is matched" : + (allPrecedingRules ? "all" : "any") + + " of preceding " + (nPrecedingRulesToMatch) + " rules are matched"; + } + + private String subsequentRuleString() { + return (nSubsequentRulesToMatch == 1) ? "subsequent rule is matched" : + (allSubsequentRules ? "all" : "any") + + " of subsequent " + (nSubsequentRulesToMatch) + " rules are matched"; + } + + public final String getExpandedCommentText() { + return commentFillString.getExpandedCommentText(commentText); + } + + private String getName() { + return commentText.trim(); + } + + public int getPriority() { + return -1; // Comments never match anything, so any priority will do. + } + + public void setPriority(int priority) { + // does nothing + } + + public String getTypeIconName() { + return "nodes/J2eeParameter"; + } + + public final boolean isAlphabetize() { + throw new UnsupportedOperationException("CommentRule.isAlphabetize() not implemented"); + } + + public final void setnPrecedingRulesToMatch(final int nPrecedingRulesToMatch) { + this.nPrecedingRulesToMatch = nPrecedingRulesToMatch; + } + + public final void setnSubsequentRulesToMatch(final int nSubsequentRulesToMatch) { + this.nSubsequentRulesToMatch = nSubsequentRulesToMatch; + } + +// ------------------------------------------------- CANONICAL METHODS ------------------------------------------------- + + public final boolean equals(final Object object) { + if (!(object instanceof CommentRule)) return false; + final CommentRule c = (CommentRule)object; + return commentText.equals(c.commentText) && + emitCondition == c.emitCondition && + nPrecedingRulesToMatch == c.nPrecedingRulesToMatch && + nSubsequentRulesToMatch == c.nSubsequentRulesToMatch && + allPrecedingRules == c.allPrecedingRules && + allSubsequentRules == c.allSubsequentRules && + commentFillString.equals(c.commentFillString); + } + + public final String toString() { + return getDescriptiveString(); + } + +// ================================================= INTERFACE METHODS ================================================= + +// ---------------------------------------------- Interface AttributeGroup --------------------------------------------- + + public final /*CommentRule*/AttributeGroup deepCopy() { + final CommentRule comment = new CommentRule(); + comment.commentText = commentText; + comment.emitCondition = emitCondition; + comment.nPrecedingRulesToMatch = nPrecedingRulesToMatch; + comment.nSubsequentRulesToMatch = nSubsequentRulesToMatch; + comment.allPrecedingRules = allPrecedingRules; + comment.allSubsequentRules = allSubsequentRules; + comment.commentFillString = commentFillString.deepCopy(); + return comment; + } + + public final void writeExternal(final Element parent) { + final Element me = new Element("Comment"); + me.setText(escape(commentText)); + me.setAttribute("condition", "" + emitCondition); + me.setAttribute("nPrecedingRulesToMatch", "" + nPrecedingRulesToMatch); + me.setAttribute("nSubsequentRulesToMatch", "" + nSubsequentRulesToMatch); + me.setAttribute("allPrecedingRules", "" + allPrecedingRules); + me.setAttribute("allSubsequentRules", "" + allSubsequentRules); + commentFillString.writeExternal(me); + parent.getChildren().add(me); + } + +// --------------------------------------------- Interface IFilePopupEntry --------------------------------------------- + + + public JLabel getPopupEntryText(RearrangerSettings settings) { + String s = commentText.trim(); + if (commentFillString != null && commentFillString.getFillString().length() > 0) { + s = commentFillString.getExpandedCommentText(s); + } + return new JLabel(s); + } + +// ------------------------------------------- Interface IPopupTreeRangeEntry ------------------------------------------ + + + public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { + DefaultMutableTreeNode myNode = new RearrangerTreeNode(this, getName()); + parent.add(myNode); + return myNode; + } + +// -------------------------------------------------- Interface IRule -------------------------------------------------- + + + public IRuleInstance createRuleInstance() { + return CommentRuleInstanceFactory.buildCommentRuleInstance(this); + } + + public boolean isMatch(RangeEntry rangeEntry) { + return false; // comment rules match no entries -- they're just placeholders to generate comments. + } + + public boolean commentsMatchGlobalPattern(String pattern) { + return commentText.matches(pattern); + } + + public List getOffendingPatterns(String pattern) { + List result = new ArrayList(1); + result.add(commentText); + return result; + } + + public void addCommentPatternsToList(List list) { + if (commentText != null && commentText.length() > 0) { + String esc = RegexUtil.escape(commentText); + String fsp = commentFillString.getFillStringPattern(); + esc = esc.replaceAll("%FS%", fsp); + list.add(esc); + } + } + +// --------------------------------------------------- OTHER METHODS --------------------------------------------------- + + public int getnPrecedingRulesToMatch() { + return nPrecedingRulesToMatch; + } + + public final int getnSubsequentRulesToMatch() { + return nSubsequentRulesToMatch; + } + +// --------------------------------------------------- INNER CLASSES --------------------------------------------------- + + final class AnyAllPanel extends JPanel { + final JCheckBox anyAllCheckbox; + final JComboBox anyAllComboBox; + final JLabel anyAllLabel; + final JFormattedTextField anyAllPrevNumber; + final JLabel rulesLabel; + + /** + * Return a JPanel that allows user to specify checkbox (enable rule), Any/All combo box, "of the " + * "preceding"/"subsequent", text field for integer >= 1, "rules" + * + * @param preceding true if handling "preceding" rules, otherwise "subsequent" rules + */ + AnyAllPanel(final boolean preceding) { + super(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.lastRow(); + constraints.fill = GridBagConstraints.BOTH; + anyAllCheckbox = new JCheckBox("items match"); + anyAllCheckbox.setSelected((emitCondition & (preceding ? 1 : 2)) > 0); + anyAllComboBox = new JComboBox(new String[]{"any", "all"}); + anyAllComboBox.setSelectedIndex(preceding ? (allPrecedingRules ? 1 : 0) + : (allSubsequentRules ? 1 : 0)); + Dimension d = anyAllComboBox.getPreferredSize(); + d.width += 3; // make room for "any", if "all" is narrower and is first selection. + anyAllComboBox.setPreferredSize(d); + anyAllLabel = new JLabel(); + anyAllLabel.setText("of the subsequent"); // calculate max size + d = anyAllLabel.getPreferredSize(); + anyAllLabel.setText(preceding ? "of the preceding" : "of the subsequent"); + anyAllLabel.setMinimumSize(d); + anyAllLabel.setPreferredSize(d); + final NumberFormat integerInstance = NumberFormat.getIntegerInstance(); + integerInstance.setMaximumIntegerDigits(2); + integerInstance.setMinimumIntegerDigits(1); + anyAllPrevNumber = new JFormattedTextField(integerInstance); + anyAllPrevNumber.setValue(new Integer("88")); + d = anyAllPrevNumber.getPreferredSize(); + d.width += 3; + anyAllPrevNumber.setPreferredSize(d); + anyAllPrevNumber.setValue(preceding ? nPrecedingRulesToMatch : nSubsequentRulesToMatch); + anyAllPrevNumber.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT); + rulesLabel = new JLabel("rules"); + constraints.insets = new Insets(0, 10, 0, 0); + add(anyAllCheckbox, constraints.nextCol()); + constraints.insets = new Insets(0, 0, 0, 0); + add(anyAllComboBox, constraints.nextCol()); + constraints.insets = new Insets(0, 4, 0, 0); + add(anyAllLabel, constraints.nextCol()); + constraints.insets = new Insets(0, 4, 0, 0); + add(anyAllPrevNumber, constraints.nextCol()); + add(rulesLabel, constraints.weightedLastCol()); + anyAllComboBox.setEnabled(anyAllCheckbox.isSelected()); + anyAllLabel.setEnabled(anyAllCheckbox.isSelected()); + anyAllPrevNumber.setEnabled(anyAllCheckbox.isSelected()); + rulesLabel.setEnabled(anyAllCheckbox.isSelected()); + anyAllCheckbox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + if (anyAllCheckbox.isSelected()) { + emitCondition |= (preceding ? 1 : 2); + } + else { + emitCondition &= (preceding ? ~1 : ~2); + } + anyAllComboBox.setEnabled(anyAllCheckbox.isSelected()); + anyAllLabel.setEnabled(anyAllCheckbox.isSelected()); + anyAllPrevNumber.setEnabled(anyAllCheckbox.isSelected()); + rulesLabel.setEnabled(anyAllCheckbox.isSelected()); + } + }); + anyAllComboBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final int s = anyAllComboBox.getSelectedIndex(); + if (preceding) { + allPrecedingRules = (s == 1); + } + else { + allSubsequentRules = (s == 1); + } + } + }); + anyAllPrevNumber.addPropertyChangeListener("value", new PropertyChangeListener() { + public void propertyChange(final PropertyChangeEvent evt) { + int n = ((Number)anyAllPrevNumber.getValue()).intValue(); + if (n <= 0) { + n = 1; + anyAllPrevNumber.setValue(n); + } + if (preceding) { + nPrecedingRulesToMatch = n; + } + else { + nSubsequentRulesToMatch = n; + } + } + }); + } + + public final void setEnabled(final boolean enable) { + anyAllCheckbox.setEnabled(enable); + anyAllComboBox.setEnabled(anyAllCheckbox.isSelected() && enable); + anyAllLabel.setEnabled(anyAllCheckbox.isSelected() && enable); + anyAllPrevNumber.setEnabled(anyAllCheckbox.isSelected() && enable); + rulesLabel.setEnabled(anyAllCheckbox.isSelected() && enable); + } + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/ForceBlankLineSetting.java b/plugins/rearranger/src/com/wrq/rearranger/settings/ForceBlankLineSetting.java new file mode 100644 index 000000000000..ab0485c14b5a --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/ForceBlankLineSetting.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings; + +import org.jdom.Element; + +/** Contains a single "force N blank lines before/after" some brace. */ +public class ForceBlankLineSetting { + public static final int CLASS_OBJECT = 0; + public static final int METHOD_OBJECT = 1; + public static final int EOF_OBJECT = 2; + + boolean force; + int nBlankLines; + final boolean before; // false => after + final boolean openBrace; // false => close brace + final int object; + final String name; + + public ForceBlankLineSetting(boolean before, boolean openBrace, int object, String name) { + this.before = before; + this.openBrace = openBrace; + this.object = object; + this.name = name; + } + + public boolean isForce() { + return force; + } + + public void setForce(boolean force) { + this.force = force; + } + + public int getnBlankLines() { + return nBlankLines; + } + + public void setnBlankLines(int nBlankLines) { + this.nBlankLines = nBlankLines; + } + + public boolean isBefore() { + return before; + } + + public boolean isOpenBrace() { + return openBrace; + } + + public int getObject() { + return object; + } + + + public boolean equals(final Object obj) { + if (!(obj instanceof ForceBlankLineSetting)) return false; + final ForceBlankLineSetting fbls = (ForceBlankLineSetting)obj; + if (fbls.force != force) return false; + if (fbls.nBlankLines != nBlankLines) return false; + if (fbls.before != before) return false; + if (fbls.openBrace != openBrace) return false; + if (fbls.object != object) return false; + return true; + } + + public final ForceBlankLineSetting deepCopy() { + final ForceBlankLineSetting result = new ForceBlankLineSetting(before, openBrace, object, name); + result.force = force; + result.nBlankLines = nBlankLines; + return result; + } + + /** + * Read the contents of this object from the JDOM element. + * + * @param entry JDOM element which contains setting values as attributes. + */ + public static ForceBlankLineSetting readExternal(final Element entry, + boolean before, + boolean openBrace, + int object, + String name) + { + ForceBlankLineSetting fbls; + Element fblsElement = entry.getChild(name); + boolean force = RearrangerSettings.getBooleanAttribute(fblsElement, "Force", false); + int nBlankLines = RearrangerSettings.getIntAttribute(fblsElement, "nBlankLines", 1); + fbls = new ForceBlankLineSetting(before, openBrace, object, name); + fbls.setForce(force); + fbls.setnBlankLines(nBlankLines); + return fbls; + } + + public final void writeExternal(final Element entry) { + final Element fblsElement = new Element(name); + entry.getChildren().add(fblsElement); + fblsElement.setAttribute("Force", Boolean.valueOf(force).toString()); + fblsElement.setAttribute("nBlankLines", "" + nBlankLines); + } + + public String toString() { + return name + ": " + (before ? "before " : "after ") + + getObjectName() + + (openBrace ? " open brace" : " close brace") + + (force ? ", force " + nBlankLines + " lines" : ", leave intact"); + } + + public String getObjectName() { + return (object == CLASS_OBJECT ? "class" : "method"); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/PrimaryMethodSetting.java b/plugins/rearranger/src/com/wrq/rearranger/settings/PrimaryMethodSetting.java new file mode 100644 index 000000000000..3ddd181a4f70 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/PrimaryMethodSetting.java @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings; + +import com.wrq.rearranger.configuration.*; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Contains settings pertinent to a single related-by-name method setting. A primary field is + * specified + */ +public class PrimaryMethodSetting + implements IListManagerObject +{ + /** Description for a single related-by-name method setting. */ + String description; + /** + * Regular expression which method name must match. If the method is to be matched to a field, there must be + * at least one capture group (parenthesized subexpression) which will be treated as the field. + * In the case of a traditional getter method, this pattern is "get(\w+)". + */ + String methodNamePattern; + /** + * The number of the capture group in methodNamePattern which corresponds to the field name. If the + * methodNamePattern is "get(\w+)", then the fieldCaptureGroupNumber is 1. + */ + int fieldCaptureGroupNumber; + /** number of parameters the primary method must have. In the case of a traditional getter method, this is zero. */ + int numParameters; + /** + * regular expression pattern of the type which primary method must return. + * In the case of a traditional getter method, this is the field type. One substitution is available: + *

+   * %FT%  field type
+   * 
+ */ + String methodTypePattern; + /** + * regular expression pattern of the attributes of the method. + * In the case of a traditional getter method, this is ".*public.*" (i.e., any public method). + */ + String methodAttributePattern; + /** + * pattern of method body (excluding comments and newline characters). Substitutions are available as follows: + *
+   * %FN%  field name
+   * %FT%  field type (if field is valid field, else empty string)
+   * %MT%  method return type
+   * %P1%  parameter 1 name (%P2%, %P3% etc for additional parameters)
+   * %T1%  parameter 1 type name
+   * 
+ */ + String body; + /** list of secondary method configurations, e.g. for "set" and "is". */ + ArrayList secondaryMethodList = new ArrayList(); + + public PrimaryMethodSetting() { + methodNamePattern = "get(\\w+)"; + fieldCaptureGroupNumber = 1; + numParameters = 0; + methodTypePattern = "%FT%"; + methodAttributePattern = ".*public.*"; + body = "{\\s*return\\s*%fn%;\\s*}"; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getMethodNamePattern() { + return methodNamePattern; + } + + public void setMethodNamePattern(String methodNamePattern) { + this.methodNamePattern = methodNamePattern; + } + + public int getFieldCaptureGroupNumber() { + return fieldCaptureGroupNumber; + } + + public void setFieldCaptureGroupNumber(int fieldCaptureGroupNumber) { + this.fieldCaptureGroupNumber = fieldCaptureGroupNumber; + } + + public int getNumParameters() { + return numParameters; + } + + public void setNumParameters(int numParameters) { + this.numParameters = numParameters; + } + + public String getMethodTypePattern() { + return methodTypePattern; + } + + public void setMethodTypePattern(String methodTypePattern) { + this.methodTypePattern = methodTypePattern; + } + + public String getMethodAttributePattern() { + return methodAttributePattern; + } + + public void setMethodAttributePattern(String methodAttributePattern) { + this.methodAttributePattern = methodAttributePattern; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public ArrayList getSecondaryMethodList() { + return secondaryMethodList; + } + + public String toString() { + return description; + } + + public boolean equals(Object obj) { + if (!(obj instanceof PrimaryMethodSetting)) return false; + PrimaryMethodSetting pms = (PrimaryMethodSetting)obj; + if (!pms.description.equals(description)) return false; + if (!pms.methodNamePattern.equals(methodNamePattern)) return false; + if (pms.fieldCaptureGroupNumber != fieldCaptureGroupNumber) return false; + if (pms.numParameters != numParameters) return false; + if (!pms.methodTypePattern.equals(methodTypePattern)) return false; + if (!pms.methodAttributePattern.equals(methodAttributePattern)) return false; + if (!pms.body.equals(body)) return false; + return true; + } + + public JPanel getPanel() { + IListManagerObjectFactory lmof = new IListManagerObjectFactory() { + public IListManagerObject create(String name) { + SecondaryMethodSetting sms = new SecondaryMethodSetting(); + sms.setDescription(name); + return sms; + } + + public List/**/ getObjectList() { + return secondaryMethodList; + } + }; + ListManager Lmgr = new ListManager(lmof, "Description:"); + JPanel pmsPanel = new JPanel(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = 1; + constraints.gridheight = 1; + constraints.weightx = 0.0d; + constraints.weighty = 0.0d; + constraints.gridy = constraints.gridx = 0; + constraints.insets = new Insets(3, 3, 3, 3); + pmsPanel.setBorder(BorderFactory.createTitledBorder( + BorderFactory.createEtchedBorder(), + "Primary (\"Getter\") Method Criteria")); + constraints.gridwidth = 1; + constraints.gridy++; + JLabel methodNamePatternLabel = new JLabel("Method name:"); + methodNamePatternLabel.setToolTipText( + "Regular expression which method name must match. " + + "If the method is to be matched to a field, there must be\n" + + " at least one capture group (parenthesized subexpression) which will be treated as the field.\n" + + " In the case of a traditional getter method, this pattern is \"get(\\w+)\"."); + pmsPanel.add(methodNamePatternLabel, constraints); + constraints.gridx++; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = .5; + StringTextField primaryPrefixText = new StringTextField() { + public void setValue(String value) { + setMethodNamePattern(value); + } + + public String getValue() { + return getMethodNamePattern(); + } + }; + pmsPanel.add(primaryPrefixText, constraints); + constraints.fill = GridBagConstraints.NONE; + constraints.weightx = 0; + constraints.gridx++; + JLabel fieldCaptureGroupLabel = new JLabel("Field capture group:"); + fieldCaptureGroupLabel.setToolTipText( + "The number of the capture group in methodNamePattern which corresponds to the field name. If the\n" + + " methodNamePattern is \"get(\\w+)\", then the fieldCaptureGroupNumber is 1." + ); + pmsPanel.add(fieldCaptureGroupLabel, constraints); + IntTextField itf = new IntTextField( + new IntTextField.IGetSet() { + public void set(int value) { + fieldCaptureGroupNumber = value; + } + + public int get() { + return fieldCaptureGroupNumber; + } + }, + null, null + ); + + constraints.gridx++; + pmsPanel.add(itf, constraints); + constraints.gridx++; + JLabel nParamLabel = new JLabel("Number of parameters:"); + nParamLabel.setToolTipText( + "number of parameters the primary method must have.\n" + + "In the case of a traditional getter method, this is zero."); + pmsPanel.add(nParamLabel, constraints); + constraints.gridx++; + IntTextField nParamText = new IntTextField( + new IntTextField.IGetSet() { + public void set(int value) { + numParameters = value; + } + + public int get() { + return numParameters; + } + }, null, null); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = GridBagConstraints.REMAINDER; + pmsPanel.add(nParamText, constraints); + + constraints.gridx = 0; + constraints.gridy++; + constraints.gridwidth = 1; + constraints.weightx = 0; + constraints.fill = GridBagConstraints.NONE; + JLabel returnTypeLabel = new JLabel("Return type:"); + returnTypeLabel.setToolTipText( + "regular expression pattern of the type which primary method must return.\n" + + " In the case of a traditional getter method, this is the field type. One substitution is available:\n" + + " * %FT% field type"); + pmsPanel.add(returnTypeLabel, constraints); + constraints.gridx++; + constraints.weightx = .5; + constraints.fill = GridBagConstraints.HORIZONTAL; + StringTextField returnTypeField = new StringTextField() { + public void setValue(String value) { + methodTypePattern = value; + } + + public String getValue() { + return methodTypePattern; + } + }; + pmsPanel.add(returnTypeField, constraints); + constraints.fill = GridBagConstraints.NONE; + constraints.gridx++; + constraints.weightx = 0; + JLabel methodAttributeLabel = new JLabel("Method attributes:"); + methodAttributeLabel.setToolTipText("Protection level or other attributes for the method.\n" + + "In the case of a getter method, this is usually \".*public.*\"."); + pmsPanel.add(methodAttributeLabel, constraints); + StringTextField methodAttributeField = new StringTextField() { + public void setValue(String value) { + methodAttributePattern = value; + } + + public String getValue() { + return methodAttributePattern; + } + }; + constraints.gridx++; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = .5; + constraints.fill = GridBagConstraints.HORIZONTAL; + pmsPanel.add(methodAttributeField, constraints); + constraints.gridx++; + constraints.weightx = 0; + constraints.fill = GridBagConstraints.NONE; + constraints.gridy++; + constraints.gridx = 0; + JLabel bodyLabel = new JLabel("Body:"); + bodyLabel.setToolTipText("regular expression pattern of method body (excluding comments and newline characters).\n" + + "Substitutions are available as follows:\n" + + " %FN% field name\n" + + " %FT% field type (if field is valid field, else empty string)\n" + + " %MT% method return type\n" + + " %P1% parameter 1 name (%P2%, %P3% etc for additional parameters)\n" + + " %T1% parameter 1 type name"); + constraints.gridwidth = 1; + constraints.weightx = 0; + constraints.fill = GridBagConstraints.NONE; + pmsPanel.add(bodyLabel, constraints); + constraints.gridx++; + StringTextArea bodyField = new StringTextArea() { + public void setValue(String value) { + body = value; + } + + public String getValue() { + return body; + } + }; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1; + constraints.weighty = .35; + constraints.fill = GridBagConstraints.BOTH; + JScrollPane sp = new JScrollPane(bodyField); + pmsPanel.add(sp, constraints); + constraints.gridx = 0; + constraints.gridy++; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.fill = GridBagConstraints.NONE; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1; + constraints.weighty = .65; + final JPanel pane = Lmgr.getPane(); + pane.setBorder(BorderFactory.createTitledBorder( + BorderFactory.createEtchedBorder(), "Related Methods")); + pmsPanel.add(pane, constraints); + return pmsPanel; + } + + public IListManagerObject deepcopy() { + PrimaryMethodSetting pms = new PrimaryMethodSetting(); + pms.description = getDescription(); + pms.methodNamePattern = getMethodNamePattern(); + pms.fieldCaptureGroupNumber = getFieldCaptureGroupNumber(); + pms.numParameters = getNumParameters(); + pms.methodTypePattern = getMethodTypePattern(); + pms.methodAttributePattern = getMethodAttributePattern(); + pms.body = getBody(); + pms.secondaryMethodList = new ArrayList(); + for (SecondaryMethodSetting sms : secondaryMethodList) { + pms.secondaryMethodList.add((SecondaryMethodSetting)sms.deepcopy()); + } + return pms; + } + + public static void main(String[] args) { + PrimaryMethodSetting ms = new PrimaryMethodSetting(); + final JDialog frame = new JDialog((Frame)null, "SwingApplication"); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1.0d; + constraints.weighty = 1.0d; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 0; + constraints.gridy = 0; + frame.getContentPane().setLayout(new GridBagLayout()); + frame.getContentPane().add(ms.getPanel(), constraints); + //Finish setting up the frame, and show it. + frame.pack(); + frame.setResizable(true); + frame.setModal(true); + frame.setVisible(true); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/RearrangerSettings.java b/plugins/rearranger/src/com/wrq/rearranger/settings/RearrangerSettings.java new file mode 100644 index 000000000000..e302e62076c2 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/RearrangerSettings.java @@ -0,0 +1,683 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings; + +import com.intellij.openapi.diagnostic.Logger; +import com.wrq.rearranger.Rearranger; +import com.wrq.rearranger.settings.attributeGroups.AttributeGroup; +import com.wrq.rearranger.settings.attributeGroups.ClassAttributes; +import com.wrq.rearranger.settings.attributeGroups.GetterSetterDefinition; +import com.wrq.rearranger.settings.attributeGroups.ItemAttributes; +import org.jdom.Attribute; +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; +import org.jdom.output.Format; +import org.jdom.output.XMLOutputter; + +import java.io.*; +import java.net.URL; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +/** + * Holds two lists of rearrangement settings, one for the outer level classes, the other for class members. Each + * list contains objects of type CommonAttributes. + */ +public final class RearrangerSettings { + +// ------------------------------ FIELDS ------------------------------ + + // BEGINNING OF FIELDS + private static final Logger logger = Logger.getInstance("#" + RearrangerSettings.class.getName()); + public static final int OVERLOADED_ORDER_RETAIN_ORIGINAL = 0; + public static final int OVERLOADED_ORDER_ASCENDING_PARAMETERS = 1; + public static final int OVERLOADED_ORDER_DESCENDING_PARAMETERS = 2; + private final List itemOrderAttributeList; + private final List classOrderAttributeList; + private RelatedMethodsSettings relatedMethodsSettings; + private boolean keepGettersSettersTogether; + private boolean keepGettersSettersWithProperty; + private boolean keepOverloadedMethodsTogether; + private String globalCommentPattern; + private boolean askBeforeRearranging; + private boolean rearrangeInnerClasses; + private boolean showParameterTypes; + private boolean showParameterNames; + private boolean showFields; + private boolean showTypeAfterMethod; + private boolean showRules; + private boolean showMatchedRules; + private boolean showComments; + private ForceBlankLineSetting afterClassLBrace; + private ForceBlankLineSetting afterClassRBrace; + private ForceBlankLineSetting beforeClassRBrace; + private ForceBlankLineSetting beforeMethodLBrace; + private ForceBlankLineSetting afterMethodLBrace; + private ForceBlankLineSetting afterMethodRBrace; + private ForceBlankLineSetting beforeMethodRBrace; + private boolean removeBlanksInsideCodeBlocks; + private ForceBlankLineSetting newlinesAtEOF; + + private int overloadedOrder; + private GetterSetterDefinition defaultGSDefinition; + private List primaryMethodList; + +// -------------------------- STATIC METHODS -------------------------- + + static public int getIntAttribute(final Element me, final String attr) { + return getIntAttribute(me, attr, 0); + } + + static public boolean getBooleanAttribute(final Element me, final String attr) { + return getBooleanAttribute(me, attr, false); + } + + public static RearrangerSettings getDefaultSettings() { + logger.debug("enter loadDefaultSettings"); + URL settingsURL = Rearranger.class.getClassLoader().getResource("com/wrq/rearranger/defaultConfiguration.xml"); + logger.debug("settings URL=" + settingsURL.getFile()); + try { + InputStream is = settingsURL.openStream(); + return getSettingsFromStream(is); + } + catch (IOException e) { + logger.debug("getDefaultSettings:" + e); + return null; + } + } + + public static RearrangerSettings getSettingsFromStream(InputStream is) { + Document document = null; + try { + SAXBuilder builder = new SAXBuilder(); + document = builder.build(is); + } + catch (JDOMException jde) { + logger.debug("JDOM exception building document:" + jde); + return null; + } + catch (IOException e) { + logger.debug("I/O exception building document:" + e); + return null; + } + finally { + if (is != null) { + try { + is.close(); + } + catch (IOException e) { + } + } + } + Element app = document.getRootElement(); + Element component = null; + if (app.getName().equals("application")) { + ListIterator li = app.getChildren().listIterator(); + while (li.hasNext()) +// for (Element child : (List)((java.util.List)app.getChildren())) + { + Element child = (Element)li.next(); + if (child.getName().equals("component") && + child.getAttribute("name") != null && + child.getAttribute("name").getValue().equals(Rearranger.COMPONENT_NAME)) + { + component = child; + break; + } + } + } + else { + if (app.getName().equals("component") && + app.getAttribute("name") != null && + app.getAttribute("name").getValue().equals(Rearranger.COMPONENT_NAME)) + { + component = app; + } + } + if (component != null) { + Element rearranger = component.getChild(Rearranger.COMPONENT_NAME); + if (rearranger != null) { + RearrangerSettings rs = new RearrangerSettings(); + rs.readExternal(rearranger); + return rs; + } + } + return null; + } + +// Level 1 methods + + /** @param entry JDOM element named "Rearranger" which contains setting values as attributes. */ + public final void readExternal(final Element entry) { + final Element items = entry.getChild("Items"); + final Element classes = entry.getChild("Classes"); + + final List itemList = items.getChildren(); + final List classList = classes.getChildren(); + + ListIterator li; + li = itemList.listIterator(); + while (li.hasNext()) +// for (Element element : itemList) + { + Element element = (Element)li.next(); + itemOrderAttributeList.add(((com.wrq.rearranger.settings.attributeGroups.AttributeGroup)ItemAttributes.readExternal(element))); + } + li = classList.listIterator(); +// for (Element element : classList) + while (li.hasNext()) { + Element element = (Element)li.next(); + classOrderAttributeList.add(((com.wrq.rearranger.settings.attributeGroups.AttributeGroup)ClassAttributes.readExternal(element))); + } + final Element gsd = entry.getChild("DefaultGetterSetterDefinition"); + defaultGSDefinition = GetterSetterDefinition.readExternal(gsd); + final Element relatedItems = entry.getChild("RelatedMethods"); + relatedMethodsSettings = RelatedMethodsSettings.readExternal(relatedItems); + keepGettersSettersTogether = getBooleanAttribute(entry, "KeepGettersSettersTogether", true); + keepGettersSettersWithProperty = getBooleanAttribute(entry, "KeepGettersSettersWithProperty", false); + keepOverloadedMethodsTogether = getBooleanAttribute(entry, "KeepOverloadedMethodsTogether", true); + final Attribute attr = RearrangerSettings.getAttribute(entry, "globalCommentPattern"); + askBeforeRearranging = getBooleanAttribute(entry, "ConfirmBeforeRearranging", false); + rearrangeInnerClasses = getBooleanAttribute(entry, "RearrangeInnerClasses", false); + globalCommentPattern = (attr == null ? "" : ((java.lang.String)attr.getValue())); + overloadedOrder = getIntAttribute(entry, "overloadedOrder", OVERLOADED_ORDER_RETAIN_ORIGINAL); + showParameterTypes = getBooleanAttribute(entry, "ShowParameterTypes", true); + showParameterNames = getBooleanAttribute(entry, "ShowParameterNames", true); + showFields = getBooleanAttribute(entry, "ShowFields", true); + showRules = getBooleanAttribute(entry, "ShowRules", false); + showMatchedRules = getBooleanAttribute(entry, "ShowMatchedRules", false); + showComments = getBooleanAttribute(entry, "ShowComments", false); + showTypeAfterMethod = getBooleanAttribute(entry, "ShowTypeAfterMethod", true); + removeBlanksInsideCodeBlocks = getBooleanAttribute(entry, "RemoveBlanksInsideCodeBlocks", false); + afterClassLBrace = ForceBlankLineSetting.readExternal(entry, false, true, ForceBlankLineSetting.CLASS_OBJECT, "AfterClassLBrace"); + afterClassRBrace = ForceBlankLineSetting.readExternal(entry, false, false, ForceBlankLineSetting.CLASS_OBJECT, "AfterClassRBrace"); + beforeClassRBrace = ForceBlankLineSetting.readExternal(entry, true, false, ForceBlankLineSetting.CLASS_OBJECT, "BeforeClassRBrace"); + beforeMethodLBrace = ForceBlankLineSetting.readExternal(entry, true, true, ForceBlankLineSetting.METHOD_OBJECT, "BeforeMethodLBrace"); + afterMethodLBrace = ForceBlankLineSetting.readExternal(entry, false, true, ForceBlankLineSetting.METHOD_OBJECT, "AfterMethodLBrace"); + afterMethodRBrace = ForceBlankLineSetting.readExternal(entry, false, false, ForceBlankLineSetting.METHOD_OBJECT, "AfterMethodRBrace"); + beforeMethodRBrace = ForceBlankLineSetting.readExternal(entry, true, false, ForceBlankLineSetting.METHOD_OBJECT, "BeforeMethodRBrace"); + newlinesAtEOF = ForceBlankLineSetting.readExternal(entry, false, false, ForceBlankLineSetting.EOF_OBJECT, "NewlinesAtEOF"); + } + +// Level 2 methods + + static public Attribute getAttribute(Element element, String attributeName) { + if (element == null) return null; + return element.getAttribute(attributeName); + } + + static public int getIntAttribute(final Element item, final String attributeName, int defaultValue) { + if (item == null) return defaultValue; + final Attribute a = item.getAttribute(attributeName); + if (a == null) return defaultValue; + final String r = a.getValue(); + if (r == null) return defaultValue; + if (r.length() == 0) return defaultValue; + return Integer.parseInt(r); + } + + static public boolean getBooleanAttribute(final Element me, final String attr, boolean defaultValue) { + if (me == null) return defaultValue; + final Attribute a = me.getAttribute(attr); + if (a == null) return defaultValue; + final String r = a.getValue(); + if (r == null) return defaultValue; + return (r.equalsIgnoreCase("true")); + } + + public static RearrangerSettings getSettingsFromFile(File f) { + try { + return getSettingsFromStream(new FileInputStream(f)); + } + catch (FileNotFoundException e) { + logger.debug("getSettingsFromFile:" + e); + } + return null; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + // END OF ALL FIELDS + public RearrangerSettings() { + itemOrderAttributeList = new ArrayList(); + classOrderAttributeList = new ArrayList(); + relatedMethodsSettings = new RelatedMethodsSettings(); + keepGettersSettersTogether = false; + keepGettersSettersWithProperty = false; + keepOverloadedMethodsTogether = false; + globalCommentPattern = ""; + overloadedOrder = OVERLOADED_ORDER_RETAIN_ORIGINAL; + askBeforeRearranging = false; + rearrangeInnerClasses = false; + showParameterTypes = true; + showParameterNames = false; + showFields = true; + showTypeAfterMethod = true; + showRules = false; + showMatchedRules = false; + showComments = false; + removeBlanksInsideCodeBlocks = false; + afterClassLBrace = new ForceBlankLineSetting(false, true, ForceBlankLineSetting.CLASS_OBJECT, "AfterClassLBrace"); + afterClassRBrace = new ForceBlankLineSetting(false, false, ForceBlankLineSetting.CLASS_OBJECT, "AfterClassRBrace"); + beforeClassRBrace = new ForceBlankLineSetting(true, false, ForceBlankLineSetting.CLASS_OBJECT, "BeforeClassRBrace"); + beforeMethodLBrace = new ForceBlankLineSetting(true, true, ForceBlankLineSetting.METHOD_OBJECT, "BeforeMethodLBrace"); + afterMethodLBrace = new ForceBlankLineSetting(false, true, ForceBlankLineSetting.METHOD_OBJECT, "AfterMethodLBrace"); + beforeMethodRBrace = new ForceBlankLineSetting(true, false, ForceBlankLineSetting.METHOD_OBJECT, "BeforeMethodRBrace"); + afterMethodRBrace = new ForceBlankLineSetting(false, false, ForceBlankLineSetting.METHOD_OBJECT, "AfterMethodRBrace"); + newlinesAtEOF = new ForceBlankLineSetting(false, false, ForceBlankLineSetting.EOF_OBJECT, "NewlinesAtEOF"); + defaultGSDefinition = new GetterSetterDefinition(); + primaryMethodList = new LinkedList(); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public ForceBlankLineSetting getAfterClassLBrace() { + return afterClassLBrace; + } + + public ForceBlankLineSetting getAfterClassRBrace() { + return afterClassRBrace; + } + + public ForceBlankLineSetting getBeforeMethodLBrace() { + return beforeMethodLBrace; + } + + public ForceBlankLineSetting getAfterMethodLBrace() { + return afterMethodLBrace; + } + + public ForceBlankLineSetting getAfterMethodRBrace() { + return afterMethodRBrace; + } + + public ForceBlankLineSetting getBeforeClassRBrace() { + return beforeClassRBrace; + } + + public ForceBlankLineSetting getBeforeMethodRBrace() { + return beforeMethodRBrace; + } + + public final List getClassOrderAttributeList() { + return classOrderAttributeList; + } + + public GetterSetterDefinition getDefaultGSDefinition() { + return defaultGSDefinition; + } + +// Level 1 methods + + public String getGlobalCommentPattern() { + return globalCommentPattern; + } + +// Level 2 methods + + public void setGlobalCommentPattern(String globalCommentPattern) { + this.globalCommentPattern = globalCommentPattern; + } + +// end of Level 2 methods +// end of Level 1 methods + + public final List getItemOrderAttributeList() { + return itemOrderAttributeList; + } + + public ForceBlankLineSetting getNewlinesAtEOF() { + return newlinesAtEOF; + } + +// Level 1 methods + + public int getOverloadedOrder() { + return overloadedOrder; + } + +// Level 2 methods + + public void setOverloadedOrder(int overloadedOrder) { + this.overloadedOrder = overloadedOrder; + } + +// end of Level 2 methods +// end of Level 1 methods + + public RelatedMethodsSettings getExtractedMethodsSettings() { + return relatedMethodsSettings; + } + +// Level 1 methods + + public boolean isAskBeforeRearranging() { + return askBeforeRearranging; + } + +// Level 2 methods + + public void setAskBeforeRearranging(boolean askBeforeRearranging) { + this.askBeforeRearranging = askBeforeRearranging; + } + + public boolean isKeepGettersSettersTogether() { + return keepGettersSettersTogether; + } + +// Level 2 methods + + public void setKeepGettersSettersTogether(boolean keepGettersSettersTogether) { + this.keepGettersSettersTogether = keepGettersSettersTogether; + } + + public boolean isKeepGettersSettersWithProperty() { + return keepGettersSettersWithProperty; + } + + public void setKeepGettersSettersWithProperty(boolean keepGettersSettersWithProperty) { + this.keepGettersSettersWithProperty = keepGettersSettersWithProperty; + } +// end of Level 2 methods +// end of Level 1 methods +// Level 1 methods + + public boolean isKeepOverloadedMethodsTogether() { + return keepOverloadedMethodsTogether; + } + +// Level 2 methods + + public void setKeepOverloadedMethodsTogether(boolean keepOverloadedMethodsTogether) { + this.keepOverloadedMethodsTogether = keepOverloadedMethodsTogether; + } + + // end of Level 2 methods +// end of Level 1 methods +// Level 1 methods + public boolean isRearrangeInnerClasses() { + return rearrangeInnerClasses; + } + + public void setRearrangeInnerClasses(boolean rearrangeInnerClasses) { + this.rearrangeInnerClasses = rearrangeInnerClasses; + } + +// end of Level 2 methods +// end of Level 1 methods +// Level 1 methods + + public boolean isRemoveBlanksInsideCodeBlocks() { + return removeBlanksInsideCodeBlocks; + } + +// Level 2 methods + + public void setRemoveBlanksInsideCodeBlocks(boolean removeBlanksInsideCodeBlocks) { + this.removeBlanksInsideCodeBlocks = removeBlanksInsideCodeBlocks; + } + + public boolean isShowComments() { + return showComments; + } + + public void setShowComments(boolean showComments) { + this.showComments = showComments; + } + +// end of Level 2 methods +// end of Level 1 methods +// Level 1 methods + + public boolean isShowFields() { + return showFields; + } + +// Level 2 methods + + public void setShowFields(boolean showFields) { + this.showFields = showFields; + } + + public boolean isShowMatchedRules() { + return showMatchedRules; + } + + public void setShowMatchedRules(boolean showMatchedRules) { + this.showMatchedRules = showMatchedRules; + } + + public boolean isShowParameterNames() { + return showParameterNames; + } + +// Level 2 methods + + public void setShowParameterNames(boolean showParameterNames) { + this.showParameterNames = showParameterNames; + } + +// end of Level 2 methods +// end of Level 1 methods +// Level 1 methods + + public boolean isShowParameterTypes() { + return showParameterTypes; + } + +// Level 2 methods + + public void setShowParameterTypes(boolean showParameterTypes) { + this.showParameterTypes = showParameterTypes; + } + + // end of Level 2 methods +// end of Level 1 methods +// Level 1 methods + public boolean isShowRules() { + return showRules; + } + + public void setShowRules(boolean showRules) { + this.showRules = showRules; + } + + // end of Level 2 methods +// end of Level 1 methods + public boolean isShowTypeAfterMethod() { + return showTypeAfterMethod; + } + + public void setShowTypeAfterMethod(boolean showTypeAfterMethod) { + this.showTypeAfterMethod = showTypeAfterMethod; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public boolean equals(final Object object) { + if (!(object instanceof RearrangerSettings)) return false; + final RearrangerSettings rs = (RearrangerSettings)object; + if (rs.getClassOrderAttributeList().size() != getClassOrderAttributeList().size()) return false; + if (rs.getItemOrderAttributeList().size() != getItemOrderAttributeList().size()) return false; + for (int i = 0; i < getClassOrderAttributeList().size(); i++) { + if (!getClassOrderAttributeList().get(i).equals(rs.getClassOrderAttributeList().get(i))) return false; + } + for (int i = 0; i < getItemOrderAttributeList().size(); i++) { + if (!getItemOrderAttributeList().get(i).equals(rs.getItemOrderAttributeList().get(i))) return false; + } + if (!rs.getExtractedMethodsSettings().equals(getExtractedMethodsSettings())) return false; + if (rs.isKeepGettersSettersTogether() != isKeepGettersSettersTogether()) return false; + if (rs.isKeepGettersSettersWithProperty() != isKeepGettersSettersWithProperty()) return false; + if (rs.isKeepOverloadedMethodsTogether() != isKeepOverloadedMethodsTogether()) return false; + if (rs.overloadedOrder != overloadedOrder) return false; + if (!rs.globalCommentPattern.equals(globalCommentPattern)) return false; + if (rs.askBeforeRearranging != askBeforeRearranging) return false; + if (rs.rearrangeInnerClasses != rearrangeInnerClasses) return false; + if (rs.showParameterTypes != showParameterTypes) return false; + if (rs.showParameterNames != showParameterNames) return false; + if (rs.showFields != showFields) return false; + if (rs.showTypeAfterMethod != showTypeAfterMethod) return false; + if (rs.showRules != showRules) return false; + if (rs.showMatchedRules != showMatchedRules) return false; + if (rs.showComments != showComments) return false; + if (rs.removeBlanksInsideCodeBlocks != removeBlanksInsideCodeBlocks) return false; + if (!rs.afterClassLBrace.equals(afterClassLBrace)) return false; + if (!rs.afterClassRBrace.equals(afterClassRBrace)) return false; + if (!rs.beforeClassRBrace.equals(beforeClassRBrace)) return false; + if (!rs.beforeMethodLBrace.equals(beforeMethodLBrace)) return false; + if (!rs.afterMethodLBrace.equals(afterMethodLBrace)) return false; + if (!rs.afterMethodRBrace.equals(afterMethodRBrace)) return false; + if (!rs.beforeMethodRBrace.equals(beforeMethodRBrace)) return false; + if (!rs.newlinesAtEOF.equals(newlinesAtEOF)) return false; + if (!rs.defaultGSDefinition.equals(defaultGSDefinition)) return false; + if (primaryMethodList.size() != rs.primaryMethodList.size()) return false; + for (int i = 0; i < primaryMethodList.size(); i++) { + PrimaryMethodSetting pms = primaryMethodList.get(i); + PrimaryMethodSetting rspms = rs.primaryMethodList.get(i); + if (!rspms.equals(pms)) return false; + } + return true; + } + +// -------------------------- OTHER METHODS -------------------------- + + public final void addClass(final AttributeGroup ca, final int index) { + if (classOrderAttributeList.size() < index) { + classOrderAttributeList.add(ca); + } + else { + classOrderAttributeList.add(index, ca); + } + } + + public final void addItem(final AttributeGroup ia, final int index) { + if (itemOrderAttributeList.size() < index) { + itemOrderAttributeList.add(ia); + } + else { + itemOrderAttributeList.add(index, ia); + } + } + + public final RearrangerSettings deepCopy() { + final RearrangerSettings result = new RearrangerSettings(); + for (AttributeGroup itemAttributes : itemOrderAttributeList) { + result.itemOrderAttributeList.add(itemAttributes.deepCopy()); + } + for (AttributeGroup classAttributes : classOrderAttributeList) { + result.classOrderAttributeList.add(classAttributes.deepCopy()); + } + result.relatedMethodsSettings = relatedMethodsSettings.deepCopy(); + result.keepGettersSettersTogether = keepGettersSettersTogether; + result.keepGettersSettersWithProperty = keepGettersSettersWithProperty; + result.keepOverloadedMethodsTogether = keepOverloadedMethodsTogether; + result.globalCommentPattern = globalCommentPattern; + result.overloadedOrder = overloadedOrder; + result.askBeforeRearranging = askBeforeRearranging; + result.rearrangeInnerClasses = rearrangeInnerClasses; + result.showParameterNames = showParameterNames; + result.showParameterTypes = showParameterTypes; + result.showFields = showFields; + result.showTypeAfterMethod = showTypeAfterMethod; + result.showRules = showRules; + result.showMatchedRules = showMatchedRules; + result.showComments = showComments; + result.removeBlanksInsideCodeBlocks = removeBlanksInsideCodeBlocks; + result.afterClassLBrace = afterClassLBrace.deepCopy(); + result.afterClassRBrace = afterClassRBrace.deepCopy(); + result.beforeClassRBrace = beforeClassRBrace.deepCopy(); + result.beforeMethodLBrace = beforeMethodLBrace.deepCopy(); + result.afterMethodLBrace = afterMethodLBrace.deepCopy(); + result.afterMethodRBrace = afterMethodRBrace.deepCopy(); + result.beforeMethodRBrace = beforeMethodRBrace.deepCopy(); + result.newlinesAtEOF = newlinesAtEOF.deepCopy(); + result.defaultGSDefinition = defaultGSDefinition.deepCopy(); + return result; + } + + public void writeSettingsToFile(File f) { + Element component = new Element("component"); + component.setAttribute("name", Rearranger.COMPONENT_NAME); + Element r = new Element(Rearranger.COMPONENT_NAME); + component.getChildren().add(r); + writeExternal(r); + Format format = Format.getPrettyFormat(); + XMLOutputter outputter = new XMLOutputter(format); + try { + final FileOutputStream fileOutputStream = new FileOutputStream(f); + outputter.output(component, fileOutputStream); + fileOutputStream.close(); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + +// end of Level 2 methods +// end of Level 1 methods + + public final void writeExternal(final Element entry) { + final Element items = new Element("Items"); + final Element classes = new Element("Classes"); + entry.getChildren().add(items); + entry.getChildren().add(classes); + for (AttributeGroup item : itemOrderAttributeList) { + item.writeExternal(items); + } + for (AttributeGroup attributes : classOrderAttributeList) { + attributes.writeExternal(classes); + } + final Element gsd = new Element("DefaultGetterSetterDefinition"); + entry.getChildren().add(gsd); + defaultGSDefinition.writeExternal(gsd); + final Element relatedItems = new Element("RelatedMethods"); + entry.getChildren().add(relatedItems); + entry.setAttribute("KeepGettersSettersTogether", Boolean.valueOf(keepGettersSettersTogether).toString()); + entry.setAttribute("KeepGettersSettersWithProperty", Boolean.valueOf(keepGettersSettersWithProperty).toString()); + entry.setAttribute("KeepOverloadedMethodsTogether", Boolean.valueOf(keepOverloadedMethodsTogether).toString()); + entry.setAttribute("ConfirmBeforeRearranging", Boolean.valueOf(askBeforeRearranging).toString()); + entry.setAttribute("RearrangeInnerClasses", Boolean.valueOf(rearrangeInnerClasses).toString()); + entry.setAttribute("globalCommentPattern", globalCommentPattern); + entry.setAttribute("overloadedOrder", "" + overloadedOrder); + entry.setAttribute("ShowParameterTypes", Boolean.valueOf(showParameterTypes).toString()); + entry.setAttribute("ShowParameterNames", Boolean.valueOf(showParameterNames).toString()); + entry.setAttribute("ShowFields", Boolean.valueOf(showFields).toString()); + entry.setAttribute("ShowTypeAfterMethod", Boolean.valueOf(showTypeAfterMethod).toString()); + entry.setAttribute("ShowRules", Boolean.valueOf(showRules).toString()); + entry.setAttribute("ShowMatchedRules", Boolean.valueOf(showMatchedRules).toString()); + entry.setAttribute("ShowComments", Boolean.valueOf(showComments).toString()); + entry.setAttribute("RemoveBlanksInsideCodeBlocks", Boolean.valueOf(removeBlanksInsideCodeBlocks).toString()); + relatedMethodsSettings.writeExternal(relatedItems); + afterClassLBrace.writeExternal(entry); + afterClassRBrace.writeExternal(entry); + beforeClassRBrace.writeExternal(entry); + beforeMethodLBrace.writeExternal(entry); + afterMethodLBrace.writeExternal(entry); + afterMethodRBrace.writeExternal(entry); + beforeMethodRBrace.writeExternal(entry); + newlinesAtEOF.writeExternal(entry); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/RelatedByNameMethodsSettings.java b/plugins/rearranger/src/com/wrq/rearranger/settings/RelatedByNameMethodsSettings.java new file mode 100644 index 000000000000..481b6820150f --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/RelatedByNameMethodsSettings.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings; + +import java.util.ArrayList; + +/** Contains settings pertaining to methods related by name, e.g. getter/setters. */ +public class RelatedByNameMethodsSettings { + ArrayList methodList; + + public RelatedByNameMethodsSettings() { + methodList = new ArrayList(); + } + + public ArrayList/**/ getMethodList() { + return methodList; + } + + public void addMethod(PrimaryMethodSetting pms) { + methodList.add(pms); + } + + public void removeMethod(PrimaryMethodSetting pms) { + methodList.remove(pms); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/RelatedMethodsSettings.java b/plugins/rearranger/src/com/wrq/rearranger/settings/RelatedMethodsSettings.java new file mode 100644 index 000000000000..d4b2ec30a89f --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/RelatedMethodsSettings.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings; + +import com.wrq.rearranger.settings.attributeGroups.RegexUtil; +import org.jdom.Element; + +import java.util.List; + +/** Contains settings regarding placement of related methods. */ +public class RelatedMethodsSettings { + private boolean moveExtractedMethods; + private boolean belowFirstCaller; // false means below last caller + private boolean depthFirstOrdering; // false means breadth first ordering + + public static final int INVOCATION_ORDER = 0; + public static final int RETAIN_ORIGINAL_ORDER = 1; + public static final int ALPHABETICAL_ORDER = 2; + private int ordering; + + public static final int NON_PRIVATE_EXTRACTED_NEVER = 0; + public static final int NON_PRIVATE_EXTRACTED_ONE_CALLER = 1; + public static final int NON_PRIVATE_EXTRACTED_ANY_CALLERS = 2; + + private int nonPrivateTreatment; + + public static final int COMMENT_TYPE_TOP_LEVEL = 0; + public static final int COMMENT_TYPE_EACH_LEVEL = 1; + public static final int COMMENT_TYPE_EACH_METHOD = 2; + public static final int COMMENT_TYPE_NEW_FAMILY = 3; + + private int commentType; + private CommentRule precedingComment; + private CommentRule trailingComment; + private CommentFillString commentFillString; + + private RelatedByNameMethodsSettings rbnms; + + public RelatedByNameMethodsSettings getRbnms() { + return rbnms; + } + + public RelatedMethodsSettings() { + belowFirstCaller = true; + depthFirstOrdering = true; + ordering = INVOCATION_ORDER; + nonPrivateTreatment = NON_PRIVATE_EXTRACTED_ANY_CALLERS; + commentType = COMMENT_TYPE_TOP_LEVEL; + precedingComment = new CommentRule(); + trailingComment = new CommentRule(); + rbnms = new RelatedByNameMethodsSettings(); + commentFillString = new CommentFillString(); + } + + public boolean isMoveExtractedMethods() { + return moveExtractedMethods; + } + + public void setMoveExtractedMethods(boolean moveExtractedMethods) { + this.moveExtractedMethods = moveExtractedMethods; + } + + public boolean isBelowFirstCaller() { + return belowFirstCaller; + } + + public void setBelowFirstCaller(boolean belowFirstCaller) { + this.belowFirstCaller = belowFirstCaller; + } + + public boolean isDepthFirstOrdering() { + return depthFirstOrdering; + } + + public void setDepthFirstOrdering(boolean depthFirstOrdering) { + this.depthFirstOrdering = depthFirstOrdering; + } + + public int getOrdering() { + return ordering; + } + + public void setOrdering(int ordering) { + this.ordering = ordering; + } + + public int getNonPrivateTreatment() { + return nonPrivateTreatment; + } + + public void setNonPrivateTreatment(int nonPrivateTreatment) { + this.nonPrivateTreatment = nonPrivateTreatment; + } + + public int getCommentType() { + return commentType; + } + + public void setCommentType(int commentType) { + this.commentType = commentType; + } + + public CommentRule getPrecedingComment() { + return precedingComment; + } + + public void setPrecedingComment(CommentRule precedingComment) { + this.precedingComment = precedingComment; + } + + public CommentRule getTrailingComment() { + return trailingComment; + } + + public void setTrailingComment(CommentRule trailingComment) { + this.trailingComment = trailingComment; + } + + public CommentFillString getCommentFillString() { + return commentFillString; + } + + public boolean equals(Object object) { + if (object instanceof RelatedMethodsSettings) { + RelatedMethodsSettings rms = (RelatedMethodsSettings)object; + return (rms.moveExtractedMethods == moveExtractedMethods && + rms.belowFirstCaller == belowFirstCaller && + rms.depthFirstOrdering == depthFirstOrdering && + rms.ordering == ordering && + rms.nonPrivateTreatment == nonPrivateTreatment && + rms.commentType == commentType && + rms.precedingComment.equals(precedingComment) && + rms.trailingComment.equals(trailingComment) && + rms.commentFillString.equals(commentFillString)); + } + return false; + } + + public RelatedMethodsSettings deepCopy() { + RelatedMethodsSettings result = new RelatedMethodsSettings(); + result.moveExtractedMethods = moveExtractedMethods; + result.belowFirstCaller = belowFirstCaller; + result.depthFirstOrdering = depthFirstOrdering; + result.ordering = ordering; + result.nonPrivateTreatment = nonPrivateTreatment; + result.commentType = commentType; + result.precedingComment = (CommentRule)precedingComment.deepCopy(); + result.trailingComment = (CommentRule)trailingComment.deepCopy(); + result.commentFillString = commentFillString.deepCopy(); + return result; + } + + public String toString() { + return "moveExtractedMethods=" + moveExtractedMethods + + ", belowFirstCaller=" + belowFirstCaller + + ", depthFirstOrdering=" + depthFirstOrdering + + ", ordering=" + ordering + + ", non-private treatment=" + nonPrivateTreatment + + ", comment type=" + commentType; + } + + public void loadAttributes(final Element me) { + moveExtractedMethods = RearrangerSettings.getBooleanAttribute(me, "moveExtractedMethods"); + belowFirstCaller = RearrangerSettings.getBooleanAttribute(me, "belowFirstCaller", true); + depthFirstOrdering = RearrangerSettings.getBooleanAttribute(me, "depthFirstOrdering", true); + ordering = RearrangerSettings.getIntAttribute(me, + "ordering", + INVOCATION_ORDER); + nonPrivateTreatment = RearrangerSettings.getIntAttribute(me, + "nonPrivateTreatment", + NON_PRIVATE_EXTRACTED_ANY_CALLERS); + commentType = RearrangerSettings.getIntAttribute(me, + "commentType", + COMMENT_TYPE_TOP_LEVEL); + Element prc = me.getChild("PrecedingComment"); + if (prc != null) prc = prc.getChild("Comment"); + precedingComment = CommentRule.readExternal(prc); + Element trc = me.getChild("TrailingComment"); + if (trc != null) trc = trc.getChild("Comment"); + trailingComment = CommentRule.readExternal(trc); + commentFillString = CommentFillString.readExternal(me); + } + + public static RelatedMethodsSettings readExternal(final Element item) { + final RelatedMethodsSettings result = new RelatedMethodsSettings(); + result.loadAttributes(item); + return result; + } + + public final void writeExternal(final Element me) { + me.setAttribute("moveExtractedMethods", Boolean.valueOf(moveExtractedMethods).toString()); + me.setAttribute("belowFirstCaller", Boolean.valueOf(belowFirstCaller).toString()); + me.setAttribute("depthFirstOrdering", Boolean.valueOf(depthFirstOrdering).toString()); + me.setAttribute("ordering", "" + ordering); + me.setAttribute("nonPrivateTreatment", "" + nonPrivateTreatment); + me.setAttribute("commentType", "" + commentType); + Element prc = new Element("PrecedingComment"); + Element trc = new Element("TrailingComment"); + me.getChildren().add(prc); + me.getChildren().add(trc); + precedingComment.writeExternal(prc); + trailingComment.writeExternal(trc); + commentFillString.writeExternal(me); + } + + public void addCommentPatternsToList(List list) { + addCommentPatternToList(precedingComment, list); + addCommentPatternToList(trailingComment, list); + } + + private void addCommentPatternToList(CommentRule comment, List list) { + String s = null; + if (comment != null) { + s = comment.getCommentText(); + } + if (s != null && s.length() > 0) { + String esc = RegexUtil.escape(s); + String fsp = commentFillString.getFillStringPattern(); + + s = RegexUtil.replaceAllFS(esc, fsp); + s = s.replaceAll("%TL%", "[A-Za-z0-9_()]+"); + s = s.replaceAll("%MN%", "[A-Za-z0-9_()]+"); + s = s.replaceAll("%AM%", "[A-Za-z0-9_\\\\[\\\\],.]+"); + s = s.replaceAll("%LV%", "[0-9]+"); + list.add(s); + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/SecondaryMethodSetting.java b/plugins/rearranger/src/com/wrq/rearranger/settings/SecondaryMethodSetting.java new file mode 100644 index 000000000000..9547a75e941d --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/SecondaryMethodSetting.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings; + +import com.wrq.rearranger.configuration.IListManagerObject; +import com.wrq.rearranger.configuration.IntTextField; +import com.wrq.rearranger.configuration.StringTextArea; +import com.wrq.rearranger.configuration.StringTextField; + +import javax.swing.*; +import java.awt.*; + + +/** + * Contains settings for each secondary method (e.g., "set", "is"). Any number of secondary method definitions + * may be associated with a primary method definition. + */ +public class SecondaryMethodSetting + implements IListManagerObject +{ + /** Description of the related method. */ + String description; + /** + * Regular expression which method name must match. If the method is to be matched to a field, there must be + * at least one capture group (parenthesized subexpression) which will be treated as the field. + * In the case of a traditional setter method, this pattern is "set%FN%". One substitution is available: + *
+   * %FN%  field name
+   * 
+ */ + String methodNamePattern; + /** number of parameters the secondary method must have. In the case of a traditional setter method, this is one. */ + int numParameters; + /** + * regular expression pattern of the type which the secondary method must return. + * In the case of a traditional getter method, this is the field type. One substitution is available: + *
+   * %FT%  field type
+   * 
+ */ + String methodTypePattern; + /** + * regular expression pattern of the attributes of the method. + * In the case of a traditional getter method, this is ".*public.*" (i.e., any public method). + */ + String methodAttributePattern; + /** + * pattern of method body (excluding comments and newline characters). Substitutions are available as follows: + *
+   * %FN%  field name
+   * %FT%  field type (if field is valid field, else empty string)
+   * %MT%  method return type
+   * %P1%  parameter 1 name (%P2%, %P3% etc for additional parameters)
+   * %T1%  parameter 1 type name
+   * 
+ */ + String body; + + public SecondaryMethodSetting() { + methodNamePattern = "set%FN%"; + numParameters = 1; + methodTypePattern = "void"; + methodAttributePattern = ".*public.*"; + body = "{\\s*return\\s*%FN%;\\s*}"; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getMethodNamePattern() { + return methodNamePattern; + } + + public void setMethodNamePattern(String methodNamePattern) { + this.methodNamePattern = methodNamePattern; + } + + public int getNumParameters() { + return numParameters; + } + + public void setNumParameters(int numParameters) { + this.numParameters = numParameters; + } + + public String getMethodTypePattern() { + return methodTypePattern; + } + + public void setMethodTypePattern(String methodTypePattern) { + this.methodTypePattern = methodTypePattern; + } + + public String getMethodAttributePattern() { + return methodAttributePattern; + } + + public void setMethodAttributePattern(String methodAttributePattern) { + this.methodAttributePattern = methodAttributePattern; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String toString() { + return description; + } + + public com.wrq.rearranger.configuration.IListManagerObject deepcopy() { + SecondaryMethodSetting pms = new SecondaryMethodSetting(); + pms.description = getDescription(); + pms.methodNamePattern = getMethodNamePattern(); + pms.numParameters = getNumParameters(); + pms.methodTypePattern = getMethodTypePattern(); + pms.methodAttributePattern = getMethodAttributePattern(); + pms.body = getBody(); + return pms; + } + + public boolean equals(Object obj) { + if (!(obj instanceof PrimaryMethodSetting)) return false; + PrimaryMethodSetting pms = (PrimaryMethodSetting)obj; + if (!pms.description.equals(description)) return false; + if (!pms.methodNamePattern.equals(methodNamePattern)) return false; + if (pms.numParameters != numParameters) return false; + if (!pms.methodTypePattern.equals(methodTypePattern)) return false; + if (!pms.methodAttributePattern.equals(methodAttributePattern)) return false; + if (!pms.body.equals(body)) return false; + return true; + } + + public JPanel getPanel() { + JPanel panel = new JPanel(new GridBagLayout()); + panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), + "Matching Method (\"Setter\") Criteria")); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = 1; + constraints.gridheight = 1; + constraints.weightx = 0.0d; + constraints.weighty = 0.0d; + constraints.gridy = constraints.gridx = 0; + constraints.insets = new Insets(3, 3, 3, 3); + JLabel methodNamePatternLabel = new JLabel("Method name:"); + methodNamePatternLabel.setToolTipText( + "Regular expression which method name must match. " + + "If the method is to be matched to a field, there must be\n" + + " at least one capture group (parenthesized subexpression) which will be treated as the field.\n" + + " In the case of a traditional setter method, this pattern is \"set%FN%\".\n" + + " One substitution is available:\n" + + " %FN% field name"); + panel.add(methodNamePatternLabel, constraints); + constraints.gridx++; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = .5; + StringTextField primaryPrefixText = new StringTextField() { + public void setValue(String value) { + setMethodNamePattern(value); + } + + public String getValue() { + return getMethodNamePattern(); + } + }; + panel.add(primaryPrefixText, constraints); + constraints.fill = GridBagConstraints.NONE; + constraints.weightx = 0; + constraints.gridx++; + JLabel nParamLabel = new JLabel("Number of parameters:"); + nParamLabel.setToolTipText( + "number of parameters the secondary method must have.\n" + + "In the case of a traditional setter method, this is 1."); + panel.add(nParamLabel, constraints); + constraints.gridx++; + IntTextField nParamText = new IntTextField( + new IntTextField.IGetSet() { + public int get() { + return numParameters; + } + + public void set(int value) { + numParameters = value; + } + }, null, null + ); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = GridBagConstraints.REMAINDER; + panel.add(nParamText, constraints); + + constraints.gridx = 0; + constraints.gridy++; + constraints.gridwidth = 1; + constraints.weightx = 0; + constraints.fill = GridBagConstraints.NONE; + JLabel returnTypeLabel = new JLabel("Return type:"); + returnTypeLabel.setToolTipText( + "regular expression pattern of the type which the secondary method must return.\n" + + " In the case of a traditional setter method, this is void. One substitution is available:\n" + + " * %FT% field type"); + panel.add(returnTypeLabel, constraints); + constraints.gridx++; + constraints.weightx = .5; + constraints.fill = GridBagConstraints.HORIZONTAL; + StringTextField returnTypeField = new StringTextField() { + public void setValue(String value) { + methodTypePattern = value; + } + + public String getValue() { + return methodTypePattern; + } + }; + panel.add(returnTypeField, constraints); + constraints.fill = GridBagConstraints.NONE; + constraints.gridx++; + constraints.weightx = 0; + JLabel methodAttributeLabel = new JLabel("Method attributes:"); + methodAttributeLabel.setToolTipText("Protection level or other attributes for the method.\n" + + "In the case of a getter method, this is usually \".*public.*\"."); + panel.add(methodAttributeLabel, constraints); + StringTextField methodAttributeField = new StringTextField() { + public void setValue(String value) { + methodAttributePattern = value; + } + + public String getValue() { + return methodAttributePattern; + } + }; + constraints.gridx++; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = .5; + constraints.fill = GridBagConstraints.HORIZONTAL; + panel.add(methodAttributeField, constraints); + constraints.gridx++; + constraints.weightx = 0; + constraints.fill = GridBagConstraints.NONE; + constraints.gridy++; + constraints.gridx = 0; + JLabel bodyLabel = new JLabel("Body:"); + bodyLabel.setToolTipText("regular expression pattern of method body (excluding comments and newline characters).\n" + + "Substitutions are available as follows:\n" + + " %FN% field name\n" + + " %FT% field type (if field is valid field, else empty string)\n" + + " %MT% method return type\n" + + " %P1% parameter 1 name (%P2%, %P3% etc for additional parameters)\n" + + " %T1% parameter 1 type name"); + constraints.gridwidth = 1; + constraints.weightx = 0; + constraints.fill = GridBagConstraints.NONE; + panel.add(bodyLabel, constraints); + constraints.gridx++; + StringTextArea bodyField = new StringTextArea() { + public void setValue(String value) { + body = value; + } + + public String getValue() { + return body; + } + }; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1; + constraints.weighty = .35; + constraints.fill = GridBagConstraints.BOTH; + JScrollPane sp = new JScrollPane(bodyField); + panel.add(sp, constraints); + constraints.gridx = 0; + constraints.gridy++; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.fill = GridBagConstraints.NONE; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1; + constraints.weighty = .65; + return panel; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AbstractAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AbstractAttribute.java new file mode 100644 index 000000000000..82f3608a656b --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AbstractAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +import java.lang.reflect.Modifier; + +/** Common routines for 'abstract' modifier. */ +public final class AbstractAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static AbstractAttribute readExternal(final Element item) { + final AbstractAttribute result = new AbstractAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public AbstractAttribute() { + super("abstract", Modifier.ABSTRACT); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*AbstractAttribute*/AtomicAttribute deepCopy() { + final AbstractAttribute aba = new AbstractAttribute(); + aba.value = value; + aba.invert = invert; + return aba; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java new file mode 100644 index 000000000000..f3180b76f6a9 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Element; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** Base class for all boolean attributes. */ +abstract public class AndNotAttribute + extends AtomicAttribute +{ +// ------------------------------ FIELDS ------------------------------ + + boolean value; + boolean invert; + private final String valueName; + private final int modifierBit; + +// --------------------------- CONSTRUCTORS --------------------------- + + AndNotAttribute(final String s, final int modifierBit) { + valueName = s; + this.modifierBit = modifierBit; + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public final JPanel getAndNotPanel() { + final JPanel andNotPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.WEST); + final JCheckBox andBox = new JCheckBox("And"); + andBox.setSelected(isValue()); + final JCheckBox notBox = new JCheckBox("not"); + notBox.setSelected(isInvert()); + notBox.setEnabled(andBox.isSelected()); + notBox.setForeground(notBox.isSelected() ? Color.BLACK : Color.GRAY); + final JLabel nameLabel = new JLabel(getName()); + nameLabel.setEnabled(andBox.isSelected()); + andNotPanel.add(andBox, constraints.firstCol()); + andNotPanel.add(notBox, constraints.nextCol()); + constraints.insets = new Insets(0, 0, 0, 4); + andNotPanel.add(nameLabel, constraints.weightedLastCol()); + andBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setValue(andBox.isSelected()); + notBox.setEnabled(andBox.isSelected()); + nameLabel.setEnabled(andBox.isSelected()); + } + }); + notBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setInvert(notBox.isSelected()); + notBox.setForeground(notBox.isSelected() ? Color.BLACK : Color.GRAY); + } + }); + return andNotPanel; + } + + private String getName() { + return valueName; + } + + public final boolean isInvert() { + return invert; + } + + public final void setInvert(final boolean invert) { + this.invert = invert; + } + + public final boolean isValue() { + return value; + } + + public final void setValue(final boolean value) { + this.value = value; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public final boolean equals(final Object obj) { + if (!(obj instanceof AndNotAttribute)) return false; + final AndNotAttribute ana = (AndNotAttribute)obj; + return (value == ana.value && + invert == ana.invert && + valueName.equals(ana.valueName) && + modifierBit == ana.modifierBit); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final void appendAttributes(final Element me) { + final Element stElement = new Element(getElementName()); + me.getChildren().add(stElement); + stElement.setAttribute("value", Boolean.valueOf(value).toString()); + stElement.setAttribute("invert", Boolean.valueOf(invert).toString()); + } + + final String getElementName() { + final StringBuffer sb = new StringBuffer(valueName.length()); + sb.append(valueName); + sb.replace(0, 1, new String("" + sb.charAt(0)).toUpperCase()); + for (int i = 1; i < sb.length(); i++) { + if (sb.charAt(i) == ' ') { + sb.deleteCharAt(i); + sb.replace(i, i + 1, new String("" + sb.charAt(i)).toUpperCase()); + } + } + return sb.toString(); + } + + public final String getDescriptiveString() { + return (isValue() ? + isInvert() ? "non-" + valueName + " " : valueName + " " + : ""); + } + + public final boolean isMatch(final int modifiers) { + return (!isValue()) ? true : ((modifiers & modifierBit) > 0) ^ isInvert(); + } + + public final void loadAttributes(final Element item) { + value = RearrangerSettings.getBooleanAttribute(item, "value"); + invert = RearrangerSettings.getBooleanAttribute(item, "invert"); + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AtomicAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AtomicAttribute.java new file mode 100644 index 000000000000..994fc492cda2 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AtomicAttribute.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + + +/** base class for all individual attributes that a field, method or class may have. */ +abstract public class AtomicAttribute { + + /** + * All subclasses will implement a static public AtomicAttribute readExternal(final Element item) method. + * However, because it is static, the interface can't contain it. + */ +// abstract public AtomicAttribute readExternal(final Element item); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/EnumAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/EnumAttribute.java new file mode 100644 index 000000000000..a58bdc2aa8c0 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/EnumAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.ModifierConstants; +import org.jdom.Element; + +/** Routines to handle 'enum' class attribute. */ +public class EnumAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static EnumAttribute readExternal(final Element item) { + final EnumAttribute result = new EnumAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public EnumAttribute() { + super("enum", ModifierConstants.ENUM); + } + +// -------------------------- OTHER METHODS -------------------------- + + /** final attribute. */ + public final /*EnumAttribute*/AtomicAttribute deepCopy() { + final EnumAttribute result = new EnumAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/FinalAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/FinalAttribute.java new file mode 100644 index 000000000000..acf75802d0de --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/FinalAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +import java.lang.reflect.Modifier; + +/** Routines to handle the 'final' modifier. */ +public final class FinalAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static FinalAttribute readExternal(final Element item) { + final FinalAttribute result = new FinalAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public FinalAttribute() { + super("final", Modifier.FINAL); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*FinalAttribute*/AtomicAttribute deepCopy() { + final FinalAttribute result = new FinalAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ImplementedAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ImplementedAttribute.java new file mode 100644 index 000000000000..92b48ae79f48 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ImplementedAttribute.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.ModifierConstants; +import org.jdom.Element; + + +public final class ImplementedAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static ImplementedAttribute readExternal(final Element item) { + final ImplementedAttribute result = new ImplementedAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public ImplementedAttribute() { + super("implemented", ModifierConstants.IMPLEMENTED); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*ImplementedAttribute*/AtomicAttribute deepCopy() { + final ImplementedAttribute result = new ImplementedAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ImplementingAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ImplementingAttribute.java new file mode 100644 index 000000000000..77059d784ba9 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ImplementingAttribute.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.ModifierConstants; +import org.jdom.Element; + +public final class ImplementingAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static ImplementingAttribute readExternal(final Element item) { + final ImplementingAttribute result = new ImplementingAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public ImplementingAttribute() { + super("implementing", ModifierConstants.IMPLEMENTING); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*ImplementingAttribute*/AtomicAttribute deepCopy() { + final ImplementingAttribute result = new ImplementingAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java new file mode 100644 index 000000000000..e3cbef25990b --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.ModifierConstants; +import org.jdom.Element; + +public final class InitToAnonClassAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static InitToAnonClassAttribute readExternal(final Element item) { + final InitToAnonClassAttribute result = new InitToAnonClassAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public InitToAnonClassAttribute() { + super("initialized to anonymous class", ModifierConstants.INIT_TO_ANON_CLASS); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*InitToAnonClassAttribute*/AtomicAttribute deepCopy() { + final InitToAnonClassAttribute result = new InitToAnonClassAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitializerAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitializerAttribute.java new file mode 100644 index 000000000000..8b18576538b1 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitializerAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.ModifierConstants; +import org.jdom.Element; + +/** Routines to handle a static initializer method. */ +public final class InitializerAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static InitializerAttribute readExternal(final Element item) { + final InitializerAttribute result = new InitializerAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public InitializerAttribute() { + super("initializer", ModifierConstants.INITIALIZER); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*InitializerAttribute*/AtomicAttribute deepCopy() { + final InitializerAttribute result = new InitializerAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/IntegerAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/IntegerAttribute.java new file mode 100644 index 000000000000..ddbc7361f745 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/IntegerAttribute.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.wrq.rearranger.configuration.IntTextField; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import com.wrq.rearranger.util.MethodUtil; +import org.jdom.Element; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** Allow item selection by comparison with an integer attribute. */ +abstract public class IntegerAttribute extends AtomicAttribute { + public static final int OP_GE = 0; + public static final int OP_LE = 1; + + // ------------------------------ FIELDS ------------------------------ + protected int value; + protected int opType; + protected boolean match; // when true, condition applies + private final String attributeDisplayName; // should be plural + private final String storageName; + +// --------------------------- CONSTRUCTORS --------------------------- + + IntegerAttribute(final String attributeDisplayName, + final String storageName, + final int opType) + { + this.attributeDisplayName = attributeDisplayName; + this.storageName = storageName; + this.opType = opType; + } + + // --------------------- GETTER / SETTER METHODS --------------------- + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public int getOpType() { + return opType; + } + + public final boolean isMatch() { + return match; + } + + public final void setMatch(final boolean match) { + this.match = match; + } + + public final JPanel getIntegerPanel() { + final JPanel intPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(); + constraints.weightedLastRow(); + final JCheckBox enableBox = new JCheckBox(opType == OP_GE ? "with at least" : "with at most"); + intPanel.add(enableBox, constraints.firstCol()); + final IntTextField intField = new IntTextField( + new IntTextField.IGetSet() { + public int get() { + return value; + } + + public void set(int v) { + value = v; + } + }, + 0, 99); + + constraints.insets = new Insets(0, 3, 0, 0); + intPanel.add(intField, constraints.nextCol()); + final JLabel attribLabel = new JLabel(attributeDisplayName + "s"); + intPanel.add(attribLabel, constraints.weightedLastCol()); + enableBox.setSelected(match); + enableBox.setForeground(enableBox.isSelected() ? Color.BLACK : Color.GRAY); + intField.setEnabled(match); + attribLabel.setEnabled(match); + enableBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setMatch(enableBox.isSelected()); + intPanel.setEnabled(enableBox.isSelected()); + enableBox.setSelected(match); + enableBox.setForeground(enableBox.isSelected() ? Color.BLACK : Color.GRAY); + intField.setEnabled(match); + attribLabel.setEnabled(match); + } + }); + return intPanel; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public boolean equals(final Object obj) { + if (!(obj instanceof IntegerAttribute)) return false; + final IntegerAttribute na = (IntegerAttribute)obj; + return match == na.match && + opType == na.opType && + value == na.value; + } + +// -------------------------- OTHER METHODS -------------------------- + + public final void appendAttributes(final Element me) { + final Element stElement = new Element(storageName); + + me.getChildren().add(stElement); + stElement.setAttribute("match", Boolean.valueOf(match).toString()); + stElement.setAttribute("opType", "" + opType); + stElement.setAttribute("value", "" + value); + } + + protected final void deepCopy(IntegerAttribute result) { + result.match = match; + result.opType = opType; + result.value = value; + } + + public final String getDescriptiveString() { + return (match ? + (opType == OP_GE ? "with at least " : "with at most ") + + value + " " + attributeDisplayName + (value != 1 ? "s" : "") + : ""); + } + + public final boolean isMatch(PsiElement value) { + if (!match) return true; + if (!(value instanceof PsiMethod)) return false; + PsiMethod method = (PsiMethod)value; + int n = MethodUtil.nofParameters(method); + if (opType == OP_GE) { + return n >= this.value; + } + else { + return n <= this.value; + } + } + + public final void loadAttributes(final Element item) { + match = RearrangerSettings.getBooleanAttribute(item, "match", false); + // opType = RearrangerSettings.getIntAttribute(item, "opType", opType); -- never load opType, it is immutable + value = RearrangerSettings.getIntAttribute(item, "value", 0); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/MaxParamsAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/MaxParamsAttribute.java new file mode 100644 index 000000000000..e6c1194557bb --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/MaxParamsAttribute.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +/** Common routines for 'maximum number of params' modifier. */ +public class MaxParamsAttribute + extends IntegerAttribute +{ + private static final String PROPNAME = "MAX_PARAMS"; + // -------------------------- STATIC METHODS -------------------------- + + public static MaxParamsAttribute readExternal(final Element item) { + final MaxParamsAttribute result = new MaxParamsAttribute(); + result.loadAttributes(item.getChild(PROPNAME)); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public MaxParamsAttribute() { + super("parameter", PROPNAME, IntegerAttribute.OP_LE); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*AbstractAttribute*/AtomicAttribute deepCopy() { + final MaxParamsAttribute mpa = new MaxParamsAttribute(); + mpa.value = value; + mpa.match = match; + return mpa; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/MinParamsAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/MinParamsAttribute.java new file mode 100644 index 000000000000..4d3f301007f1 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/MinParamsAttribute.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +/** Common routines for 'minimum number of params' modifier. */ +public class MinParamsAttribute + extends IntegerAttribute +{ + private static final String PROPNAME = "MIN_PARAMS"; + // -------------------------- STATIC METHODS -------------------------- + + public static MinParamsAttribute readExternal(final Element item) { + final MinParamsAttribute result = new MinParamsAttribute(); + result.loadAttributes(item.getChild(PROPNAME)); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public MinParamsAttribute() { + super("parameter", PROPNAME, IntegerAttribute.OP_GE); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*AbstractAttribute*/AtomicAttribute deepCopy() { + final MinParamsAttribute mpa = new MinParamsAttribute(); + mpa.value = value; + mpa.match = match; + return mpa; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/NameAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/NameAttribute.java new file mode 100644 index 000000000000..d77f755ab4a8 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/NameAttribute.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +/** Allows item selection by matching its name to a regular expression. */ +public final class NameAttribute extends StringAttribute { + +// -------------------------- STATIC METHODS -------------------------- + + public static NameAttribute readExternal(final Element item) { + final NameAttribute result = new NameAttribute(); + result.loadAttributes(item.getChild("NameMatch")); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public NameAttribute() { + super("names", "NameMatch"); + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public final boolean equals(final Object object) { + if (!(object instanceof NameAttribute)) return false; + return super.equals(object); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*NameAttribute*/AtomicAttribute deepCopy() { + final NameAttribute result = new NameAttribute(); + super.deepCopy(result); + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/NativeAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/NativeAttribute.java new file mode 100644 index 000000000000..e36af5c7fe3b --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/NativeAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +import java.lang.reflect.Modifier; + +/** Handles the 'native' modifier. */ +public final class NativeAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static NativeAttribute readExternal(final Element item) { + final NativeAttribute result = new NativeAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public NativeAttribute() { + super("native", Modifier.NATIVE); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*NativeAttribute*/AtomicAttribute deepCopy() { + final NativeAttribute result = new NativeAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/OverriddenAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/OverriddenAttribute.java new file mode 100644 index 000000000000..e922cc316a34 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/OverriddenAttribute.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.ModifierConstants; +import org.jdom.Element; + + +public final class OverriddenAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static OverriddenAttribute readExternal(final Element item) { + final OverriddenAttribute result = new OverriddenAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public OverriddenAttribute() { + super("overridden", ModifierConstants.OVERRIDDEN); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*OverriddenAttribute*/AtomicAttribute deepCopy() { + final OverriddenAttribute result = new OverriddenAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/OverridingAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/OverridingAttribute.java new file mode 100644 index 000000000000..3e3af6a95909 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/OverridingAttribute.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.ModifierConstants; +import org.jdom.Element; + +public final class OverridingAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static OverridingAttribute readExternal(final Element item) { + final OverridingAttribute result = new OverridingAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public OverridingAttribute() { + super("overriding", ModifierConstants.OVERRIDING); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*OverridingAttribute*/AtomicAttribute deepCopy() { + final OverridingAttribute result = new OverridingAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ProtectionLevelAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ProtectionLevelAttributes.java new file mode 100644 index 000000000000..9ff8cfc8b3c8 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ProtectionLevelAttributes.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Element; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.reflect.Modifier; + +/** Routines to handle the four protection level modifiers. */ +public final class ProtectionLevelAttributes + extends AtomicAttribute +{ + +// ------------------------------ FIELDS ------------------------------ + + /** protection levels. */ + private boolean plPublic; + private boolean plPrivate; + private boolean plProtected; + private boolean plPackage; + private boolean invertProtectionLevel; + +// -------------------------- STATIC METHODS -------------------------- + + public static ProtectionLevelAttributes readExternal(final Element item) { + final ProtectionLevelAttributes result = new ProtectionLevelAttributes(); + final Element me = item.getChild("ProtectionLevel"); + result.loadAttributes(me); + return result; + } + + private void loadAttributes(final Element me) { + plPublic = RearrangerSettings.getBooleanAttribute(me, "public"); + plPrivate = RearrangerSettings.getBooleanAttribute(me, "private"); + plProtected = RearrangerSettings.getBooleanAttribute(me, "protected"); + plPackage = RearrangerSettings.getBooleanAttribute(me, "package"); + invertProtectionLevel = RearrangerSettings.getBooleanAttribute(me, "invert"); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + private boolean isInvertProtectionLevel() { + return invertProtectionLevel; + } + + public final void setInvertProtectionLevel(final boolean invertProtectionLevel) { + this.invertProtectionLevel = invertProtectionLevel; + } + + private boolean isPlPackage() { + return plPackage; + } + + public final void setPlPackage(final boolean plPackage) { + this.plPackage = plPackage; + } + + private boolean isPlPrivate() { + return plPrivate; + } + + public void setPlPrivate(final boolean plPrivate) { + this.plPrivate = plPrivate; + } + + private boolean isPlProtected() { + return plProtected; + } + + public final void setPlProtected(final boolean plProtected) { + this.plProtected = plProtected; + } + + private boolean isPlPublic() { + return plPublic; + } + + public final void setPlPublic(final boolean plPublic) { + this.plPublic = plPublic; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public boolean equals(final Object obj) { + if (!(obj instanceof ProtectionLevelAttributes)) return false; + final ProtectionLevelAttributes pla = (ProtectionLevelAttributes)obj; + return plPublic == pla.plPublic && + plPrivate == pla.plPrivate && + plProtected == pla.plProtected && + plPackage == pla.plPackage && + invertProtectionLevel == pla.invertProtectionLevel; + } + +// -------------------------- OTHER METHODS -------------------------- + + public final void appendAttributes(final Element me) { + final Element plElement = new Element("ProtectionLevel"); + me.getChildren().add(plElement); + plElement.setAttribute("public", Boolean.valueOf(plPublic).toString()); + plElement.setAttribute("private", Boolean.valueOf(plPrivate).toString()); + plElement.setAttribute("protected", Boolean.valueOf(plProtected).toString()); + plElement.setAttribute("package", Boolean.valueOf(plPackage).toString()); + plElement.setAttribute("invert", Boolean.valueOf(invertProtectionLevel).toString()); + } + + public final /*ProtectionLevelAttributes*/AtomicAttribute deepCopy() { + final ProtectionLevelAttributes pla = new ProtectionLevelAttributes(); + pla.plPublic = plPublic; + pla.plPrivate = plPrivate; + pla.plProtected = plProtected; + pla.plPackage = plPackage; + pla.invertProtectionLevel = invertProtectionLevel; + return pla; + } + + public final JPanel getProtectionLevelPanel() { + final JPanel plPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(); + constraints.weightedLastRow(); + constraints.fill = GridBagConstraints.BOTH; + final JCheckBox notBox = new JCheckBox("not"); + notBox.setSelected(isInvertProtectionLevel()); + notBox.setForeground(notBox.isSelected() ? Color.BLACK : Color.GRAY); + plPanel.add(notBox, constraints.firstCol()); + final JPanel plLevels = getProtLevels(); + plPanel.add(plLevels, constraints.weightedLastCol()); + notBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setInvertProtectionLevel(notBox.isSelected()); + notBox.setForeground(notBox.isSelected() ? Color.BLACK : Color.GRAY); + } + }); + + return plPanel; + } + + private JPanel getProtLevels() { + final JPanel plPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(); + final JCheckBox publicBox = new JCheckBox("public or"); + publicBox.setSelected(isPlPublic()); + final JCheckBox privateBox = new JCheckBox("private or"); + privateBox.setSelected(isPlPrivate()); + final JCheckBox protectedBox = new JCheckBox("protected or"); + protectedBox.setSelected(isPlProtected()); + final JCheckBox packageBox = new JCheckBox("package"); + packageBox.setSelected(isPlPackage()); + plPanel.add(publicBox, constraints.weightedLastCol()); + constraints.newRow(); + plPanel.add(privateBox, constraints.weightedLastCol()); + constraints.newRow(); + plPanel.add(protectedBox, constraints.weightedLastCol()); + constraints.weightedLastRow(); + plPanel.add(packageBox, constraints.weightedLastCol()); + publicBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setPlPublic(publicBox.isSelected()); + } + }); + privateBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setPlPrivate(privateBox.isSelected()); + } + }); + protectedBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setPlProtected(protectedBox.isSelected()); + } + }); + packageBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setPlPackage(packageBox.isSelected()); + } + }); + return plPanel; + } + + public final String getProtectionLevelString() { + final StringBuffer sb = new StringBuffer(60); + final int nProtLevels = (isPlPublic() ? 1 : 0) + + (isPlPrivate() ? 1 : 0) + + (isPlProtected() ? 1 : 0) + + (isPlPackage() ? 1 : 0); + + int nProtLevelsSeen = 0; + if (isPlPublic()) { + sb.append(isInvertProtectionLevel() ? "non-public" : "public"); + nProtLevelsSeen++; + if (nProtLevelsSeen < nProtLevels) { + sb.append("/"); + } + } + if (isPlPrivate()) { + sb.append(isInvertProtectionLevel() ? "non-private" : "private"); + nProtLevelsSeen++; + if (nProtLevelsSeen < nProtLevels) { + sb.append("/"); + } + } + if (isPlProtected()) { + sb.append(isInvertProtectionLevel() ? "non-protected" : "protected"); + nProtLevelsSeen++; + if (nProtLevelsSeen < nProtLevels) { + sb.append("/"); + } + } + if (isPlPackage()) { + sb.append(isInvertProtectionLevel() ? "non-package" : "package"); + nProtLevelsSeen++; + if (nProtLevelsSeen < nProtLevels) { + sb.append("/"); + } + } + if (nProtLevels > 0) { + sb.append(' '); + } + return sb.toString(); + } + + /** + * @param modifiers Java modifiers for the field, method or class. + * @return true if the supplied protection level modifiers match this object's modifier requirements. + */ + public final boolean isMatch(final int modifiers) { + boolean result; + if (!plPublic && !plPrivate && !plProtected && !plPackage) { + return true; // nothing selected, so don't take protection level into account. + } + result = + (plPublic && Modifier.isPublic(modifiers)) || + (plPrivate && Modifier.isPrivate(modifiers)) || + (plProtected && Modifier.isProtected(modifiers)) || + (plPackage && !(Modifier.isPublic(modifiers) || + Modifier.isPrivate(modifiers) || + Modifier.isProtected(modifiers))); + result ^= invertProtectionLevel; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ReturnTypeAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ReturnTypeAttribute.java new file mode 100644 index 000000000000..645d5e422d33 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/ReturnTypeAttribute.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +/** Allows method selection by matching its return type to a regular expression. */ +public final class ReturnTypeAttribute extends StringAttribute { + +// -------------------------- STATIC METHODS -------------------------- + + public static ReturnTypeAttribute readExternal(final Element item) { + final ReturnTypeAttribute result = new ReturnTypeAttribute(); + result.loadAttributes(item.getChild("ReturnTypeMatch")); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public ReturnTypeAttribute() { + super("return types", "ReturnTypeMatch"); + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public final boolean equals(final Object object) { + if (!(object instanceof ReturnTypeAttribute)) return false; + return super.equals(object); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*ReturnTypeAttribute*/AtomicAttribute deepCopy() { + final ReturnTypeAttribute result = new ReturnTypeAttribute(); + super.deepCopy(result); + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/SortOptions.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/SortOptions.java new file mode 100644 index 000000000000..1b1f43b26ce9 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/SortOptions.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Element; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Contains sorting attributes (part of common attributes; applies to fields, methods, inner and outer classes). + *

+ * Originally, methods and classes could only be sorted alphabetically by name (case sensitive). Fields could be + * sorted by type (optionally ignoring case), by name (case sensitive), or both. + *

+ * Beginning with release 4.4, all of these types (fields, methods and classes) can be sorted optionally by + * modifiers, optionally by type (optionally ignoring case), and by name (optionally ignoring case). This covers + * all permutations. Modifiers are always lower case so no need to ask about whether to ignore case. + */ +public class SortOptions + extends AtomicAttribute +{ + private boolean byModifiers; + private boolean byType; + private boolean isTypeCaseInsensitive; + private boolean byName; + private boolean isNameCaseInsensitive; + + public SortOptions() { + byModifiers = false; + byType = false; + isTypeCaseInsensitive = false; + byName = false; + isNameCaseInsensitive = false; + } + + public boolean isByModifiers() { + return byModifiers; + } + + public void setByModifiers(boolean byModifiers) { + this.byModifiers = byModifiers; + } + + public boolean isByName() { + return byName; + } + + public void setByName(boolean byName) { + this.byName = byName; + } + + public boolean isByType() { + return byType; + } + + public void setByType(boolean byType) { + this.byType = byType; + } + + public boolean isNameCaseInsensitive() { + return isNameCaseInsensitive; + } + + public void setNameCaseInsensitive(boolean nameCaseInsensitive) { + isNameCaseInsensitive = nameCaseInsensitive; + } + + public boolean isTypeCaseInsensitive() { + return isTypeCaseInsensitive; + } + + public void setTypeCaseInsensitive(boolean typeCaseInsensitive) { + isTypeCaseInsensitive = typeCaseInsensitive; + } + + public final boolean equals(final Object obj) { + if (!(obj instanceof SortOptions)) return false; + SortOptions so = (SortOptions)obj; + return byModifiers == so.byModifiers && + byType == so.byType && + isTypeCaseInsensitive == so.isTypeCaseInsensitive && + byName == so.byName && + isNameCaseInsensitive == so.isNameCaseInsensitive; + } + + public static SortOptions readExternal(final Element item) { + SortOptions result = new SortOptions(); + final Element me = item.getChild("SortOptions"); + result.loadAttributes(me); + // support old settings + result.byName |= RearrangerSettings.getBooleanAttribute(item, "alphabetize"); + result.byType |= RearrangerSettings.getBooleanAttribute(item, "sortByType", false); + result.isTypeCaseInsensitive |= RearrangerSettings.getBooleanAttribute(item, "ignoreTypeCase", false); + return result; + } + + private void loadAttributes(final Element me) { + byModifiers = RearrangerSettings.getBooleanAttribute(me, "byModifiers"); + byType = RearrangerSettings.getBooleanAttribute(me, "byType"); + isTypeCaseInsensitive = RearrangerSettings.getBooleanAttribute(me, "isTypeCaseInsensitive"); + byName = RearrangerSettings.getBooleanAttribute(me, "byName"); + isNameCaseInsensitive = RearrangerSettings.getBooleanAttribute(me, "isNameCaseInsensitive"); + } + + public final /*SortOptions*/ AtomicAttribute deepCopy() { + final SortOptions result = new SortOptions(); + result.byModifiers = byModifiers; + result.byType = byType; + result.isTypeCaseInsensitive = isTypeCaseInsensitive; + result.byName = byName; + result.isNameCaseInsensitive = isNameCaseInsensitive; + return result; + } + + public final void appendAttributes(final Element me) { + final Element plElement = new Element("SortOptions"); + me.getChildren().add(plElement); + plElement.setAttribute("byModifiers", Boolean.valueOf(byModifiers).toString()); + plElement.setAttribute("byType", Boolean.valueOf(byType).toString()); + plElement.setAttribute("isTypeCaseInsensitive", Boolean.valueOf(isTypeCaseInsensitive).toString()); + plElement.setAttribute("byName", Boolean.valueOf(byName).toString()); + plElement.setAttribute("isNameCaseInsensitive", Boolean.valueOf(isNameCaseInsensitive).toString()); + } + + public final String getDescriptiveString() { + StringBuilder sb = new StringBuilder(80); + if (byName && !isNameCaseInsensitive && !byModifiers && !byType) { + return " (alphabetized)"; + } + if (byModifiers || byType || byName) { + sb.append(" (sorted by"); + boolean needComma = false; + if (byModifiers) { + sb.append(" modifiers"); + needComma = true; + } + if (byType) { + if (needComma) { + sb.append(','); + } + sb.append(" type"); + if (isTypeCaseInsensitive) { + sb.append("(CI)"); + } + needComma = true; + } + if (byName) { + if (needComma) { + sb.append(','); + } + sb.append(" name"); + if (isNameCaseInsensitive) { + sb.append("(CI)"); + } + } + sb.append(")"); + } + return sb.toString(); + } + + public final JPanel getSortOptionsPanel() { + final JPanel abPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(); + final JLabel sortLabel = new JLabel("Sort"); + constraints.insets = new Insets(0, 5, 0, 5); + abPanel.add(sortLabel, constraints.firstCol()); + final JCheckBox byModifiersBox = new JCheckBox("by modifiers"); + final JCheckBox byTypeBox = new JCheckBox("by type"); + final JCheckBox typeCIBox = new JCheckBox("case insensitive"); + final JCheckBox byNameBox = new JCheckBox("by name"); + final JCheckBox nameCIBox = new JCheckBox("case insensitive"); + constraints.insets = new Insets(0, 0, 0, 0); + abPanel.add(byModifiersBox, constraints.weightedLastCol()); + constraints.newRow(); + constraints.nextCol(); + abPanel.add(byTypeBox, constraints.nextCol()); + abPanel.add(typeCIBox, constraints.weightedLastCol()); + constraints.weightedLastRow(); + constraints.nextCol(); + abPanel.add(byNameBox, constraints.nextCol()); + abPanel.add(nameCIBox, constraints.weightedLastCol()); + + byModifiersBox.setSelected(isByModifiers()); + byTypeBox.setSelected(isByType()); + typeCIBox.setSelected(isTypeCaseInsensitive()); + byNameBox.setSelected(isByName()); + nameCIBox.setSelected(isNameCaseInsensitive()); + + byModifiersBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setByModifiers(byModifiersBox.isSelected()); + } + }); + byTypeBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setByType(byTypeBox.isSelected()); + } + }); + typeCIBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setTypeCaseInsensitive(typeCIBox.isSelected()); + } + }); + byNameBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setByName(byNameBox.isSelected()); + } + }); + nameCIBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setNameCaseInsensitive(nameCIBox.isSelected()); + } + }); + + return abPanel; + } + + public String generateSortString(RangeEntry entry) { + String modifiers = entry.getModifierString(); + String type = entry.getType(); + String name = entry.getName(); + StringBuilder sb = new StringBuilder(modifiers.length() + type.length() + name.length()); + if (byModifiers) { + sb.append(modifiers); + } + if (byType) { + sb.append(isTypeCaseInsensitive ? type.toLowerCase() : type); + } + if (byName) { + sb.append(isNameCaseInsensitive ? name.toLowerCase() : name); + } + return sb.toString(); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/StaticAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/StaticAttribute.java new file mode 100644 index 000000000000..5c4b5f883f64 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/StaticAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +import java.lang.reflect.Modifier; + +/** Routines to handle the 'static' modifier. */ +public final class StaticAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static StaticAttribute readExternal(final Element item) { + final StaticAttribute result = new StaticAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public StaticAttribute() { + super("static", Modifier.STATIC); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*StaticAttribute*/AtomicAttribute deepCopy() { + final StaticAttribute result = new StaticAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/StringAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/StringAttribute.java new file mode 100644 index 000000000000..147c9b75b5f7 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/StringAttribute.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Attribute; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** Allows item selection by matching a string attribute to a regular expression. */ +abstract public class StringAttribute extends AtomicAttribute { + +// ------------------------------ FIELDS ------------------------------ + + private String expression; + private boolean match; + private boolean invert; + private final String attributeDisplayName; // should be plural + private final String storageName; + +// --------------------------- CONSTRUCTORS --------------------------- + + StringAttribute(String attributeDisplayName, String storageName) { + this.attributeDisplayName = attributeDisplayName; + this.storageName = storageName; + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public final String getExpression() { + return expression; + } + + public final void setExpression(final String expression) { + this.expression = expression; + } + + public final JPanel getStringPanel() { + final JPanel stringPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(); + constraints.weightedLastRow(); + final JCheckBox enableBox = new JCheckBox("whose " + attributeDisplayName); + stringPanel.add(enableBox, constraints.firstCol()); + final JComboBox invertBox = new JComboBox(new Object[]{"match", "do not match"}); + invertBox.setSelectedIndex(isInvert() ? 1 : 0); + final JTextField patternField = new JTextField(20); + stringPanel.add(invertBox, constraints.nextCol()); + stringPanel.add(patternField, constraints.weightedLastCol()); + enableBox.setSelected(isMatch()); + invertBox.setEnabled(isMatch()); + patternField.setEnabled(isMatch()); + patternField.setText(getExpression()); + enableBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setMatch(enableBox.isSelected()); + invertBox.setEnabled(enableBox.isSelected()); + patternField.setEnabled(enableBox.isSelected()); + } + }); + invertBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setInvert(invertBox.getSelectedIndex() == 1); + } + }); + patternField.getDocument().addDocumentListener(new DocumentListener() { + public void changedUpdate(final DocumentEvent e) { + setExpression(patternField.getText()); + } + + public void insertUpdate(final DocumentEvent e) { + setExpression(patternField.getText()); + } + + public void removeUpdate(final DocumentEvent e) { + setExpression(patternField.getText()); + } + }); + return stringPanel; + } + + public final boolean isInvert() { + return invert; + } + + private void setInvert(final boolean invert) { + this.invert = invert; + } + + public final boolean isMatch() { + return match; + } + + public final void setMatch(final boolean match) { + this.match = match; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public boolean equals(final Object object) { + if (!(object instanceof StringAttribute)) return false; + final StringAttribute na = (StringAttribute)object; + return match == na.match && + (expression == null || na.expression == null ? + expression == null && na.expression == null : expression.equals(na.expression)) && + invert == na.invert; + } + +// -------------------------- OTHER METHODS -------------------------- + + public final void appendAttributes(final Element me) { + final Element stElement = new Element(storageName); + if (expression == null) { + expression = ""; + } + me.getChildren().add(stElement); + stElement.setAttribute("match", Boolean.valueOf(match).toString()); + stElement.setAttribute("invert", Boolean.valueOf(invert).toString()); + stElement.setAttribute("pattern", expression); + } + + protected final void deepCopy(StringAttribute result) { + result.match = match; + result.expression = expression; + result.invert = invert; + } + + public final String getDescriptiveString() { + return (match ? "whose " + + attributeDisplayName + + (invert ? " do not match '" : " match '") + + expression + "'" + : ""); + } + + public final boolean isMatch(final String string) { + return !match || string.matches(expression) ^ invert; + } + + public final void loadAttributes(final Element item) { + match = RearrangerSettings.getBooleanAttribute(item, "match", false); + invert = RearrangerSettings.getBooleanAttribute(item, "invert", false); + final Attribute attr = RearrangerSettings.getAttribute(item, "pattern"); + expression = (attr == null ? "" : ((java.lang.String)attr.getValue())); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/SynchronizedAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/SynchronizedAttribute.java new file mode 100644 index 000000000000..8e166fc6ae63 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/SynchronizedAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +import java.lang.reflect.Modifier; + +/** Handles the 'synchronized' modifier. */ +public final class SynchronizedAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static SynchronizedAttribute readExternal(final Element item) { + final SynchronizedAttribute result = new SynchronizedAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public SynchronizedAttribute() { + super("synchronized", Modifier.SYNCHRONIZED); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*SynchronizedAttribute*/AtomicAttribute deepCopy() { + final SynchronizedAttribute result = new SynchronizedAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/TransientAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/TransientAttribute.java new file mode 100644 index 000000000000..2f48fb93cdc4 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/TransientAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +import java.lang.reflect.Modifier; + +/** Handles the 'transient' modifier. */ +public final class TransientAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static TransientAttribute readExternal(final Element item) { + final TransientAttribute result = new TransientAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public TransientAttribute() { + super("transient", Modifier.TRANSIENT); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*TransientAttribute*/AtomicAttribute deepCopy() { + final TransientAttribute result = new TransientAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/TypeAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/TypeAttribute.java new file mode 100644 index 000000000000..0627b20ff8ea --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/TypeAttribute.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +/** Allows field selection by matching its type to a regular expression. */ + +public class TypeAttribute extends StringAttribute { + +// -------------------------- STATIC METHODS -------------------------- + + public static TypeAttribute readExternal(final Element item) { + final TypeAttribute result = new TypeAttribute(); + result.loadAttributes(item.getChild("TypeMatch")); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public TypeAttribute() { + super("types", "TypeMatch"); + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public final boolean equals(final Object object) { + if (!(object instanceof TypeAttribute)) return false; + return super.equals(object); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*TypeAttribute*/AtomicAttribute deepCopy() { + final TypeAttribute result = new TypeAttribute(); + super.deepCopy(result); + return result; + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/VolatileAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/VolatileAttribute.java new file mode 100644 index 000000000000..6bc6a05c17d9 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/VolatileAttribute.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.atomicAttributes; + +import org.jdom.Element; + +import java.lang.reflect.Modifier; + +/** Handles the 'volatile' modifier. */ +public final class VolatileAttribute + extends AndNotAttribute +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static VolatileAttribute readExternal(final Element item) { + final VolatileAttribute result = new VolatileAttribute(); + result.loadAttributes(item.getChild(result.getElementName())); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public VolatileAttribute() { + super("volatile", Modifier.VOLATILE); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final /*VolatileAttribute*/AtomicAttribute deepCopy() { + final VolatileAttribute result = new VolatileAttribute(); + result.value = value; + result.invert = invert; + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java new file mode 100644 index 000000000000..dc1bd8e3d3c9 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import org.jdom.Element; + +/** Methods implemented by rule objects, which are saved in configuration. */ +public interface AttributeGroup + extends IRule +{ + +// -------------------------- OTHER METHODS -------------------------- + + public AttributeGroup deepCopy(); + + public void writeExternal(final Element parent); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java new file mode 100644 index 000000000000..0af457a9d854 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiJavaToken; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.atomicAttributes.AbstractAttribute; +import com.wrq.rearranger.settings.atomicAttributes.EnumAttribute; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; + +/** Routines to handle class modifiers other than those already handled by CommonAttributes. */ +public final class ClassAttributes + extends CommonAttributes + implements AttributeGroup +{ + +// ------------------------------ FIELDS ------------------------------ + + private AbstractAttribute abAttr; + private EnumAttribute enumAttr; + +// -------------------------- STATIC METHODS -------------------------- + + public static AttributeGroup readExternal(final Element element) { + if (element.getName().equals("Class")) { + final ClassAttributes result = new ClassAttributes(); + CommonAttributes.readExternal(result, element); + result.abAttr = AbstractAttribute.readExternal(element); + result.enumAttr = EnumAttribute.readExternal(element); + return result; + } + else if (element.getName().equals("Comment")) { + return CommentRule.readExternal(element); + } + else { + return null; + } + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public ClassAttributes() { + abAttr = new AbstractAttribute(); + enumAttr = new EnumAttribute(); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + private AbstractAttribute getAbAttr() { + return abAttr; + } + + public EnumAttribute getEnumAttr() { + return enumAttr; + } +// ------------------------ CANONICAL METHODS ------------------------ + + public final String toString() { + final StringBuffer sb = new StringBuffer(70); + sb.append(abAttr.getDescriptiveString()); + sb.append(plAttr.getProtectionLevelString()); + sb.append(stAttr.getDescriptiveString()); + sb.append(fAttr.getDescriptiveString()); + sb.append(enumAttr.getDescriptiveString()); + if (sb.length() == 0) { + sb.append("all classes"); + } + else { + sb.append("classes"); + } + if (nameAttr.isMatch()) { + sb.append(' '); + sb.append(nameAttr.getDescriptiveString()); + } + sb.append(sortAttr.getDescriptiveString()); + return sb.toString(); + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface AttributeGroup --------------------- + + public final /*ClassAttributes*/AttributeGroup deepCopy() { + final ClassAttributes result = new ClassAttributes(); + deepCopyCommonItems(result); + result.abAttr = (AbstractAttribute)abAttr.deepCopy(); + result.enumAttr = (EnumAttribute)enumAttr.deepCopy(); + return result; + } + + public final void writeExternal(final Element parent) { + final Element me = new Element("Class"); + writeExternalCommonAttributes(me); + abAttr.appendAttributes(me); + enumAttr.appendAttributes(me); + parent.getChildren().add(me); + } + +// -------------------------- OTHER METHODS -------------------------- + + public boolean equals(final Object obj) { + if (!(obj instanceof ClassAttributes)) { + return false; + } + final ClassAttributes ca = (ClassAttributes)obj; + return super.equals(ca) && + abAttr.equals(ca.abAttr) && + enumAttr.equals(ca.enumAttr); + } + + public final JPanel getClassAttributesPanel() { + final JPanel caPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + caPanel.setBorder(border); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 4; + constraints.weightx = 1.0d; + constraints.weighty = 0.0d; + constraints.insets = new Insets(0, 0, 10, 0); + caPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + constraints.gridy = 4; + constraints.gridheight = 1; + caPanel.add(getStAttr().getAndNotPanel(), constraints); + constraints.gridy++; + caPanel.add(getAbAttr().getAndNotPanel(), constraints); + constraints.gridy++; + caPanel.add(getfAttr().getAndNotPanel(), constraints); + constraints.gridy++; + caPanel.add(getEnumAttr().getAndNotPanel(), constraints); + constraints.gridy++; + caPanel.add(getNameAttr().getStringPanel(), constraints); + constraints.gridy++; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.weighty = 1.0d; + constraints.insets = new Insets(0, 0, 0, 0); + caPanel.add(sortAttr.getSortOptionsPanel(), constraints); + return caPanel; + } + + public final boolean isMatch(RangeEntry entry) + // final int modifiers, final String name, final String returnType) + { + return entry.getEnd().getParent() instanceof PsiClass && + entry.getEnd() instanceof PsiJavaToken && +// ((PsiJavaToken)entry.getEnd()).getTokenType() == PsiJavaToken.LBRACE && + entry.getEnd().getText().equals("{") && + super.isMatch(entry) && + abAttr.isMatch(entry.getModifiers()) && + enumAttr.isMatch(entry.getModifiers()); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java new file mode 100644 index 000000000000..d0f14db787e1 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.ruleinstance.DefaultRuleInstance; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.atomicAttributes.*; +import org.jdom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * Routines for Java modifiers common to fields, methods and classes, namely: protection levels (public, private, + * protected, package), final modifier, and static modifier. Ability to match the name to a regular + * expression is also supported. + */ +public abstract class CommonAttributes + implements AttributeGroup, IPrioritizableRule +{ +// ------------------------------ FIELDS ------------------------------ + + ProtectionLevelAttributes plAttr; + FinalAttribute fAttr; + StaticAttribute stAttr; + NameAttribute nameAttr; + SortOptions sortAttr; + int priority; // 1 = low priority, > 1 is higher priority + +// -------------------------- STATIC METHODS -------------------------- + + static void readExternal(final CommonAttributes result, final Element item) { + result.plAttr = ProtectionLevelAttributes.readExternal(item); + result.stAttr = StaticAttribute.readExternal(item); + result.fAttr = FinalAttribute.readExternal(item); + result.nameAttr = NameAttribute.readExternal(item); + result.sortAttr = SortOptions.readExternal(item); + result.priority = RearrangerSettings.getIntAttribute(item, "priority", 1); + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public CommonAttributes() { + plAttr = new ProtectionLevelAttributes(); + fAttr = new FinalAttribute(); + stAttr = new StaticAttribute(); + nameAttr = new NameAttribute(); + sortAttr = new SortOptions(); + priority = 1; + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public final NameAttribute getNameAttr() { + return nameAttr; + } + + final public ProtectionLevelAttributes getPlAttr() { + return plAttr; + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + final public StaticAttribute getStAttr() { + return stAttr; + } + + public SortOptions getSortAttr() { + return sortAttr; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public boolean equals(final Object obj) { + if (!(obj instanceof CommonAttributes)) { + return false; + } + final CommonAttributes ca = (CommonAttributes)obj; + return plAttr.equals(ca.plAttr) && + stAttr.equals(ca.stAttr) && + fAttr.equals(ca.fAttr) && + nameAttr.equals(ca.nameAttr) && + sortAttr.equals(ca.sortAttr) && + priority == ca.priority; + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface IRule --------------------- + + public IRuleInstance createRuleInstance() { + return new DefaultRuleInstance(this); + } + + public boolean isMatch(RangeEntry rangeEntry) { + final boolean result = plAttr.isMatch(rangeEntry.getModifiers()) && + stAttr.isMatch(rangeEntry.getModifiers()) && + fAttr.isMatch(rangeEntry.getModifiers()) && + nameAttr.isMatch(rangeEntry.getName()); + return result; + } + + /** + * Returns a boolean indicating if the comments associated with this rule match a global comment pattern. + * Most rules don't have comments, so by default it returns true. + * + * @param pattern global pattern to which all comments should conform + * @return true if comments conform to pattern + */ + public boolean commentsMatchGlobalPattern(String pattern) { + return true; + } + + public List getOffendingPatterns(String pattern) { + return new ArrayList(1); + } + + public int getCommentCount() { + return 0; + } + + /** + * Calculates a list of regular expression patterns, one for each comment that the rule might create, which will + * match any comment that the rule might generate. These can be combined to form a global comment pattern which + * will match all possible generated comments from all rules. These patterns will be appended to the supplied + * list. + */ + public void addCommentPatternsToList(List list) { + return; + } + +// -------------------------- OTHER METHODS -------------------------- + + final void deepCopyCommonItems(final CommonAttributes result) { + result.plAttr = (ProtectionLevelAttributes)plAttr.deepCopy(); + result.fAttr = (FinalAttribute)fAttr.deepCopy(); + result.stAttr = (StaticAttribute)stAttr.deepCopy(); + result.nameAttr = (NameAttribute)nameAttr.deepCopy(); + result.sortAttr = (SortOptions)sortAttr.deepCopy(); + result.priority = priority; + } + + final public FinalAttribute getfAttr() { + return fAttr; + } + + final void writeExternalCommonAttributes(final Element child) { + plAttr.appendAttributes(child); + stAttr.appendAttributes(child); + fAttr.appendAttributes(child); + nameAttr.appendAttributes(child); + sortAttr.appendAttributes(child); + child.setAttribute("priority", "" + priority); + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java new file mode 100644 index 000000000000..b33bbd6157e5 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.ruleinstance.DefaultRuleInstance; +import com.wrq.rearranger.ruleinstance.IRuleInstance; + +import java.util.ArrayList; +import java.util.List; + +/** + * A rule to match whatever is not matched by other rules. Always the last rule emitted except for any trailing + * constant (unparsed) text. + */ +public class DefaultRule + implements IRule +{ + public IRuleInstance createRuleInstance() { + return new DefaultRuleInstance(this); + } + + public int getPriority() { + return -1; // this rule matches every remaining entry, so must go last. + } + + public void setPriority(int priority) { + // does nothing + } + + public boolean isMatch(RangeEntry entry) { + return !(entry.isFixedHeader() || entry.isFixedTrailer()); + } + + public boolean commentsMatchGlobalPattern(String pattern) { + return true; + } + + public List getOffendingPatterns(String pattern) { + return new ArrayList(1); + } + + public int getCommentCount() { + return 0; + } + + public void addCommentPatternsToList(List list) { + } + + public String toString() { + return ""; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java new file mode 100644 index 000000000000..6706b7fae11e --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.intellij.psi.PsiField; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.settings.atomicAttributes.InitToAnonClassAttribute; +import com.wrq.rearranger.settings.atomicAttributes.TransientAttribute; +import com.wrq.rearranger.settings.atomicAttributes.TypeAttribute; +import com.wrq.rearranger.settings.atomicAttributes.VolatileAttribute; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; + +/** Routines to handle field attributes not covered by CommonAttributes. */ +public final class FieldAttributes + extends ItemAttributes +{ + +// ------------------------------ FIELDS ------------------------------ + + private InitToAnonClassAttribute initToAnonClassAttr; + private TransientAttribute transientAttr; + private VolatileAttribute volatileAttr; + private TypeAttribute typeAttr; + +// -------------------------- STATIC METHODS -------------------------- + + public static /*FieldAttributes*/AttributeGroup readExternal(final Element item) { + final FieldAttributes result = new FieldAttributes(); + CommonAttributes.readExternal(result, item); + result.initToAnonClassAttr = InitToAnonClassAttribute.readExternal(item); + result.transientAttr = TransientAttribute.readExternal(item); + result.volatileAttr = VolatileAttribute.readExternal(item); + result.typeAttr = TypeAttribute.readExternal(item); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public FieldAttributes() { + initToAnonClassAttr = new InitToAnonClassAttribute(); + transientAttr = new TransientAttribute(); + volatileAttr = new VolatileAttribute(); + typeAttr = new TypeAttribute(); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public InitToAnonClassAttribute getInitToAnonClassAttr() { + return initToAnonClassAttr; + } + + private TransientAttribute getTransientAttr() { + return transientAttr; + } + + public TypeAttribute getTypeAttr() { + return typeAttr; + } + + private VolatileAttribute getVolatileAttr() { + return volatileAttr; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public final String toString() { + final StringBuffer sb = new StringBuffer(70); + sb.append(plAttr.getProtectionLevelString()); + sb.append(stAttr.getDescriptiveString()); + sb.append(fAttr.getDescriptiveString()); + sb.append(transientAttr.getDescriptiveString()); + sb.append(volatileAttr.getDescriptiveString()); + + if (sb.length() == 0) { + sb.append("all fields"); + } + else { + sb.append("fields"); + } + if (initToAnonClassAttr.isValue()) { + if (!initToAnonClassAttr.isInvert()) { + sb.append(" which are initialized to an anonymous class"); + } + else { + sb.append(" which are not initialized to an anonymous class"); + } + } + if (nameAttr.isMatch()) { + if (initToAnonClassAttr.isValue()) { + sb.append(" and"); + } + sb.append(' '); + sb.append(nameAttr.getDescriptiveString()); + } + if (typeAttr.isMatch()) { + if (nameAttr.isMatch() || initToAnonClassAttr.isValue()) { + sb.append(" and"); + } + sb.append(' '); + sb.append(typeAttr.getDescriptiveString()); + } + sb.append(sortAttr.getDescriptiveString()); + return sb.toString(); + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface AttributeGroup --------------------- + + public final /*FieldAttributes*/AttributeGroup deepCopy() { + final FieldAttributes result = new FieldAttributes(); + deepCopyCommonItems(result); + result.initToAnonClassAttr = (InitToAnonClassAttribute)initToAnonClassAttr.deepCopy(); + result.transientAttr = (TransientAttribute)transientAttr.deepCopy(); + result.volatileAttr = (VolatileAttribute)volatileAttr.deepCopy(); + result.typeAttr = (TypeAttribute)typeAttr.deepCopy(); + return result; + } + + public final void writeExternal(final Element parent) { + final Element child = new Element("Field"); + writeExternalCommonAttributes(child); + initToAnonClassAttr.appendAttributes(child); + transientAttr.appendAttributes(child); + volatileAttr.appendAttributes(child); + typeAttr.appendAttributes(child); + parent.getChildren().add(child); + } + +// -------------------------- OTHER METHODS -------------------------- + + public boolean equals(final Object object) { + if (!(object instanceof FieldAttributes)) return false; + final FieldAttributes fa = (FieldAttributes)object; + return super.equals(fa) && + transientAttr.equals(fa.transientAttr) && + volatileAttr.equals(fa.volatileAttr) && + initToAnonClassAttr.equals(fa.initToAnonClassAttr) && + typeAttr.equals(fa.typeAttr); + } + + public JPanel getFieldAttributes() { + final JPanel plPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + plPanel.setBorder(border); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.gridwidth = 1; + constraints.gridheight = 4; + constraints.weightx = 1.0d; + plPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridy = 0; + constraints.gridx = 1; + constraints.gridheight = 1; + constraints.weighty = 0; + plPanel.add(getStAttr().getAndNotPanel(), constraints); + constraints.gridy++; + plPanel.add(getfAttr().getAndNotPanel(), constraints); + constraints.gridy++; + plPanel.add(getTransientAttr().getAndNotPanel(), constraints); + constraints.gridy++; + plPanel.add(getVolatileAttr().getAndNotPanel(), constraints); + constraints.insets = new Insets(5, 0, 0, 0); + constraints.gridx = 0; + constraints.gridy++; + plPanel.add(getInitToAnonClassAttr().getAndNotPanel(), constraints); + constraints.gridy++; + plPanel.add(getNameAttr().getStringPanel(), constraints); + constraints.gridy++; + plPanel.add(getTypeAttr().getStringPanel(), constraints); + constraints.gridy++; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.weighty = 1.0d; + constraints.insets = new Insets(0, 0, 0, 0); + plPanel.add(sortAttr.getSortOptionsPanel(), constraints); + return plPanel; + } + + public boolean isMatch(RangeEntry rangeEntry) { + return rangeEntry.getEnd() instanceof PsiField && + initToAnonClassAttr.isMatch(rangeEntry.getModifiers()) && + transientAttr.isMatch(rangeEntry.getModifiers()) && + volatileAttr.isMatch(rangeEntry.getModifiers()) && + typeAttr.isMatch(rangeEntry.getType()) && + super.isMatch(rangeEntry); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/GetterSetterDefinition.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/GetterSetterDefinition.java new file mode 100644 index 000000000000..8a7b7ca1ebf3 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/GetterSetterDefinition.java @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.wrq.rearranger.settings.RearrangerSettings; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** Specifies criteria defining what constitutes a getter or setter method. */ +public class GetterSetterDefinition { + +// ------------------------------ FIELDS ------------------------------ + + public static final int GETTER_BODY_RETURNS_FIELD = 0; + public static final int GETTER_BODY_RETURNS = 1; + public static final int GETTER_BODY_IMMATERIAL = 2; + + public static final int GETTER_NAME_MATCHES_FIELD = 0; + public static final int GETTER_NAME_CORRECT_PREFIX = 1; + + public static final int SETTER_BODY_SETS_FIELD = 0; + public static final int SETTER_BODY_IMMATERIAL = 1; + + public static final int SETTER_NAME_MATCHES_FIELD = 0; + public static final int SETTER_NAME_CORRECT_PREFIX = 1; + + private int getterBodyCriterion; + private int getterNameCriterion; + private int setterBodyCriterion; + private int setterNameCriterion; + +// -------------------------- STATIC METHODS -------------------------- + + public static GetterSetterDefinition readExternal(Element item) { + final GetterSetterDefinition result = new GetterSetterDefinition(); + if (item != null) { + Element child = item.getChild("GetterSetterDefinition"); + if (child != null) { + result.loadAttributes(child); + } + } + return result; + } + + public void loadAttributes(Element me) { + getterBodyCriterion = RearrangerSettings.getIntAttribute(me, "getterBody"); + getterNameCriterion = RearrangerSettings.getIntAttribute(me, "getterName"); + setterBodyCriterion = RearrangerSettings.getIntAttribute(me, "setterBody"); + setterNameCriterion = RearrangerSettings.getIntAttribute(me, "setterName"); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public int getGetterBodyCriterion() { + return getterBodyCriterion; + } + + public void setGetterBodyCriterion(int getterBodyCriterion) { + this.getterBodyCriterion = getterBodyCriterion; + } + + public int getGetterNameCriterion() { + return getterNameCriterion; + } + + public void setGetterNameCriterion(int getterNameCriterion) { + this.getterNameCriterion = getterNameCriterion; + } + + public int getSetterBodyCriterion() { + return setterBodyCriterion; + } + + public void setSetterBodyCriterion(int setterBodyCriterion) { + this.setterBodyCriterion = setterBodyCriterion; + } + + public int getSetterNameCriterion() { + return setterNameCriterion; + } + + public void setSetterNameCriterion(int setterNameCriterion) { + this.setterNameCriterion = setterNameCriterion; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public boolean equals(Object obj) { + if (obj instanceof GetterSetterDefinition) { + GetterSetterDefinition gsd = (GetterSetterDefinition)obj; + if (gsd.getterBodyCriterion == getterBodyCriterion && + gsd.getterNameCriterion == getterNameCriterion && + gsd.setterBodyCriterion == setterBodyCriterion && + gsd.setterNameCriterion == setterNameCriterion) + { + return true; + } + } + return false; + } + +// -------------------------- OTHER METHODS -------------------------- + + public final GetterSetterDefinition deepCopy() { + final GetterSetterDefinition result = new GetterSetterDefinition(); + result.getterBodyCriterion = getterBodyCriterion; + result.getterNameCriterion = getterNameCriterion; + result.setterBodyCriterion = setterBodyCriterion; + result.setterNameCriterion = setterNameCriterion; + return result; + } + + public JPanel getGSDefinitionPanel() { + final JPanel gsdPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 1; + constraints.anchor = GridBagConstraints.WEST; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1.0d; + constraints.weighty = 0.0d; + constraints.gridx = constraints.gridy = 0; + constraints.insets = new Insets(5, 5, 0, 5); + { + JPanel getterPanel = new JPanel(new GridBagLayout()); + final Border getterBorder = BorderFactory.createEtchedBorder(); + final TitledBorder titledBorder = BorderFactory.createTitledBorder(getterBorder, "Getter definition"); + getterPanel.setBorder(titledBorder); + final GridBagConstraints gc = new GridBagConstraints(); + gc.gridwidth = 1; + gc.gridheight = 1; + gc.anchor = GridBagConstraints.WEST; + gc.fill = GridBagConstraints.BOTH; + gc.weightx = 0; + gc.weighty = 0; + gc.gridx = gc.gridy = 0; + JLabel methodBodyLabel = new JLabel("Method body:"); + getterPanel.add(methodBodyLabel, gc); + gc.gridx++; + gc.gridwidth = GridBagConstraints.REMAINDER; + gc.weightx = 1.0; + final JComboBox getterBodyBox = new JComboBox( + new Object[]{ + "Contains \"return ;\" only", + "Contains one return statement only", + "Ignore body" + } + ); + JLabel methodNameLabel = new JLabel("Method name:"); + final JComboBox getterNameBox = new JComboBox( + new Object[]{ + "Has prefix plus correct field name", + "Has \"get/is/has\" prefix", + } + ); + getterPanel.add(getterBodyBox, gc); + gc.gridy++; + getterBodyBox.setSelectedIndex(getterBodyCriterion); + getterBodyBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + getterBodyCriterion = getterBodyBox.getSelectedIndex(); + if (getterBodyCriterion == GETTER_BODY_RETURNS_FIELD && + getterNameCriterion != GETTER_NAME_MATCHES_FIELD) + { + getterNameBox.setSelectedIndex(getterNameCriterion = GETTER_NAME_MATCHES_FIELD); + } + if (getterBodyCriterion != GETTER_BODY_RETURNS_FIELD && + getterNameCriterion != GETTER_NAME_CORRECT_PREFIX) + { + getterNameBox.setSelectedIndex(getterNameCriterion = GETTER_NAME_CORRECT_PREFIX); + } + } + } + ); + gc.weightx = 0; + gc.gridx = 0; + gc.gridwidth = 1; + getterPanel.add(methodNameLabel, gc); + gc.gridx++; + gc.gridwidth = GridBagConstraints.REMAINDER; + gc.weightx = 1.0; + getterNameBox.setSelectedIndex(getterNameCriterion); + getterPanel.add(getterNameBox, gc); + gc.gridy++; + getterNameBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + getterNameCriterion = getterNameBox.getSelectedIndex(); + if (getterNameCriterion == GETTER_NAME_MATCHES_FIELD && + getterBodyCriterion != GETTER_BODY_RETURNS_FIELD) + { + getterBodyBox.setSelectedIndex(getterBodyCriterion = GETTER_BODY_RETURNS_FIELD); + } + if (getterNameCriterion == GETTER_NAME_CORRECT_PREFIX && + getterBodyCriterion == GETTER_BODY_RETURNS_FIELD) + { + getterBodyBox.setSelectedIndex(getterBodyCriterion = GETTER_BODY_RETURNS); + } + } + } + ); + gsdPanel.add(getterPanel, constraints); + } + constraints.gridy++; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.weighty = 1; + { + JPanel setterPanel = new JPanel(new GridBagLayout()); + final Border setterBorder = BorderFactory.createEtchedBorder(); + final TitledBorder titledBorder = BorderFactory.createTitledBorder(setterBorder, "Setter definition"); + setterPanel.setBorder(titledBorder); + final GridBagConstraints gc = new GridBagConstraints(); + gc.gridwidth = 1; + gc.gridheight = 1; + gc.anchor = GridBagConstraints.WEST; + gc.fill = GridBagConstraints.BOTH; + gc.weightx = 0; + gc.weighty = 0; + gc.gridx = gc.gridy = 0; + JLabel methodBodyLabel = new JLabel("Method body:"); + setterPanel.add(methodBodyLabel, gc); + gc.gridx++; + gc.gridwidth = GridBagConstraints.REMAINDER; + gc.weightx = 1.0; + final JComboBox setterBodyBox = new JComboBox( + new Object[]{ + "Contains one assignment statement \" = ;\" only", + "Ignore body"} + ); + final JComboBox setterNameBox = new JComboBox( + new Object[]{ + "Has prefix plus correct field name", + "Has \"set\" prefix", + } + ); + setterPanel.add(setterBodyBox, gc); + gc.gridy++; + setterBodyBox.setSelectedIndex(setterBodyCriterion); + setterBodyBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + setterBodyCriterion = setterBodyBox.getSelectedIndex(); + if (setterBodyCriterion == SETTER_BODY_IMMATERIAL && + setterNameCriterion != SETTER_NAME_CORRECT_PREFIX) + { + setterNameBox.setSelectedIndex(setterNameCriterion = SETTER_NAME_CORRECT_PREFIX); + } + if (setterBodyCriterion == SETTER_BODY_SETS_FIELD && + setterNameCriterion != SETTER_NAME_MATCHES_FIELD) + { + setterNameBox.setSelectedIndex(setterNameCriterion = SETTER_NAME_MATCHES_FIELD); + } + } + } + ); + gc.weightx = 0; + gc.gridx = 0; + gc.gridwidth = 1; + JLabel methodNameLabel = new JLabel("Method name:"); + setterPanel.add(methodNameLabel, gc); + gc.gridx++; + gc.gridwidth = GridBagConstraints.REMAINDER; + gc.weightx = 1.0; + setterPanel.add(setterNameBox, gc); + setterNameBox.setSelectedIndex(setterNameCriterion); + gsdPanel.add(setterPanel, constraints); + setterNameBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + setterNameCriterion = setterNameBox.getSelectedIndex(); + if (setterNameCriterion == SETTER_NAME_CORRECT_PREFIX && + setterBodyCriterion != SETTER_BODY_IMMATERIAL) + { + setterBodyBox.setSelectedIndex(setterBodyCriterion = SETTER_BODY_IMMATERIAL); + } + if (setterNameCriterion == SETTER_NAME_MATCHES_FIELD && + setterBodyCriterion != SETTER_BODY_SETS_FIELD) + { + setterBodyBox.setSelectedIndex(setterBodyCriterion = SETTER_BODY_SETS_FIELD); + } + } + } + ); + } + return gsdPanel; + } + + public final void writeExternal(final Element items) { + appendAttributes(items); + } + + public final void appendAttributes(final Element me) { + final Element stElement = new Element("GetterSetterDefinition"); + me.getChildren().add(stElement); + stElement.setAttribute("getterBody", "" + getterBodyCriterion); + stElement.setAttribute("getterName", "" + getterNameCriterion); + stElement.setAttribute("setterBody", "" + setterBodyCriterion); + stElement.setAttribute("setterName", "" + setterNameCriterion); + } +} \ No newline at end of file diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java new file mode 100644 index 000000000000..0d6f759ea2de --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.ruleinstance.HeaderTrailerRuleInstance; +import com.wrq.rearranger.ruleinstance.IRuleInstance; + +import java.util.ArrayList; +import java.util.List; + +/** A rule to match header text (text which does not constitute a matchable item such as a field or method.) */ +public class HeaderRule + implements IRule +{ + public IRuleInstance createRuleInstance() { + return new HeaderTrailerRuleInstance(this); + } + + public int getPriority() { + return -1; // priority doesn't matter since header rules only match the one header entry (if it exists), and + // the header entry is never matched by another rule. + } + + public void setPriority(int priority) { + // does nothing + } + + public boolean isMatch(RangeEntry rangeEntry) { + return rangeEntry.isFixedHeader(); + } + + public boolean commentsMatchGlobalPattern(String pattern) { + return true; + } + + public List getOffendingPatterns(String pattern) { + return new ArrayList(1); + } + + public int getCommentCount() { + return 0; + } + + public void addCommentPatternsToList(List list) { + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IHasGetterSetterDefinition.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IHasGetterSetterDefinition.java new file mode 100644 index 000000000000..b6a70f0f0f15 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IHasGetterSetterDefinition.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +/** + * Marker interface for rules that have unique getter/setter definitions. Currently this is only the MethodAttributes + * rule. + */ +public interface IHasGetterSetterDefinition { + public GetterSetterDefinition getGetterSetterDefinition(); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IPrioritizableRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IPrioritizableRule.java new file mode 100644 index 000000000000..29668d76448f --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IPrioritizableRule.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +/** + * Marker interface for rules which have a user-assignable priority. This excludes comment rules, and invisible + * header and trailer rules. + */ +public interface IPrioritizableRule { +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IRestrictMethodExtraction.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IRestrictMethodExtraction.java new file mode 100644 index 000000000000..32f4016a3245 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IRestrictMethodExtraction.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +/** + * Interface implemented by rules which can prevent extracted methods being grouped with the + * calling method, in spite of the global setting. + */ +public interface IRestrictMethodExtraction { + public boolean isNoExtractedMethods(); + + public void setNoExtractedMethods(boolean noExtractedMethods); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IRule.java new file mode 100644 index 000000000000..c6ff7952e6b8 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/IRule.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.ruleinstance.IRuleInstance; + +import java.util.List; + +/** Interface which all rules implement. */ +public interface IRule { + IRuleInstance createRuleInstance(); + + // all rules have a priority; but some are not settable by the user. Those that are user settable implement + // the marker interface IPrioritizableRule. + int getPriority(); + + void setPriority(int priority); + + boolean isMatch(RangeEntry rangeEntry); + + /** + * @param pattern global pattern to which all comments should conform. + * @return true if all comments associated with this rule match the pattern. + */ + boolean commentsMatchGlobalPattern(String pattern); + + /** + * @param pattern global pattern to which all comments should conform. + * @return list of comments which fail to match the pattern. + */ + List getOffendingPatterns(String pattern); + + /** @return the number of comments associated with this rule. */ + int getCommentCount(); + + /** + * Calculates a list of regular expression patterns, one for each comment that the rule might create, which + * will match any comment that the rule might generate. These can be combined to form a global comment pattern + * which will match all possible generated comments from all rules. These patterns will be appended + * to the supplied list. + */ + void addCommentPatternsToList(List list); +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java new file mode 100644 index 000000000000..80ebd47b7766 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiJavaToken; +import com.wrq.rearranger.ModifierConstants; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.settings.atomicAttributes.AbstractAttribute; +import com.wrq.rearranger.settings.atomicAttributes.EnumAttribute; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; + +/** Routines to handle inner class modifiers not already covered by ItemAttributes. */ +public final class InnerClassAttributes + extends ItemAttributes +{ + +// ------------------------------ FIELDS ------------------------------ + + private AbstractAttribute abAttr; + private EnumAttribute enumAttr; + +// -------------------------- STATIC METHODS -------------------------- + + public static /*InnerClassAttributes*/AttributeGroup readExternal(final Element item) { + final InnerClassAttributes result = new InnerClassAttributes(); + CommonAttributes.readExternal(result, item); + result.abAttr = AbstractAttribute.readExternal(item); + result.enumAttr = EnumAttribute.readExternal(item); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public InnerClassAttributes() { + abAttr = new AbstractAttribute(); + enumAttr = new EnumAttribute(); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + private AbstractAttribute getAbAttr() { + return abAttr; + } + + public EnumAttribute getEnumAttr() { + return enumAttr; + } +// ------------------------ CANONICAL METHODS ------------------------ + + public final String toString() { + final StringBuffer sb = new StringBuffer(70); + sb.append(abAttr.getDescriptiveString()); + sb.append(plAttr.getProtectionLevelString()); + sb.append(stAttr.getDescriptiveString()); + sb.append(fAttr.getDescriptiveString()); + sb.append(enumAttr.getDescriptiveString()); + if (sb.length() == 0) { + sb.append("all inner classes"); + } + else { + sb.append("inner classes"); + } + if (nameAttr.isMatch()) { + sb.append(' '); + sb.append(nameAttr.getDescriptiveString()); + } + sb.append(sortAttr.getDescriptiveString()); + return sb.toString(); + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface AttributeGroup --------------------- + + public final /*InnerClassAttributes*/AttributeGroup deepCopy() { + final InnerClassAttributes result = new InnerClassAttributes(); + deepCopyCommonItems(result); + result.abAttr = (AbstractAttribute)abAttr.deepCopy(); + result.enumAttr = (EnumAttribute)enumAttr.deepCopy(); + return result; + } + + public final void writeExternal(final Element parent) { + final Element me = new Element("InnerClass"); + writeExternalCommonAttributes(me); + abAttr.appendAttributes(me); + enumAttr.appendAttributes(me); + parent.getChildren().add(me); + } + +// -------------------------- OTHER METHODS -------------------------- + + public boolean equals(final Object obj) { + if (!(obj instanceof InnerClassAttributes)) { + return false; + } + final InnerClassAttributes ica = (InnerClassAttributes)obj; + return super.equals(ica) && + abAttr.equals(ica.abAttr) && + enumAttr.equals(ica.enumAttr); + } + + public JPanel getInnerClassAttributes() { + final JPanel caPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + caPanel.setBorder(border); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 1; + constraints.weightx = 1.0d; + constraints.weighty = 0.0d; + constraints.gridx = constraints.gridy = 0; + constraints.insets = new Insets(0, 0, 5, 0); + caPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + constraints.gridy = 1; + constraints.gridheight = 1; + caPanel.add(getStAttr().getAndNotPanel(), constraints); + constraints.gridy++; + caPanel.add(getAbAttr().getAndNotPanel(), constraints); + constraints.gridy++; + caPanel.add(getfAttr().getAndNotPanel(), constraints); + constraints.gridy++; + caPanel.add(getEnumAttr().getAndNotPanel(), constraints); + constraints.gridy++; + caPanel.add(getNameAttr().getStringPanel(), constraints); + constraints.gridy++; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.weighty = 1.0d; + constraints.insets = new Insets(0, 0, 0, 0); + caPanel.add(sortAttr.getSortOptionsPanel(), constraints); + return caPanel; + } + + public final boolean isMatch(RangeEntry entry) { +// return entry.getEnd() instanceof PsiClass && + // entry.getEnd() should be the LBrace of a class. + return entry.getEnd().getParent() instanceof PsiClass && + ((entry.getModifiers() & ModifierConstants.ENUM) != 0) || + (entry.getEnd() instanceof PsiJavaToken && + // ((PsiJavaToken)entry.getEnd()).getTokenType() == PsiJavaToken.LBRACE && + entry.getEnd().getText().equals("{")) && + super.isMatch(entry) && + abAttr.isMatch(entry.getModifiers()) && + enumAttr.isMatch(entry.getModifiers()); + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java new file mode 100644 index 000000000000..78eb7e4ca1bd --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.wrq.rearranger.entry.MethodEntry; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.ruleinstance.IRuleInstance; +import com.wrq.rearranger.ruleinstance.InterfaceRuleInstance; +import com.wrq.rearranger.settings.CommentFillString; +import com.wrq.rearranger.settings.CommentRule; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.atomicAttributes.NameAttribute; +import com.wrq.rearranger.util.Constraints; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +/** Rule and attributes to support grouping of methods that implement interface methods. */ +public class InterfaceAttributes + implements AttributeGroup, IRestrictMethodExtraction, IPrioritizableRule +{ + private boolean noExtractedMethods; + NameAttribute nameAttr; + boolean alphabetizeInterfaces; + private int priority; + + public static final int METHOD_ORDER_ALPHABETICAL = 0; + public static final int METHOD_ORDER_INTERFACE_ORDER = 1; + public static final int METHOD_ORDER_ENCOUNTERED = 2; + private int methodOrder; + + CommentRule precedingComment; + CommentRule trailingComment; + private CommentFillString commentFillString; + + public InterfaceAttributes() { + nameAttr = new NameAttribute(); + noExtractedMethods = false; + alphabetizeInterfaces = false; + methodOrder = METHOD_ORDER_ENCOUNTERED; + precedingComment = new CommentRule(); + trailingComment = new CommentRule(); + commentFillString = new CommentFillString(); + priority = 1; + } + + public NameAttribute getNameAttr() { + return nameAttr; + } + + public boolean isNoExtractedMethods() { + return noExtractedMethods; + } + + public void setNoExtractedMethods(boolean noExtractedMethods) { + this.noExtractedMethods = noExtractedMethods; + } + + public boolean isAlphabetize() { + return alphabetizeInterfaces; + } + + public void setAlphabetizeInterfaces(boolean alphabetizeInterfaces) { + this.alphabetizeInterfaces = alphabetizeInterfaces; + } + + public CommentRule getTrailingComment() { + return trailingComment; + } + + public void setTrailingComment(CommentRule trailingComment) { + this.trailingComment = trailingComment; + } + + public final String getExpandedTrailingCommentText() { + return commentFillString.getExpandedCommentText(trailingComment.getCommentText()); + } + + public CommentRule getPrecedingComment() { + return precedingComment; + } + + public void setPrecedingComment(CommentRule precedingComment) { + this.precedingComment = precedingComment; + } + + public final String getExpandedPrecedingCommentText() { + return commentFillString.getExpandedCommentText(precedingComment.getCommentText()); + } + + public CommentFillString getCommentFillString() { + return commentFillString; + } + + public int getMethodOrder() { + return methodOrder; + } + + public void setMethodOrder(int methodOrder) { + this.methodOrder = methodOrder; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + public int getPriority() { + return priority; + } + + public IRuleInstance createRuleInstance() { + return new InterfaceRuleInstance(this); + } + + public final boolean isMatch(RangeEntry rangeEntry) { + if (rangeEntry instanceof MethodEntry) { + MethodEntry me = (MethodEntry)rangeEntry; + if (me.getInterfaceName() != null) { + return nameAttr.isMatch(me.getInterfaceName()); + } + } + return false; + } + + public boolean equals(final Object obj) { + if (!(obj instanceof InterfaceAttributes)) return false; + final InterfaceAttributes ia = (InterfaceAttributes)obj; + return nameAttr.equals(ia.getNameAttr()) && + alphabetizeInterfaces == ia.alphabetizeInterfaces && + methodOrder == ia.methodOrder && + noExtractedMethods == ia.noExtractedMethods && + precedingComment.equals(ia.precedingComment) && + trailingComment.equals(ia.trailingComment) && + commentFillString.equals(ia.commentFillString); + } + + public final String toString() { + // convert settings to readable English description of the method. + // + final StringBuffer sb = new StringBuffer(80); + + sb.append("Methods implementing interfaces"); + + if (nameAttr.isMatch()) { + sb.append(' '); + sb.append(nameAttr.getDescriptiveString()); + } + + if (alphabetizeInterfaces) { + sb.append(" (interfaces alphabetized)"); + } + if (noExtractedMethods) { + sb.append(" (no extracted methods)"); + } + if (precedingComment.getCommentText().length() != 0) { + sb.append(" Preceding "); + sb.append(precedingComment.getDescriptiveString()); + } + if (trailingComment.getCommentText().length() != 0) { + sb.append(" Trailing "); + sb.append(trailingComment.getDescriptiveString()); + } + return sb.toString(); + } + + public final /*InterfaceAttributes*/AttributeGroup deepCopy() { + final InterfaceAttributes result = new InterfaceAttributes(); + result.nameAttr = (NameAttribute)nameAttr.deepCopy(); + result.alphabetizeInterfaces = alphabetizeInterfaces; + result.noExtractedMethods = noExtractedMethods; + result.methodOrder = methodOrder; + result.precedingComment = (CommentRule)precedingComment.deepCopy(); + result.trailingComment = (CommentRule)trailingComment.deepCopy(); + result.commentFillString = commentFillString.deepCopy(); + result.priority = priority; + return result; + } + + public static /*InterfaceAttributes*/AttributeGroup readExternal(final Element item) { + final InterfaceAttributes result = new InterfaceAttributes(); + result.loadAttributes(item); + return result; + } + + public void loadAttributes(final Element item) { + nameAttr = NameAttribute.readExternal(item); + alphabetizeInterfaces = RearrangerSettings.getBooleanAttribute(item, "alphabetizeInterfaces"); + noExtractedMethods = RearrangerSettings.getBooleanAttribute(item, "noExtractedMethods"); + methodOrder = RearrangerSettings.getIntAttribute(item, "methodOrder", METHOD_ORDER_ENCOUNTERED); + Element prc = item.getChild("PrecedingComment"); + if (prc != null) prc = prc.getChild("Comment"); + precedingComment = CommentRule.readExternal(prc); + Element trc = item.getChild("TrailingComment"); + if (trc != null) trc = trc.getChild("Comment"); + trailingComment = CommentRule.readExternal(trc); + commentFillString = CommentFillString.readExternal(item); + priority = RearrangerSettings.getIntAttribute(item, "priority", 1); + } + + public final void writeExternal(final Element parent) { + final Element me = new Element("Interface"); + parent.getChildren().add(me); + nameAttr.appendAttributes(me); + me.setAttribute("alphabetizeInterfaces", Boolean.valueOf(alphabetizeInterfaces).toString()); + me.setAttribute("noExtractedMethods", Boolean.valueOf(noExtractedMethods).toString()); + me.setAttribute("methodOrder", "" + methodOrder); + me.setAttribute("priority", "" + priority); + Element prc = new Element("PrecedingComment"); + Element trc = new Element("TrailingComment"); + me.getChildren().add(prc); + me.getChildren().add(trc); + precedingComment.writeExternal(prc); + trailingComment.writeExternal(trc); + commentFillString.writeExternal(me); + } + + public JPanel getInterfaceAttributes() { + final JPanel interfacePanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + Border titleBorder = BorderFactory.createTitledBorder(border, "Match methods implementing interfaces"); + interfacePanel.setBorder(titleBorder); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.insets = new Insets(5, 0, 0, 0); + interfacePanel.add(getNameAttr().getStringPanel(), constraints.weightedLastCol()); + constraints.newRow(); + interfacePanel.add(getAlphabetizePanel(), constraints.weightedLastCol()); + constraints.weightedNewRow(); + interfacePanel.add(getCommentPanel(), constraints.weightedLastCol()); + constraints.newRow(); + interfacePanel.add(getExcludePanel(), constraints.weightedLastCol()); + constraints.lastRow(); + interfacePanel.add(getMethodOrderPanel(), constraints.weightedLastCol()); + return interfacePanel; + } + + public final JPanel getExcludePanel() { + final JPanel excludePanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.lastRow(); + final JCheckBox excludeBox = new JCheckBox("Exclude from extracted method processing"); + excludeBox.setSelected(noExtractedMethods); + excludeBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + noExtractedMethods = excludeBox.isSelected(); + } + } + ); + excludePanel.add(excludeBox, constraints.weightedLastCol()); + return excludePanel; + } + + private final JPanel getAlphabetizePanel() { + final JPanel abPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(); + constraints.weightedLastRow(); + final JCheckBox alphabetizeBox = new JCheckBox("Alphabetize Interfaces"); + abPanel.add(alphabetizeBox, constraints.weightedLastCol()); + alphabetizeBox.setSelected(isAlphabetize()); + alphabetizeBox.addActionListener( + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + alphabetizeInterfaces = alphabetizeBox.isSelected(); + } + } + ); + return abPanel; + } + + private JPanel getMethodOrderPanel() { + JPanel orderPanel = new JPanel(new GridBagLayout()); + Constraints constraints = new Constraints(); + constraints.weightedLastRow(); + constraints.fill = GridBagConstraints.BOTH; + constraints.insets = new Insets(0, 5, 0, 0); + JLabel orderLabel = new JLabel("Order methods"); + orderPanel.add(orderLabel, constraints.firstCol()); + final JComboBox orderBox = new JComboBox( + new String[]{ + "Alphabetically", + "In order declared in interface", + "In order encountered" + } + ); + orderBox.setSelectedIndex(methodOrder); + orderPanel.add(orderBox, constraints.weightedLastCol()); + orderBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + methodOrder = orderBox.getSelectedIndex(); + } + } + ); + return orderPanel; + } + + private JPanel getCommentPanel() { + JPanel commentPanel = new JPanel(new GridBagLayout()); + Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + Border b = BorderFactory.createEtchedBorder(); + TitledBorder t = BorderFactory.createTitledBorder(b, "Comments"); + commentPanel.setBorder(t); + constraints.fill = GridBagConstraints.BOTH; + + JLabel legendLabel = new JLabel("Comment Substitutions: use %IF% for interface name"); + JLabel precedingCommentLabel = new JLabel("Preceding Comment:"); + JLabel trailingCommentLabel = new JLabel("Trailing Comment:"); + JPanel precedingCommentPanel = getCommentAreaPanel(getPrecedingComment()); + JPanel trailingCommentPanel = getCommentAreaPanel(getTrailingComment()); + JPanel legendPanel = new JPanel(new GridBagLayout()); + Border border = BorderFactory.createEtchedBorder(); + legendPanel.setBorder(border); + constraints.insets = new Insets(5, 5, 5, 5); + constraints.gridwidth = GridBagConstraints.REMAINDER; + legendPanel.add(legendLabel, constraints.lastCol()); + constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.insets = new Insets(5, 5, 0, 5); + commentPanel.add(legendPanel, constraints.weightedLastCol()); + constraints.newRow(); + commentPanel.add(precedingCommentLabel, constraints.weightedLastCol()); + constraints.weightedNewRow(0.50d); + commentPanel.add(precedingCommentPanel, constraints.weightedLastCol()); + constraints.newRow(); + commentPanel.add(trailingCommentLabel, constraints.weightedLastCol()); + constraints.weightedNewRow(0.50d); + constraints.insets = new Insets(5, 5, 5, 5); + commentPanel.add(trailingCommentPanel, constraints.weightedLastCol()); + constraints.lastRow(); + constraints.insets = new Insets(5, 5, 0, 5); + commentPanel.add(commentFillString.getCommentFillStringPanel(), constraints.weightedLastCol()); + return commentPanel; + } + + private JPanel getCommentAreaPanel(final CommentRule comment) { + JPanel commentPanel = new JPanel(new GridBagLayout()); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.weightedLastRow(); + final JTextArea commentArea = new JTextArea(4, 40); + commentArea.setText(comment.getCommentText()); + final JScrollPane scrollPane = new JScrollPane(commentArea); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + commentPanel.add(scrollPane, constraints.weightedLastCol()); + commentArea.getDocument().addDocumentListener( + new DocumentListener() { + public void changedUpdate(final DocumentEvent e) { + comment.setCommentText(commentArea.getText()); + } + + public void insertUpdate(final DocumentEvent e) { + comment.setCommentText(commentArea.getText()); + } + + public void removeUpdate(final DocumentEvent e) { + comment.setCommentText(commentArea.getText()); + } + } + ); + return commentPanel; + } + + public boolean commentsMatchGlobalPattern(String pattern) { + return getOffendingPatterns(pattern).size() == 0; + } + + public List getOffendingPatterns(String pattern) { + List result = new ArrayList(2); + if (precedingComment != null && + precedingComment.getCommentText() != null && + precedingComment.getCommentText().length() > 0) + { + final String expandedComment = precedingComment.getCommentText().replaceAll( + "%IF%", "Interface_ExampleName0" + ); + if (!expandedComment.matches(pattern)) { + result.add(((java.lang.String)precedingComment.getCommentText())); + } + } + if (trailingComment != null && + trailingComment.getCommentText() != null && + trailingComment.getCommentText().length() > 0) + { + final String expandedComment = trailingComment.getCommentText().replaceAll( + "%IF%", "Interface_ExampleName0" + ); + if (!expandedComment.matches(pattern)) { + result.add(((java.lang.String)trailingComment.getCommentText())); + } + } + return result; + } + + public int getCommentCount() { + int count = 0; + if (precedingComment != null && + precedingComment.getCommentText() != null && + precedingComment.getCommentText().length() > 0) + { + count++; + } + if (trailingComment != null && + trailingComment.getCommentText() != null && + trailingComment.getCommentText().length() > 0) + { + count++; + } + return count; + } + + public void addCommentPatternsToList(List list) { + if (precedingComment != null) { + addInterfaceCommentPatternToList(list, precedingComment.getCommentText()); + } + if (trailingComment != null) { + addInterfaceCommentPatternToList(list, trailingComment.getCommentText()); + } + } + + private void addInterfaceCommentPatternToList(List list, String commentText) { + if (commentText != null && commentText.length() > 0) { + String esc = RegexUtil.escape(commentText); + String fsp = commentFillString.getFillStringPattern(); + esc = esc.replaceAll("%IF%", "[A-Za-z0-9_]+"); + esc = esc.replaceAll("%FS%", fsp); + list.add(esc); + } + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java new file mode 100644 index 000000000000..369c97c14cea --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.wrq.rearranger.settings.CommentRule; +import org.jdom.Element; + +/** Routines to handle attributes common to class members (fields, methods, and inner classes.) */ +abstract public class ItemAttributes + extends CommonAttributes +{ + +// -------------------------- STATIC METHODS -------------------------- + + public static AttributeGroup readExternal(final Element element) { + if (element.getName().equals("Field")) { + return FieldAttributes.readExternal(element); + } + else if (element.getName().equals("Method")) { + return MethodAttributes.readExternal(element); + } + else if (element.getName().equals("InnerClass")) { + return InnerClassAttributes.readExternal(element); + } + else if (element.getName().equals("Interface")) { + return InterfaceAttributes.readExternal(element); + } + else if (element.getName().equals("Comment")) { + return CommentRule.readExternal(element); + } + else { + return null; + } + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface AttributeGroup --------------------- + + abstract public /*ItemAttributes*/AttributeGroup deepCopy(); +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java new file mode 100644 index 000000000000..79161877cbf8 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java @@ -0,0 +1,680 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.intellij.psi.PsiClassInitializer; +import com.intellij.psi.PsiMethod; +import com.wrq.rearranger.ModifierConstants; +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.atomicAttributes.*; +import com.wrq.rearranger.util.MethodUtil; +import org.jdom.Element; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Routines to handle method modifiers other than those supported by CommonAttributes. These are the 'abstract' + * modifier, a type discriminator (constructor, getter/setter, other), and a boolean flag indicating whether the + * method is overridden or not. + */ +public final class MethodAttributes + extends ItemAttributes + implements IRestrictMethodExtraction, + IHasGetterSetterDefinition +{ + +// ------------------------------ FIELDS ------------------------------ + + private AbstractAttribute abstractAttr; + private OverriddenAttribute overriddenAttr; + private OverridingAttribute overridingAttr; + private InitializerAttribute staticInitAttr; + private NativeAttribute nativeAttr; + private SynchronizedAttribute syncAttr; + private ReturnTypeAttribute returnTypeAttr; + private ImplementedAttribute implementedAttr; + private ImplementingAttribute implementingAttr; + private MinParamsAttribute minParamsAttr; + private MaxParamsAttribute maxParamsAttr; + + private boolean constructorMethodType; + private boolean getterSetterMethodType; + private boolean canonicalMethodType; + private boolean otherMethodType; + private boolean invertMethodType; + private boolean noExtractedMethods; + private GetterSetterDefinition getterSetterDefinition; + +// -------------------------- STATIC METHODS -------------------------- + + public static /*MethodAttributes*/AttributeGroup readExternal(final Element item) { + final MethodAttributes result = new MethodAttributes(); + CommonAttributes.readExternal(result, item); + result.abstractAttr = AbstractAttribute.readExternal(item); + result.syncAttr = SynchronizedAttribute.readExternal(item); + result.overriddenAttr = OverriddenAttribute.readExternal(item); + result.overridingAttr = OverridingAttribute.readExternal(item); + result.staticInitAttr = InitializerAttribute.readExternal(item); + result.nativeAttr = NativeAttribute.readExternal(item); + result.returnTypeAttr = ReturnTypeAttribute.readExternal(item); + result.implementedAttr = ImplementedAttribute.readExternal(item); + result.implementingAttr = ImplementingAttribute.readExternal(item); + result.minParamsAttr = MinParamsAttribute.readExternal(item); + result.maxParamsAttr = MaxParamsAttribute.readExternal(item); + final Element me = item.getChild("Misc"); + + result.constructorMethodType = RearrangerSettings.getBooleanAttribute(me, "constructorMethod"); + result.getterSetterMethodType = RearrangerSettings.getBooleanAttribute(me, "getterSetter"); + result.canonicalMethodType = RearrangerSettings.getBooleanAttribute(me, "canonicalMethod"); + result.otherMethodType = RearrangerSettings.getBooleanAttribute(me, "otherMethod"); + result.invertMethodType = RearrangerSettings.getBooleanAttribute(me, "invertMethod"); + result.noExtractedMethods = RearrangerSettings.getBooleanAttribute(me, "noExtractedMethods"); + result.getterSetterDefinition = GetterSetterDefinition.readExternal(item); + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public MethodAttributes() { + init(); + getterSetterDefinition = new GetterSetterDefinition(); + } + + private void init() { + abstractAttr = new AbstractAttribute(); + overriddenAttr = new OverriddenAttribute(); + overridingAttr = new OverridingAttribute(); + staticInitAttr = new InitializerAttribute(); + nativeAttr = new NativeAttribute(); + syncAttr = new SynchronizedAttribute(); + returnTypeAttr = new ReturnTypeAttribute(); + implementedAttr = new ImplementedAttribute(); + implementingAttr = new ImplementingAttribute(); + minParamsAttr = new MinParamsAttribute(); + maxParamsAttr = new MaxParamsAttribute(); + } + + public MethodAttributes(GetterSetterDefinition defaultGetterSetterDefinition) { + init(); + getterSetterDefinition = defaultGetterSetterDefinition.deepCopy(); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public AbstractAttribute getAbstractAttr() { + return abstractAttr; + } + + public final JPanel getExcludePanel() { + final JPanel excludePanel = new JPanel(new GridBagLayout()); +// final Border border = BorderFactory.createEtchedBorder(); +// excludePanel.setBorder(border); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.NONE; + constraints.weightx = 1.0d; + constraints.weighty = 0.0d; + constraints.gridx = constraints.gridy = 0; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = GridBagConstraints.REMAINDER; + final JCheckBox excludeBox = new JCheckBox("Exclude from extracted method processing"); + excludeBox.setSelected(noExtractedMethods); + excludeBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + noExtractedMethods = excludeBox.isSelected(); + } + }); + excludePanel.add(excludeBox, constraints); + return excludePanel; + } + + public GetterSetterDefinition getGetterSetterDefinition() { + return getterSetterDefinition; + } + + private NativeAttribute getNativeAttr() { + return nativeAttr; + } + + private OverriddenAttribute getOverriddenAttr() { + return overriddenAttr; + } + + private OverridingAttribute getOverridingAttr() { + return overridingAttr; + } + + public ReturnTypeAttribute getReturnTypeAttr() { + return returnTypeAttr; + } + + public InitializerAttribute getStaticInitAttr() { + return staticInitAttr; + } + + private SynchronizedAttribute getSyncAttr() { + return syncAttr; + } + + public ImplementedAttribute getImplementedAttr() { + return implementedAttr; + } + + public ImplementingAttribute getImplementingAttr() { + return implementingAttr; + } + + public MinParamsAttribute getMinParamsAttr() { + return minParamsAttr; + } + + public MaxParamsAttribute getMaxParamsAttr() { + return maxParamsAttr; + } + + public boolean isCanonicalMethodType() { + return canonicalMethodType; + } + + public void setCanonicalMethodType(boolean canonicalMethodType) { + this.canonicalMethodType = canonicalMethodType; + } + + private boolean isConstructorMethodType() { + return constructorMethodType; + } + + public final void setConstructorMethodType(final boolean constructorMethodType) { + this.constructorMethodType = constructorMethodType; + } + + private boolean isGetterSetterMethodType() { + return getterSetterMethodType; + } + + public final void setGetterSetterMethodType(final boolean getterSetterMethodType) { + this.getterSetterMethodType = getterSetterMethodType; + } + + private boolean isInvertMethodType() { + return invertMethodType; + } + + public void setInvertMethodType(boolean invertMethodType) { + this.invertMethodType = invertMethodType; + } + + public boolean isNoExtractedMethods() { + return noExtractedMethods; + } + + public void setNoExtractedMethods(boolean noExtractedMethods) { + this.noExtractedMethods = noExtractedMethods; + } + + private boolean isOtherMethodType() { + return otherMethodType; + } + + public final void setOtherMethodType(final boolean otherMethodType) { + this.otherMethodType = otherMethodType; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + private boolean predicateAdded = false; + private String nextPredicate = null; + + public final String toString() { + // convert settings to readable English description of the method. + // + final StringBuffer sb = new StringBuffer(80); + + sb.append(plAttr.getProtectionLevelString()); + sb.append(stAttr.getDescriptiveString()); + sb.append(fAttr.getDescriptiveString()); + sb.append(staticInitAttr.getDescriptiveString()); + sb.append(nativeAttr.getDescriptiveString()); + sb.append(syncAttr.getDescriptiveString()); + + final int nTypes = (isConstructorMethodType() ? 1 : 0) + + (isGetterSetterMethodType() ? 1 : 0) + + (isCanonicalMethodType() ? 1 : 0) + + (isOtherMethodType() ? 1 : 0); + + int nTypesSeen = 0; + if (isConstructorMethodType()) { + sb.append(isInvertMethodType() ? "non-constructor" : "constructor"); + nTypesSeen++; + if (nTypesSeen < nTypes) { + sb.append("/"); + } + } + if (isGetterSetterMethodType()) { + sb.append(isInvertMethodType() ? "non-getter/setter" : "getter/setter"); + nTypesSeen++; + if (nTypesSeen < nTypes) { + sb.append("/"); + } + } + if (isCanonicalMethodType()) { + sb.append(isInvertMethodType() ? "non-canonical" : "canonical"); + nTypesSeen++; + if (nTypesSeen < nTypes) { + sb.append("/"); + } + } + if (isOtherMethodType()) { + sb.append(isInvertMethodType() ? "non-other-type" : "other"); + nTypesSeen++; + if (nTypesSeen < nTypes) { + sb.append("/"); + } + } + if (nTypes > 0) { + sb.append(' '); + } + sb.append(abstractAttr.getDescriptiveString()); + sb.append(overriddenAttr.getDescriptiveString()); + sb.append(overridingAttr.getDescriptiveString()); + sb.append(implementedAttr.getDescriptiveString()); + sb.append(implementingAttr.getDescriptiveString()); + + if (sb.length() == 0) { + sb.append("all methods"); + } + else { + sb.append("methods"); + } + predicateAdded = false; + nextPredicate = null; + if (minParamsAttr.isMatch() || maxParamsAttr.isMatch()) { + if (!maxParamsAttr.isMatch()) { + nextPredicate = minParamsAttr.getDescriptiveString(); + } + else if (!minParamsAttr.isMatch()) { + nextPredicate = maxParamsAttr.getDescriptiveString(); + } + else { + if (minParamsAttr.getValue() == maxParamsAttr.getValue()) { + nextPredicate = "with " + minParamsAttr.getValue() + + (minParamsAttr.getValue() == 1 + ? " parameter" + : " parameters"); + } + else { + nextPredicate = "with " + minParamsAttr.getValue() + " to " + + maxParamsAttr.getValue() + " parameters"; + } + } + } + if (nameAttr.isMatch()) { + checkPredicate(sb, false); + nextPredicate = nameAttr.getDescriptiveString(); + } + if (returnTypeAttr.isMatch()) { + checkPredicate(sb, false); + nextPredicate = returnTypeAttr.getDescriptiveString(); + } + checkPredicate(sb, true); + sb.append(sortAttr.getDescriptiveString()); + if (noExtractedMethods) { + sb.append(" (no extracted methods)"); + } + return sb.toString(); + } + + private void checkPredicate(StringBuffer sb, boolean finalPredicate) { + if (predicateAdded && nextPredicate != null) { + sb.append(','); + if (finalPredicate) { + sb.append(" and"); + } + } + if (nextPredicate != null) { + sb.append(' '); + sb.append(nextPredicate); + predicateAdded = true; + nextPredicate = null; + } + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface AttributeGroup --------------------- + + // Start Methods of Interface AttributeGroup + public final /*ItemAttributes*/AttributeGroup deepCopy() { + final MethodAttributes result = new MethodAttributes(); + deepCopyCommonItems(result); + result.abstractAttr = (AbstractAttribute)abstractAttr.deepCopy(); + result.nativeAttr = (NativeAttribute)nativeAttr.deepCopy(); + result.syncAttr = (SynchronizedAttribute)syncAttr.deepCopy(); + result.constructorMethodType = constructorMethodType; + result.getterSetterMethodType = getterSetterMethodType; + result.canonicalMethodType = canonicalMethodType; + result.otherMethodType = otherMethodType; + result.invertMethodType = invertMethodType; + result.overriddenAttr = (OverriddenAttribute)overriddenAttr.deepCopy(); + result.overridingAttr = (OverridingAttribute)overridingAttr.deepCopy(); + result.implementedAttr = (ImplementedAttribute)implementedAttr.deepCopy(); + result.implementingAttr = (ImplementingAttribute)implementingAttr.deepCopy(); + result.staticInitAttr = (InitializerAttribute)staticInitAttr.deepCopy(); + result.returnTypeAttr = (ReturnTypeAttribute)returnTypeAttr.deepCopy(); + result.minParamsAttr = (MinParamsAttribute)minParamsAttr.deepCopy(); + result.maxParamsAttr = (MaxParamsAttribute)maxParamsAttr.deepCopy(); + result.noExtractedMethods = noExtractedMethods; + result.getterSetterDefinition = getterSetterDefinition.deepCopy(); + return result; + } + + public final void writeExternal(final Element parent) { + final Element me = new Element("Method"); + writeExternalCommonAttributes(me); + abstractAttr.appendAttributes(me); + nativeAttr.appendAttributes(me); + syncAttr.appendAttributes(me); + overriddenAttr.appendAttributes(me); + overridingAttr.appendAttributes(me); + implementedAttr.appendAttributes(me); + implementingAttr.appendAttributes(me); + staticInitAttr.appendAttributes(me); + returnTypeAttr.appendAttributes(me); + minParamsAttr.appendAttributes(me); + maxParamsAttr.appendAttributes(me); + final Element miscElement = new Element("Misc"); + me.getChildren().add(miscElement); + miscElement.setAttribute("constructorMethod", Boolean.valueOf(constructorMethodType).toString()); + miscElement.setAttribute("getterSetter", Boolean.valueOf(getterSetterMethodType).toString()); + miscElement.setAttribute("canonicalMethod", Boolean.valueOf(canonicalMethodType).toString()); + miscElement.setAttribute("otherMethod", Boolean.valueOf(otherMethodType).toString()); + miscElement.setAttribute("invertMethod", Boolean.valueOf(invertMethodType).toString()); + miscElement.setAttribute("noExtractedMethods", Boolean.valueOf(noExtractedMethods).toString()); + getterSetterDefinition.appendAttributes(me); + parent.getChildren().add(me); + } + +// -------------------------- OTHER METHODS -------------------------- + + public boolean equals(final Object object) { + if (!(object instanceof MethodAttributes)) return false; + final MethodAttributes ma = (MethodAttributes)object; + return (super.equals(object) && + abstractAttr.equals(ma.abstractAttr) && + overriddenAttr.equals(ma.overriddenAttr) && + overridingAttr.equals(ma.overridingAttr) && + implementedAttr.equals(ma.implementedAttr) && + implementingAttr.equals(ma.implementingAttr) && + staticInitAttr.equals(ma.staticInitAttr) && + nativeAttr.equals(ma.nativeAttr) && + syncAttr.equals(ma.syncAttr) && + returnTypeAttr.equals(ma.returnTypeAttr) && + minParamsAttr.equals(ma.minParamsAttr) && + maxParamsAttr.equals(ma.maxParamsAttr) && + isConstructorMethodType() == ma.isConstructorMethodType() && + isGetterSetterMethodType() == ma.isGetterSetterMethodType() && + isCanonicalMethodType() == ma.isCanonicalMethodType() && + isOtherMethodType() == ma.isOtherMethodType() && + invertMethodType == ma.invertMethodType && + noExtractedMethods == ma.noExtractedMethods && + getterSetterDefinition.equals(ma.getterSetterDefinition)); + } + +// End Methods of Interface IRule + + public JPanel getMethodAttributes() { + final JPanel methodPanel = new JPanel(new GridBagLayout()); + final Border border = BorderFactory.createEtchedBorder(); + methodPanel.setBorder(border); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = 1; + constraints.gridheight = 1; + constraints.weightx = 0.0d; + constraints.weighty = 0.0d; + constraints.gridx = constraints.gridy = 0; + methodPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 1; + constraints.gridx = 1; + constraints.weightx = 1; + methodPanel.add(getMethodTypePanel(), constraints); + constraints.gridy = 1; + constraints.insets = new Insets(5, 0, 0, 0); + constraints.gridx = 0; + constraints.gridheight = 1; + constraints.gridwidth = 1; + methodPanel.add(getStAttr().getAndNotPanel(), constraints); + constraints.gridx++; + methodPanel.add(getAbstractAttr().getAndNotPanel(), constraints); + constraints.gridx = 0; + constraints.gridy++; + methodPanel.add(getfAttr().getAndNotPanel(), constraints); + constraints.gridx++; + methodPanel.add(getSyncAttr().getAndNotPanel(), constraints); + constraints.gridx = 0; + constraints.gridy++; + methodPanel.add(getOverriddenAttr().getAndNotPanel(), constraints); + constraints.gridx++; + methodPanel.add(getOverridingAttr().getAndNotPanel(), constraints); + constraints.gridx = 0; + constraints.gridy++; + methodPanel.add(getImplementedAttr().getAndNotPanel(), constraints); + constraints.gridx++; + methodPanel.add(getImplementingAttr().getAndNotPanel(), constraints); + constraints.gridx = 0; + constraints.gridy++; + methodPanel.add(getStaticInitAttr().getAndNotPanel(), constraints); + constraints.gridx++; + methodPanel.add(getNativeAttr().getAndNotPanel(), constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 0; + constraints.gridy++; + methodPanel.add(getMinParamsAttr().getIntegerPanel(), constraints); + constraints.gridy++; + methodPanel.add(getMaxParamsAttr().getIntegerPanel(), constraints); + constraints.gridy++; + methodPanel.add(getNameAttr().getStringPanel(), constraints); + constraints.gridy++; + methodPanel.add(getReturnTypeAttr().getStringPanel(), constraints); + constraints.gridy++; + constraints.insets = new Insets(0, 0, 0, 0); + methodPanel.add(getExcludePanel(), constraints); + constraints.gridy++; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.weighty = 1.0d; + methodPanel.add(sortAttr.getSortOptionsPanel(), constraints); + return methodPanel; + } + + private JPanel getMethodTypePanel() { + final JPanel mtPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.fill = GridBagConstraints.BOTH; + constraints.gridwidth = 1; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.anchor = GridBagConstraints.WEST; + constraints.weightx = 0.0d; + constraints.weighty = 1.0d; + constraints.gridx = constraints.gridy = 0; + final JCheckBox notBox = new JCheckBox("not"); + notBox.setSelected(isInvertMethodType()); + notBox.setForeground(notBox.isSelected() ? Color.BLACK : Color.GRAY); + mtPanel.add(notBox, constraints); + constraints.gridx++; + constraints.weightx = 1.0d; + constraints.gridwidth = GridBagConstraints.REMAINDER; + mtPanel.add(getMethodTypeInnerPanel(), constraints); + notBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setInvertMethodType(notBox.isSelected()); + notBox.setForeground(notBox.isSelected() ? Color.BLACK : Color.GRAY); + } + }); + + return mtPanel; + } + + private JPanel getMethodTypeInnerPanel() { + final JPanel mtPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 1; + constraints.anchor = GridBagConstraints.WEST; + constraints.fill = GridBagConstraints.NONE; + constraints.weightx = 1.0d; + constraints.weighty = 0.0d; + constraints.gridx = constraints.gridy = 0; + final JCheckBox constructorBox = new JCheckBox("constructor or"); + constructorBox.setSelected(isConstructorMethodType()); + final JCheckBox getterSetterBox = new JCheckBox(); + final JButton gsDefButton = new JButton("getter/setter"); + final JLabel gsOrLabel = new JLabel(" or"); + getterSetterBox.setSelected(isGetterSetterMethodType()); + final JCheckBox canonicalBox = new JCheckBox("canonical or"); + canonicalBox.setSelected(isCanonicalMethodType()); + final JCheckBox otherTypeBox = new JCheckBox("other type"); + otherTypeBox.setSelected(isOtherMethodType()); + mtPanel.add(constructorBox, constraints); + constraints.gridy++; + constraints.weightx = 0; + constraints.gridwidth = 1; + mtPanel.add(getterSetterBox, constraints); + constraints.gridx++; + mtPanel.add(gsDefButton, constraints); + constraints.gridx++; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1; + mtPanel.add(gsOrLabel, constraints); + constraints.gridx = 0; + constraints.gridy++; + mtPanel.add(canonicalBox, constraints); + constraints.gridy++; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.weighty = 1.0d; + mtPanel.add(otherTypeBox, constraints); + constructorBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setConstructorMethodType(constructorBox.isSelected()); + } + }); + getterSetterBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setGetterSetterMethodType(getterSetterBox.isSelected()); + } + }); + canonicalBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setCanonicalMethodType(canonicalBox.isSelected()); + } + }); + otherTypeBox.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setOtherMethodType(otherTypeBox.isSelected()); + } + }); + gsDefButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + GetterSetterDefinition tempgsd = getterSetterDefinition.deepCopy(); + final JPanel gsDefPanel = tempgsd.getGSDefinitionPanel(); + final JOptionPane op = new JOptionPane( + gsDefPanel, + JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, + null, null, null); + final JDialog jd = op.createDialog(null, "Getter/Setter definition"); + jd.setVisible(true); + final Object result = op.getValue(); + if (result != null && + ((Integer)result) == JOptionPane.OK_OPTION) + { + getterSetterDefinition = tempgsd; + } + } + }); + + return mtPanel; + } + +// End Methods of Interface AttributeGroup +// Start Methods of Interface IRule + + public final boolean isMatch(RangeEntry entry) { + final boolean result = (entry.getEnd() instanceof PsiMethod || + entry.getEnd() instanceof PsiClassInitializer) && + super.isMatch(entry) && + abstractAttr.isMatch(entry.getModifiers()) && + overriddenAttr.isMatch(entry.getModifiers()) && + overridingAttr.isMatch(entry.getModifiers()) && + implementedAttr.isMatch(entry.getModifiers()) && + implementingAttr.isMatch(entry.getModifiers()) && + staticInitAttr.isMatch(entry.getModifiers()) && + nativeAttr.isMatch(entry.getModifiers()) && + syncAttr.isMatch(entry.getModifiers()) && + returnTypeAttr.isMatch(entry.getType()) && + minParamsAttr.isMatch(entry.getEnd()) && + maxParamsAttr.isMatch(entry.getEnd()); + if (result == false) { + return false; + } + boolean typeResult = false; + if (isConstructorMethodType()) { + typeResult |= (entry.getModifiers() & ModifierConstants.CONSTRUCTOR) == ModifierConstants.CONSTRUCTOR; + } + if (isGetterSetterMethodType() && + entry.getEnd() instanceof PsiMethod) + { + /** + * determine if the method is a getter or setter according to this rule's specific + * definition. + */ + boolean isGetter = MethodUtil.isGetter((PsiMethod)entry.getEnd(), + getterSetterDefinition); + boolean isSetter = MethodUtil.isSetter((PsiMethod)entry.getEnd(), + getterSetterDefinition); + typeResult |= isGetter | isSetter; + } + if (isCanonicalMethodType()) { + typeResult |= (entry.getModifiers() & ModifierConstants.CANONICAL) == ModifierConstants.CANONICAL; + } + if (isOtherMethodType()) { + typeResult |= (entry.getModifiers() & ModifierConstants.OTHER_METHOD) == ModifierConstants.OTHER_METHOD; + } + typeResult ^= invertMethodType; + if (!constructorMethodType && + !getterSetterMethodType && + !canonicalMethodType && + !otherMethodType) + { + typeResult = true; // true if no method type options are selected. + } + return result && typeResult; + } +} + diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/RegexUtil.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/RegexUtil.java new file mode 100644 index 000000000000..4ea8f5a0838d --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/RegexUtil.java @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.regex.PatternSyntaxException; + +/** Supplies several utilities for regular expression handling and global comment generation. */ +public class RegexUtil { + /** + * Handles escaping of regular expression syntax in an ordinary string so that the resulting string may be used as + * a pattern to match the original string. + * + * @param in original string + * @return pattern match string, which matches original string + */ + public static String escape(String in) { + StringBuffer sb = new StringBuffer(in.length() * 2); + for (int i = 0; i < in.length(); i++) { + char c = in.charAt(i); + switch (c) { + case '\t': + sb.append("\\t"); + break; + case '\n': + sb.append("\\n"); + break; + case '\\': + case '[': + case ']': + case '(': + case ')': + case '.': + case '^': + case '$': + case '?': + case '*': + case '+': + sb.append('\\'); + sb.append(c); + break; + default: + sb.append(c); + } + } + // now inspect for occurrences of the same character 4 times or more in a row; replace with + // {N} where N is the number of occurrences. + final int MIN_REPEAT = 4; + for (int i = 0; i < sb.length() - MIN_REPEAT; i++) { + /** Count the number of identical characters in sequence at this location. */ + boolean escaped = sb.charAt(i) == '\\'; + int escapeBias = (escaped ? 1 : 0); + char match = sb.charAt(i + escapeBias); + int sequenceCount = 1; // a character always begins a sequence of at least one character + for (int j = i + 1 + escapeBias; + j < sb.length() - escapeBias; + j += 1 + escapeBias) + { + if (escaped) { + if (sb.charAt(j) == '\\' && + sb.charAt(j + 1) == match) + { + sequenceCount++; + continue; + } + } + else if (sb.charAt(j) == match) { + sequenceCount++; + continue; + } + break; + } + if (sequenceCount >= MIN_REPEAT) { + // we've seen a sequence of MIN_REPEAT identical characters. + // Substitute {sequenceCount} + int startOffset = i; + int endOffset = i + sequenceCount * (1 + escapeBias); + sb.delete(startOffset, endOffset); + final String s = (escaped ? "\\" : "") + match + "{" + sequenceCount + "}"; + sb.insert(startOffset, s); + i += s.length() - 1; // subtract one; the for-loop will increment it + } + } + return sb.toString(); + } + + /** + * Performs a literal substitution in commentText, replacing all occurrences of "%FS%" with the + * fill string. + * + * @param commentText + * @param fillString + * @return + */ + public static String replaceAllFS(String commentText, String fillString) { + StringBuffer sb = new StringBuffer(commentText.length()); + int i; + int lastOffset = 0; + while ((i = commentText.indexOf("%FS%", lastOffset)) >= 0) { + // copy everything from last offset to index. + sb.append(commentText.substring(lastOffset, i)); + // copy the replacement string. + sb.append(fillString); + // bump index past %FS%. + i += 4; + lastOffset = i; + } + // now copy everything from lastOffset to end of string. + sb.append(commentText.substring(lastOffset)); + return sb.toString(); + } + + /** + * Extracts common starting and ending characters from a list of expression patterns and creates a new + * combined expression pattern. + * + * @param expressionList list of individual regular expression patterns + * @return combined expression pattern + */ + public static String combineExpressions(List expressionList) { + final String firstString = expressionList.get(0); + if (expressionList.size() == 1) { + return firstString; + } + int commonStart = 0, commonEnd = 0; + commonStart = calculateCommonStart(expressionList); + commonEnd = calculateCommonEnd(commonStart, expressionList); + + if (commonStart == 0 && commonEnd == 0) { + return combineSubgroups(expressionList); + } + String result = ""; + /** + * now check validity of resulting pattern. If commonStart or commonEnd broke apart some regular expression + * syntax, e.g. // \*{(10}|20}) the pattern is invalid. Try all combinations of commonStart/commonEnd + * until we find one that works. + */ + boolean valid = false; + for (int start = commonStart; start >= 0; start--) { + for (int end = commonEnd; end >= 0; end--) { + valid = true; + int totalLength = 0; + for (Object aExpressionList : expressionList) { + String s = ((String)aExpressionList); + totalLength += s.length() + 1; + } + StringBuffer sb = new StringBuffer(totalLength + 2); + sb.append(firstString.substring(0, start)); + List subgroups = new ArrayList(expressionList.size()); + for (Object aExpressionList1 : expressionList) { + String s = ((String)aExpressionList1); + s = s.substring(start, s.length() - end); + subgroups.add(s); + } + String combined = combineSubgroups(subgroups); + sb.append(combined); + sb.append(firstString.substring(firstString.length() - end, firstString.length())); + result = sb.toString(); + try { + if (valid && " ".matches(result)) ; + } + catch (PatternSyntaxException e) { + valid = false; + } + if (valid) { + return result; + } + } + } + return result; + } + + private static String combineSubgroups(List expressionList) { + int totalSize = 0; + List> groups = new ArrayList>(); + List strings = new ArrayList(expressionList); + while (strings.size() > 0) { + List subgroup = new ArrayList(); + String firstString = strings.remove(0); + totalSize += firstString.length(); + subgroup.add(firstString); + + + ListIterator otherStrings = strings.listIterator(); + while (otherStrings.hasNext()) { + String otherString = otherStrings.next(); + List testGroup = new ArrayList(); + testGroup.add(firstString); + testGroup.add(otherString); + int commonStart = calculateCommonStart(testGroup); + int commonEnd = calculateCommonEnd(commonStart, testGroup); + if (commonStart >= 2 || commonEnd >= 2) { + subgroup.add(otherString); + totalSize += otherString.length(); + otherStrings.remove(); + } + } + groups.add(subgroup); + } + // now groups contains a list of subgroups. Each subgroup consists of one or more strings. + // strings in a subgroup share at least two leading and/or trailing characters. + // return a parenthesized list of the subgroups. + StringBuffer sb = new StringBuffer(totalSize); + ListIterator> groupLI = groups.listIterator(); + if (groups.size() > 1) { + sb.append('('); + } + boolean first = true; + while (groupLI.hasNext()) { + if (first) { + first = false; + } + else { + sb.append('|'); + } + List nextGroup = groupLI.next(); + final String s = combineExpressions(nextGroup); + sb.append(s); + } + if (groups.size() > 1) { + sb.append(')'); + } + return sb.toString(); + } + + private static int calculateCommonEnd(int commonStart, List expressionList) { + final String firstString = expressionList.get(0); + return calculateCommonEnd(commonStart, expressionList, firstString.length() - commonStart); + } + + private static int calculateCommonEnd(int commonStart, List expressionList, int maxCommonEnd) { + final String firstString = (expressionList.get(0)); + int commonEnd = 0; + boolean matching = true; + while (matching && commonEnd < maxCommonEnd) { + if (commonEnd == firstString.length() - commonStart) { + break; + } + commonEnd++; + String match = firstString.substring(firstString.length() - commonEnd, + firstString.length()); + for (int i = 1; i < expressionList.size(); i++) { + if (!((expressionList.get(i))).endsWith(match)) { + matching = false; + commonEnd--; + break; + } + } + } + String match = firstString.substring(firstString.length() - commonEnd, + firstString.length()); + if (commonEnd > 0 && + !checkSubstringPatternValidity(match)) + { + return calculateCommonEnd(commonStart - 1, expressionList, commonEnd - 1); + } + return commonEnd; + } + + private static int calculateCommonStart(List expressionList) { + final String firstString = ((java.lang.String)expressionList.get(0)); + return calculateCommonStart(expressionList, firstString.length()); + } + + private static int calculateCommonStart(List expressionList, int maxCommonStart) { + final String firstString = ((java.lang.String)expressionList.get(0)); + int commonStart = 0; + boolean matching = true; + while (matching && commonStart < maxCommonStart) { + if (commonStart == firstString.length()) { + break; + } + commonStart++; + String match = firstString.substring(0, commonStart); + for (int i = 1; i < expressionList.size(); i++) { + if (!(((java.lang.String)expressionList.get(i))).startsWith(match)) { + matching = false; + commonStart--; + break; + } + } + } + if (commonStart > 0) { + if (!checkSubstringPatternValidity(firstString.substring(0, commonStart)) || + !checkRemainderPatternValidity(firstString.substring(commonStart))) + { + return calculateCommonStart(expressionList, commonStart - 1); + } + } + return commonStart; + } + + private static boolean checkRemainderPatternValidity(String s) { + char c = s.charAt(0); + return (c != '{' && c != '}'); + } + + private static boolean checkSubstringPatternValidity(String s) { + char c = s.charAt(0); + if (c == '+' || c == '*' || c == '?') return false; + if (s.length() >= 2) { + if (s.charAt(s.length() - 1) == '\\' && s.charAt(s.length() - 2) != '\\') { + return false; + } + } + return (count(s, '[') == count(s, ']') && + count(s, '{') == count(s, '}')); + } + + private static int count(String s, char c) { + char[] chars = s.toCharArray(); + int result = 0; + for (int i = 0; i < chars.length; i++) { + if (chars[i] == c) { + if (i == 0 || chars[i - 1] != '\\') { + // character is not escaped, count it + result++; + } + } + } + return result; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java new file mode 100644 index 000000000000..388c92f79896 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.settings.attributeGroups; + +import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.ruleinstance.HeaderTrailerRuleInstance; +import com.wrq.rearranger.ruleinstance.IRuleInstance; + +import java.util.ArrayList; +import java.util.List; + +/** A rule to match header text (text which does not constitute a matchable item such as a field or method.) */ +public class TrailerRule + implements IRule +{ + public IRuleInstance createRuleInstance() { + return new HeaderTrailerRuleInstance(this); + } + + public int getPriority() { + return -1; // priority doesn't matter since header rules only match the one trailer entry (if it exists), and + // the trailer entry is never matched by another rule. + } + + public void setPriority(int priority) { + // does nothing + } + + public boolean isMatch(RangeEntry rangeEntry) { + return rangeEntry.isFixedTrailer(); + } + + public boolean commentsMatchGlobalPattern(String pattern) { + return true; + } + + public List getOffendingPatterns(String pattern) { + return new ArrayList(1); + } + + public int getCommentCount() { + return 0; + } + + public void addCommentPatternsToList(List list) { + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java b/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java new file mode 100644 index 000000000000..64ade9ae3e29 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.util; + +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.IRule; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CommentUtil { + final RearrangerSettings settings; + static CommentUtil singleton; + List commentStrings; + List commentMatchers; + + public CommentUtil(RearrangerSettings settings) { + this.settings = settings; + createCommentPatternList(); + createCommentMatcherList(); + singleton = this; + } + + public static List getCommentStrings() { + return singleton.commentStrings; + } + + public static List getCommentMatchers() { + return singleton.commentMatchers; + } + + private void createCommentMatcherList() { + if (settings.getGlobalCommentPattern() != null && + settings.getGlobalCommentPattern().length() > 0) + { + // create only one Matcher for the global comment pattern. + commentMatchers = new ArrayList(1); + commentMatchers.add((getMatcher(settings.getGlobalCommentPattern()))); + } + else { + commentMatchers = new ArrayList(commentStrings.size()); + for (String comment : commentStrings) { + Matcher matcher = getMatcher(comment); + commentMatchers.add(matcher); + } + } + } + + /** + * Strips any "\n" patterns off the front and end of the comment; inserts "\n*" patterns at front and end + * of the comment; and creates a Matcher for the comment. This will ultimately match any sequence of + * blank lines before/after the separator comment. + * Also ignores leading blanks after any newline character. + * + * @param comment comment string, already 'escaped' so it is safe for literal matching + * @return matcher which will match that comment, ignoring any leading or trailing newline characters and + * any leading space. + */ + private Matcher getMatcher(String comment) { + StringBuffer sb = new StringBuffer(comment); + /** + * remove any literal newline characters or escaped equivalent ('\n') at beginning of comment. + */ + while (true) { + if (sb.length() >= 2 && sb.charAt(0) == '\\' && sb.charAt(1) == 'n') { + sb.delete(0, 2); + continue; + } + if (sb.length() >= 1 && sb.charAt(0) == '\n') { + sb.delete(0, 1); + continue; + } + break; + } + /** + * similarly, remove any literal newline characters or escaped equivalents at end of comment. + */ + while (true) { + if (sb.length() >= 2 && sb.charAt(sb.length() - 2) == '\\' && sb.charAt(sb.length() - 1) == 'n') { + sb.delete(sb.length() - 2, sb.length()); + continue; + } + if (sb.length() >= 1 && sb.charAt(sb.length() - 1) == '\n') { + sb.delete(sb.length() - 1, sb.length()); + continue; + } + break; + } + if (sb.length() > 0) { + // now replace all intermediate newline characters with an expression to match leading spaces as well. + String intermediate = sb.toString().replaceAll("\\\\n", "\\\\n\\\\s*"); + sb.replace(0, sb.length(), intermediate); + sb.insert(0, "([\\n\\s]*"); + sb.append(")+[\\n\\s]*?\\n+"); + } + else { + sb.replace(0, sb.length(), "[\\n\\s]*?\\n+"); + } + Matcher matcher = Pattern.compile(sb.toString()).matcher(""); + return matcher; + } + + private void createCommentPatternList() { + commentStrings = new ArrayList(); + for (IRule rule : settings.getClassOrderAttributeList()) { + rule.addCommentPatternsToList(commentStrings); + } + for (IRule rule : settings.getItemOrderAttributeList()) { + rule.addCommentPatternsToList(commentStrings); + } + settings.getExtractedMethodsSettings().addCommentPatternsToList(commentStrings); + } + + /** + * Calculate the apparent length of a string if tabs are expanded. + * Leading tabs are no problem; embedded tabs would be, if the %FS% fill string expansions are not multiples of + * "%FS%".length() == 4, because after expansion the embedded tabs would misalign. However, I'm not going to + * address that yet. (This is just to fix Thomas Singer's bug with leading tab.) + * + * @param s + * @param tabSize + * @return + */ + private static int logicalLength(String s, int tabSize) { + int result = 0; + boolean sawNonTab = false; + for (char c : s.toCharArray()) { + if (c == '\t' && !sawNonTab) { + result += tabSize; + } + else { + sawNonTab = true; + result++; + } + } + return result; + } + + /** + * Utility to take a comment string which may contain %FS% keywords and replace them with equal number of + * fill characters to cause the comment to fill an entire line. + * + * @param comment String containing comment; may contain zero or more %FS% keywords; may be multiline. + * @param width desired column width of line. + * @param tabSize + * @param fillString string containing characters to replicate as needed for fill. @return + */ + public static String expandFill(String comment, + int width, + int tabSize, + String fillString) + { + StringBuffer result = new StringBuffer(comment.length() * 2); + int EOLindex = 0; + StringBuffer fillChars = new StringBuffer(); + if (fillString.length() == 0) { + fillString = " "; // fill with spaces if no pattern supplied + } + do { + // strip next line from previous end of line index to next new line character (or end of string if none) + int index = comment.indexOf('\n', EOLindex); + if (index < 0) { + index = comment.length(); + } + else { + index++; // include newline character + } + String str = comment.substring(EOLindex, index); + if (str.length() > 0) { + // count number of %FS% occurrences in the string. + int nFS = 0; + int offset = 0; + while ((offset = str.indexOf("%FS%", offset)) >= 0) { + nFS++; + offset += 4; // bump past %FS% + } + // determine line length excluding %FS% strings. Don't count final newline character, if present. + int fixedLength = logicalLength(str, tabSize) - nFS * 4; + if (str.charAt(str.length() - 1) == '\n') { + fixedLength--; + } + // determine number of characters to fill + int fillLength = width - fixedLength; + int[] fillWidths = new int[nFS]; + int maxFillWidth = 0; + // do no filling if the length of the comment is already the desired width (or greater). + if (fillLength > 0 && nFS > 0) { + int eachFill = fillLength / nFS; + int remainder = fillLength % nFS; + for (int i = 0; i < nFS; i++) { + // calculate fill widths for each %FS%. + // any remainder (fillLength % nFS) is distributed among the first %FS% fills. + fillWidths[i] = eachFill + (i < remainder ? 1 : 0); + maxFillWidth = Math.max(maxFillWidth, fillWidths[i]); + } + } + // get enough fill chars + fillChars.ensureCapacity(maxFillWidth); + while (fillChars.length() < maxFillWidth) { + fillChars.append(fillString); + } + // now do the expansion + offset = 0; + int previousOffset = 0; + int fillWidthIndex = 0; + while ((offset = str.indexOf("%FS%", offset)) >= 0) { + // copy everything from previousOffset to offset. + result.append(str.substring(previousOffset, offset)); + offset += 4; // bump past %FS% + previousOffset = offset; + // then expand the fill string to fillWidths[fillWidthIndex] characters and append it. + result.append(fillChars.toString().substring(0, fillWidths[fillWidthIndex++])); + // todo - JDK 1.5, .append(fillChars, 0, width) + } + // copy everything from previousOffset to end of line, and append a new line. + result.append(str.substring(previousOffset)); + } + EOLindex = index; + } + while (EOLindex < comment.length()); + return result.toString(); + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/util/Constraints.java b/plugins/rearranger/src/com/wrq/rearranger/util/Constraints.java new file mode 100644 index 000000000000..bdaa6754d85a --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/util/Constraints.java @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.util; + +import java.awt.*; + +/** Utility class for performing common operations on GridBagConstraints. */ +public class Constraints + extends GridBagConstraints +{ + boolean newRow; + + /** + * Constructs a new Constraints object and initializes a new row.
+ * Side effects are: + *

+   *    gridy = 0
+   *    gridx = 0
+   *    gridheight = 1
+   *    gridwidth = 1
+   *    weightx = 0
+   *    weighty = 0
+   *    fill = NONE
+   *    anchor = WEST
+   * 
+ */ + public Constraints() { + fill = GridBagConstraints.NONE; + gridwidth = 1; + gridheight = 1; + anchor = GridBagConstraints.WEST; + weightx = 0.0d; + weighty = 0.0d; + gridx = gridy = 0; + newRow = true; + newRow(); + } + + /** + * Constructs a new Constraints object and initializes a new row.
+ * Side effects are: + *
+   *    gridy = 0
+   *    gridx = 0
+   *    gridheight = 1
+   *    gridwidth = 1
+   *    weightx = 0
+   *    weighty = 0
+   *    fill = NONE
+   *    anchor = specified parameter
+   * 
+ */ + public Constraints(int anchor) { + this(); + this.anchor = anchor; + } + + /** + * Prepares for adding components to a new row.
+ * Side effects are: + *
+   *    gridy++ (if not already at the beginning of a new row)
+   *    gridx = 0
+   *    gridheight = 1
+   *    weighty = 0
+   * 
+ */ + public void newRow() { + if (!newRow) { + gridy++; + } + gridx = 0; + gridheight = 1; + weighty = 0; + newRow = true; + } + + /** + * Prepares for adding components to a new row, which is weighted.
+ * Side effects are: + *
+   *    gridy++ (if not the first row)
+   *    gridx = 0
+   *    gridheight = 1
+   *    weighty = supplied parameter
+   * 
+ */ + public void weightedNewRow(double weight) { + newRow(); + weighty = weight; + } + + /** + * Prepares for adding components to a new row, which is weighted.
+ * Side effects are: + *
+   *    gridy++ (if not the first row)
+   *    gridx = 0
+   *    gridheight = 1
+   *    weighty = 1
+   * 
+ */ + public void weightedNewRow() { + weightedNewRow(1); + } + + /** + * Prepares for adding components to a new row which will be the last row.
+ * Side effects are: + *
+   *    gridy++ (if not the first row)
+   *    gridx = 0
+   *    gridheight = REMAINDER
+   *    weighty = 0
+   * 
+ */ + public void lastRow() { + newRow(); + gridheight = REMAINDER; + } + + /** + * Prepares for adding components to a new weightd row which will be the last row.
+ * Side effects are: + *
+   *    gridy++ (if not the first row)
+   *    gridx = 0
+   *    gridheight = REMAINDER
+   *    weighty = supplied parameter
+   * 
+ */ + public void weightedLastRow(double weight) { + lastRow(); + weighty = weight; + } + + /** + * Prepares for adding components to a new weightd row which will be the last row.
+ * Side effects are: + *
+   *    gridy++ (if not the first row)
+   *    gridx = 0
+   *    gridheight = REMAINDER
+   *    weighty = 1
+   * 
+ */ + public void weightedLastRow() { + weightedLastRow(1); + } + + /** + * Automatically starts a new row if not explicitly done already or if columns have been added since the last + * newRow() call.
+ * Side effects are: + *
+   *    gridx = 0
+   *    newRow = false
+   *    gridwidth = 1
+   *    weightx = 0
+   * 
+ * + * @return this Constraints object + */ + public Constraints firstCol() { + if (!newRow) { + newRow(); + } + gridx = 0; + newRow = false; + gridwidth = 1; + weightx = 0; + return this; + } + + /** + * Automatically starts a new weighted row if not explicitly done already or if columns have been added since the last + * newRow() call.
+ * Side effects are: + *
+   *    gridx = 0
+   *    newRow = false
+   *    gridwidth = 1
+   *    weightx = 1
+   * 
+ * + * @return this Constraints object + */ + public Constraints weightedFirstCol() { + firstCol(); + weightx = 1; + return this; + } + + /** + * Prepares to add a component to the next column. If this is the first column in the row, + * gridx will be zero (not one).
+ * Side effects are: + *
+   *    gridx = gridx + 1 (or zero, if this is the beginning of a new row)
+   *    newRow = false
+   *    gridwidth = 1
+   *    weightx = 0
+   * 
+ * + * @return this Constraints object + */ + public Constraints nextCol() { + gridx = newRow ? 0 : gridx + 1; + newRow = false; + gridwidth = 1; + weightx = 0; + return this; + } + + /** + * Prepares to add a weighted component to the next column.
+ * Side effects are: + *
+   *    gridx = gridx + 1 (or zero, if this is the beginning of a new row)
+   *    newRow = false
+   *    gridwidth = 1
+   *    weightx = supplied parameter
+   * 
+ * + * @return this Constraints object + */ + public Constraints weightedNextCol(double weight) { + nextCol(); + weightx = weight; + return this; + } + + /** + * Prepares to add a weighted component to the next column.
+ * Side effects are: + *
+   *    gridx = gridx + 1 (or zero, if this is the beginning of a new row)
+   *    newRow = false
+   *    gridwidth = 1
+   *    weightx = 1
+   * 
+ * + * @return this Constraints object + */ + public Constraints weightedNextCol() { + return weightedNextCol(1); + } + + /** + * Prepares to add a component to the last column.
+ * Side effects are: + *
+   *    gridx = gridx + 1 (or zero, if this is the beginning of a new row)
+   *    newRow = false
+   *    gridwidth = REMAINDER
+   *    weightx = 0
+   * 
+ * + * @return this Constraints object + */ + public Constraints lastCol() { + nextCol(); + gridwidth = REMAINDER; + return this; + } + + /** + * Prepares to add a weighted component to the last column.
+ * Side effects are: + *
+   *    gridx = gridx + 1 (or zero, if this is the beginning of a new row)
+   *    newRow = false
+   *    gridwidth = REMAINDER
+   *    weightx = supplied parameter
+   * 
+ * + * @return this Constraints object + */ + public Constraints weightedLastCol(double weight) { + weightedNextCol(weight); + gridwidth = REMAINDER; + return this; + } + + /** + * Prepares to add a weighted component to the last column.
+ * Side effects are: + *
+   *    gridx = gridx + 1 (or zero, if this is the beginning of a new row)
+   *    newRow = false
+   *    gridwidth = REMAINDER
+   *    weightx = 1
+   * 
+ * + * @return this Constraints object + */ + public Constraints weightedLastCol() { + weightedLastCol(1); + gridwidth = REMAINDER; + return this; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/util/IconUtil.java b/plugins/rearranger/src/com/wrq/rearranger/util/IconUtil.java new file mode 100644 index 000000000000..2e5c5437a23d --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/util/IconUtil.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.util; + +import com.intellij.openapi.diagnostic.Logger; +import com.wrq.rearranger.Rearranger; + +import javax.swing.*; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +/** Utility methods to obtain an icon from a resource or file. */ +public class IconUtil { +// ------------------------------ FIELDS ------------------------------ + + private static final Logger LOG = Logger.getInstance("#" + IconUtil.class.getName()); + +// -------------------------- STATIC METHODS -------------------------- + + + public static final Icon getIcon(String iconName) { + URL iconURL = Rearranger.class.getClassLoader().getResource("com/wrq/rearranger/" + iconName + ".png"); + if (iconURL == null) { + if (true) { +// // for debugging only; +// // in development, there's no resource (no jar file built), +// // so go to the file directly. + try { + URLClassLoader cl = new URLClassLoader( + new URL[] + {new File("/rearranger/lib/rearranger.jar").toURL(), + new File("/IntelliJ-IDEA-4.0/lib/icons.jar").toURL()} + ); + iconURL = cl.getResource("com/wrq/rearranger/" + iconName + ".png"); + if (iconURL == null) { + iconURL = cl.getResource(iconName + ".png"); + } + } + catch (MalformedURLException e) { + iconURL = null; + } + } + } + if (iconURL != null) { + final ImageIcon imageIcon = new ImageIcon(iconURL, iconName); + return imageIcon; + } + LOG.debug( + "getIcon: getResource() could not locate URL for com/wrq/rearranger/" + + iconName + + ".png or " + + iconName + ".png in icons.jar" + ); + return null; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/util/MethodUtil.java b/plugins/rearranger/src/com/wrq/rearranger/util/MethodUtil.java new file mode 100644 index 000000000000..c83ba74f8157 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/util/MethodUtil.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.util; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; +import com.wrq.rearranger.settings.attributeGroups.GetterSetterDefinition; + +/** Code to determine if a method is truly a simple getter or setter, courtesy of Alain Ravet. */ +public final class MethodUtil { + + public static boolean isGetter(PsiMethod i_method, + GetterSetterDefinition gsd) + { + if (i_method == null) { + return false; + } + + final boolean hasParameters = 1 <= nofParameters(i_method); + if (hasParameters) { + return false; + } + + + final String name = i_method.getName(); + + if (name.startsWith("get")) return getterNameMatchedReturnedValue(i_method, name, "get", gsd); + if (name.startsWith("is")) return getterNameMatchedReturnedValue(i_method, name, "is", gsd); + if (name.startsWith("has")) return getterNameMatchedReturnedValue(i_method, name, "has", gsd); + + return false; + } + + private static boolean getterNameMatchedReturnedValue(PsiMethod i_method, + String i_name, + String i_prefix, + GetterSetterDefinition gsd) + { + String i_methodNameTrail = i_name.substring(i_prefix.length()); + if (!nameIsWellFormed(i_methodNameTrail)) { + return false; + } + + if (isAbstract(i_method)) { + return false; + } + + boolean nameOK = false, bodyOK = false; + switch (gsd.getGetterNameCriterion()) { + case GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX: + nameOK = true; + break; + case GetterSetterDefinition.GETTER_NAME_MATCHES_FIELD: + final String nameFromBody = nameOfVariableReturnedInBody(i_method); + final String propertyName = propertyNameFromMethodTrail(i_methodNameTrail); + nameOK = nameFromBody.equals(fieldName(propertyName, i_method.getProject())); + break; + } + switch (gsd.getGetterBodyCriterion()) { + case GetterSetterDefinition.GETTER_BODY_IMMATERIAL: + bodyOK = true; + break; + case GetterSetterDefinition.GETTER_BODY_RETURNS: + bodyOK = methodContainsReturnStatementOnly(i_method); + break; + case GetterSetterDefinition.GETTER_BODY_RETURNS_FIELD: + final String nameFromBody = nameOfVariableReturnedInBody(i_method); + final String propertyName = propertyNameFromMethodTrail(i_methodNameTrail); + bodyOK = nameFromBody.equals(fieldName(propertyName, i_method.getProject())); + break; + } + return nameOK && bodyOK; + } + + private static boolean methodContainsReturnStatementOnly(PsiMethod i_method) { + final PsiStatement[] statements = i_method.getBody().getStatements(); + return isReturnStatement(statements[0]); + } + + private static String nameOfVariableReturnedInBody(PsiMethod i_method) { + + final PsiStatement[] statements = i_method.getBody().getStatements(); + + if (nofStatements(i_method) == 0) { + return ""; + } + + int returnIndex = statements.length - 1; + if (!isReturnStatement(statements[returnIndex])) { + return ""; + } + final PsiReturnStatement returnStatement = (PsiReturnStatement)statements[returnIndex]; + final PsiExpression returnValue = returnStatement.getReturnValue(); + if (null == returnValue) { + return ""; + } + String returnValueText = returnValue.getText(); + returnValueText = returnValueText.replaceFirst("this\\.", ""); + return returnValueText; + } + + private static String propertyNameFromMethodTrail(String i_source) { + if (i_source.length() > 0) { + final String left = i_source.substring(0, 1).toLowerCase(); + final String right = i_source.substring(1); + + return left + right; + } + else { + return ""; + } + } + + public static String getPropertyName(PsiMethod i_method) { + final String name = i_method.getName(); + + if (name.startsWith("get") || + name.startsWith("has") || + name.startsWith("set")) + { + return name.substring(3); + } + + if (name.startsWith("is")) return name.substring(2); + return name; + } + + public static boolean isSetter(PsiMethod i_method, + GetterSetterDefinition gsd) + { + if (i_method == null) return false; + if (i_method.getBody() == null) return false; + if (nofParameters(i_method) != 1) return false; + if (!i_method.getName().startsWith("set")) return false; + String i_methodNameTrail = i_method.getName().substring("set".length()); + if (i_methodNameTrail.length() == 0) return false; + /** if setter body is immaterial, it can be empty. Otherwise, it must contain at least one statement. */ + if (nofStatements(i_method) == 0 && + gsd.getSetterBodyCriterion() != GetterSetterDefinition.SETTER_BODY_IMMATERIAL) + { + return false; + } + + boolean nameOK = false, bodyOK = false; + PsiElement psiElement = null; + if (nofStatements(i_method) > 0) { + psiElement = i_method.getBody().getStatements()[nofStatements(i_method) - 1].getChildren()[0]; + } + PsiAssignmentExpression assignment = null; + String lExpression = null; + String parameterName = null; + if (psiElement instanceof PsiAssignmentExpression) { + assignment = (PsiAssignmentExpression)psiElement; + lExpression = ((assignment.getLExpression()).getText()).replaceFirst("this.", ""); + parameterName = (i_method.getParameterList()).getParameters()[0].getName(); + } + + String fieldName = fieldName(propertyNameFromMethodTrail(i_methodNameTrail), i_method.getProject()); + switch (gsd.getSetterNameCriterion()) { + case GetterSetterDefinition.SETTER_NAME_CORRECT_PREFIX: + nameOK = true; + break; + case GetterSetterDefinition.SETTER_NAME_MATCHES_FIELD: + nameOK = lExpression != null && + lExpression.equals(fieldName); + break; + } + switch (gsd.getSetterBodyCriterion()) { + case GetterSetterDefinition.SETTER_BODY_IMMATERIAL: + bodyOK = true; + break; + case GetterSetterDefinition.SETTER_BODY_SETS_FIELD: + if (assignment != null && + nameIsWellFormed(i_methodNameTrail) && + assignment.getOperationSign().getText().equals("=")) +// PsiJavaToken.EQ == assignment.getOperationSign().getTokenType() ) + { + PsiExpression rExpressionRaw = assignment.getRExpression(); + bodyOK = rExpressionRaw != null && + parameterName.equals(rExpressionRaw.getText()) && + lExpression != null && + lExpression.equals(fieldName); + } + break; + } + return nameOK && bodyOK; + } + + private static boolean nameIsWellFormed(String i_methodNameTrail) { + final boolean methodNameIsTooShort = i_methodNameTrail.length() == 0; + if (methodNameIsTooShort) { + return false; + } + + final char firstCandidateMemberChar = i_methodNameTrail.charAt(0); + return !Character.isLowerCase(firstCandidateMemberChar); + } + + + private static String fieldName(String i_propertyName, Project project) { + JavaCodeStyleManager i_codeStyleManager = JavaCodeStyleManager.getInstance(project); + return i_codeStyleManager.propertyNameToVariableName(i_propertyName, VariableKind.FIELD); + } + + public static int nofParameters(PsiMethod i_method) { + return i_method.getParameterList().getParameters().length; + } + + private static int nofStatements(PsiMethod i_method) { + return i_method.getBody().getStatements().length; + } + + private static boolean isAbstract(PsiMethod i_method) { + return null == i_method.getBody(); + } + + private static boolean isReturnStatement(final PsiStatement i_statement) { + return i_statement instanceof PsiReturnStatement; + } +} diff --git a/plugins/rearranger/src/com/wrq/rearranger/util/ModifierUtils.java b/plugins/rearranger/src/com/wrq/rearranger/util/ModifierUtils.java new file mode 100644 index 000000000000..a72551d101b8 --- /dev/null +++ b/plugins/rearranger/src/com/wrq/rearranger/util/ModifierUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger.util; + +import java.lang.reflect.Modifier; +import java.util.StringTokenizer; + +/** Contains utility functions to parse modifiers. */ +public final class ModifierUtils { + /** + * Converts string form of modifiers into a mask. + * + * @param modifierString modifiers to be parsed. + * @return modifier mask corresponding to modifiers in the supplied string. + */ + public static int getModifierMask(final String modifierString) { + /** + * first, determine the modifier mask for the modifiers in the incoming modifier string. + */ + final StringTokenizer st = new StringTokenizer(modifierString); + int mask = 0; + while (st.hasMoreTokens()) { + final String m = st.nextToken(); + for (int i = 1; i != 0; i <<= 1) { + if (Modifier.toString(i).equals(m)) { + mask = mask | i; + break; + } + } + } + return mask; + } +} diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/InteractiveTest.java b/plugins/rearranger/test/src/com/wrq/rearranger/InteractiveTest.java new file mode 100644 index 000000000000..a8c6653d1ad2 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/InteractiveTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger; + +import com.intellij.openapi.editor.Document; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.LightCodeInsightTestCase; +import com.wrq.rearranger.configuration.RearrangerSettingsPanel; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.settings.attributeGroups.IPrioritizableRule; +import com.wrq.rearranger.settings.attributeGroups.IRule; +import com.wrq.rearranger.util.Constraints; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ListIterator; + +/** + * @author davek + * Date: Mar 30, 2004 + */ +public class InteractiveTest + extends LightCodeInsightTestCase +{ + private RearrangerSettings rs; + public static final String DEFAULT_CONFIGURATION_ROOT = ".."; // up one level from test + public static final String DEFAULT_CONFIGURATION = DEFAULT_CONFIGURATION_ROOT + "/src/com/wrq/rearranger/defaultConfiguration.xml"; + + @Override + protected String getTestDataPath() { + return "testData"; // run unit tests with effective working directory of "C:\Rearranger\test" + } + + protected final void setUp() throws Exception { + super.setUp(); + Logger logger = Logger.getLogger("com.wrq.rearranger"); +// logger.setAdditivity(false); +// logger.addAppender(new ConsoleAppender(new PatternLayout("[%7r] %6p - %30.30c - %m \n"))); +// logger.setLevel(Level.DEBUG); + logger.setLevel(Level.INFO); + rs = new RearrangerSettings(); + rs.setAskBeforeRearranging(true); + rs.setRearrangeInnerClasses(true); + } + + public final void testLiveRearrangerDialog() throws Exception { + configureByFile("/com/wrq/rearranger/RearrangementTest28.java"); + final PsiFile file = getFile(); + final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); + final LiveRearrangerActionHandler rah = new LiveRearrangerActionHandler(); + rah.liveRearrangeDocument(getProject(), file, rs, doc, 0); + super.checkResultByFile("/com/wrq/rearranger/RearrangementTest28.java"); + } + + public final void testSettingsPanel() throws Exception { + Rearranger rearranger = new Rearranger(); + SAXBuilder builder = new SAXBuilder(); + org.jdom.Document doc = null; + try { + FileInputStream f = new FileInputStream(new File(DEFAULT_CONFIGURATION)); + doc = builder.build(f); + f.close(); + } + catch (JDOMException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + catch (FileNotFoundException e) { + File f = new File(DEFAULT_CONFIGURATION); + System.out.println(f.getAbsolutePath()); + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + catch (IOException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + Element appElement = doc.getRootElement(); + java.util.List componentList = appElement.getChildren(); + Element rearrangerElement = null; + if (appElement.getName().equals("component") && + appElement.getAttributeValue("name").equals(Rearranger.COMPONENT_NAME)) + { + rearrangerElement = appElement; + } + else { + ListIterator li = componentList.listIterator(); + while (li.hasNext()) +// for (Element e : componentList) + { + Element e = (Element)li.next(); + if (e.getAttributeValue("name").equals(Rearranger.COMPONENT_NAME)) { + rearrangerElement = e; + break; + } + } + } + if (rearrangerElement != null) { + rearranger.readExternal(rearrangerElement); + } + final JDialog frame = new JDialog((Frame)null, "SwingApplication"); + final Constraints constraints = new Constraints(GridBagConstraints.NORTHWEST); + constraints.fill = GridBagConstraints.BOTH; + constraints.weightedLastRow(); + RearrangerSettings settings = rearranger.getSettings(); + final RearrangerSettingsPanel object = new RearrangerSettingsPanel(settings); + frame.getContentPane().setLayout(new GridBagLayout()); + frame.getContentPane().add(object, constraints.weightedLastCol()); + //Finish setting up the frame, and show it. + frame.pack(); + frame.setResizable(true); + frame.setModal(true); + frame.setVisible(true); + final RearrangerSettings rs = object.settings.deepCopy(); + assertTrue("Settings are unequal", rs.equals(object.settings)); + System.out.println("Class Order"); + ListIterator li; + for (Object o : object.settings.getClassOrderAttributeList()) { + if (o instanceof IPrioritizableRule) { + System.out.println(o + ", pri=" + ((IRule)o).getPriority()); + } + else { + System.out.println(o); + } + } + System.out.println("Item order"); + for (Object o : object.settings.getItemOrderAttributeList()) { + if (o instanceof IPrioritizableRule) { + System.out.println(o + ", pri=" + ((IRule)o).getPriority()); + } + else { + System.out.println(o); + } + } + object.checkCommentsAgainstGlobalPattern(object.settings); + } +} diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy new file mode 100644 index 000000000000..a0667d6e1593 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy @@ -0,0 +1,2188 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.wrq.rearranger; + + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.wrq.rearranger.settings.RearrangerSettings +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable + +/** JUnit tests for the rearranger plugin. */ +class RearrangerTest extends LightCodeInsightFixtureTestCase { + + private RearrangerSettings mySettings; + + @Override + protected String getBasePath() { + return "/plugins/rearranger/test/testData/com/wrq/rearranger"; + } + + protected final void setUp() throws Exception { + super.setUp(); + mySettings = new RearrangerSettings(); +// rs.setAskBeforeRearranging(true); // uncomment for debugging file structure popup + mySettings.showFields = true + mySettings.showParameterNames = true + mySettings.showParameterTypes = true + mySettings.showRules = true + mySettings.rearrangeInnerClasses =true + } + + public final void testNoRearrangement() throws Exception { + doTest('RearrangementTest', 'NoRearrangementResult1') + } + +// public final void testPublicFieldRearrangement() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final FieldAttributes fa; +// fa = new FieldAttributes(); +// fa.getPlAttr().setPlPublic(true); +// rs.addItem(fa, 0); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult2.java"); +// } +// +// public final void testNotPublicFieldRearrangement() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final FieldAttributes fa; +// fa = new FieldAttributes(); +// fa.getPlAttr().setPlPublic(true); +// fa.getPlAttr().setInvertProtectionLevel(true); +// rs.addItem(fa, 0); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult3.java"); +// } +// +// public final void testConstructorRearrangement() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final MethodAttributes ma; +// ma = new MethodAttributes(); +// ma.getPlAttr().setPlPackage(true); +// ma.getPlAttr().setPlPublic(true); +// ma.setConstructorMethodType(true); +// rs.addItem(ma, 0); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult4.java"); +// } +// +// public final void testClassRearrangement() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final ClassAttributes ca = new ClassAttributes(); +// ca.getPlAttr().setPlPackage(true); +// rs.addClass(ca, 0); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult5.java"); +// } +// +// public final void testPSFRearrangement() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest2.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final FieldAttributes fa; +// fa = new FieldAttributes(); +// fa.getPlAttr().setPlPublic(true); +// fa.getfAttr().setValue(true); +// fa.getStAttr().setValue(true); +// rs.addItem(fa, 0); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult6.java"); +// } +// +// public final void testAnonClassInit() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest7.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final FieldAttributes fa; +// fa = new FieldAttributes(); +// fa.getInitToAnonClassAttr().setValue(true); +// rs.addItem(fa, 0); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult7.java"); +// } +// +// public final void testNameMatch() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final FieldAttributes fa; +// fa = new FieldAttributes(); +// fa.getNameAttr().setMatch(true); +// fa.getNameAttr().setExpression(".*5"); +// rs.addItem(fa, 0); +// final MethodAttributes ma = new MethodAttributes(); +// ma.getNameAttr().setMatch(true); +// ma.getNameAttr().setExpression(".*2"); +// rs.addItem(ma, 1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult8.java"); +// } +// +// public final void testStaticInitializer() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest8.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final MethodAttributes ma; +// ma = new MethodAttributes(); +// ma.getStaticInitAttr().setValue(true); +// rs.addItem(ma, 0); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult8A.java"); +// } +// +// public final void testAlphabetizingGSMethods() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final MethodAttributes ma; +// ma = new MethodAttributes(); +// ma.setGetterSetterMethodType(true); +// ma.setOtherMethodType(true); +// ma.setConstructorMethodType(false); +// ma.getSortAttr().setByName(true); +// rs.addItem(ma, 0); +// rs.setKeepGettersSettersTogether(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult9.java"); +// } +// +// public final void testSimpleComment() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlPublic(true); +// rs.addItem(fa, 0); +// final CommentRule c = new CommentRule(); +// c.setCommentText("// simple comment **********"); +// c.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_PRECEDING_RULE); +// rs.addItem(c, 1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult10.java"); +// } +// +// /** +// * Delete old comment and insert (identical) new one. This tests proper identification and deletion of old +// * comments. +// * +// * @throws Exception test exception +// */ +// public final void testReplayComment() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementResult10.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlPublic(true); +// rs.addItem(fa, 0); +// final CommentRule c = new CommentRule(); +// c.setCommentText("// simple comment **********"); +// c.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_PRECEDING_RULE); +// rs.addItem(c, 1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult10.java"); +// } +// +// public final void testMultipleRuleCommentMatch() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest11.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// CommentRule c; +// FieldAttributes fa; +// +// c = new CommentRule(); +// c.setCommentText("// FIELDS:"); +// c.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE); +// c.setAllSubsequentRules(false); +// c.setnSubsequentRulesToMatch(3); +// rs.addItem(c, 0); +// +// c = new CommentRule(); +// c.setCommentText("// PROTECTED FIELDS:"); +// c.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE); +// c.setAllSubsequentRules(false); +// c.setnSubsequentRulesToMatch(1); +// rs.addItem(c, 1); +// +// fa = new FieldAttributes(); +// fa.getPlAttr().setPlProtected(true); +// rs.addItem(fa, 2); +// +// c = new CommentRule(); +// c.setCommentText("// FINAL FIELDS:"); +// c.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE); +// c.setAllSubsequentRules(true); +// c.setnSubsequentRulesToMatch(1); +// rs.addItem(c, 3); +// +// fa = new FieldAttributes(); +// fa.getfAttr().setValue(true); +// rs.addItem(fa, 4); +// +// c = new CommentRule(); +// c.setCommentText("// NON-FINAL FIELDS:"); +// c.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE); +// c.setAllSubsequentRules(true); +// c.setnSubsequentRulesToMatch(1); +// rs.addItem(c, 5); +// +// fa = new FieldAttributes(); +// fa.getfAttr().setValue(true); +// fa.getfAttr().setInvert(true); +// rs.addItem(fa, 6); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult11.java"); +// } +// +// public final void testOpsBlockingQueueExample() throws Exception { +// testOpsBlockingQueueExampleWorker(false, "/com/wrq/rearranger/OpsBlockingQueue.java", +// false, "/com/wrq/rearranger/OpsBlockingQueue.java"); +// } +// +// public final void testOpsBlockingQueueExampleWithGlobalPattern() throws Exception { +// testOpsBlockingQueueExampleWorker(true, "/com/wrq/rearranger/OpsBlockingQueue.java", +// false, "/com/wrq/rearranger/OpsBlockingQueue.java"); +// } +// +// public final void testOpsBlockingQueueExampleWithIndentedComments() throws Exception { +// testOpsBlockingQueueExampleWorker(false, "/com/wrq/rearranger/OpsBlockingQueueIndented.java", +// true, "/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java"); +// } +// +// private void testOpsBlockingQueueExampleWorker(boolean doGlobalPattern, +// String srcFilename, +// boolean doublePublicMethods, +// String compareFilename) +// throws Exception +// { +// // submitted by Joe Martinez. +// configureByFile(srcFilename); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// CommentRule c; +// FieldAttributes fa; +// c = new CommentRule(); +// c.setCommentText("//************************************** PUBLIC STATIC FIELDS *************************************"); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(2); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(false); +// rs.addItem(c, 0); +// fa = new FieldAttributes(); +// fa.getSortAttr().setByName(true); +// fa.getPlAttr().setPlPublic(true); +// fa.getStAttr().setValue(true); +// fa.getfAttr().setValue(true); +// rs.addItem(fa, 1); +// fa = new FieldAttributes(); +// fa.getSortAttr().setByName(true); +// fa.getPlAttr().setPlPublic(true); +// fa.getStAttr().setValue(true); +// rs.addItem(fa, 2); +// c = new CommentRule(); +// c.setCommentText("//************************************** PUBLIC FIELDS *****************************************"); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(1); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(true); +// rs.addItem(c, 3); +// fa = new FieldAttributes(); +// fa.getSortAttr().setByName(true); +// fa.getPlAttr().setPlPublic(true); +// rs.addItem(fa, 4); +// c = new CommentRule(); +// c.setCommentText("//*********************************** PROTECTED/PACKAGE FIELDS **************************************"); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(3); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(false); +// rs.addItem(c, 5); +// fa = new FieldAttributes(); +// fa.getSortAttr().setByName(true); +// fa.getPlAttr().setPlProtected(true); +// fa.getPlAttr().setPlPackage(true); +// fa.getStAttr().setValue(true); +// fa.getfAttr().setValue(true); +// rs.addItem(fa, 6); +// fa = new FieldAttributes(); +// fa.getSortAttr().setByName(true); +// fa.getPlAttr().setPlProtected(true); +// fa.getPlAttr().setPlPackage(true); +// fa.getStAttr().setValue(true); +// rs.addItem(fa, 7); +// fa = new FieldAttributes(); +// fa.getSortAttr().setByName(true); +// fa.getPlAttr().setPlProtected(true); +// fa.getPlAttr().setPlPackage(true); +// rs.addItem(fa, 8); +// c = new CommentRule(); +// c.setCommentText("//************************************** PRIVATE FIELDS *****************************************"); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(1); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(false); +// rs.addItem(c, 9); +// fa = new FieldAttributes(); +// fa.getSortAttr().setByName(true); +// fa.getPlAttr().setPlPrivate(true); +// rs.addItem(fa, 10); +// c = new CommentRule(); +// c.setCommentText("//************************************** CONSTRUCTORS ************************************* "); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(2); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(false); +// rs.addItem(c, 11); +// MethodAttributes ma = new MethodAttributes(); +// ma.getPlAttr().setPlPublic(true); +// ma.setConstructorMethodType(true); +// rs.addItem(ma, 12); +// ma = new MethodAttributes(); +// ma.setConstructorMethodType(true); +// rs.addItem(ma, 13); +// c = new CommentRule(); +// c.setCommentText("//*********************************** GETTERS AND SETTERS ********************************** "); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(2); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(false); +// rs.addItem(c, 14); +// ma = new MethodAttributes(); +// ma.getSortAttr().setByName(true); +// ma.getPlAttr().setPlPublic(true); +// ma.setGetterSetterMethodType(true); +// rs.addItem(ma, 15); +// ma = new MethodAttributes(); +// ma.getSortAttr().setByName(true); +// ma.setGetterSetterMethodType(true); +// rs.addItem(ma, 16); +// c = new CommentRule(); +// String commentText = +// "//************************************** PUBLIC METHODS ************************************* "; +// if (doublePublicMethods) { +// commentText += "\n// PUBLIC METHODS LINE 2"; +// } +// c.setCommentText(commentText); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(1); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(true); +// rs.addItem(c, 17); +// ma = new MethodAttributes(); +// ma.getSortAttr().setByName(true); +// ma.getPlAttr().setPlPublic(true); +// rs.addItem(ma, 18); +// c = new CommentRule(); +// c.setCommentText("//********************************* PACKAGE/PROTECTED METHODS ******************************** "); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(1); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(true); +// rs.addItem(c, 19); +// ma = new MethodAttributes(); +// ma.getSortAttr().setByName(true); +// ma.getPlAttr().setPlProtected(true); +// ma.getPlAttr().setPlPackage(true); +// rs.addItem(ma, 20); +// c = new CommentRule(); +// c.setCommentText("//************************************** PRIVATE METHODS *************************************"); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(1); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(true); +// rs.addItem(c, 21); +// ma = new MethodAttributes(); +// ma.getSortAttr().setByName(true); +// ma.getPlAttr().setPlPrivate(true); +// rs.addItem(ma, 22); +// c = new CommentRule(); +// c.setCommentText("//************************************** INNER CLASSES ************************************* "); +// c.setEmitCondition(2); +// c.setnPrecedingRulesToMatch(1); +// c.setnSubsequentRulesToMatch(1); +// c.setAllPrecedingRules(true); +// c.setAllSubsequentRules(true); +// rs.addItem(c, 23); +// InnerClassAttributes ic = new InnerClassAttributes(); +// ic.getSortAttr().setByName(true); +// rs.addItem(ic, 24); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(false); +// if (doGlobalPattern) { +// rs.setGlobalCommentPattern("//\\*{20,45}[A-Z /]*\\*{20,45}\n"); +// } +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile(compareFilename); +// } +// +// public final void testReturnTypeMatch() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest12.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// MethodAttributes ma; +// ma = new MethodAttributes(); +// ma.getReturnTypeAttr().setMatch(true); +// ma.getReturnTypeAttr().setExpression("void"); +// rs.addItem(ma, 0); +// FieldAttributes fa = new FieldAttributes(); +// fa.getTypeAttr().setMatch(true); +// fa.getTypeAttr().setExpression("int"); +// rs.addItem(fa, 1); +// ma = new MethodAttributes(); +// ma.getReturnTypeAttr().setMatch(true); +// ma.getReturnTypeAttr().setExpression(".*je.*"); +// rs.addItem(ma, 2); +// ma = new MethodAttributes(); +// ma.getReturnTypeAttr().setMatch(true); +// ma.getReturnTypeAttr().setExpression("Integer\\[\\]"); +// rs.addItem(ma, 3); +// ma = new MethodAttributes(); +// ma.getReturnTypeAttr().setMatch(true); +// ma.getReturnTypeAttr().setExpression("int"); +// rs.addItem(ma, 4); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult12.java"); +// } +// +// public final void testRelatedMethodsDepthOriginal() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13DO.java"); +// } +// +// public final void testRelatedMethodsDepthAlphabetical() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.ALPHABETICAL_ORDER); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13DA.java"); +// } +// +// public final void testRelatedMethodsDepthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13DI.java"); +// } +// +// public final void testRelatedMethodsBreadthOriginal() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13BO.java"); +// } +// +// public final void testRelatedMethodsBreadthAlphabetical() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.ALPHABETICAL_ORDER); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13BA.java"); +// } +// +// public final void testRelatedMethodsBreadthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13BI.java"); +// } +// +// public final void testEmitTLCommentsRelatedMethodsBreadthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_TOP_LEVEL); +// CommentRule c = new CommentRule(); +// c.setCommentText("// Preceding comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setPrecedingComment(c); +// c = new CommentRule(); +// c.setCommentText("// Trailing comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setTrailingComment(c); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13BITLC.java"); +// } +// +// public final void testEmitEMCommentsRelatedMethodsBreadthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_EACH_METHOD); +// CommentRule c = new CommentRule(); +// c.setCommentText("// Preceding comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setPrecedingComment(c); +// c = new CommentRule(); +// c.setCommentText("// Trailing comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setTrailingComment(c); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13BIEMC.java"); +// } +// +// public final void testEmitELCommentsRelatedMethodsBreadthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_EACH_LEVEL); +// CommentRule c = new CommentRule(); +// c.setCommentText("// Preceding comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setPrecedingComment(c); +// c = new CommentRule(); +// c.setCommentText("// Trailing comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setTrailingComment(c); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13BIELC.java"); +// } +// +// public final void testEmitNFCommentsRelatedMethodsBreadthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_NEW_FAMILY); +// CommentRule c = new CommentRule(); +// c.setCommentText("// Preceding comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setPrecedingComment(c); +// c = new CommentRule(); +// c.setCommentText("// Trailing comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setTrailingComment(c); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13BINFC.java"); +// } +// +// public final void testEmitTLCommentsRelatedMethodsDepthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_TOP_LEVEL); +// CommentRule c = new CommentRule(); +// c.setCommentText("// Preceding comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setPrecedingComment(c); +// c = new CommentRule(); +// c.setCommentText("// Trailing comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setTrailingComment(c); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13DITLC.java"); +// } +// +// public final void testEmitEMCommentsRelatedMethodsDepthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_EACH_METHOD); +// CommentRule c = new CommentRule(); +// c.setCommentText("// Preceding comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setPrecedingComment(c); +// c = new CommentRule(); +// c.setCommentText("// Trailing comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setTrailingComment(c); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13DIEMC.java"); +// } +// +// public final void testEmitELCommentsRelatedMethodsDepthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_EACH_LEVEL); +// CommentRule c = new CommentRule(); +// c.setCommentText("// Preceding comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setPrecedingComment(c); +// c = new CommentRule(); +// c.setCommentText("// Trailing comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setTrailingComment(c); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13DIELC.java"); +// } +// +// public final void testEmitNFCommentsRelatedMethodsDepthInvocation() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_NEW_FAMILY); +// CommentRule c = new CommentRule(); +// c.setCommentText("// Preceding comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setPrecedingComment(c); +// c = new CommentRule(); +// c.setCommentText("// Trailing comment: TL=%TL%\n" + +// "// MN=%MN%\n" + +// "// AM=%AM%\n" + +// "// Level %LV%"); +// rs.getExtractedMethodsSettings().setTrailingComment(c); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13DINFC.java"); +// } +// +// public final void testRelatedMethodsException() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.RETAIN_ORIGINAL_ORDER); +// MethodAttributes ma = new MethodAttributes(); +// ma.setNoExtractedMethods(true); +// ma.getNameAttr().setMatch(true); +// ma.getNameAttr().setExpression("GF"); +// rs.addItem(ma, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult13Ex.java"); +// } +// +// public final void testKeepOverloadedMethodsTogether() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest14.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(false); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.INVOCATION_ORDER); +// rs.setKeepOverloadedMethodsTogether(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult14.java"); +// } +// +// public final void testOverrides() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest15.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// } +// +// public final void testImplements() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest16.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// } +// +// public final void testXML() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest17.xml"); +// // we should not do anything to XML files. +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementTest17.xml"); +// } +// +// public final void testKeepGSTogether() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest18.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.ALPHABETICAL_ORDER); +// FieldAttributes fa = new FieldAttributes(); +// rs.addItem(fa, 0); +// MethodAttributes ma = new MethodAttributes(); +// ma.setConstructorMethodType(true); +// rs.addItem(ma, 1); +// ma = new MethodAttributes(); +// ma.setGetterSetterMethodType(true); +// ma.getSortAttr().setByName(true); +// rs.addItem(ma, 2); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult18.java"); +// } +// +// public final void testKeepGSWithProperty() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest18.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(true); +// rs.setKeepGettersSettersWithProperty(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.ALPHABETICAL_ORDER); +// FieldAttributes fa = new FieldAttributes(); +// rs.addItem(fa, 0); +// MethodAttributes ma = new MethodAttributes(); +// ma.setConstructorMethodType(true); +// rs.addItem(ma, 1); +// ma = new MethodAttributes(); +// ma.setGetterSetterMethodType(true); +// ma.getSortAttr().setByName(true); +// rs.addItem(ma, 2); +//// rs.setAskBeforeRearranging(true); // testing only +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult18A.java"); +// } +// +// public final void testKeepGSWithPropertyElseTogether() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest18B.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(true); +// rs.setKeepGettersSettersWithProperty(true); +// rs.getExtractedMethodsSettings().setOrdering(RelatedMethodsSettings.ALPHABETICAL_ORDER); +// FieldAttributes fa = new FieldAttributes(); +// rs.addItem(fa, 0); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("// Getters/Setters"); +// cr.setEmitCondition(CommentRule.EMIT_ALWAYS); +// rs.addItem(cr, 1); +// MethodAttributes ma = new MethodAttributes(); +// ma.setGetterSetterMethodType(true); +// ma.getSortAttr().setByName(true); +// ma.getGetterSetterDefinition().setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// ma.getGetterSetterDefinition().setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_IMMATERIAL); +// ma.getGetterSetterDefinition().setSetterNameCriterion(GetterSetterDefinition.SETTER_NAME_CORRECT_PREFIX); +// ma.getGetterSetterDefinition().setSetterBodyCriterion(GetterSetterDefinition.SETTER_BODY_IMMATERIAL); +// rs.addItem(ma, 2); +// cr = new CommentRule(); +// cr.setCommentText("// Other Methods"); +// cr.setEmitCondition(CommentRule.EMIT_ALWAYS); +// rs.addItem(cr, 3); +// ma = new MethodAttributes(); +// ma.getSortAttr().setByName(true); +// rs.addItem(ma, 4); +// +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult18B.java"); +// } +// +// public final void testKeepOverloadsTogetherOriginalOrder() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest19.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(false); +// rs.setKeepOverloadedMethodsTogether(true); +// rs.setOverloadedOrder(RearrangerSettings.OVERLOADED_ORDER_RETAIN_ORIGINAL); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult19A.java"); +// } +// +// public final void testKeepOverloadsTogetherAscendingOrder() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest19.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(false); +// rs.setKeepOverloadedMethodsTogether(true); +// rs.setOverloadedOrder(RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult19B.java"); +// } +// +// public final void testKeepOverloadsTogetherDescendingOrder() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest19.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(false); +// rs.setKeepOverloadedMethodsTogether(true); +// rs.setOverloadedOrder(RearrangerSettings.OVERLOADED_ORDER_DESCENDING_PARAMETERS); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult19C.java"); +// } +// +// public final void testInnerClassReferenceToChild() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest20.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult20.java"); +// } +// +// public final void testMultipleFieldDecl() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest21.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getSortAttr().setByName(true); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult21.java"); +// } +// +// public final void testRemoveBlankLines() throws Exception { +// configureByFile("/com/wrq/rearranger/SpaceTest1.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getAfterClassLBrace().setForce(true); +// rs.getAfterClassLBrace().setnBlankLines(0); +// rs.getAfterMethodLBrace().setForce(true); +// rs.getAfterMethodLBrace().setnBlankLines(0); +// rs.getBeforeMethodRBrace().setForce(true); +// rs.getBeforeMethodRBrace().setnBlankLines(0); +// rs.getAfterMethodRBrace().setForce(true); +// rs.getAfterMethodRBrace().setnBlankLines(0); +// rs.getBeforeClassRBrace().setForce(true); +// rs.getBeforeClassRBrace().setnBlankLines(0); +// rs.getAfterClassRBrace().setForce(true); +// rs.getAfterClassRBrace().setnBlankLines(0); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// rs.setRemoveBlanksInsideCodeBlocks(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/SpaceResult1.java"); +// } +// +// public final void testAddBlankLines() throws Exception { +// configureByFile("/com/wrq/rearranger/SpaceTest2.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getAfterClassLBrace().setForce(true); +// rs.getAfterClassLBrace().setnBlankLines(2); +// rs.getAfterMethodLBrace().setForce(true); +// rs.getAfterMethodLBrace().setnBlankLines(3); +// rs.getBeforeMethodRBrace().setForce(true); +// rs.getBeforeMethodRBrace().setnBlankLines(2); +// rs.getAfterMethodRBrace().setForce(true); +// rs.getAfterMethodRBrace().setnBlankLines(1); +// rs.getBeforeClassRBrace().setForce(true); +// rs.getBeforeClassRBrace().setnBlankLines(3); +// rs.getAfterClassRBrace().setForce(true); +// rs.getAfterClassRBrace().setnBlankLines(4); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// rs.setRemoveBlanksInsideCodeBlocks(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/SpaceResult2.java"); +// } +// +// public final void testInnerClassBlankLines() throws Exception { +// configureByFile("/com/wrq/rearranger/SpaceTest4.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getAfterClassLBrace().setForce(true); +// rs.getAfterClassLBrace().setnBlankLines(0); +// rs.getAfterMethodLBrace().setForce(true); +// rs.getAfterMethodLBrace().setnBlankLines(0); +// rs.getBeforeMethodRBrace().setForce(true); +// rs.getBeforeMethodRBrace().setnBlankLines(0); +// rs.getAfterMethodRBrace().setForce(true); +// rs.getAfterMethodRBrace().setnBlankLines(1); +// rs.getBeforeClassRBrace().setForce(true); +// rs.getBeforeClassRBrace().setnBlankLines(1); +// rs.getAfterClassRBrace().setForce(true); +// rs.getAfterClassRBrace().setnBlankLines(1); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// rs.setRemoveBlanksInsideCodeBlocks(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/SpaceResult4.java"); +// } +// +// public void testInnerClassSpacing() throws Exception { +// configureByFile("/com/wrq/rearranger/SpaceTest5.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final File physFile = new File(InteractiveTest.DEFAULT_CONFIGURATION); +// rs = RearrangerSettings.getSettingsFromFile(physFile); +// rs.setAskBeforeRearranging(false); +// rs.getAfterClassRBrace().setnBlankLines(2); +// rs.getAfterClassRBrace().setForce(true); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(3); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/SpaceResult5.java"); +// } +// +// public void testNoRearrangementInnerClass() throws Exception { +// configureByFile("/com/wrq/rearranger/NoRearrangeInnerClassTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final File settingsFile = new File(InteractiveTest.DEFAULT_CONFIGURATION_ROOT + +// "/test/testData/com/wrq/rearranger/NoRearrangementInnerClassCfg.xml"); +// rs = RearrangerSettings.getSettingsFromFile(settingsFile); +// rs.setAskBeforeRearranging(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/NoRearrangeInnerClassResult.java"); +// } +// +// public void testSpacingWithTrailingWhitespace() throws Exception { +// configureByFile("/com/wrq/rearranger/SpaceTest6.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/SpaceResult6.java"); +// } +// +// public void testSpacingJoinLineBug() throws Exception { +// configureByFile("/com/wrq/rearranger/SpaceTest7.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// File settingsFile = new File(InteractiveTest.DEFAULT_CONFIGURATION_ROOT + +// "/test/testData/com/wrq/rearranger/SpaceTest7cfg.xml"); +// rs = RearrangerSettings.getSettingsFromFile(settingsFile); +// rs.setAskBeforeRearranging(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/SpaceResult7.java"); +// } +// +// /** +// * Submitted by Brian Buckley. +// * +// * @throws Exception test exception +// */ +// public void testSpacingConflictingSettingBug() throws Exception { +// configureByFile("/com/wrq/rearranger/SpaceTest8.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.getAfterClassLBrace().setForce(true); +// rs.getAfterClassLBrace().setnBlankLines(0); +// rs.getBeforeMethodLBrace().setForce(true); +// rs.getBeforeMethodLBrace().setnBlankLines(1); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/SpaceResult8.java"); +// } +// +// public void testGetPrefixImmaterial() throws Exception { +// configureByFile("/com/wrq/rearranger/GetterDefinitionTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma = new MethodAttributes(); +// GetterSetterDefinition gsd = ma.getGetterSetterDefinition(); +// rs.addItem(ma, 0); +// ma.setGetterSetterMethodType(true); +// gsd.setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// gsd.setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_IMMATERIAL); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/GetPrefixImmaterialResult.java"); +// } +// +// public void testGetPrefixReturns() throws Exception { +// configureByFile("/com/wrq/rearranger/GetterDefinitionTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma = new MethodAttributes(); +// GetterSetterDefinition gsd = ma.getGetterSetterDefinition(); +// rs.addItem(ma, 0); +// ma.setGetterSetterMethodType(true); +// gsd.setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// gsd.setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_RETURNS); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/GetPrefixReturnsResult.java"); +// } +// +// public void testGetPrefixReturnsField() throws Exception { +// configureByFile("/com/wrq/rearranger/GetterDefinitionTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma = new MethodAttributes(); +// GetterSetterDefinition gsd = ma.getGetterSetterDefinition(); +// rs.addItem(ma, 0); +// ma.setGetterSetterMethodType(true); +// gsd.setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// gsd.setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_RETURNS_FIELD); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/GetPrefixReturnsFieldResult.java"); +// } +// +// public void testGetFieldReturns() throws Exception { +// configureByFile("/com/wrq/rearranger/GetterDefinitionTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma = new MethodAttributes(); +// GetterSetterDefinition gsd = ma.getGetterSetterDefinition(); +// rs.addItem(ma, 0); +// ma.setGetterSetterMethodType(true); +// gsd.setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_MATCHES_FIELD); +// gsd.setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_RETURNS); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/GetFieldReturnsResult.java"); +// } +// +// public void testGetFieldReturnsField() throws Exception { +// configureByFile("/com/wrq/rearranger/GetterDefinitionTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma = new MethodAttributes(); +// GetterSetterDefinition gsd = ma.getGetterSetterDefinition(); +// rs.addItem(ma, 0); +// ma.setGetterSetterMethodType(true); +// gsd.setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_MATCHES_FIELD); +// gsd.setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_RETURNS_FIELD); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/GetFieldReturnsFieldResult.java"); +// } +// +// public void testSpecialGS() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest22.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma = new MethodAttributes(); +// GetterSetterDefinition gsd = ma.getGetterSetterDefinition(); +// rs.addItem(ma, 0); +// ma.setGetterSetterMethodType(true); +// gsd.setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// gsd.setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_RETURNS); +// gsd.setSetterBodyCriterion(GetterSetterDefinition.SETTER_BODY_IMMATERIAL); +// gsd.setSetterNameCriterion(GetterSetterDefinition.SETTER_NAME_CORRECT_PREFIX); +// rs.setKeepGettersSettersTogether(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult22.java"); +// } +// +// public void testInterfaceNoNameNotAlphabeticalNoExcludeMethodAlphabetical() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest23.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(false); +// InterfaceAttributes ia = new InterfaceAttributes(); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("/**** Interface %IF% Header ****/"); +// ia.setPrecedingComment(cr); +// cr = new CommentRule(); +// cr.setCommentText("/**** Interface %IF% Trailer ***/"); +// ia.setTrailingComment(cr); +// ia.setNoExtractedMethods(true); +// ia.setMethodOrder(InterfaceAttributes.METHOD_ORDER_ALPHABETICAL); +// ia.setAlphabetizeInterfaces(false); +// rs.addItem(ia, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult23NNNANXMA.java"); +// } +// +// public void testInterfaceNoNameNotAlphabeticalNoExcludeMethodEncountered() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest23.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(false); +// InterfaceAttributes ia = new InterfaceAttributes(); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("/**** Interface %IF% Header ****/"); +// ia.setPrecedingComment(cr); +// cr = new CommentRule(); +// cr.setCommentText("/**** Interface %IF% Trailer ***/"); +// ia.setTrailingComment(cr); +// ia.setNoExtractedMethods(true); +// ia.setMethodOrder(InterfaceAttributes.METHOD_ORDER_ENCOUNTERED); +// ia.setAlphabetizeInterfaces(false); +// rs.addItem(ia, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult23NNNANXME.java"); +// } +// +// public void testInterfaceNoNameNotAlphabeticalNoExcludeMethodInterfaceOrder() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest23.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(false); +// InterfaceAttributes ia = new InterfaceAttributes(); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("/**** Interface %IF% Header ****/"); +// ia.setPrecedingComment(cr); +// cr = new CommentRule(); +// cr.setCommentText("/**** Interface %IF% Trailer ***/"); +// ia.setTrailingComment(cr); +// ia.setNoExtractedMethods(true); +// ia.setMethodOrder(InterfaceAttributes.METHOD_ORDER_INTERFACE_ORDER); +// ia.setAlphabetizeInterfaces(false); +// rs.addItem(ia, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult23NNNANXMI.java"); +// } +// +// public void testInterfaceByNameNotAlphabeticalNoExcludeMethodEncountered() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest23.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(false); +// InterfaceAttributes ia = new InterfaceAttributes(); +// ia.getNameAttr().setMatch(true); +// ia.getNameAttr().setExpression("IFace1"); +// ia.setNoExtractedMethods(true); +// ia.setMethodOrder(InterfaceAttributes.METHOD_ORDER_ENCOUNTERED); +// ia.setAlphabetizeInterfaces(false); +// rs.addItem(ia, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult23BNNANXME.java"); +// } +// +// public void testInterfaceIsAlphabeticalNoExcludeMethodEncountered() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest23.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(false); +// InterfaceAttributes ia = new InterfaceAttributes(); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("/**** Interface %IF% Header ****/"); +// ia.setPrecedingComment(cr); +// cr = new CommentRule(); +// cr.setCommentText("/**** Interface %IF% Trailer ***/"); +// ia.setTrailingComment(cr); +// ia.setNoExtractedMethods(true); +// ia.setMethodOrder(InterfaceAttributes.METHOD_ORDER_ENCOUNTERED); +// ia.setAlphabetizeInterfaces(true); +// rs.addItem(ia, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult23NNIANXME.java"); +// } +// +// public void testNPE24() throws Exception { +// // submitted by Nathan Brown. Caused NPE in Rearranger plugin version 1.7. +// int itemIndex = 0; +// configureByFile("/com/wrq/rearranger/RearrangementTest24.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(true); +// rs.setKeepOverloadedMethodsTogether(true); +//// rs.setAskBeforeRearranging(false); +// rs.setOverloadedOrder(1); +// rs.setGlobalCommentPattern(""); +// rs.setRemoveBlanksInsideCodeBlocks(false); +// FieldAttributes fa; +// fa = new FieldAttributes(); +// fa.getSortAttr().setByName(false); +// fa.getPlAttr().setPlPublic(true); +// fa.getPlAttr().setPlPrivate(true); +// fa.getPlAttr().setPlProtected(true); +// fa.getPlAttr().setPlPackage(true); +// fa.getPlAttr().setInvertProtectionLevel(false); +// fa.getStAttr().setValue(true); +// fa.getStAttr().setInvert(false); +// rs.addItem(fa, itemIndex++); +// fa = new FieldAttributes(); +// fa.getStAttr().setValue(true); +// fa.getStAttr().setInvert(true); +// fa.getInitToAnonClassAttr().setValue(true); +// fa.getInitToAnonClassAttr().setInvert(true); +// rs.addItem(fa, itemIndex++); +// fa = new FieldAttributes(); +// fa.getInitToAnonClassAttr().setValue(true); +// rs.addItem(fa, itemIndex++); +// MethodAttributes ma; +// ma = new MethodAttributes(); +// ma.getStaticInitAttr().setValue(true); +// rs.addItem(ma, itemIndex++); +// ma = new MethodAttributes(); +// ma.setConstructorMethodType(true); +// rs.addItem(ma, itemIndex++); +// ma = new MethodAttributes(); +// ma.getNameAttr().setMatch(true); +// ma.getNameAttr().setExpression("clone"); +// rs.addItem(ma, itemIndex++); +// ma = new MethodAttributes(); +// ma.getNameAttr().setMatch(true); +// ma.getNameAttr().setExpression("dispose"); +// rs.addItem(ma, itemIndex++); +// ma = new MethodAttributes(); +// ma.getNameAttr().setMatch(true); +// ma.getNameAttr().setExpression("_dispose"); +// rs.addItem(ma, itemIndex++); +// ma = new MethodAttributes(); +// ma.getNameAttr().setMatch(true); +// ma.getNameAttr().setExpression("build"); +// rs.addItem(ma, itemIndex++); +// ma = new MethodAttributes(); +// ma.getAbstractAttr().setValue(true); +// rs.addItem(ma, itemIndex++); +// ma = new MethodAttributes(); +// ma.getStAttr().setValue(true); +// ma.getStAttr().setInvert(true); +// ma.getAbstractAttr().setValue(true); +// ma.getAbstractAttr().setInvert(true); +// ma.setOtherMethodType(true); +// rs.addItem(ma, itemIndex++); +// ma = new MethodAttributes(); +// ma.setGetterSetterMethodType(true); +// rs.addItem(ma, itemIndex++); +// InnerClassAttributes ica = new InnerClassAttributes(); +// rs.addItem(ica, itemIndex++); +// ma = new MethodAttributes(); +// ma.getStAttr().setValue(true); +// rs.addItem(ma, itemIndex); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setBelowFirstCaller(false); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// rs.getExtractedMethodsSettings().setOrdering(0); +// rs.getExtractedMethodsSettings().setNonPrivateTreatment(2); +// rs.getExtractedMethodsSettings().setCommentType(0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// } +// +// public void testSpacingOptions() throws Exception { +// /** +// * From Thomas Singer: +// * I've enabled +// * - Force 0 blank lines before class close brace "}" +// * - Force 0 blank lines before method close brace "}" +// * - Remove initial and final blank lines inside code block +// * but in the code below the blank lines don't get removed when invoking +// * Rearrager from editor's context menu: +// */ +// configureByFile("/com/wrq/rearranger/RearrangementTest25.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getBeforeClassRBrace().setForce(true); +// rs.getBeforeClassRBrace().setnBlankLines(0); +// rs.getBeforeMethodRBrace().setForce(true); +// rs.getBeforeMethodRBrace().setnBlankLines(0); +// rs.setRemoveBlanksInsideCodeBlocks(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult25.java"); +// } +// +// public void testPriority() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma; +// ma = new MethodAttributes(); +// ma.setPriority(1); +// rs.addItem(ma, 0); +// ma = new MethodAttributes(); +// ma.setPriority(2); +// ma.getNameAttr().setMatch(true); +// ma.getNameAttr().setExpression("method.*"); +// rs.addItem(ma, 1); +// ma = new MethodAttributes(); +// ma.setPriority(2); +// ma.getNameAttr().setMatch(true); +// ma.getNameAttr().setExpression(".*Method"); +// rs.addItem(ma, 2); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult1A.java"); +// } +// +// public void testGSRuleWithClassInitializer() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest26.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma; +// ma = new MethodAttributes(); +// ma.setGetterSetterMethodType(true); +// rs.addItem(ma, 0); +// rs.setKeepGettersSettersTogether(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult26.java"); +// } +// +// public void testKeepGSTogetherAndExtractedMethods() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest27.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(true); +// rs.setKeepOverloadedMethodsTogether(true); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult27.java"); +// } +// +// public void testRegexEscape() throws Exception { +// String s = "// ********* start of fields *********"; +// String result = RegexUtil.escape(s); +// assertEquals("sequence reduction failed", "// \\*{9} start of fields \\*{9}", result); +// s = "// \\ backslash \n \t \\d [...] (^...$)"; +// result = RegexUtil.escape(s); +// assertEquals("special character escape failed", "// \\\\ backslash \\n \\t \\\\d \\[\\.\\.\\.\\]" + +// " \\(\\^\\.\\.\\.\\$\\)", result); +// } +// +// public void testRegexCombine() throws Exception { +// String p1 = RegexUtil.escape("// ********* start of fields *********"); +// String p2 = RegexUtil.escape("// ********* start of methods *********"); +// List list = new ArrayList(); +// list.add(p1); +// list.add(p2); +// String result = RegexUtil.combineExpressions(list); +// assertEquals("combination failed", "// \\*{9} start of (fiel|metho)ds \\*{9}", result); +// String p3 = RegexUtil.escape("// ***** start of interfaces *******"); +// list.add(p3); +// result = RegexUtil.combineExpressions(list); +// assertEquals("combination failed", "// (\\*{9} start of (fiel|metho)ds \\*{9}|" + +// "\\*{5} start of interfaces \\*{7})", result); +// } +// +// public void testVariousComments() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest28.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(true); +// rs.setKeepOverloadedMethodsTogether(true); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("// start of fields"); +// cr.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE); +// cr.setAllSubsequentRules(true); +// cr.setnSubsequentRulesToMatch(1); +// rs.addItem(cr, 0); +// FieldAttributes fa = new FieldAttributes(); +// rs.addItem(fa, 1); +// cr = new CommentRule(); +// cr.setCommentText("// end of fields"); +// cr.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_PRECEDING_RULE); +// cr.setAllPrecedingRules(true); +// cr.setnPrecedingRulesToMatch(1); +// rs.addItem(cr, 2); +// InterfaceAttributes ia = new InterfaceAttributes(); +// ia.setMethodOrder(InterfaceAttributes.METHOD_ORDER_ENCOUNTERED); +// ia.setAlphabetizeInterfaces(false); +// ia.setNoExtractedMethods(false); +// cr = new CommentRule(); +// cr.setCommentText("// start of interface %IF%"); +// ia.setPrecedingComment(cr); +// cr = new CommentRule(); +// cr.setCommentText("// end of interface %IF%"); +// ia.setTrailingComment(cr); +// rs.addItem(ia, 3); +// rs.getExtractedMethodsSettings().setBelowFirstCaller(false); +// rs.getExtractedMethodsSettings().setMoveExtractedMethods(true); +// rs.getExtractedMethodsSettings().setCommentType(RelatedMethodsSettings.COMMENT_TYPE_EACH_LEVEL); +// rs.getExtractedMethodsSettings().setNonPrivateTreatment(RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ANY_CALLERS); +// rs.getExtractedMethodsSettings().setDepthFirstOrdering(true); +// cr = new CommentRule(); +// cr.setCommentText("// Level %LV% methods"); +// rs.getExtractedMethodsSettings().setPrecedingComment(cr); +// cr = new CommentRule(); +// cr.setCommentText("// end Level %LV% methods"); +// rs.getExtractedMethodsSettings().setTrailingComment(cr); +// // should work with or without the global comment pattern +//// rs.setGlobalCommentPattern("// (((start|end) of (fields|interface [A-Za-z_0-9]+))|(end|)Level [0-9]+ methods)"); +// rah.rearrangeDocument(getProject(), file, rs, doc); // note - blank lines end up "reversed" +// // where a blank line, generated comment, and method occur in order; the generated comment is removed +// // and the blank line precedes the method; when the new comment is generated, it is inserted before +// // the blank line. +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult28.java"); +// } +// +// public void testParseBugInfiniteLoop() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest29.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementTest29.java"); +// } +// +// public void testSpacingBug() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest30.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getAfterClassLBrace().setForce(true); +// rs.getAfterClassLBrace().setnBlankLines(0); +// rs.getAfterClassRBrace().setForce(true); +// rs.getAfterClassRBrace().setnBlankLines(1); +// rs.getAfterMethodLBrace().setForce(true); +// rs.getAfterMethodLBrace().setnBlankLines(0); +// rs.getAfterMethodRBrace().setForce(true); +// rs.getAfterMethodRBrace().setnBlankLines(1); +// rs.getBeforeClassRBrace().setForce(true); +// rs.getBeforeClassRBrace().setnBlankLines(0); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// rs.setRemoveBlanksInsideCodeBlocks(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult30.java"); +// } +// +// public void testSpacingBug2() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest31.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getAfterClassLBrace().setForce(true); +// rs.getAfterClassLBrace().setnBlankLines(0); +// rs.getAfterClassRBrace().setForce(true); +// rs.getAfterClassRBrace().setnBlankLines(1); +// rs.getAfterMethodLBrace().setForce(true); +// rs.getAfterMethodLBrace().setnBlankLines(0); +// rs.getAfterMethodRBrace().setForce(true); +// rs.getAfterMethodRBrace().setnBlankLines(1); +// rs.getBeforeClassRBrace().setForce(true); +// rs.getBeforeClassRBrace().setnBlankLines(0); +// rs.getBeforeMethodRBrace().setForce(true); +// rs.getBeforeMethodRBrace().setnBlankLines(0); +// rs.setRemoveBlanksInsideCodeBlocks(true); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult31.java"); +// } +// +// public void testSpacingBug3() throws Exception { +// configureByFile("/com/wrq/rearranger/DomainExpanderTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getAfterClassLBrace().setForce(true); +// rs.getAfterClassLBrace().setnBlankLines(0); +// rs.getAfterClassRBrace().setForce(true); +// rs.getAfterClassRBrace().setnBlankLines(1); +// rs.getAfterMethodLBrace().setForce(true); +// rs.getAfterMethodLBrace().setnBlankLines(0); +// rs.getAfterMethodRBrace().setForce(true); +// rs.getAfterMethodRBrace().setnBlankLines(0); +// rs.getBeforeClassRBrace().setForce(true); +// rs.getBeforeClassRBrace().setnBlankLines(0); +// rs.getBeforeMethodRBrace().setForce(true); +// rs.getBeforeMethodRBrace().setnBlankLines(0); +// rs.setRemoveBlanksInsideCodeBlocks(true); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/DomainExpanderResult.java"); +// } +// +// /** +// * Bug occurs when one or more blank lines precede a generated comment. +// * When comment is removed, blank lines now precede the item. Comment is inserted +// * at the beginning (i.e. before the blank lines) and a newline character is +// * prefixed to the comment. Net effect is that new blank line(s) appear after the comment. +// * +// * @throws Exception test exception +// */ +// public void testGeneratedCommentSpacingBug() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest32.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult32.java"); +// } +// +// public void testGeneratedCommentSpacing() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest32.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult32.java"); +// } +// +// public void testInnerClassComments() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest34.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.setRearrangeInnerClasses(true); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("// ----- OUTER CLASS -----\n"); +// rs.getClassOrderAttributeList().add(0, cr); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult34.java"); +// } +// +// public void testInnerClassCommentsNoRearrangement() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest34.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.setRearrangeInnerClasses(false); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("// ----- OUTER CLASS -----\n"); +// rs.getClassOrderAttributeList().add(0, cr); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult34B.java"); +// } +// +// public void testFirstInsertionOfComment() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest35.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// CommentRule cr = new CommentRule(); +// cr.setCommentText("// ----- FIELDS -----\n"); +// FieldAttributes fa = new FieldAttributes(); +// rs.addItem(cr, 0); +// rs.addItem(fa, 1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult35.java"); +// } +// +// public void testExcludeFromExtraction() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest36.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementTest36.java"); +// } +// +// public void testInterferingGSNames() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest37.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(true); +// rs.getDefaultGSDefinition().setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_IMMATERIAL); +// rs.getDefaultGSDefinition().setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// rs.getDefaultGSDefinition().setSetterBodyCriterion(GetterSetterDefinition.SETTER_BODY_IMMATERIAL); +// rs.getDefaultGSDefinition().setSetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult37.java"); +// } +// +// public void testInterferingGSNamesNoKGSTogether() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest37.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.setKeepGettersSettersTogether(false); +// rs.getDefaultGSDefinition().setGetterBodyCriterion(GetterSetterDefinition.GETTER_BODY_IMMATERIAL); +// rs.getDefaultGSDefinition().setGetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// rs.getDefaultGSDefinition().setSetterBodyCriterion(GetterSetterDefinition.SETTER_BODY_IMMATERIAL); +// rs.getDefaultGSDefinition().setSetterNameCriterion(GetterSetterDefinition.GETTER_NAME_CORRECT_PREFIX); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementTest37.java"); +// } +// +// public void testRemoveBlankLineInsideMethodBug() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest38.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// File settingsFile = new File(InteractiveTest.DEFAULT_CONFIGURATION_ROOT + +// "/test/testData/com/wrq/rearranger/RearrangementTest38cfg.xml"); +// rs = RearrangerSettings.getSettingsFromFile(settingsFile); +// rs.setAskBeforeRearranging(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementTest38.java"); +// } +// +// public void testSortFieldsByTypeAndName() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest39.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getSortAttr().setByType(true); +// fa.getSortAttr().setByName(true); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult39B.java"); +// } +// +// public void testSortFieldsByType() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest39.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getSortAttr().setByType(true); +// fa.getSortAttr().setByName(false); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult39C.java"); +// } +// +// public void testSortFieldsByTypeICAndName() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest39.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getSortAttr().setByType(true); +// fa.getSortAttr().setTypeCaseInsensitive(true); +// fa.getSortAttr().setByName(true); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult39.java"); +// } +// +// public void testSortFieldsByTypeIC() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest39.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getSortAttr().setByType(true); +// fa.getSortAttr().setTypeCaseInsensitive(true); +// fa.getSortAttr().setByName(false); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult39A.java"); +// } +// +// /** +// * test detection of method overrides/overridden/implements/implemented attributes. +// * +// * @throws Exception test exception +// */ +// public void testOverImpl() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest40.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult40.java"); +// } +// +// public final void testRemoveBlankLinesBeforeMethod() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest41.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rs.getAfterClassLBrace().setForce(true); +// rs.getAfterClassLBrace().setnBlankLines(0); +// rs.getBeforeMethodLBrace().setForce(true); +// rs.getBeforeMethodLBrace().setnBlankLines(0); +// rs.getAfterMethodLBrace().setForce(true); +// rs.getAfterMethodLBrace().setnBlankLines(0); +// rs.getBeforeMethodRBrace().setForce(true); +// rs.getBeforeMethodRBrace().setnBlankLines(0); +// rs.getAfterMethodRBrace().setForce(true); +// rs.getAfterMethodRBrace().setnBlankLines(0); +// rs.getBeforeClassRBrace().setForce(true); +// rs.getBeforeClassRBrace().setnBlankLines(0); +// rs.getAfterClassRBrace().setForce(true); +// rs.getAfterClassRBrace().setnBlankLines(0); +// rs.setRemoveBlanksInsideCodeBlocks(true); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult41.java"); +// } +// +// public final void testEnumClass() throws Exception { +// final Project project = getProject(); +// final LanguageLevelProjectExtension llpExtension = LanguageLevelProjectExtension.getInstance(project); +// LanguageLevel oldLevel = llpExtension.getLanguageLevel(); +// llpExtension.setLanguageLevel(LanguageLevel.JDK_1_5); +// configureByFile("/com/wrq/rearranger/RearrangementTest42.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult42.java"); +// llpExtension.setLanguageLevel(oldLevel); +// } +// +// public final void testNumParameters() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest43.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// MethodAttributes ma; +// ma = new MethodAttributes(); +// ma.getMinParamsAttr().setMatch(true); +// ma.getMinParamsAttr().setValue(2); +// ma.getMaxParamsAttr().setMatch(true); +// ma.getMaxParamsAttr().setValue(3); +// rs.addItem(ma, 0); +// ma = new MethodAttributes(); +// ma.getMinParamsAttr().setMatch(true); +// ma.getMinParamsAttr().setValue(1); +// rs.addItem(ma, 1); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult43.java"); +// } +// +// public final void testGeneratedComment() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest44.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// CommentRule cr = new CommentRule(); +// CommentFillString cfs = cr.getCommentFillString(); +// cfs.setFillString("-+"); +// cfs.setUseProjectWidthForFill(false); +// cfs.setFillWidth(30); +// cr.setEmitCondition(CommentRule.EMIT_ALWAYS); +// cr.setCommentText("// %FS% METHODS %FS%"); +// rs.addItem(cr, 0); +// MethodAttributes ma; +// ma = new MethodAttributes(); // match all methods +// rs.addItem(ma, 1); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult44.java"); +// } +// +// public void testEnum1() throws Exception { +// final Project project = getProject(); +// final LanguageLevelProjectExtension llpExtension = LanguageLevelProjectExtension.getInstance(project); +// LanguageLevel oldLevel = llpExtension.getLanguageLevel(); +// llpExtension.setLanguageLevel(LanguageLevel.JDK_1_5); +// configureByFile("/com/wrq/rearranger/Enum1Test.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(project).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// rs.setRearrangeInnerClasses(true); +// rs.getExtractedMethodsSettings().setBelowFirstCaller(true); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(project, file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/Enum1Result.java"); +// llpExtension.setLanguageLevel(oldLevel); +// } +// +// public void testEnum2() throws Exception { +// final Project project = getProject(); +// final LanguageLevelProjectExtension llpExtension = LanguageLevelProjectExtension.getInstance(project); +// LanguageLevel oldLevel = llpExtension.getLanguageLevel(); +// llpExtension.setLanguageLevel(LanguageLevel.JDK_1_5); +// configureByFile("/com/wrq/rearranger/Enum2Test.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(project).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.setRearrangeInnerClasses(true); +// rs.getAfterClassRBrace().setForce(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(project, file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/Enum2Result.java"); +// llpExtension.setLanguageLevel(oldLevel); +// } +// +// public void testEnum2A() throws Exception { +// final Project project = getProject(); +// final LanguageLevelProjectExtension llpExtension = LanguageLevelProjectExtension.getInstance(project); +// LanguageLevel oldLevel = llpExtension.getLanguageLevel(); +// llpExtension.setLanguageLevel(LanguageLevel.JDK_1_5); +// configureByFile("/com/wrq/rearranger/Enum2Test.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(project).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.setRearrangeInnerClasses(false); +// rs.getAfterClassRBrace().setForce(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(project, file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/Enum2AResult.java"); +// llpExtension.setLanguageLevel(oldLevel); +// } +// +// public void testRearrangementIncompleteLastLine() throws Exception { +// configureByFile("/com/wrq/rearranger/IncompleteLineTest.java"); +// final PsiFile file = getFile(); +// Project project = getProject(); +// final Document doc = PsiDocumentManager.getInstance(project).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(project, file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/IncompleteLineResult.java"); +// } +// +// public void testOverloadedMethodCategorization() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest45.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File(InteractiveTest.DEFAULT_CONFIGURATION)); +// rs.setAskBeforeRearranging(false); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(1); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult45.java"); +// } +// +// public void testSuperclassAlgorithm() throws Exception { +// final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(getProject()); +// final PsiClass aClass = +// psiFacade.getElementFactory(). +// createClassFromText("public String toString() {return null;}", null); +// final PsiMethod method = aClass.getMethods()[0]; +// final PsiMethod[] superMethods = method.findSuperMethods(); +// assertEquals(1, superMethods.length); +// PsiClass psiClass = superMethods[0].getContainingClass(); +// if (psiClass == null) { +// fail("missing containing class"); +// } +// else { +// assertEquals("java.lang.Object", psiClass.getQualifiedName()); +// } +// } +// +// public void testSortingOriginalOrder() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest46.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlProtected(true); +// fa.getSortAttr().setByModifiers(false); +// fa.getSortAttr().setByType(false); +// fa.getSortAttr().setTypeCaseInsensitive(false); +// fa.getSortAttr().setByName(false); +// fa.getSortAttr().setNameCaseInsensitive(false); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult46A.java"); +// } +// +// public void testSortingModifierOrder() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest46.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlProtected(true); +// fa.getSortAttr().setByModifiers(true); +// fa.getSortAttr().setByType(false); +// fa.getSortAttr().setTypeCaseInsensitive(false); +// fa.getSortAttr().setByName(false); +// fa.getSortAttr().setNameCaseInsensitive(false); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult46B.java"); +// } +// +// public void testSortingTypeOrder() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest46.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlProtected(true); +// fa.getSortAttr().setByModifiers(false); +// fa.getSortAttr().setByType(true); +// fa.getSortAttr().setTypeCaseInsensitive(false); +// fa.getSortAttr().setByName(false); +// fa.getSortAttr().setNameCaseInsensitive(false); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult46C.java"); +// } +// +// public void testSortingTypeOrderCI() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest46.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlProtected(true); +// fa.getSortAttr().setByModifiers(false); +// fa.getSortAttr().setByType(true); +// fa.getSortAttr().setTypeCaseInsensitive(true); +// fa.getSortAttr().setByName(false); +// fa.getSortAttr().setNameCaseInsensitive(false); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult46D.java"); +// } +// +// public void testSortingMTNOrderCI() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest46.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlProtected(true); +// fa.getSortAttr().setByModifiers(true); +// fa.getSortAttr().setByType(true); +// fa.getSortAttr().setTypeCaseInsensitive(true); +// fa.getSortAttr().setByName(true); +// fa.getSortAttr().setNameCaseInsensitive(true); +// rs.addItem(fa, 0); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult46E.java"); +// } +// +// public void testEnumSelection() throws Exception { +// configureByFile("/com/wrq/rearranger/RearrangementTest47.java"); +// final PsiFile file = getFile(); +// final Project project = getProject(); +// final LanguageLevelProjectExtension llpExtension = LanguageLevelProjectExtension.getInstance(project); +// LanguageLevel oldLevel = llpExtension.getLanguageLevel(); +// llpExtension.setLanguageLevel(LanguageLevel.JDK_1_5); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// FieldAttributes fa = new FieldAttributes(); +// fa.getStAttr().setValue(true); +// rs.addItem(fa, 0); +// InnerClassAttributes ica = new InnerClassAttributes(); +// ica.getEnumAttr().setValue(true); +// rs.addItem(ica, 1); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult47.java"); +// llpExtension.setLanguageLevel(oldLevel); +// } +// +// public void testOverloaded1() throws Exception { +// configureByFile("/com/wrq/rearranger/OverloadedTest1.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File("testData/com/wrq/rearranger/OverloadedConfig.xml")); +// rs.setAskBeforeRearranging(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/OverloadedResult1.java"); +// } +// +// public void testGenerics1() throws Exception { +// configureByFile("/com/wrq/rearranger/GenericsTest1.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File("testData/com/wrq/rearranger/OverloadedConfig.xml")); +// rs.setAskBeforeRearranging(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/GenericsResult1.java"); +// } +// +// public void testInterface1() throws Exception { +// configureByFile("/com/wrq/rearranger/InterfaceTest1.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlPublic(true); // match all public fields; in an interface, all constants are regarded as public +// fa.getStAttr().setValue(true); // match all static fields; in an interface, all constants are regarded as public +// rs.addItem(fa, 0); +// MethodAttributes ma = new MethodAttributes(); +// ma.getPlAttr().setPlPublic(true); // match all public methods; in an interface, all methods are regarded as public +// rs.addItem(ma, 1); +// rs.setAskBeforeRearranging(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/InterfaceResult1.java"); +// } +// +// public void testCorruptRespacing() throws Exception { +// configureByFile("/com/wrq/rearranger/CorruptRespacingTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// rs = RearrangerSettings.getSettingsFromFile(new File("testData/com/wrq/rearranger/CorruptionConfig.xml")); +// rs.setAskBeforeRearranging(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/CorruptRespacingResult.java"); +// } +// +// public void testCommentSeparator1() throws Exception { +// configureByFile("/com/wrq/rearranger/CommentSeparatorTest1.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final CommentRule c = new CommentRule(); +// c.setCommentText("\n\t// Fields %FS%\n"); +// c.setEmitCondition(CommentRule.EMIT_IF_ITEMS_MATCH_SUBSEQUENT_RULE); +// CommentFillString cfs = new CommentFillString(); +// cfs.setFillString("="); +// cfs.setUseProjectWidthForFill(false); +// cfs.setFillWidth(80); +// c.setCommentFillString(cfs); +// rs.addItem(c, 0); +// FieldAttributes fa = new FieldAttributes(); +// fa.getPlAttr().setPlPublic(true); +// rs.addItem(fa, 1); +// rs.setAskBeforeRearranging(false); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.setTabSize(4); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/CommentSeparatorResult1.java"); +// } +// +// public void testEmptySetter() throws Exception { +// configureByFile("/com/wrq/rearranger/BitFieldTest.java"); +// final PsiFile file = getFile(); +// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); +// final File physFile = new File(InteractiveTest.DEFAULT_CONFIGURATION); +// rs = RearrangerSettings.getSettingsFromFile(physFile); +// rs.setAskBeforeRearranging(false); +// rs.getAfterClassRBrace().setnBlankLines(2); +// rs.getAfterClassRBrace().setForce(true); +// rs.getNewlinesAtEOF().setForce(true); +// rs.getNewlinesAtEOF().setnBlankLines(3); +// final RearrangerActionHandler rah = new RearrangerActionHandler(); +// rah.rearrangeDocument(getProject(), file, rs, doc); +// super.checkResultByFile("/com/wrq/rearranger/BitFieldResult.java"); +// } + + private void doTest(@NotNull String srcFileName, @Nullable String expectedResultFileName) { + myFixture.configureByFile("${srcFileName}.java") + ApplicationManager.application.runWriteAction { + new RearrangerActionHandler().rearrangeDocument(myFixture.project, myFixture.file, mySettings, myFixture.editor.document); + } + myFixture.checkResultByFile("${expectedResultFileName}.java") + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/settings/CommentFillStringTest.java b/plugins/rearranger/test/src/com/wrq/rearranger/settings/CommentFillStringTest.java new file mode 100644 index 000000000000..58da684adbb4 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/settings/CommentFillStringTest.java @@ -0,0 +1,27 @@ +package com.wrq.rearranger.settings; + +/** + * Test fill string pattern generation. + */ + +import junit.framework.TestCase; + +public class CommentFillStringTest + extends TestCase +{ + CommentFillString cfs; + + public void testGetFillStringPattern() throws Exception { + String result; + cfs = new CommentFillString(); + cfs.setFillString("a"); + result = cfs.getFillStringPattern(); + assertEquals("(a)*", result); + cfs.setFillString("abc"); + result = cfs.getFillStringPattern(); + assertEquals("(abc)*(ab|a)?", result); + cfs.setFillString("-=*"); + result = cfs.getFillStringPattern(); + assertEquals("(-=\\*)*(-=|-)?", result); + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java b/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java new file mode 100644 index 000000000000..ccb6a4281ad3 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java @@ -0,0 +1,66 @@ +package com.wrq.rearranger.settings.attributeGroups; + +/** + * Test toString() method for MethodAttributes. + */ + +import junit.framework.TestCase; + +public class MethodAttributesTest + extends TestCase +{ + MethodAttributes ma; + + public void testToString() throws Exception { + ma = new MethodAttributes(); + // test various combinations of min/max parameters, name, and return type. + ma.getPlAttr().setPlPublic(true); + // min = ? max = ? name = ? return = ? + setma(false, 0, false, 0, null, null, "public methods"); + // min = 1 max = ? name = ? return = ? + setma(true, 0, false, 0, null, null, "public methods with at least 0 parameters"); + setma(true, 1, false, 0, null, null, "public methods with at least 1 parameter"); + setma(true, 2, false, 0, null, null, "public methods with at least 2 parameters"); + // min = ? max = 1 name = ? return = ? + setma(false, 0, true, 0, null, null, "public methods with at most 0 parameters"); + setma(false, 0, true, 1, null, null, "public methods with at most 1 parameter"); + setma(false, 0, true, 2, null, null, "public methods with at most 2 parameters"); + // min = ? max = ? name = N return = ? + setma(false, 0, false, 0, "NAME", null, "public methods whose names match 'NAME'"); + // min = ? max = ? name = ? return = R + setma(false, 0, false, 0, null, "int", "public methods whose return types match 'int'"); + // + // min = 1 max = 3 name = ? return = ? + setma(true, 0, true, 0, null, null, "public methods with 0 parameters"); + setma(true, 1, true, 1, null, null, "public methods with 1 parameter"); + setma(true, 2, true, 2, null, null, "public methods with 2 parameters"); + setma(true, 0, true, 2, null, null, "public methods with 0 to 2 parameters"); + // min = 1 max = 1 name = N return = ? + setma(true, 0, true, 2, "NAME", null, "public methods with 0 to 2 parameters, " + + "and whose names match 'NAME'"); + // min = 1 max = 1 name = ? return = R + setma(true, 0, true, 2, null, "int", "public methods with 0 to 2 parameters, " + + "and whose return types match 'int'"); + // min = 1 max = 1 name = N return = R + setma(true, 0, true, 2, "NAME", "int", "public methods with 0 to 2 parameters, " + + "whose names match 'NAME', and whose return types match 'int'"); + ma.getMinParamsAttr().setMatch(true); + ma.getMinParamsAttr().setValue(1); + ma.getMinParamsAttr().setMatch(true); + ma.getMinParamsAttr().setValue(1); + } + + private void setma(boolean minMatch, int min, boolean maxMatch, int max, String name, String returnValue, + String description) + { + ma.getMinParamsAttr().setMatch(minMatch); + ma.getMinParamsAttr().setValue(min); + ma.getMaxParamsAttr().setMatch(maxMatch); + ma.getMaxParamsAttr().setValue(max); + ma.getNameAttr().setMatch(name != null); + ma.getNameAttr().setExpression(name); + ma.getReturnTypeAttr().setMatch(returnValue != null); + ma.getReturnTypeAttr().setExpression(returnValue); + assertEquals("wrong description", description, ma.toString()); + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/RegexUtilTest.java b/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/RegexUtilTest.java new file mode 100644 index 000000000000..1be748071964 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/RegexUtilTest.java @@ -0,0 +1,25 @@ +package com.wrq.rearranger.settings.attributeGroups; + +/** + * Todo - describe class. + *

+ * Corresponds to portions of: todo - insert .c and .h file references + */ + +import junit.framework.TestCase; + +public class RegexUtilTest + extends TestCase +{ + RegexUtil regexUtil; + + public void testReplaceAllFS() throws Exception { + String result; + result = RegexUtil.replaceAllFS("abc", ""); + assertEquals("abc", result); + result = RegexUtil.replaceAllFS("ab%FS%c", ""); + assertEquals("abc", result); + result = RegexUtil.replaceAllFS("%FS%ab%FS%", "xx"); + assertEquals("xxabxx", result); + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestClass1.java b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestClass1.java new file mode 100644 index 000000000000..0c978a0f09d2 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestClass1.java @@ -0,0 +1,19 @@ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. + * User: davek + * Date: Oct 30, 2003 + * Time: 2:53:43 PM + * To change this template use Options | File Templates. + */ +final class TestClass1 { + public static final int CONSTANT1 = 1; + public static final int CONSTANT2 = 2; + /** end of public static final fields */ + private final int privateField1; + + public TestClass1(final int privateField1) { + this.privateField1 = privateField1; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestClass2.java b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestClass2.java new file mode 100644 index 000000000000..86871ec6db2f --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestClass2.java @@ -0,0 +1,38 @@ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. + * User: davek + * Date: Oct 31, 2003 + * Time: 11:48:02 AM + * To change this template use Options | File Templates. + */ +final class TestClass2 { +// ------------------------------ FIELDS ------------------------------ + + public static final int CONSTANT3 = 3; + public static final int CONSTANT4 = 4; + /** end of public static final fields */ + private final int privateField5; + +// --------------------------- CONSTRUCTORS --------------------------- + + public TestClass2(final int privateField1) { + this.privateField5 = privateField1; + } + +// -------------------------- INNER CLASSES -------------------------- + + class inner1 { + // test class + } + + + class inner2 { + // test class + } +} + +class outer1 { + // test class +} diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestEnum.java b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestEnum.java new file mode 100644 index 000000000000..e641493305d4 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestEnum.java @@ -0,0 +1,24 @@ +/** + * $id + * Author: Dave Kriewall + * Created: Oct 20, 2005 + * Copyright 2004, WRQ, Inc. + */ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. User: JJohnson Date: Aug 30, 2005 Time: 11:06:54 AM To change this template use File | + * Settings | File Templates. + */ +public class TestEnum implements Cloneable { +} + +class Utilities { +// -------------------------- STATIC METHODS -------------------------- + + public static String toString(Object receipt) + + { + return null; //To change body of created methods use File | Settings | File Templates. + } +} diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestImplementation.java b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestImplementation.java new file mode 100644 index 000000000000..277ff056f252 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestImplementation.java @@ -0,0 +1,13 @@ +package com.wrq.rearranger.testClasses; + +public class TestImplementation + implements TestInterface +{ + public void method1() { + // implements the method of the interface + } + + public boolean equals(Object obj) { + return super.equals(obj); + } +} diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestInterface.java b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestInterface.java new file mode 100644 index 000000000000..4b7787460917 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestInterface.java @@ -0,0 +1,19 @@ +package com.wrq.rearranger.testClasses; + +public interface TestInterface { +// -------------------------- OTHER METHODS -------------------------- + + void method1(); + +// -------------------------- INNER CLASSES -------------------------- + + class inner { + int i; + } +} + +class outer { +// ------------------------------ FIELDS ------------------------------ + + int j; +} diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestOverride.java b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestOverride.java new file mode 100644 index 000000000000..831806681dc1 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/testClasses/TestOverride.java @@ -0,0 +1,20 @@ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. + * User: davek + * Date: Dec 31, 2003 + * Time: 2:27:46 PM + * To change this template use Options | File Templates. + */ +public class TestOverride + extends TestImplementation +{ + public void method1() { + super.method1(); //To change body of overriden methods use Options | File Templates. + } + + public boolean equals(Object obj) { + return super.equals(obj); //To change body of overriden methods use Options | File Templates. + } +} diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/util/CommentUtilTest.java b/plugins/rearranger/test/src/com/wrq/rearranger/util/CommentUtilTest.java new file mode 100644 index 000000000000..854d10bfb7f4 --- /dev/null +++ b/plugins/rearranger/test/src/com/wrq/rearranger/util/CommentUtilTest.java @@ -0,0 +1,57 @@ +package com.wrq.rearranger.util; + +/** + * Test comment expansion with fill patterns. + */ + +import junit.framework.TestCase; + +public class CommentUtilTest + extends TestCase +{ + CommentUtil commentUtil; + + public void testExpandFill() throws Exception { + String result; + // test left justify, right justify, center justify, multiline, multiple fills + result = CommentUtil.expandFill("Method Name %FS%\n", 30, 4, "-="); + assertEquals("left justify failed", "Method Name -=-=-=-=-=-=-=-=-=\n", result); + result = CommentUtil.expandFill("%FS% Method Name\n", 30, 4, "-="); + assertEquals("right justify failed", "-=-=-=-=-=-=-=-=-= Method Name\n", result); + result = CommentUtil.expandFill("%FS% Method Name %FS%\n", 30, 4, "-="); + assertEquals("center justify failed", "-=-=-=-=- Method Name -=-=-=-=\n", result); + result = CommentUtil.expandFill("Method Name %FS%\n" + + "%FS% Method Name\n" + + "%FS% Method Name %FS%\n\n", 30, 4, "-="); + assertEquals("multiline failed", "Method Name -=-=-=-=-=-=-=-=-=\n" + + "-=-=-=-=-=-=-=-=-= Method Name\n" + + "-=-=-=-=- Method Name -=-=-=-=\n\n", result); + result = CommentUtil.expandFill("Method Name %FS%\n" + + "%FS% Method Name\n" + + "%FS% Method Name %FS%\n", 30, 4, "-="); + assertEquals("multiline failed", "Method Name -=-=-=-=-=-=-=-=-=\n" + + "-=-=-=-=-=-=-=-=-= Method Name\n" + + "-=-=-=-=- Method Name -=-=-=-=\n", result); + result = CommentUtil.expandFill("Method Name %FS%\n" + + "%FS% Method Name\n" + + "%FS% Method Name %FS%", 30, 4, "-="); + assertEquals("multiline failed", "Method Name -=-=-=-=-=-=-=-=-=\n" + + "-=-=-=-=-=-=-=-=-= Method Name\n" + + "-=-=-=-=- Method Name -=-=-=-=", result); + result = CommentUtil.expandFill("1%FS%2%FS%3%FS%4\n", 36, 4, "abcde"); + assertEquals("multiple fills failed", "1abcdeabcdea2abcdeabcdea3abcdeabcde4\n", result); + // test no fill with too few and too many characters + result = CommentUtil.expandFill("Method Name", 30, 4, "-="); + assertEquals("no fill failed", "Method Name", result); + result = CommentUtil.expandFill("Method Name", 5, 4, "-="); + assertEquals("no fill failed", "Method Name", result); + result = CommentUtil.expandFill("Method Name\n", 30, 4, "-="); + assertEquals("no fill failed", "Method Name\n", result); + result = CommentUtil.expandFill("Method Name\n", 5, 4, "-="); + assertEquals("no fill failed", "Method Name\n", result); + result = CommentUtil.expandFill("\n\t// Fields %FS%\n", 80, 4, "="); + assertEquals("tab fill failed", + "\n\t// Fields ==================================================================\n", + result); + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/BitFieldResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/BitFieldResult.java new file mode 100644 index 000000000000..b9fcce1caad8 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/BitFieldResult.java @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.parboiled.common; + +import com.google.common.base.Preconditions; + +import java.util.ArrayList; +import java.util.List; + +/** This class represents an arbitrarily sized bitfield that provides for efficient operations on large arrays of booleans. */ +public class BitField { +// ------------------------------ FIELDS ------------------------------ + + private final int[] data; + private final int length; + +// -------------------------- STATIC METHODS -------------------------- + + /** + * ORs the given BitFields. + * + * @param a the first Field. + * @param b the second Field. + * @return the OR of of both fields. + */ + public static BitField or(BitField a, BitField b) { + BitField result = new BitField(a.length); + for (int i = 0; i < result.data.length; i++) { + result.data[i] = a.data[i] | b.data[i]; + } + return result; + } + + /** + * XORs the given BitFields. + * + * @param a the first Field. + * @param b the second Field. + * @return the XOR of of both fields. + */ + public static BitField xor(BitField a, BitField b) { + BitField result = new BitField(a.length); + for (int i = 0; i < result.data.length; i++) { + result.data[i] = a.data[i] ^ b.data[i]; + } + return result; + } + + /** + * Determines whether the AND of the two given BitFields is non-empty. + * + * @param a the first field. + * @param b the second field. + * @return a boolean indicating whether the two given fields overlap. + */ + public static boolean overlap(BitField a, BitField b) { + if ((a.data[0] & b.data[0]) > 0) { + return true; + } + + int l = a.data.length; + for (int i = 1; i < l; i++) { + if ((a.data[i] & b.data[i]) > 0) { + return true; + } + } + return false; + } + + /** + * Parses the specified string into a BitField. + * + * @param str the string to parse + * @return the created BitField + * @throws IllegalArgumentException for non-wellformed input strings + */ + public static BitField valueOf(String str) throws IllegalArgumentException { + if (StringUtils.isEmpty(str)) { + throw new IllegalArgumentException(); + } + + String[] s = str.split("|"); + if (s.length < 2) { + throw new IllegalArgumentException(); + } + + BitField bf = new BitField(Integer.decode(s[0])); + if (bf.data.length != s.length - 1) { + throw new IllegalArgumentException(); + } + + for (int i = 0; i < bf.data.length; i++) { + bf.data[i] = Integer.decode(s[i + 1]); + } + + return bf; + } + + /** + * Returns a BitField with only those bits that are set in a but not in b. + * + * @param a the first field + * @param b the second field + * @return the substract field. + */ + public static BitField substract(BitField a, BitField b) { + return and(a, not(and(a, b))); + } + + /** + * Negates the given field. + * + * @param a the field to negate. + * @return the bitwise NOT of the given field. + */ + public static BitField not(BitField a) { + BitField result = new BitField(a.length); + for (int i = 0; i < result.data.length; i++) { + result.data[i] = ~a.data[i]; + } + return result; + } + + /** + * ANDs the given BitFields. + * + * @param a the first Field. + * @param b the second Field. + * @return the AND of of both fields. + */ + public static BitField and(BitField a, BitField b) { + BitField result = new BitField(a.length); + for (int i = 0; i < result.data.length; i++) { + result.data[i] = a.data[i] & b.data[i]; + } + return result; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + /** + * Creates a new BitField with the given number of bits. + * + * @param length the number of bits + */ + public BitField(int length) { + Preconditions.checkArgument(length > 0); + this.length = length; + this.data = new int[(length >> 5) + 1]; // the number of ints we need to store the field is length / 32 + } + + /** + * Creates a new BitField initialized with the contents of the given BitField. + * + * @param field the BitField to initialize with + */ + public BitField(BitField field) { + this.length = field.getLength(); + this.data = field.data.clone(); + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + /** + * Gets the indexes of the set bit as an array of int. + * + * @return a list of all indices of the set bits in this field. + */ + public List getBits() { + List bits = new ArrayList(); + for (int i = 0; i < length; i++) { + if (get(i)) { + bits.add(i); + } + } + return bits; + } + + /** + * @param ix the index of the bit to get. + * @return the bit at the given position + */ + public boolean get(int ix) { + Preconditions.checkArgument(0 <= ix && ix < length); + return ((data[ix >> 5] >> ix) & 0x1) != 0; + } + + /** @return the number of bits in this field */ + public int getLength() { + return length; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + /** + * @param other another BitField to compare against. + * @return a boolean indicating whether this BitField is equal to the given one. + */ + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof BitField)) return false; + + BitField bitField = (BitField)other; + if (bitField.length != length) return false; + + for (int i = 0; i < data.length; i++) { + if (bitField.data[i] != data[i]) return false; + } + return true; + } + + /** @return A hashcode for this BitField. */ + @Override + public int hashCode() { + int hash = 31 * length; + for (int i = 0; i < data.length; i++) { + hash ^= data[i] + i; + } + return hash; + } + + /** @return A string representation of this field. */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(length); + for (int d : data) { + sb.append('|'); + sb.append(d); + } + return sb.toString(); + } + +// -------------------------- OTHER METHODS -------------------------- + + /** + * ANDs the given field into this one. + * + * @param field the other field to AND in. + */ + public void and(BitField field) { + for (int i = 0; i < data.length; i++) { + data[i] &= field.data[i]; + } + } + + /** + * Determines whether this BitField fully covers the given BitField, + * i.e. whether this BitField doesn't change when the given one is ORed in. + * + * @param field The field to check for inclusion for. + * @return A boolean indicating whether all bits of the given field are also set in this field. + */ + public boolean contains(BitField field) { + for (int i = 0; i < data.length; i++) { + int d = data[i]; + if (d != (d | field.data[i])) { + return false; + } + } + return true; + } + + /** @return A boolean indicating whether no bit in the field is currently set. */ + public boolean isAllClear() { + for (int d : data) { + if (d != 0x00000000) { + return false; + } + } + return true; + } + + /** @return A boolean indicating whether all bits in the field are currently set. */ + public boolean isAllSet() { + for (int d : data) { + if (d != 0xFFFFFFFF) { + return false; + } + } + return true; + } + + /** Performs a bitwise NOT operation on this field. */ + public void not() { + for (int i = 0; i < data.length; i++) { + data[i] = ~data[i]; + } + } + + /** + * ORs the given field into this one. + * + * @param field the other field to OR in. + */ + public void or(BitField field) { + for (int i = 0; i < data.length; i++) { + data[i] |= field.data[i]; + } + } + + /** + * Set the given bit. + * + * @param ix the index of the bit to set + */ + public void set(int ix) { + Preconditions.checkArgument(0 <= ix && ix < length); + + // fill up the unused bits with the highest bit + int d = ix == length - 1 ? 0xFFFFFFFF << ix : 0x1 << ix; + data[ix >> 5] |= d; // switch the respective bit "on" by ORing in the bit mask + } + + /** + * Sets the bit at the given index to the given value. + * + * @param value the value to set the bit to. + * @param ix the index of the bit to set. + */ + public void set(boolean value, int ix) { + if (value) { + set(ix); + } + else { + clear(ix); + } + } + + /** + * Unsets the given bit. + * + * @param ix the index of the bit to clear + */ + public void clear(int ix) { + Preconditions.checkArgument(0 <= ix && ix < length); + + // fill up the unused bits with the highest bit + int d = ix == length - 1 ? 0xFFFFFFFF << ix : 0x1 << ix; + data[ix >> 5] &= ~d; // switch the respective bit "off" by ANDing with the inversed mask + } + + /** + * Sets all bits in the field to the given value. + * + * @param value The bit value to set all bits to. + */ + public void setAll(boolean value) { + int d = value ? 0xFFFFFFFF : 0x00000000; + for (int i = 0; i < data.length; i++) { + data[i] = d; + } + } + + /** + * XORs the given field into this one. + * + * @param field the other field to XOR in. + */ + public void xor(BitField field) { + for (int i = 0; i < data.length; i++) { + data[i] ^= field.data[i]; + } + } +} + + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/BitFieldTest.java b/plugins/rearranger/test/testData/com/wrq/rearranger/BitFieldTest.java new file mode 100644 index 000000000000..3b78c7865a50 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/BitFieldTest.java @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2003, 2010, Dave Kriewall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.parboiled.common; + +import com.google.common.base.Preconditions; + +import java.util.ArrayList; +import java.util.List; + +/** This class represents an arbitrarily sized bitfield that provides for efficient operations on large arrays of booleans. */ +public class BitField { + + private final int[] data; + private final int length; + + /** + * Creates a new BitField with the given number of bits. + * + * @param length the number of bits + */ + public BitField(int length) { + Preconditions.checkArgument(length > 0); + this.length = length; + this.data = new int[(length >> 5) + 1]; // the number of ints we need to store the field is length / 32 + } + + /** + * Creates a new BitField initialized with the contents of the given BitField. + * + * @param field the BitField to initialize with + */ + public BitField(BitField field) { + this.length = field.getLength(); + this.data = field.data.clone(); + } + + /** @return the number of bits in this field */ + public int getLength() { + return length; + } + + /** + * @param ix the index of the bit to get. + * @return the bit at the given position + */ + public boolean get(int ix) { + Preconditions.checkArgument(0 <= ix && ix < length); + return ((data[ix >> 5] >> ix) & 0x1) != 0; + } + + /** + * Set the given bit. + * + * @param ix the index of the bit to set + */ + public void set(int ix) { + Preconditions.checkArgument(0 <= ix && ix < length); + + // fill up the unused bits with the highest bit + int d = ix == length - 1 ? 0xFFFFFFFF << ix : 0x1 << ix; + data[ix >> 5] |= d; // switch the respective bit "on" by ORing in the bit mask + } + + /** + * Unsets the given bit. + * + * @param ix the index of the bit to clear + */ + public void clear(int ix) { + Preconditions.checkArgument(0 <= ix && ix < length); + + // fill up the unused bits with the highest bit + int d = ix == length - 1 ? 0xFFFFFFFF << ix : 0x1 << ix; + data[ix >> 5] &= ~d; // switch the respective bit "off" by ANDing with the inversed mask + } + + /** + * Sets the bit at the given index to the given value. + * + * @param value the value to set the bit to. + * @param ix the index of the bit to set. + */ + public void set(boolean value, int ix) { + if (value) { + set(ix); + } + else { + clear(ix); + } + } + + /** + * Sets all bits in the field to the given value. + * + * @param value The bit value to set all bits to. + */ + public void setAll(boolean value) { + int d = value ? 0xFFFFFFFF : 0x00000000; + for (int i = 0; i < data.length; i++) { + data[i] = d; + } + } + + /** @return A boolean indicating whether all bits in the field are currently set. */ + public boolean isAllSet() { + for (int d : data) { + if (d != 0xFFFFFFFF) { + return false; + } + } + return true; + } + + /** @return A boolean indicating whether no bit in the field is currently set. */ + public boolean isAllClear() { + for (int d : data) { + if (d != 0x00000000) { + return false; + } + } + return true; + } + + /** @return A hashcode for this BitField. */ + @Override + public int hashCode() { + int hash = 31 * length; + for (int i = 0; i < data.length; i++) { + hash ^= data[i] + i; + } + return hash; + } + + /** + * @param other another BitField to compare against. + * @return a boolean indicating whether this BitField is equal to the given one. + */ + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (!(other instanceof BitField)) return false; + + BitField bitField = (BitField)other; + if (bitField.length != length) return false; + + for (int i = 0; i < data.length; i++) { + if (bitField.data[i] != data[i]) return false; + } + return true; + } + + /** + * ANDs the given BitFields. + * + * @param a the first Field. + * @param b the second Field. + * @return the AND of of both fields. + */ + public static BitField and(BitField a, BitField b) { + BitField result = new BitField(a.length); + for (int i = 0; i < result.data.length; i++) { + result.data[i] = a.data[i] & b.data[i]; + } + return result; + } + + /** + * ANDs the given field into this one. + * + * @param field the other field to AND in. + */ + public void and(BitField field) { + for (int i = 0; i < data.length; i++) { + data[i] &= field.data[i]; + } + } + + /** + * ORs the given BitFields. + * + * @param a the first Field. + * @param b the second Field. + * @return the OR of of both fields. + */ + public static BitField or(BitField a, BitField b) { + BitField result = new BitField(a.length); + for (int i = 0; i < result.data.length; i++) { + result.data[i] = a.data[i] | b.data[i]; + } + return result; + } + + /** + * ORs the given field into this one. + * + * @param field the other field to OR in. + */ + public void or(BitField field) { + for (int i = 0; i < data.length; i++) { + data[i] |= field.data[i]; + } + } + + /** + * XORs the given BitFields. + * + * @param a the first Field. + * @param b the second Field. + * @return the XOR of of both fields. + */ + public static BitField xor(BitField a, BitField b) { + BitField result = new BitField(a.length); + for (int i = 0; i < result.data.length; i++) { + result.data[i] = a.data[i] ^ b.data[i]; + } + return result; + } + + /** + * XORs the given field into this one. + * + * @param field the other field to XOR in. + */ + public void xor(BitField field) { + for (int i = 0; i < data.length; i++) { + data[i] ^= field.data[i]; + } + } + + /** + * Negates the given field. + * + * @param a the field to negate. + * @return the bitwise NOT of the given field. + */ + public static BitField not(BitField a) { + BitField result = new BitField(a.length); + for (int i = 0; i < result.data.length; i++) { + result.data[i] = ~a.data[i]; + } + return result; + } + + /** Performs a bitwise NOT operation on this field. */ + public void not() { + for (int i = 0; i < data.length; i++) { + data[i] = ~data[i]; + } + } + + /** + * Determines whether the AND of the two given BitFields is non-empty. + * + * @param a the first field. + * @param b the second field. + * @return a boolean indicating whether the two given fields overlap. + */ + public static boolean overlap(BitField a, BitField b) { + if ((a.data[0] & b.data[0]) > 0) { + return true; + } + + int l = a.data.length; + for (int i = 1; i < l; i++) { + if ((a.data[i] & b.data[i]) > 0) { + return true; + } + } + return false; + } + + /** + * Determines whether this BitField fully covers the given BitField, + * i.e. whether this BitField doesn't change when the given one is ORed in. + * + * @param field The field to check for inclusion for. + * @return A boolean indicating whether all bits of the given field are also set in this field. + */ + public boolean contains(BitField field) { + for (int i = 0; i < data.length; i++) { + int d = data[i]; + if (d != (d | field.data[i])) { + return false; + } + } + return true; + } + + /** @return A string representation of this field. */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(length); + for (int d : data) { + sb.append('|'); + sb.append(d); + } + return sb.toString(); + } + + /** + * Parses the specified string into a BitField. + * + * @param str the string to parse + * @return the created BitField + * @throws IllegalArgumentException for non-wellformed input strings + */ + public static BitField valueOf(String str) throws IllegalArgumentException { + if (StringUtils.isEmpty(str)) { + throw new IllegalArgumentException(); + } + + String[] s = str.split("|"); + if (s.length < 2) { + throw new IllegalArgumentException(); + } + + BitField bf = new BitField(Integer.decode(s[0])); + if (bf.data.length != s.length - 1) { + throw new IllegalArgumentException(); + } + + for (int i = 0; i < bf.data.length; i++) { + bf.data[i] = Integer.decode(s[i + 1]); + } + + return bf; + } + + /** + * Gets the indexes of the set bit as an array of int. + * + * @return a list of all indices of the set bits in this field. + */ + public List getBits() { + List bits = new ArrayList(); + for (int i = 0; i < length; i++) { + if (get(i)) { + bits.add(i); + } + } + return bits; + } + + /** + * Returns a BitField with only those bits that are set in a but not in b. + * + * @param a the first field + * @param b the second field + * @return the substract field. + */ + public static BitField substract(BitField a, BitField b) { + return and(a, not(and(a, b))); + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/CommentSeparatorResult1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/CommentSeparatorResult1.java new file mode 100644 index 000000000000..8f113e82c851 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/CommentSeparatorResult1.java @@ -0,0 +1,6 @@ +public class CommentSeparatorTest1 { + + // Fields ================================================================== + + public int i; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/CommentSeparatorTest1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/CommentSeparatorTest1.java new file mode 100644 index 000000000000..4d6744b96350 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/CommentSeparatorTest1.java @@ -0,0 +1,3 @@ +public class CommentSeparatorTest1 { + public int i; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptRespacingResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptRespacingResult.java new file mode 100644 index 000000000000..a65d0d0061e1 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptRespacingResult.java @@ -0,0 +1,15 @@ +import javax.swing.*; + + +public abstract class TestCorrupt implements ComboBoxModel { + //-------------------------------------------------------------------- + //---------------------------------------------- ComboBoxModel Methods + + public Object getSelectedItem() { + return null; + } + + + public void setSelectedItem(Object p_item) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptRespacingTest.java b/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptRespacingTest.java new file mode 100644 index 000000000000..a7c0327dcec1 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptRespacingTest.java @@ -0,0 +1,12 @@ +import javax.swing.*; + + +public abstract class TestCorrupt implements ComboBoxModel { + public Object getSelectedItem() { + return null; + } + + + public void setSelectedItem(Object p_item) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptionConfig.xml b/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptionConfig.xml new file mode 100644 index 000000000000..259eabb68ecf --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/CorruptionConfig.xml @@ -0,0 +1,557 @@ + + + + \ \ \ //%FS%\n\ \ \ //%FS%\ Constants\n + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Inner\ Classes\n + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Instance\ Variables\n + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Variables\n + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Constructors\n + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Instance\ Methods\n + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Getters/Setters\n + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Public\ Methods\n + + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ %IF%\ Methods\n + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Protected/Package\ + Getters/Setters\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Protected/Package\ Methods\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Private\ Methods\n + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Inner\ Classes\n + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Variables\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Private\ Constants\n + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Instance\ Variables\n + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Main\ Method\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\n//%FS%\n//%FS%\n\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/DomainExpanderResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/DomainExpanderResult.java new file mode 100644 index 000000000000..c1aa26047f76 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/DomainExpanderResult.java @@ -0,0 +1,230 @@ +package com.carp.casper2.chitchat; + +import com.carp.nlp.lexicon.Word; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.Vector; + +/** + * Gebruikt de synoniemen lijst om onbekende woorden af te beeld op de bekende woorden uit de + * patterns. Met een synoniemen lijst breid deze de patterns uit met rules om van onbekende woorden + * op bekende te komen Hij maakt dus het (wiskundige) domein groter omdat er op meer dingen + * getriggerd wordt, vandaar de naam. Het is een beetje onhandig om door DomainExpander gemaakt + * rules weer toe te voegen. Voordat je de terminals uit een grammar haalt wil je meestal eerst die + * synoniemen rules er uit plukken.
Je stopt er een hashset met bekende dingen in en je krijgt + * een mapping terug. + * + * @author Oebele van der Veen + * @version 1.0 + */ +public class DomainExpander { + Vector baselevel = new Vector(); + + + // idee + // Er is een baseset waarop geprojecteerd moet worden + // dit gaat met een reduction graph die iteratief opgebouwd word + // reductiongraph = vector of level + // level = vector of (word,backref) + // baseset word in level 0 gezet en dan wordt elke element bij na gegaan + // is er een synoniem s van woord x dan krijgt s een ref naar x en komt s een level hoger + // daarna wordt het volgende level verwerkt. + // Als er niks meer toegevoegd kan worden, dan wordt bij elke woord uit de baseset alle synoniemen + // verzameld en wordt er een rule (synoniem1|..|synoniemx) do rewrite(woord) end van gemaakt. (collapsen) + // mischien frontref ipv backref. Dan gaat het collapsen makkelijker. laten we dat ook doen ja + // merk op dat er geen dubbelen in de reduction graph mogen voorkomen + + + // een node van de reduction tree + + Set noDubArea = new HashSet(); // elk woord gooien we ook hierin (bij reference) + + + // Dat is fijn want dan kunnen we snel doublures voorkomen + Vector reductionGraph = new Vector(); //elk element is een level met nodes + SynonymList synlist; + + /** + * Maakt een Domain Expander bij een baseset en synoniemenlijst. Gegeven de bekende woorden van de + * patterns in de baseset kan deze DomainExpander met de synoniemen nieuwe patterns maken + * + * @param baseset een HashSet met de terminals van de patterns + * @param synlist een synonymList, + */ + public DomainExpander(Set baseset, SynonymList synlist) { + // we zetten de basisset op level 0 van de reductionGraph; + setBase(baseset); + // even onthouden + this.synlist = synlist; + } + + /** + * Slaat de mapping plat zodat deze weggeschreven kan worden Als er genoeg woorden zijn toegevoegd + * dan zorgt deze functie er voor dat de data structuur wordt aangepast voor wegschrijven als + * grammar rules + */ + public void collapse() { + // de nodes van de base level hebben nu alle kinderen als hun kinderen + Vector base = (Vector)reductionGraph.firstElement(); + Node thisnode; + for (int i = 0; i < base.size(); i++) { + thisnode = (Node)base.elementAt(i); + thisnode.children = thisnode.getChildren(); // de kinderen gelijk stellen aan alle kinderen + } + } + + /** + * Voegt meer woorden toe aan de mapping. Dit ding voegt meer woorden toe aan de mapping. + * expand(3);expand(4) is hetzelfde als expand(7) + * + * @param max het maximum aantal hops door de synoniemen vanaf de bekende woorden + * @return hoeveel hops de laatste woorden echt zijn. Dit kan kleiner zijn dan max als er geen + * synoniemen meer zijn. + */ + public int expand(int max) { + int curlevels = reductionGraph.size(); + Vector newlevel; + boolean adding = true; // houd bij of er wat toegevoegd wordt, anders kunnen we ook wel stoppen. + while ((adding) && (reductionGraph.size() - curlevels) < max) { + newlevel = expandLevel((Vector)reductionGraph.lastElement()); + reductionGraph.add(newlevel); + if (newlevel.size() == 0) { + adding = false; + } + } + return reductionGraph.size() - curlevels; + } + + private Vector expandLevel(Vector level) { + System.out.println("Expanding level with " + level.size() + " elements"); + System.out.println("Strings in noDubArea: " + noDubArea.size()); + Vector synonyms; + Node thisnode, newnode; + Vector newlevel = new Vector(); + String aword; + + for (int i = 0; i < level.size(); i++) { + thisnode = ((Node)level.elementAt(i)); + synonyms = synlist.getSynonymsOf(thisnode.word); + if (synonyms != null) { + for (int s = 0; s < synonyms.size(); s++) { + aword = (String)synonyms.elementAt(s); + if (!noDubArea.contains(aword)) { + newnode = new Node(aword); //Node(s) stopts s ook direct in de noDubArea + newlevel.add(newnode); + thisnode.addChild(newnode); + } + } + } + } + return newlevel; + } + + private void setBase(Set baseSet) { + Word word; + String str; + System.out.println("Adding base set"); + if (baseSet == null) { + System.out.println("Given baseset is null"); + return; + } + Vector newlevel = new Vector(200); + Iterator iterator = baseSet.iterator(); + while (iterator.hasNext()) { + word = (Word)iterator.next(); + if (word != null) { + str = word.toString(); + if (str != null) { + newlevel.add(new Node(str)); + } + } + } + reductionGraph.add(newlevel); + System.out.println("Done"); + } + + /** + * Schrijf de synoniemen mapping naar rules. Stopt de mapping in de writer + * + * @param w een Writer waar de rules heen geschreven worden. + */ + public void writeToGrammar(Writer w) throws IOException { + BufferedWriter writer = new BufferedWriter(w); + String setting = "rule ^setIgnoreHead(true) ^setIgnoreTail(true) ^setMaxIgnored(256) end"; + String commentaar = + "// Dit bestand is automatisch gegenereert door een DomainExpander object, Het is absoluut slim hier af te blijven."; + String line; + Vector base = (Vector)reductionGraph.firstElement(); + Node thisnode; + try { + writer.write(commentaar, 0, commentaar.length()); + writer.newLine(); + writer.newLine(); + writer.newLine(); + writer.write(setting, 0, setting.length()); + writer.newLine(); + for (int i = 0; i < base.size(); i++) { + thisnode = (Node)base.elementAt(i); + line = thisnode.toParserString(); + if (line.length() > 0) { + writer.write(line, 0, line.length()); + writer.newLine(); + } + } + } + finally { + writer.close(); + } + } + + private class Node { + private Vector children = new Vector(); // de synonymen van dit woord in een hoger level + private String word; + + Node(String word) { + this.word = word; + noDubArea.add(word); // Kijk stoppen we er gewoon direct in + } + + public void addChild(Node node) { + children.add(node); + } + + //recursief alle kinderen verzamelen + public Vector getChildren() { + Vector result = new Vector(); + for (int i = 0; i < children.size(); i++) { + result.addAll(((Node)children.elementAt(i)).getChildren()); + } + result.addAll(children); + return result; + } + + public String toParserString() { + // maak een "rule (childer1|childer2...) do rewrite(word) end" + if (children.size() == 0) { + return ""; // geen kinderen, geen regel + } + if (children.size() == 1) { + return "rule \"" + ((Node)children.firstElement()).word + "\" do rewrite(" + word + ") end"; + } + StringBuffer result = new StringBuffer(); + result.append("rule ("); + for (int i = 0; i < children.size(); i++) { + if (i > 0) { + result.append("|"); + } + result.append("\""); + result.append(((Node)children.elementAt(i)).word); + result.append("\""); + } + result.append(") do rewrite(" + word + ") end"); + return result.toString(); + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/DomainExpanderTest.java b/plugins/rearranger/test/testData/com/wrq/rearranger/DomainExpanderTest.java new file mode 100644 index 000000000000..544ccf33fa0f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/DomainExpanderTest.java @@ -0,0 +1,231 @@ +package com.carp.casper2.chitchat; + +import com.carp.nlp.lexicon.Word; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.Vector; + +/** + * Gebruikt de synoniemen lijst om onbekende woorden af te beeld op de bekende woorden uit de + * patterns. Met een synoniemen lijst breid deze de patterns uit met rules om van onbekende woorden + * op bekende te komen Hij maakt dus het (wiskundige) domein groter omdat er op meer dingen + * getriggerd wordt, vandaar de naam. Het is een beetje onhandig om door DomainExpander gemaakt + * rules weer toe te voegen. Voordat je de terminals uit een grammar haalt wil je meestal eerst die + * synoniemen rules er uit plukken.
Je stopt er een hashset met bekende dingen in en je krijgt + * een mapping terug. + * + * @author Oebele van der Veen + * @version 1.0 + */ +public class DomainExpander { + Vector baselevel = new Vector(); + + + // idee + // Er is een baseset waarop geprojecteerd moet worden + // dit gaat met een reduction graph die iteratief opgebouwd word + // reductiongraph = vector of level + // level = vector of (word,backref) + // baseset word in level 0 gezet en dan wordt elke element bij na gegaan + // is er een synoniem s van woord x dan krijgt s een ref naar x en komt s een level hoger + // daarna wordt het volgende level verwerkt. + // Als er niks meer toegevoegd kan worden, dan wordt bij elke woord uit de baseset alle synoniemen + // verzameld en wordt er een rule (synoniem1|..|synoniemx) do rewrite(woord) end van gemaakt. (collapsen) + // mischien frontref ipv backref. Dan gaat het collapsen makkelijker. laten we dat ook doen ja + // merk op dat er geen dubbelen in de reduction graph mogen voorkomen + + + // een node van de reduction tree + + Set noDubArea = new HashSet(); // elk woord gooien we ook hierin (bij reference) + + + // Dat is fijn want dan kunnen we snel doublures voorkomen + Vector reductionGraph = new Vector(); //elk element is een level met nodes + SynonymList synlist; + + /** + * Maakt een Domain Expander bij een baseset en synoniemenlijst. Gegeven de bekende woorden van de + * patterns in de baseset kan deze DomainExpander met de synoniemen nieuwe patterns maken + * + * @param baseset een HashSet met de terminals van de patterns + * @param synlist een synonymList, + */ + public DomainExpander(Set baseset, SynonymList synlist) { + // we zetten de basisset op level 0 van de reductionGraph; + setBase(baseset); + // even onthouden + this.synlist = synlist; + } + + /** + * Slaat de mapping plat zodat deze weggeschreven kan worden Als er genoeg woorden zijn toegevoegd + * dan zorgt deze functie er voor dat de data structuur wordt aangepast voor wegschrijven als + * grammar rules + */ + public void collapse() { + // de nodes van de base level hebben nu alle kinderen als hun kinderen + Vector base = (Vector)reductionGraph.firstElement(); + Node thisnode; + for (int i = 0; i < base.size(); i++) { + thisnode = (Node)base.elementAt(i); + thisnode.children = thisnode.getChildren(); // de kinderen gelijk stellen aan alle kinderen + } + } + + /** + * Voegt meer woorden toe aan de mapping. Dit ding voegt meer woorden toe aan de mapping. + * expand(3);expand(4) is hetzelfde als expand(7) + * + * @param max het maximum aantal hops door de synoniemen vanaf de bekende woorden + * @return hoeveel hops de laatste woorden echt zijn. Dit kan kleiner zijn dan max als er geen + * synoniemen meer zijn. + */ + public int expand(int max) { + int curlevels = reductionGraph.size(); + Vector newlevel; + boolean adding = true; // houd bij of er wat toegevoegd wordt, anders kunnen we ook wel stoppen. + while ((adding) && (reductionGraph.size() - curlevels) < max) { + newlevel = expandLevel((Vector)reductionGraph.lastElement()); + reductionGraph.add(newlevel); + if (newlevel.size() == 0) { + adding = false; + } + } + return reductionGraph.size() - curlevels; + } + + + private Vector expandLevel(Vector level) { + System.out.println("Expanding level with " + level.size() + " elements"); + System.out.println("Strings in noDubArea: " + noDubArea.size()); + Vector synonyms; + Node thisnode, newnode; + Vector newlevel = new Vector(); + String aword; + + for (int i = 0; i < level.size(); i++) { + thisnode = ((Node)level.elementAt(i)); + synonyms = synlist.getSynonymsOf(thisnode.word); + if (synonyms != null) { + for (int s = 0; s < synonyms.size(); s++) { + aword = (String)synonyms.elementAt(s); + if (!noDubArea.contains(aword)) { + newnode = new Node(aword); //Node(s) stopts s ook direct in de noDubArea + newlevel.add(newnode); + thisnode.addChild(newnode); + } + } + } + } + return newlevel; + } + + private void setBase(Set baseSet) { + Word word; + String str; + System.out.println("Adding base set"); + if (baseSet == null) { + System.out.println("Given baseset is null"); + return; + } + Vector newlevel = new Vector(200); + Iterator iterator = baseSet.iterator(); + while (iterator.hasNext()) { + word = (Word)iterator.next(); + if (word != null) { + str = word.toString(); + if (str != null) { + newlevel.add(new Node(str)); + } + } + } + reductionGraph.add(newlevel); + System.out.println("Done"); + } + + /** + * Schrijf de synoniemen mapping naar rules. Stopt de mapping in de writer + * + * @param w een Writer waar de rules heen geschreven worden. + */ + public void writeToGrammar(Writer w) throws IOException { + BufferedWriter writer = new BufferedWriter(w); + String setting = "rule ^setIgnoreHead(true) ^setIgnoreTail(true) ^setMaxIgnored(256) end"; + String commentaar = + "// Dit bestand is automatisch gegenereert door een DomainExpander object, Het is absoluut slim hier af te blijven."; + String line; + Vector base = (Vector)reductionGraph.firstElement(); + Node thisnode; + try { + writer.write(commentaar, 0, commentaar.length()); + writer.newLine(); + writer.newLine(); + writer.newLine(); + writer.write(setting, 0, setting.length()); + writer.newLine(); + for (int i = 0; i < base.size(); i++) { + thisnode = (Node)base.elementAt(i); + line = thisnode.toParserString(); + if (line.length() > 0) { + writer.write(line, 0, line.length()); + writer.newLine(); + } + } + } + finally { + writer.close(); + } + } + + private class Node { + private Vector children = new Vector(); // de synonymen van dit woord in een hoger level + private String word; + + Node(String word) { + this.word = word; + noDubArea.add(word); // Kijk stoppen we er gewoon direct in + } + + public void addChild(Node node) { + children.add(node); + } + + //recursief alle kinderen verzamelen + public Vector getChildren() { + Vector result = new Vector(); + for (int i = 0; i < children.size(); i++) { + result.addAll(((Node)children.elementAt(i)).getChildren()); + } + result.addAll(children); + return result; + } + + public String toParserString() { + // maak een "rule (childer1|childer2...) do rewrite(word) end" + if (children.size() == 0) { + return ""; // geen kinderen, geen regel + } + if (children.size() == 1) { + return "rule \"" + ((Node)children.firstElement()).word + "\" do rewrite(" + word + ") end"; + } + StringBuffer result = new StringBuffer(); + result.append("rule ("); + for (int i = 0; i < children.size(); i++) { + if (i > 0) { + result.append("|"); + } + result.append("\""); + result.append(((Node)children.elementAt(i)).word); + result.append("\""); + } + result.append(") do rewrite(" + word + ") end"); + return result.toString(); + } + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/Enum1Result.java b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum1Result.java new file mode 100644 index 000000000000..3d662839533a --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum1Result.java @@ -0,0 +1,715 @@ +/** + * $id + * Author: Dave Kriewall + * Created: Oct 20, 2005 + * Copyright 2004, WRQ, Inc. + */ +package com.wrq.rearranger.testClasses; + +import com.intellij.codeInspection.dataFlow.DataFlowRunner; + +import javax.swing.tree.TreePath; +import java.io.File; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** + * Created by IntelliJ IDEA. User: JJohnson Date: Aug 30, 2005 Time: 11:06:54 AM To change this template use File | + * Settings | File Templates. + */ +public class Enum1Test implements Cloneable { +// ------------------------------ FIELDS ------------------------------ + + private static final String STEREOTYPE_PREFIX = "STEREOTYPE_"; + private Enum1Test parent = null; + private SuiteModel suiteModel; + private SuiteItem storage; + private List childNodes = new ArrayList(10); + +// -------------------------- STATIC METHODS -------------------------- + + public static Stereotype getStereotype(String stStr) { + return null; + } + +// --------------------------- CONSTRUCTORS --------------------------- + + public Enum1Test(SuiteModel model, Stereotype type) { + } + +// --------------------- GETTER / SETTER METHODS --------------------- + + public Enum1Test getParent() { + return parent; + } + + public ExecutionState getState() { + ExecutionState state = ExecutionState.UNTESTED; + if (storage.getInstructionItem() != null) { + byte[] receipt = getInstructionItem().getReceipt(); + if (receipt != null) { + byte[] expectedReceipt = getInstructionItem().getExpectedReceipt(); + if (expectedReceipt == null) { + state = ExecutionState.FAILED; + } + else if (receipt.length != expectedReceipt.length) { + state = ExecutionState.FAILED; + } + else { + state = ExecutionState.PASSED; + for (int i = 0; i < receipt.length; i++) { + if (receipt[i] != expectedReceipt[i]) { + state = ExecutionState.FAILED; + break; + } + } + } + } + } + return state; + } + + public SuiteItem getStorage() { + return storage; + } + +// ------------------------ CANONICAL METHODS ------------------------ + + public Object clone() throws CloneNotSupportedException { + try { + return super.clone(); + } + catch (final CloneNotSupportedException e) { + return null; + } + } + + public String toString() { + return getName(); + } + + public String getName() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return getInstruction(getInstructionItem().getInstructionRef()).getName(); + } + return storage.getName(); + } + +// -------------------------- OTHER METHODS -------------------------- + + public void add(Enum1Test appendingNode, boolean createStorage) { + childNodes.add(appendingNode); + appendingNode.setParent(this, createStorage); + } + + public void setParent(Enum1Test parent, boolean createStorage) { + Enum1Test oldParent = this.parent; + this.parent = parent; + if (createStorage) { + parent.addChild(this); + } + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_PARENT, oldParent, parent, this); + } + + private void addChild(Enum1Test childNode) { + storage.addSuiteItem(childNode.getStorage()); + } + + public void add(Enum1Test insertingNode, Enum1Test selection) { + childNodes.add(childNodes.indexOf(selection) + 1, insertingNode); + insertingNode.setParent(this, true); + } + + public void add(int index, Enum1Test t) { + t.setParent(this, true); + childNodes.add(index, t); + } + + public boolean canMove(Direction direction) { + switch (direction) { + case UP: + return (getNextUp() != null); + case DOWN: + return (getNextDown() != null); + } + return false; + } + + public Enum1Test getNextUp() { + if (getStereotype().equals(Stereotype.STEREOTYPE_ROOT)) { + return null; + } + Enum1Test nextUpNode; + if (isFirstChild()) { +// nextUpNode = getParent().getNextUp(); + nextUpNode = getParent().getNextDown(); + } + else { + int newIndexUp = indexOf() - 1; + nextUpNode = (Enum1Test)getParent().getChild(newIndexUp); + } + return nextUpNode; + } + + public boolean isFirstChild() { + return indexOf() == 0; + } + + /** Get index of this node within its parents children list. */ + public int indexOf() { + Enum1Test parent = getParent(); + if (parent == null) { + return 0; + } + return parent.indexOf(this); + } + + public Object getChild(int index) { + return childNodes.get(index); + } + + public Enum1Test getNextDown() { + if (getStereotype().equals(Stereotype.STEREOTYPE_ROOT)) { + return null; + } + Enum1Test nextDownNode; + if (isLastChild()) { +// nextDownNode = getParent().getNextDown(); + nextDownNode = getParent().getNextUp(); + } + else { + int newIndexDown = indexOf() + 1; + nextDownNode = (Enum1Test)getParent().getChild(newIndexDown); + } + return nextDownNode; + } + + public boolean isLastChild() { + if (parent == null) { + return true; // root is an only-child + } + int indexOf = indexOf(); + return (indexOf == parent.getChildCount() - 1); + } + + public int getChildCount() { + return childNodes.size(); + } + + public void execute() { + // Repeat this node -iterations- times + for (int repeatCount = 0; repeatCount < getIterations(); repeatCount++) { + if (getStereotype().equals(Enum1Test.Stereotype.STEREOTYPE_INSTRUCTION)) { + executeInstruction(); + } + else { + executeChildren(); + } + // Pause after each execution this number of milliseconds before continuing + try { + Thread.sleep(getDelay()); + } + catch (InterruptedException e) { + e.printStackTrace(); // todo - logger + } + } + } + + public int getIterations() { + return storage.getIterations(); + } + + private void executeInstruction() { + } + + private void executeChildren() { + Enum1Test[] children = getChildren(); + for (Enum1Test node : children) { + node.execute(); // recursive execution for nested groups of instructions. + } + } + + public Enum1Test[] getChildren() { + return childNodes.toArray(new Enum1Test[]{}); + } + + public long getDelay() { + return storage.getDelay(); + } + + private String getExpectedReceiptString() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return Utilities.toString(getInstructionItem().getExpectedReceipt()); + } + return ""; + } + + public Instruction getInstruction() { + String id = this.getInstructionItem().getInstructionRef(); + return getInstruction(id); + } + + public ByteBuffer getPacketToSend() { + return getPacketToSend(getInstructionItem()); + } + + private ByteBuffer getPacketToSend(InstructionItem instruction) { + return null; + } + + public String getParameter() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return getInstructionItem().getParameter(); + } + return ""; + } + + public TreePath getPath() { + List parents = new ArrayList(20); + for (Enum1Test node = this; node != null; node = node.getParent()) { + parents.add(node); + } + Collections.reverse(parents); + return new TreePath(parents.toArray(new Enum1Test[0])); + } + + public String getReceiptString() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return Utilities.toString(getInstructionItem().getReceipt()); + } + return ""; + } + + public String getStateText() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + ExecutionState state = getState(); + switch (state) { + case UNTESTED: + return "Untested"; + case PASSED: + return "Passed"; + case FAILED: + return "Failed"; + } + } + return this.getPassed() + " / " + this.getFailed() + " of " + this.getTotalInstructions(); + } + + public int getTotalInstructions() { + int count = 0; + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + count++; + } + for (Enum1Test t : childNodes) { + if (!getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + count += t.getTotalInstructions(); + } + } + return count; + } + + public int getFailed() { + int count = 0; + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + if (getState().equals(ExecutionState.FAILED)) { + count++; + } + } + else { + for (Enum1Test t : childNodes) { + count += t.getFailed(); + } + } + return count; + } + + public int getPassed() { + int count = 0; + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + if (getState().equals(ExecutionState.PASSED)) { + count++; + } + } + else { + for (Enum1Test t : childNodes) { + count += t.getPassed(); + } + } + return count; + } + + public String getStateText(boolean firstCap) { + String stateText; + switch (getState()) { + case UNTESTED: + stateText = "untested"; + break; + case PASSED: + stateText = "passed"; + break; + case FAILED: + stateText = "failed"; + break; + default: + stateText = "** unknown **"; + } + return stateText; + } + + public String getToolTip() { + StringBuilder tt = new StringBuilder(200); + tt.append(""); + switch (getStereotype()) { + case STEREOTYPE_ROOT: + buildRootToolTip(tt); + break; + case STEREOTYPE_GROUP: + buildGroupToolTip(tt); + break; + case STEREOTYPE_INSTRUCTION: + buildInstructionToolTip(tt); + break; + } + buildRunInfoToolTip(tt); + tt.append(""); + return tt.toString(); + } + + public Stereotype getStereotype() { + return null; + } + + private void buildRootToolTip(StringBuilder tt) { + String author = suiteModel.getAuthor(); + String desc = getDescription(); + String filePath = suiteModel.hasStorage() ? suiteModel.getStorageFile().getAbsolutePath() : null; + if (author != null && author.length() > 0) { + tt.append(author).append("

"); + } + if (desc != null && desc.length() > 0) { + tt.append(desc).append("

"); + } + if (filePath != null && filePath.length() > 0) { + tt.append(filePath).append("

"); + } + } + + private void buildGroupToolTip(StringBuilder tt) { + String desc = getDescription(); + if (desc != null && desc.length() > 0) { + tt.append(desc).append("

"); + } + } + + public String getDescription() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return getInstruction(getInstructionItem().getInstructionRef()).getDescription(); + } + return storage.getDescription(); + } + + private void buildInstructionToolTip(StringBuilder tt) { + InstructionItem inst = getInstructionItem(); + if (inst != null) { + String id = inst.getInstructionRef(); + Instruction instruction = getInstruction(id); + tt.append("Command: ").append(instruction.getCommand()).append("

"); + } + tt.append("Parameter: ").append(getParameter()).append("

"); + tt.append("Received: ").append(getReceiptString()).append("

"); + tt.append("Expected: ").append(getExpectedReceiptString()).append("

"); + } + + public InstructionItem getInstructionItem() { + return storage.getInstructionItem(); + } + + public Instruction getInstruction(String id) { + return null; + } + + private void buildRunInfoToolTip(StringBuilder tt) { + tt.append("


"); // a divider line + tt.append("Iterations: ").append(getIterations()).append("

"); + tt.append("Pause: ").append(getDelay()).append("

"); + tt.append("State: ").append(getStateText()).append("

"); // todo add state color getStatecolor()... + tt.append("Duration: ").append(getDuration()).append("

"); + tt.append("Executed: ").append(getLastTested()).append("

"); + } + + public boolean hasChildren() { + return childNodes.size() > 0; + } + + public int indexOf(Enum1Test t) { + return childNodes.indexOf(t); + } + + public boolean isGroup() { + return getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION); + } + + public void remove(Enum1Test node) { + childNodes.remove(node); + // node.setParent(null); + } + + public void setDelay(long delay) { + long oldDelay = storage.getDelay(); + storage.setDelay(delay); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_DELAY, oldDelay, delay, this); + } + + public void setDescription(String description) { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return; // name is fixed for instructions + } + String oldDescription = storage.getDescription(); + storage.setDescription(description); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_DESC, oldDescription, description, this); + } + + public void setDuration(long duration) { + if (!getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return; // name is fixed anything execept instructions + } + long oldDuration = getDuration(); + storage.setDuration(duration); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_DURATION, oldDuration, duration, this); + } + + public long getDuration() { + long durationSum = 0; + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + durationSum += storage.getDuration(); + } + else { + for (Enum1Test t : childNodes) { + durationSum += t.getDuration(); + } + } + return durationSum; + } + + public void setExpectedReceipt(byte[] newValue) { + } + + public void setInstructionItem(InstructionItem instruction) { + InstructionItem oldInstruction = this.getInstructionItem(); + storage.setInstructionItem(instruction); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_INSTRUCTION, oldInstruction, instruction, this); + } + + public void setIterations(int iterations) { + int oldIterations = storage.getIterations(); + storage.setIterations(iterations); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_ITERATIONS, oldIterations, iterations, this); + } + + public void setLastTested(Date lastTested) { + Date oldLastTested = getLastTested(); + storage.setLastTested(new Date()); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_LAST_TESTED, oldLastTested, lastTested, this); + } + + public Date getLastTested() { + Date date = storage.getLastTested(); + return date == null ? null : date; + } + + public void setName(String name) { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return; // name is fixed for instructions + } + String oldName = storage.getName(); + storage.setName(name); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_NAME, oldName, name, this); + } + + public void setParameter(String value) { + } + + private void setStereotype(Stereotype type) { + } + + public void setStorage(SuiteItem suiteItem) { + } + +// -------------------------- ENUMERATIONS -------------------------- + + public enum ExecutionState { + PASSED, FAILED, UNTESTED + } + + public enum Stereotype { + STEREOTYPE_ROOT, STEREOTYPE_GROUP, STEREOTYPE_INSTRUCTION + } + + public enum Direction { + UP, DOWN + } +} + +class InstructionItem { +// -------------------------- OTHER METHODS -------------------------- + + public byte[] getExpectedReceipt() { + return new byte[0]; //To change body of created methods use File | Settings | File Templates. + } + + public String getInstructionRef() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public String getParameter() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public byte[] getReceipt() { + return null; + } + + public void setExpectedReceipt(byte[] newValue) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setParameter(String value) { + //To change body of created methods use File | Settings | File Templates. + } +} + +class Instruction { +// -------------------------- OTHER METHODS -------------------------- + + public String getCommand() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public String getDescription() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public String getName() { + return null; //To change body of created methods use File | Settings | File Templates. + } +} + +class SuiteModel { +// ------------------------------ FIELDS ------------------------------ + + public static final Object EVT_TOPIC_EXPECTED_RECEIPT = ""; + public static final Object EVT_TOPIC_PARAMETER = ""; + public static final Object EVT_TOPIC_PARENT = ""; + public static final Object EVT_TOPIC_DELAY = ""; + public static Object EVT_TOPIC_DESC = ""; + public static Object EVT_TOPIC_DURATION = ""; + public static Object EVT_TOPIC_INSTRUCTION = ""; + public static Object EVT_TOPIC_ITERATIONS = ""; + public static Object EVT_TOPIC_LAST_TESTED = ""; + public static Object EVT_TOPIC_NAME = ""; + +// -------------------------- OTHER METHODS -------------------------- + + public void fireChangeEvent(Object p0, Object oldValue, Object newValue, Enum1Test testEnum) { + //To change body of created methods use File | Settings | File Templates. + } + + public String getAuthor() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public DataFlowRunner getInstructionSet() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public File getStorageFile() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public boolean hasStorage() { + return false; //To change body of created methods use File | Settings | File Templates. + } +} + +class SuiteItem { +// -------------------------- OTHER METHODS -------------------------- + + public void addSuiteItem(SuiteItem storage) { + //To change body of created methods use File | Settings | File Templates. + } + + public long getDelay() { + return 0; //To change body of created methods use File | Settings | File Templates. + } + + public String getDescription() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public long getDuration() { + return 0; //To change body of created methods use File | Settings | File Templates. + } + + public InstructionItem getInstructionItem() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public int getIterations() { + return 0; //To change body of created methods use File | Settings | File Templates. + } + + public Date getLastTested() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public String getName() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public String getStereotype() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public void setDelay(long delay) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setDescription(String description) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setDuration(long duration) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setInstructionItem(InstructionItem instruction) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setIterations(int i) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setLastTested(Date date) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setName(String name) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setStereotype(String s) { + //To change body of created methods use File | Settings | File Templates. + } +} + +class Utilities { +// -------------------------- STATIC METHODS -------------------------- + + public static String toString(Object receipt) { + return null; //To change body of created methods use File | Settings | File Templates. + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/Enum1Test.java b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum1Test.java new file mode 100644 index 000000000000..a6c07a06482d --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum1Test.java @@ -0,0 +1,696 @@ +/** + * $id + * Author: Dave Kriewall + * Created: Oct 20, 2005 + * Copyright 2004, WRQ, Inc. + */ +package com.wrq.rearranger.testClasses; + +import com.intellij.codeInspection.dataFlow.DataFlowRunner; + +import javax.swing.tree.TreePath; +import java.io.File; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** + * Created by IntelliJ IDEA. User: JJohnson Date: Aug 30, 2005 Time: 11:06:54 AM To change this template use File | + * Settings | File Templates. + */ +public class Enum1Test implements Cloneable { + private static final String STEREOTYPE_PREFIX = "STEREOTYPE_"; + + public void setExpectedReceipt(byte[] newValue) { + } + + public void setParameter(String value) { + } + + public void setStorage(SuiteItem suiteItem) { + } + + // ------------------------------ FIELDS ------------------------------ + public enum ExecutionState { + PASSED, FAILED, UNTESTED + } + + private Enum1Test parent = null; + private SuiteModel suiteModel; + private SuiteItem storage; + private List childNodes = new ArrayList(10); + + // --------------------------- CONSTRUCTORS --------------------------- + public Enum1Test(SuiteModel model, Stereotype type) { + } + + // --------------------- GETTER / SETTER METHODS --------------------- + private void setStereotype(Stereotype type) { + } + + public Stereotype getStereotype() { + return null; + } + + public static Stereotype getStereotype(String stStr) { + return null; + } + + public long getDelay() { + return storage.getDelay(); + } + + public InstructionItem getInstructionItem() { + return storage.getInstructionItem(); + } + + public int getIterations() { + return storage.getIterations(); + } + + public Date getLastTested() { + Date date = storage.getLastTested(); + return date == null ? null : date; + } + + public String getName() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return getInstruction(getInstructionItem().getInstructionRef()).getName(); + } + return storage.getName(); + } + + public Enum1Test getParent() { + return parent; + } + + // ------------------------ CANONICAL METHODS ------------------------ + public Object clone() throws CloneNotSupportedException { + try { + return super.clone(); + } + catch (final CloneNotSupportedException e) { + return null; + } + } + + public String toString() { + return getName(); + } + + // -------------------------- OTHER METHODS -------------------------- + public void add(Enum1Test appendingNode, boolean createStorage) { + childNodes.add(appendingNode); + appendingNode.setParent(this, createStorage); + } + + public void add(Enum1Test insertingNode, Enum1Test selection) { + childNodes.add(childNodes.indexOf(selection) + 1, insertingNode); + insertingNode.setParent(this, true); + } + + public void add(int index, Enum1Test t) { + t.setParent(this, true); + childNodes.add(index, t); + } + + public void setParent(Enum1Test parent, boolean createStorage) { + Enum1Test oldParent = this.parent; + this.parent = parent; + if (createStorage) { + parent.addChild(this); + } + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_PARENT, oldParent, parent, this); + } + + private void addChild(Enum1Test childNode) { + storage.addSuiteItem(childNode.getStorage()); + } + + public SuiteItem getStorage() { + return storage; + } + + public boolean canMove(Direction direction) { + switch (direction) { + case UP: + return (getNextUp() != null); + case DOWN: + return (getNextDown() != null); + } + return false; + } + + public Enum1Test getNextUp() { + if (getStereotype().equals(Stereotype.STEREOTYPE_ROOT)) { + return null; + } + Enum1Test nextUpNode; + if (isFirstChild()) { +// nextUpNode = getParent().getNextUp(); + nextUpNode = getParent().getNextDown(); + } + else { + int newIndexUp = indexOf() - 1; + nextUpNode = (Enum1Test)getParent().getChild(newIndexUp); + } + return nextUpNode; + } + + public boolean isFirstChild() { + return indexOf() == 0; + } + + /** Get index of this node within its parents children list. */ + public int indexOf() { + Enum1Test parent = getParent(); + if (parent == null) { + return 0; + } + return parent.indexOf(this); + } + + public Object getChild(int index) { + return childNodes.get(index); + } + + public Enum1Test getNextDown() { + if (getStereotype().equals(Stereotype.STEREOTYPE_ROOT)) { + return null; + } + Enum1Test nextDownNode; + if (isLastChild()) { +// nextDownNode = getParent().getNextDown(); + nextDownNode = getParent().getNextUp(); + } + else { + int newIndexDown = indexOf() + 1; + nextDownNode = (Enum1Test)getParent().getChild(newIndexDown); + } + return nextDownNode; + } + + public boolean isLastChild() { + if (parent == null) { + return true; // root is an only-child + } + int indexOf = indexOf(); + return (indexOf == parent.getChildCount() - 1); + } + + public int getChildCount() { + return childNodes.size(); + } + + public Enum1Test[] getChildren() { + return childNodes.toArray(new Enum1Test[]{}); + } + + public String getDescription() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return getInstruction(getInstructionItem().getInstructionRef()).getDescription(); + } + return storage.getDescription(); + } + + public long getDuration() { + long durationSum = 0; + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + durationSum += storage.getDuration(); + } + else { + for (Enum1Test t : childNodes) { + durationSum += t.getDuration(); + } + } + return durationSum; + } + + public String getParameter() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return getInstructionItem().getParameter(); + } + return ""; + } + + public TreePath getPath() { + List parents = new ArrayList(20); + for (Enum1Test node = this; node != null; node = node.getParent()) { + parents.add(node); + } + Collections.reverse(parents); + return new TreePath(parents.toArray(new Enum1Test[0])); + } + + public String getReceiptString() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return Utilities.toString(getInstructionItem().getReceipt()); + } + return ""; + } + + public ExecutionState getState() { + ExecutionState state = ExecutionState.UNTESTED; + if (storage.getInstructionItem() != null) { + byte[] receipt = getInstructionItem().getReceipt(); + if (receipt != null) { + byte[] expectedReceipt = getInstructionItem().getExpectedReceipt(); + if (expectedReceipt == null) { + state = ExecutionState.FAILED; + } + else if (receipt.length != expectedReceipt.length) { + state = ExecutionState.FAILED; + } + else { + state = ExecutionState.PASSED; + for (int i = 0; i < receipt.length; i++) { + if (receipt[i] != expectedReceipt[i]) { + state = ExecutionState.FAILED; + break; + } + } + } + } + } + return state; + } + + public String getStateText() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + ExecutionState state = getState(); + switch (state) { + case UNTESTED: + return "Untested"; + case PASSED: + return "Passed"; + case FAILED: + return "Failed"; + } + } + return this.getPassed() + " / " + this.getFailed() + " of " + this.getTotalInstructions(); + } + + public int getPassed() { + int count = 0; + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + if (getState().equals(ExecutionState.PASSED)) { + count++; + } + } + else { + for (Enum1Test t : childNodes) { + count += t.getPassed(); + } + } + return count; + } + + public int getFailed() { + int count = 0; + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + if (getState().equals(ExecutionState.FAILED)) { + count++; + } + } + else { + for (Enum1Test t : childNodes) { + count += t.getFailed(); + } + } + return count; + } + + public int getTotalInstructions() { + int count = 0; + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + count++; + } + for (Enum1Test t : childNodes) { + if (!getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + count += t.getTotalInstructions(); + } + } + return count; + } + + public String getToolTip() { + StringBuilder tt = new StringBuilder(200); + tt.append(""); + switch (getStereotype()) { + case STEREOTYPE_ROOT: + buildRootToolTip(tt); + break; + case STEREOTYPE_GROUP: + buildGroupToolTip(tt); + break; + case STEREOTYPE_INSTRUCTION: + buildInstructionToolTip(tt); + break; + } + buildRunInfoToolTip(tt); + tt.append(""); + return tt.toString(); + } + + private void buildRunInfoToolTip(StringBuilder tt) { + tt.append("


"); // a divider line + tt.append("Iterations: ").append(getIterations()).append("

"); + tt.append("Pause: ").append(getDelay()).append("

"); + tt.append("State: ").append(getStateText()).append("

"); // todo add state color getStatecolor()... + tt.append("Duration: ").append(getDuration()).append("

"); + tt.append("Executed: ").append(getLastTested()).append("

"); + } + + private void buildInstructionToolTip(StringBuilder tt) { + InstructionItem inst = getInstructionItem(); + if (inst != null) { + String id = inst.getInstructionRef(); + Instruction instruction = getInstruction(id); + tt.append("Command: ").append(instruction.getCommand()).append("

"); + } + tt.append("Parameter: ").append(getParameter()).append("

"); + tt.append("Received: ").append(getReceiptString()).append("

"); + tt.append("Expected: ").append(getExpectedReceiptString()).append("

"); + } + + private String getExpectedReceiptString() { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return Utilities.toString(getInstructionItem().getExpectedReceipt()); + } + return ""; + } + + private void buildGroupToolTip(StringBuilder tt) { + String desc = getDescription(); + if (desc != null && desc.length() > 0) { + tt.append(desc).append("

"); + } + } + + private void buildRootToolTip(StringBuilder tt) { + String author = suiteModel.getAuthor(); + String desc = getDescription(); + String filePath = suiteModel.hasStorage() ? suiteModel.getStorageFile().getAbsolutePath() : null; + if (author != null && author.length() > 0) { + tt.append(author).append("

"); + } + if (desc != null && desc.length() > 0) { + tt.append(desc).append("

"); + } + if (filePath != null && filePath.length() > 0) { + tt.append(filePath).append("

"); + } + } + + public boolean hasChildren() { + return childNodes.size() > 0; + } + + public int indexOf(Enum1Test t) { + return childNodes.indexOf(t); + } + + public boolean isGroup() { + return getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION); + } + + public void remove(Enum1Test node) { + childNodes.remove(node); + // node.setParent(null); + } + + public void setDelay(long delay) { + long oldDelay = storage.getDelay(); + storage.setDelay(delay); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_DELAY, oldDelay, delay, this); + } + + public void setDescription(String description) { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return; // name is fixed for instructions + } + String oldDescription = storage.getDescription(); + storage.setDescription(description); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_DESC, oldDescription, description, this); + } + + public void setDuration(long duration) { + if (!getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return; // name is fixed anything execept instructions + } + long oldDuration = getDuration(); + storage.setDuration(duration); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_DURATION, oldDuration, duration, this); + } + + public void setInstructionItem(InstructionItem instruction) { + InstructionItem oldInstruction = this.getInstructionItem(); + storage.setInstructionItem(instruction); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_INSTRUCTION, oldInstruction, instruction, this); + } + + public void setIterations(int iterations) { + int oldIterations = storage.getIterations(); + storage.setIterations(iterations); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_ITERATIONS, oldIterations, iterations, this); + } + + public void setLastTested(Date lastTested) { + Date oldLastTested = getLastTested(); + storage.setLastTested(new Date()); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_LAST_TESTED, oldLastTested, lastTested, this); + } + + public void setName(String name) { + if (getStereotype().equals(Stereotype.STEREOTYPE_INSTRUCTION)) { + return; // name is fixed for instructions + } + String oldName = storage.getName(); + storage.setName(name); + suiteModel.fireChangeEvent(SuiteModel.EVT_TOPIC_NAME, oldName, name, this); + } + + // -------------------------- INNER CLASSES -------------------------- + public enum Stereotype { + STEREOTYPE_ROOT, STEREOTYPE_GROUP, STEREOTYPE_INSTRUCTION + } + + public enum Direction { + UP, DOWN + } + + public void execute() { + // Repeat this node -iterations- times + for (int repeatCount = 0; repeatCount < getIterations(); repeatCount++) { + if (getStereotype().equals(Enum1Test.Stereotype.STEREOTYPE_INSTRUCTION)) { + executeInstruction(); + } + else { + executeChildren(); + } + // Pause after each execution this number of milliseconds before continuing + try { + Thread.sleep(getDelay()); + } + catch (InterruptedException e) { + e.printStackTrace(); // todo - logger + } + } + } + + private void executeChildren() { + Enum1Test[] children = getChildren(); + for (Enum1Test node : children) { + node.execute(); // recursive execution for nested groups of instructions. + } + } + + private void executeInstruction() { + } + + private ByteBuffer getPacketToSend(InstructionItem instruction) { + return null; + } + + public ByteBuffer getPacketToSend() { + return getPacketToSend(getInstructionItem()); + } + + public String getStateText(boolean firstCap) { + String stateText; + switch (getState()) { + case UNTESTED: + stateText = "untested"; + break; + case PASSED: + stateText = "passed"; + break; + case FAILED: + stateText = "failed"; + break; + default: + stateText = "** unknown **"; + } + return stateText; + } + + public Instruction getInstruction(String id) { + return null; + } + + public Instruction getInstruction() { + String id = this.getInstructionItem().getInstructionRef(); + return getInstruction(id); + } +} + +class InstructionItem { + public byte[] getExpectedReceipt() { + return new byte[0]; //To change body of created methods use File | Settings | File Templates. + } + + public void setExpectedReceipt(byte[] newValue) { + //To change body of created methods use File | Settings | File Templates. + } + + public String getParameter() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public void setParameter(String value) { + //To change body of created methods use File | Settings | File Templates. + } + + public String getInstructionRef() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public byte[] getReceipt() { + return null; + } +} + +class Instruction { + public String getName() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public String getDescription() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public String getCommand() { + return null; //To change body of created methods use File | Settings | File Templates. + } +} + +class SuiteModel { + public static final Object EVT_TOPIC_EXPECTED_RECEIPT = ""; + public static final Object EVT_TOPIC_PARAMETER = ""; + public static final Object EVT_TOPIC_PARENT = ""; + public static final Object EVT_TOPIC_DELAY = ""; + public static Object EVT_TOPIC_DESC = ""; + public static Object EVT_TOPIC_DURATION = ""; + public static Object EVT_TOPIC_INSTRUCTION = ""; + public static Object EVT_TOPIC_ITERATIONS = ""; + public static Object EVT_TOPIC_LAST_TESTED = ""; + public static Object EVT_TOPIC_NAME = ""; + + public void fireChangeEvent(Object p0, Object oldValue, Object newValue, Enum1Test testEnum) { + //To change body of created methods use File | Settings | File Templates. + } + + public String getAuthor() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public boolean hasStorage() { + return false; //To change body of created methods use File | Settings | File Templates. + } + + public File getStorageFile() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public DataFlowRunner getInstructionSet() { + return null; //To change body of created methods use File | Settings | File Templates. + } +} + +class SuiteItem { + public void setIterations(int i) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setStereotype(String s) { + //To change body of created methods use File | Settings | File Templates. + } + + public String getStereotype() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public long getDelay() { + return 0; //To change body of created methods use File | Settings | File Templates. + } + + public InstructionItem getInstructionItem() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public int getIterations() { + return 0; //To change body of created methods use File | Settings | File Templates. + } + + public Date getLastTested() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public String getName() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public void addSuiteItem(SuiteItem storage) { + //To change body of created methods use File | Settings | File Templates. + } + + public String getDescription() { + return null; //To change body of created methods use File | Settings | File Templates. + } + + public long getDuration() { + return 0; //To change body of created methods use File | Settings | File Templates. + } + + public void setDelay(long delay) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setDescription(String description) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setDuration(long duration) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setInstructionItem(InstructionItem instruction) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setLastTested(Date date) { + //To change body of created methods use File | Settings | File Templates. + } + + public void setName(String name) { + //To change body of created methods use File | Settings | File Templates. + } +} + +class Utilities { + public static String toString(Object receipt) { + return null; //To change body of created methods use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2AResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2AResult.java new file mode 100644 index 000000000000..2b078c110cbf --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2AResult.java @@ -0,0 +1,26 @@ +class Enum2Test { +// -------------------------- ENUMERATIONS -------------------------- + + /** Presentation Events. */ + public enum Event { + barcodeBorder, + htmlResponse; + } + + public enum Event2 { + barcodeBorder, + htmlResponse + } + + ; + + enum Coin { + Nickel(5), + Dime(10); + final int value; + + Coin(int value) { + this.value = value; + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2Result.java b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2Result.java new file mode 100644 index 000000000000..a7326ea7056b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2Result.java @@ -0,0 +1,31 @@ +class Enum2Test { +// -------------------------- ENUMERATIONS -------------------------- + + /** Presentation Events. */ + public enum Event { + barcodeBorder, + htmlResponse; + } + + public enum Event2 { + barcodeBorder, + htmlResponse + } + + ; + + enum Coin { + Nickel(5), + Dime(10); + +// ------------------------------ FIELDS ------------------------------ + + final int value; + +// --------------------------- CONSTRUCTORS --------------------------- + + Coin(int value) { + this.value = value; + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2Test.java b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2Test.java new file mode 100644 index 000000000000..3eae2a547765 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/Enum2Test.java @@ -0,0 +1,24 @@ +class Enum2Test { + /** Presentation Events. */ + public enum Event { + barcodeBorder, + htmlResponse; + } + + public enum Event2 { + barcodeBorder, + htmlResponse + } + + ; + + enum Coin { + Nickel(5), + Dime(10); + final int value; + + Coin(int value) { + this.value = value; + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/GenericsResult1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/GenericsResult1.java new file mode 100644 index 000000000000..16b18c44c73d --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/GenericsResult1.java @@ -0,0 +1,8 @@ +public class TestGenerics { + //-------------------------------------------------------------------- + //------------------------------------------ Protected/Package Methods + + static T test() { + return null; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/GenericsTest1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/GenericsTest1.java new file mode 100644 index 000000000000..8322066c1ab1 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/GenericsTest1.java @@ -0,0 +1,5 @@ +public class TestGenerics { + static T test() { + return null; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/GetFieldReturnsFieldResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/GetFieldReturnsFieldResult.java new file mode 100644 index 000000000000..a0f03cfacfab --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/GetFieldReturnsFieldResult.java @@ -0,0 +1,33 @@ +public class GetterDefinitionTest { + /** name: matches field; body: returns field */ + public int getField2() { + return field2; + } + + int dummyField; + int field; + int field2; + + /** name: correct prefix; body: immaterial */ + public int getY() { + dummyField++; + return dummyField; + } + + /** name: correct prefix; body: returns */ + public int getX() { + return field + 1; + } + + /** name: correct prefix; body: returns field */ + public int getZ() { + return field; + } + + /** name: matches field; body: returns */ + public int getField() { + return field + 1; + } + + int dummyField2; +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/GetFieldReturnsResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/GetFieldReturnsResult.java new file mode 100644 index 000000000000..a0f03cfacfab --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/GetFieldReturnsResult.java @@ -0,0 +1,33 @@ +public class GetterDefinitionTest { + /** name: matches field; body: returns field */ + public int getField2() { + return field2; + } + + int dummyField; + int field; + int field2; + + /** name: correct prefix; body: immaterial */ + public int getY() { + dummyField++; + return dummyField; + } + + /** name: correct prefix; body: returns */ + public int getX() { + return field + 1; + } + + /** name: correct prefix; body: returns field */ + public int getZ() { + return field; + } + + /** name: matches field; body: returns */ + public int getField() { + return field + 1; + } + + int dummyField2; +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixImmaterialResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixImmaterialResult.java new file mode 100644 index 000000000000..4e4b1508b8b1 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixImmaterialResult.java @@ -0,0 +1,32 @@ +public class GetterDefinitionTest { + /** name: correct prefix; body: immaterial */ + public int getY() { + dummyField++; + return dummyField; + } + + /** name: correct prefix; body: returns */ + public int getX() { + return field + 1; + } + + /** name: correct prefix; body: returns field */ + public int getZ() { + return field; + } + + /** name: matches field; body: returns */ + public int getField() { + return field + 1; + } + + /** name: matches field; body: returns field */ + public int getField2() { + return field2; + } + + int dummyField; + int field; + int field2; + int dummyField2; +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixReturnsFieldResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixReturnsFieldResult.java new file mode 100644 index 000000000000..a0f03cfacfab --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixReturnsFieldResult.java @@ -0,0 +1,33 @@ +public class GetterDefinitionTest { + /** name: matches field; body: returns field */ + public int getField2() { + return field2; + } + + int dummyField; + int field; + int field2; + + /** name: correct prefix; body: immaterial */ + public int getY() { + dummyField++; + return dummyField; + } + + /** name: correct prefix; body: returns */ + public int getX() { + return field + 1; + } + + /** name: correct prefix; body: returns field */ + public int getZ() { + return field; + } + + /** name: matches field; body: returns */ + public int getField() { + return field + 1; + } + + int dummyField2; +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixReturnsResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixReturnsResult.java new file mode 100644 index 000000000000..07e95ab15c4f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/GetPrefixReturnsResult.java @@ -0,0 +1,33 @@ +public class GetterDefinitionTest { + /** name: correct prefix; body: returns */ + public int getX() { + return field + 1; + } + + /** name: correct prefix; body: returns field */ + public int getZ() { + return field; + } + + /** name: matches field; body: returns */ + public int getField() { + return field + 1; + } + + /** name: matches field; body: returns field */ + public int getField2() { + return field2; + } + + int dummyField; + int field; + int field2; + + /** name: correct prefix; body: immaterial */ + public int getY() { + dummyField++; + return dummyField; + } + + int dummyField2; +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/GetterDefinitionTest.java b/plugins/rearranger/test/testData/com/wrq/rearranger/GetterDefinitionTest.java new file mode 100644 index 000000000000..f4aed22fccbb --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/GetterDefinitionTest.java @@ -0,0 +1,33 @@ +public class GetterDefinitionTest { + int dummyField; + int field; + int field2; + + /** name: correct prefix; body: immaterial */ + public int getY() { + dummyField++; + return dummyField; + } + + /** name: correct prefix; body: returns */ + public int getX() { + return field + 1; + } + + /** name: correct prefix; body: returns field */ + public int getZ() { + return field; + } + + /** name: matches field; body: returns */ + public int getField() { + return field + 1; + } + + /** name: matches field; body: returns field */ + public int getField2() { + return field2; + } + + int dummyField2; +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/IncompleteLineResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/IncompleteLineResult.java new file mode 100644 index 000000000000..8e684354b3e7 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/IncompleteLineResult.java @@ -0,0 +1,22 @@ +/** + * $id + * Author: Dave Kriewall + * Created: Oct 20, 2005 + * Copyright 2004, WRQ, Inc. + */ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. User: JJohnson Date: Aug 30, 2005 Time: 11:06:54 AM To change this template use File | + * Settings | File Templates. + */ +public class TestEnum implements Cloneable { +} + +class Utilities { +// -------------------------- STATIC METHODS -------------------------- + + public static String toString(Object receipt) { + return null; //To change body of created methods use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/IncompleteLineTest.java b/plugins/rearranger/test/testData/com/wrq/rearranger/IncompleteLineTest.java new file mode 100644 index 000000000000..0a0141eb148a --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/IncompleteLineTest.java @@ -0,0 +1,20 @@ +/** + * $id + * Author: Dave Kriewall + * Created: Oct 20, 2005 + * Copyright 2004, WRQ, Inc. + */ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. User: JJohnson Date: Aug 30, 2005 Time: 11:06:54 AM To change this template use File | + * Settings | File Templates. + */ +public class TestEnum implements Cloneable { +} + +class Utilities { + public static String toString(Object receipt) { + return null; //To change body of created methods use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/InterfaceResult1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/InterfaceResult1.java new file mode 100644 index 000000000000..0add5205bd14 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/InterfaceResult1.java @@ -0,0 +1,8 @@ +public interface TestInterface { + int CONSTANT = 5; + public int CONSTANT2 = 6; + + void testMethod(); + + public void testMethod2(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/InterfaceTest1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/InterfaceTest1.java new file mode 100644 index 000000000000..651208159a9f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/InterfaceTest1.java @@ -0,0 +1,9 @@ +public interface TestInterface { + int CONSTANT = 5; + + void testMethod(); + + public int CONSTANT2 = 6; + + public void testMethod2(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangeInnerClassResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangeInnerClassResult.java new file mode 100644 index 000000000000..ee6c7c065aad --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangeInnerClassResult.java @@ -0,0 +1,25 @@ +public class RearrangerTrouble { + + // ----- Constructor(s) -------------------------------------------------------------------------------------------- + + + // ----- Public API ------------------------------------------------------------------------------------------------ + + + // ----- Package API ----------------------------------------------------------------------------------------------- + + + // ----- Helper method(s) ------------------------------------------------------------------------------------------ + + + // ----- Helper class(es) ------------------------------------------------------------------------------------------ + + private class DoNotRearrangeMe + implements Comparable + { + + public int compareTo(Object o) { + return 0; + } + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangeInnerClassTest.java b/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangeInnerClassTest.java new file mode 100644 index 000000000000..1fc6ce984e42 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangeInnerClassTest.java @@ -0,0 +1,12 @@ +public class RearrangerTrouble { + + + private class DoNotRearrangeMe + implements Comparable + { + + public int compareTo(Object o) { + return 0; + } + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangementInnerClassCfg.xml b/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangementInnerClassCfg.xml new file mode 100644 index 000000000000..06765c372a62 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangementInnerClassCfg.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\ \ + //\ -----\ Constructor(s)\ --------------------------------------------------------------------------------------------\n + + + + + + + + + + + + + + + + + + + + + + + \n\ \ //-----\ Interface\ %IF%\ \ ----------------------------------\n + + + + + + + \n\ \ + //\ -----\ Public\ API\ ------------------------------------------------------------------------------------------------\n + + + + + + + + + + + + + + + + + + + \n\ \ + //\ -----\ Package\ API\ -----------------------------------------------------------------------------------------------\n + + + + + + + + + + + + + + + + + + + \n\ \ + //\ -----\ Helper\ method(s)\ ------------------------------------------------------------------------------------------\n + + + + + + + + + + + + + + + + + + + \n\ \ + //\ -----\ Helper\ class(es)\ ------------------------------------------------------------------------------------------\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangementResult1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangementResult1.java new file mode 100644 index 000000000000..8882b2f69480 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/NoRearrangementResult1.java @@ -0,0 +1,57 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + /** field 1. */ + private int field1; + private int field2; + public static final int field3 = 3; + public static final int field4 = 4; + final int field5 = 5; + protected int field6 = 6; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + NoRearrangementTest() { + // constructor body + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + void anotherMethod(int j) { + // anotherMethod body + } + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueue.java b/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueue.java new file mode 100644 index 000000000000..fedb5e2587e5 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueue.java @@ -0,0 +1,70 @@ +/* + * OpsBlockingQueue.java + * + * Created on May 3, 2001, 3:11 PM + */ +package opsx.util; + +import opsx.log.OpsLogCategory; +import opsx.server.email.OpsEmailGenerator; + +/** @author dchan */ +public class OpsBlockingQueue extends OpsNonBlockingQueue { + //*********************************** PROTECTED/PACKAGE FIELDS ************************************** + protected final Object putLock; + protected final Object takeLock; + protected volatile int waitCount; + //************************************** PRIVATE FIELDS ***************************************** + private static final OpsLogCategory logCat = (OpsLogCategory)OpsLogCategory.getInstance(OpsEmailGenerator.class); +//************************************** CONSTRUCTORS ************************************* + + /** Creates new OpsBlockingQueue */ + public OpsBlockingQueue() { + takeLock = new Object(); + putLock = new Object(); + waitCount = 0; + } + + //************************************** PUBLIC METHODS ************************************* + public void put(Object obj) { + synchronized (putLock) { + insert(obj); + if (waitCount > 0) { + putLock.notifyAll(); + } + } + } + + public Object take() { + Object obj = takeNext(); + if (obj != null) { + return obj; + } + else { + synchronized (putLock) { + waitCount++; + while (true) { + obj = takeNext(); + if (obj != null) { + waitCount--; + return obj; + } + try { + putLock.wait(); + } + catch (InterruptedException e) { + logCat.error("Blocking Queue threw interrupt", e); + return null; + } + } + } + } + } + + //********************************* PACKAGE/PROTECTED METHODS ******************************** + protected Object takeNext() { + synchronized (takeLock) { + return super.takeNext(); + } + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndented.java b/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndented.java new file mode 100644 index 000000000000..1dc7e756fc9f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndented.java @@ -0,0 +1,75 @@ +/* + * OpsBlockingQueue.java + * + * Created on May 3, 2001, 3:11 PM + */ +package opsx.util; + +import opsx.log.OpsLogCategory; +import opsx.server.email.OpsEmailGenerator; + +/** @author dchan */ +public class OpsBlockingQueue extends OpsNonBlockingQueue { + //*********************************** PROTECTED/PACKAGE FIELDS ************************************** + protected final Object putLock; + protected final Object takeLock; + protected volatile int waitCount; + + //************************************** PRIVATE FIELDS ***************************************** + + private static final OpsLogCategory logCat = (OpsLogCategory)OpsLogCategory.getInstance(OpsEmailGenerator.class); + + //************************************** CONSTRUCTORS ************************************* + + /** Creates new OpsBlockingQueue */ + public OpsBlockingQueue() { + takeLock = new Object(); + putLock = new Object(); + waitCount = 0; + } + + //************************************** PUBLIC METHODS ************************************* + // PUBLIC METHODS LINE 2 + + public void put(Object obj) { + synchronized (putLock) { + insert(obj); + if (waitCount > 0) { + putLock.notifyAll(); + } + } + } + + public Object take() { + Object obj = takeNext(); + if (obj != null) { + return obj; + } + else { + synchronized (putLock) { + waitCount++; + while (true) { + obj = takeNext(); + if (obj != null) { + waitCount--; + return obj; + } + try { + putLock.wait(); + } + catch (InterruptedException e) { + logCat.error("Blocking Queue threw interrupt", e); + return null; + } + } + } + } + } + + //********************************* PACKAGE/PROTECTED METHODS ******************************** + protected Object takeNext() { + synchronized (takeLock) { + return super.takeNext(); + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java new file mode 100644 index 000000000000..a8ba010d2f51 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java @@ -0,0 +1,71 @@ +/* + * OpsBlockingQueue.java + * + * Created on May 3, 2001, 3:11 PM + */ +package opsx.util; + +import opsx.log.OpsLogCategory; +import opsx.server.email.OpsEmailGenerator; + +/** @author dchan */ +public class OpsBlockingQueue extends OpsNonBlockingQueue { + //*********************************** PROTECTED/PACKAGE FIELDS ************************************** + protected final Object putLock; + protected final Object takeLock; + protected volatile int waitCount; + //************************************** PRIVATE FIELDS ***************************************** + private static final OpsLogCategory logCat = (OpsLogCategory)OpsLogCategory.getInstance(OpsEmailGenerator.class); +//************************************** CONSTRUCTORS ************************************* + + /** Creates new OpsBlockingQueue */ + public OpsBlockingQueue() { + takeLock = new Object(); + putLock = new Object(); + waitCount = 0; + } + + //************************************** PUBLIC METHODS ************************************* +// PUBLIC METHODS LINE 2 + public void put(Object obj) { + synchronized (putLock) { + insert(obj); + if (waitCount > 0) { + putLock.notifyAll(); + } + } + } + + public Object take() { + Object obj = takeNext(); + if (obj != null) { + return obj; + } + else { + synchronized (putLock) { + waitCount++; + while (true) { + obj = takeNext(); + if (obj != null) { + waitCount--; + return obj; + } + try { + putLock.wait(); + } + catch (InterruptedException e) { + logCat.error("Blocking Queue threw interrupt", e); + return null; + } + } + } + } + } + + //********************************* PACKAGE/PROTECTED METHODS ******************************** + protected Object takeNext() { + synchronized (takeLock) { + return super.takeNext(); + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedConfig.xml b/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedConfig.xml new file mode 100644 index 000000000000..8f00c29e79a3 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedConfig.xml @@ -0,0 +1,500 @@ + + + + \ \ \ //%FS%\n\ \ \ //%FS%\ Constants\n + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Inner\ Classes\n + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Instance\ Variables\n + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Variables\n + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Constructors\n + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Instance\ Methods\n + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Getters/Setters\n + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Public\ Methods\n + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ %IF%\ Methods\n + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Protected/Package\ + Getters/Setters\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Protected/Package\ Methods\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Private\ Methods\n + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Inner\ Classes\n + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Variables\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Instance\ Variables\n + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Private\ Constants\n + + + + + + + + + + + + \n\n\ \ \ //%FS%\n\ \ \ //%FS%\ Main\ Method\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\n//%FS%\n//%FS%\n\n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedResult1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedResult1.java new file mode 100644 index 000000000000..64ec60be8083 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedResult1.java @@ -0,0 +1,11 @@ +public class TestOverloaded { + //-------------------------------------------------------------------- + //------------------------------------------------------- Constructors + + public TestOverloaded(String p_login) { + } + + + public TestOverloaded(Integer p_user) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedTest1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedTest1.java new file mode 100644 index 000000000000..64ec60be8083 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/OverloadedTest1.java @@ -0,0 +1,11 @@ +public class TestOverloaded { + //-------------------------------------------------------------------- + //------------------------------------------------------- Constructors + + public TestOverloaded(String p_login) { + } + + + public TestOverloaded(Integer p_user) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult10.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult10.java new file mode 100644 index 000000000000..07f2dd6cbab9 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult10.java @@ -0,0 +1,58 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + public static final int field3 = 3; + public static final int field4 = 4; +// simple comment ********** + /** field 1. */ + private int field1; + private int field2; + final int field5 = 5; + protected int field6 = 6; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + NoRearrangementTest() { + // constructor body + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + void anotherMethod(int j) { + // anotherMethod body + } + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult11.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult11.java new file mode 100644 index 000000000000..6686430237da --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult11.java @@ -0,0 +1,8 @@ +public class RearrangementTest11 { + // FIELDS: +// FINAL FIELDS: + final int i; + public final int k; + // NON-FINAL FIELDS: + int j; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult12.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult12.java new file mode 100644 index 000000000000..fdcee3db5fb1 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult12.java @@ -0,0 +1,21 @@ +class RearrangementTest12 { + void method(int y) { + x = y; + } + + int x; + + Object convertX() { + return new Integer(x); + } + + Integer[] convertXs() { + return new Integer[]{new Integer(x), new Integer(0)}; + } + + int getX() { + return x; + } + + String s; +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13.java new file mode 100644 index 000000000000..171b824726d8 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } + + void S1B() { + } + + void S1A() { + } + + private void F2() { + S2A(); + S2B(); + } + + void S2A() { + } + + void S2B() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BA.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BA.java new file mode 100644 index 000000000000..a66c1c573e7a --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BA.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } + + private void F2() { + S2A(); + S2B(); + } + + void S1A() { + } + + void S1B() { + } + + void S2A() { + } + + void S2B() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BI.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BI.java new file mode 100644 index 000000000000..01a2d9fa3a53 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BI.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } + + private void F2() { + S2A(); + S2B(); + } + + void S1B() { + } + + void S1A() { + } + + void S2A() { + } + + void S2B() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BIELC.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BIELC.java new file mode 100644 index 000000000000..1c8c38a5889c --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BIELC.java @@ -0,0 +1,52 @@ +public class RearrangerTest13 { + // Preceding comment: TL=GF +// MN=GF +// AM= +// Level 1 + void GF() { // grandfather + F1(); + F2(); + } +// Preceding comment: TL=GF +// MN=GF +// AM=GF() +// Level 2 + + private void F1() { + S1B(); + S1A(); + } + + private void F2() { + S2A(); + S2B(); + } + + // Preceding comment: TL=GF +// MN=F2 +// AM=GF().[F1(),F2()] +// Level 3 + void S1B() { + } + + void S1A() { + } + + void S2A() { + } + + void S2B() { + } +// Trailing comment: TL=GF +// MN=F2 +// AM=GF().[F1(),F2()] +// Level 3 +// Trailing comment: TL=GF +// MN=GF +// AM=GF() +// Level 2 +// Trailing comment: TL=GF +// MN=GF +// AM= +// Level 1 +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BIEMC.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BIEMC.java new file mode 100644 index 000000000000..a1767777decb --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BIEMC.java @@ -0,0 +1,84 @@ +public class RearrangerTest13 { + // Preceding comment: TL=GF +// MN=GF +// AM= +// Level 1 + void GF() { // grandfather + F1(); + F2(); + } +// Trailing comment: TL=GF +// MN=GF +// AM= +// Level 1 +// Preceding comment: TL=GF +// MN=F1 +// AM=GF() +// Level 2 + + private void F1() { + S1B(); + S1A(); + } +// Trailing comment: TL=GF +// MN=F1 +// AM=GF() +// Level 2 +// Preceding comment: TL=GF +// MN=F2 +// AM=GF() +// Level 2 + + private void F2() { + S2A(); + S2B(); + } + + // Trailing comment: TL=GF +// MN=F2 +// AM=GF() +// Level 2 +// Preceding comment: TL=GF +// MN=S1B +// AM=GF().[F1(),F2()] +// Level 3 + void S1B() { + } + + // Trailing comment: TL=GF +// MN=S1B +// AM=GF().[F1(),F2()] +// Level 3 +// Preceding comment: TL=GF +// MN=S1A +// AM=GF().[F1(),F2()] +// Level 3 + void S1A() { + } + + // Trailing comment: TL=GF +// MN=S1A +// AM=GF().[F1(),F2()] +// Level 3 +// Preceding comment: TL=GF +// MN=S2A +// AM=GF().[F1(),F2()] +// Level 3 + void S2A() { + } + + // Trailing comment: TL=GF +// MN=S2A +// AM=GF().[F1(),F2()] +// Level 3 +// Preceding comment: TL=GF +// MN=S2B +// AM=GF().[F1(),F2()] +// Level 3 + void S2B() { + } +// Trailing comment: TL=GF +// MN=S2B +// AM=GF().[F1(),F2()] +// Level 3 +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BINFC.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BINFC.java new file mode 100644 index 000000000000..70229ad1245b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BINFC.java @@ -0,0 +1,32 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } +// Preceding comment: TL=GF +// MN=GF +// AM=GF() +// Level 2 + + private void F2() { + S2A(); + S2B(); + } + + void S1B() { + } + + void S1A() { + } + + void S2A() { + } + + void S2B() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BITLC.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BITLC.java new file mode 100644 index 000000000000..2e6913993b4e --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BITLC.java @@ -0,0 +1,36 @@ +public class RearrangerTest13 { + // Preceding comment: TL=GF +// MN=GF +// AM= +// Level 1 + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } + + private void F2() { + S2A(); + S2B(); + } + + void S1B() { + } + + void S1A() { + } + + void S2A() { + } + + void S2B() { + } +// Trailing comment: TL=GF +// MN=GF +// AM= +// Level 1 +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BO.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BO.java new file mode 100644 index 000000000000..1060fea2f3dd --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13BO.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F2() { + S2A(); + S2B(); + } + + private void F1() { + S1B(); + S1A(); + } + + void S2B() { + } + + void S1B() { + } + + void S2A() { + } + + void S1A() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DA.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DA.java new file mode 100644 index 000000000000..c8aa6eae8825 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DA.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } + + void S1A() { + } + + void S1B() { + } + + private void F2() { + S2A(); + S2B(); + } + + void S2A() { + } + + void S2B() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DI.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DI.java new file mode 100644 index 000000000000..171b824726d8 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DI.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } + + void S1B() { + } + + void S1A() { + } + + private void F2() { + S2A(); + S2B(); + } + + void S2A() { + } + + void S2B() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DIELC.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DIELC.java new file mode 100644 index 000000000000..16cafde0c90f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DIELC.java @@ -0,0 +1,60 @@ +public class RearrangerTest13 { + // Preceding comment: TL=GF +// MN=GF +// AM= +// Level 1 + void GF() { // grandfather + F1(); + F2(); + } +// Preceding comment: TL=GF +// MN=GF +// AM=GF() +// Level 2 + + private void F1() { + S1B(); + S1A(); + } + + // Preceding comment: TL=GF +// MN=F1 +// AM=GF().F1() +// Level 3 + void S1B() { + } + + void S1A() { + } +// Trailing comment: TL=GF +// MN=F1 +// AM=GF().F1() +// Level 3 + + private void F2() { + S2A(); + S2B(); + } + + // Preceding comment: TL=GF +// MN=F2 +// AM=GF().F2() +// Level 3 + void S2A() { + } + + void S2B() { + } +// Trailing comment: TL=GF +// MN=F2 +// AM=GF().F2() +// Level 3 +// Trailing comment: TL=GF +// MN=GF +// AM=GF() +// Level 2 +// Trailing comment: TL=GF +// MN=GF +// AM= +// Level 1 +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DIEMC.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DIEMC.java new file mode 100644 index 000000000000..6f90b4913aa3 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DIEMC.java @@ -0,0 +1,84 @@ +public class RearrangerTest13 { + // Preceding comment: TL=GF +// MN=GF +// AM= +// Level 1 + void GF() { // grandfather + F1(); + F2(); + } +// Trailing comment: TL=GF +// MN=GF +// AM= +// Level 1 +// Preceding comment: TL=GF +// MN=F1 +// AM=GF() +// Level 2 + + private void F1() { + S1B(); + S1A(); + } + + // Trailing comment: TL=GF +// MN=F1 +// AM=GF() +// Level 2 +// Preceding comment: TL=GF +// MN=S1B +// AM=GF().F1() +// Level 3 + void S1B() { + } + + // Trailing comment: TL=GF +// MN=S1B +// AM=GF().F1() +// Level 3 +// Preceding comment: TL=GF +// MN=S1A +// AM=GF().F1() +// Level 3 + void S1A() { + } +// Trailing comment: TL=GF +// MN=S1A +// AM=GF().F1() +// Level 3 +// Preceding comment: TL=GF +// MN=F2 +// AM=GF() +// Level 2 + + private void F2() { + S2A(); + S2B(); + } + + // Trailing comment: TL=GF +// MN=F2 +// AM=GF() +// Level 2 +// Preceding comment: TL=GF +// MN=S2A +// AM=GF().F2() +// Level 3 + void S2A() { + } + + // Trailing comment: TL=GF +// MN=S2A +// AM=GF().F2() +// Level 3 +// Preceding comment: TL=GF +// MN=S2B +// AM=GF().F2() +// Level 3 + void S2B() { + } +// Trailing comment: TL=GF +// MN=S2B +// AM=GF().F2() +// Level 3 +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DINFC.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DINFC.java new file mode 100644 index 000000000000..235760aaf93f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DINFC.java @@ -0,0 +1,32 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } + + void S1B() { + } + + void S1A() { + } +// Preceding comment: TL=GF +// MN=GF +// AM=GF() +// Level 2 + + private void F2() { + S2A(); + S2B(); + } + + void S2A() { + } + + void S2B() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DITLC.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DITLC.java new file mode 100644 index 000000000000..b238fa8d540c --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DITLC.java @@ -0,0 +1,36 @@ +public class RearrangerTest13 { + // Preceding comment: TL=GF +// MN=GF +// AM= +// Level 1 + void GF() { // grandfather + F1(); + F2(); + } + + private void F1() { + S1B(); + S1A(); + } + + void S1B() { + } + + void S1A() { + } + + private void F2() { + S2A(); + S2B(); + } + + void S2A() { + } + + void S2B() { + } +// Trailing comment: TL=GF +// MN=GF +// AM= +// Level 1 +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DO.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DO.java new file mode 100644 index 000000000000..4654b27e6d55 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13DO.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F2() { + S2A(); + S2B(); + } + + void S2B() { + } + + void S2A() { + } + + private void F1() { + S1B(); + S1A(); + } + + void S1B() { + } + + void S1A() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13Ex.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13Ex.java new file mode 100644 index 000000000000..4654b27e6d55 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult13Ex.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F2() { + S2A(); + S2B(); + } + + void S2B() { + } + + void S2A() { + } + + private void F1() { + S1B(); + S1A(); + } + + void S1B() { + } + + void S1A() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult14.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult14.java new file mode 100644 index 000000000000..3b56c71a5c79 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult14.java @@ -0,0 +1,14 @@ +public class RearrangementTest14 { + + void GF() { + doIt(2, 3); + } + + int doIt(int x, int y) { + return x + y; + } + + int doIt(int x) { + return x + 1; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18.java new file mode 100644 index 000000000000..061e8da24d9b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18.java @@ -0,0 +1,34 @@ +public class RearrangementTest18 { + int field1; + char char2; + + RearrangementTest18() { + field1 = 10; + } + + char getChar2() { + return char2; + } + + void setChar2(char val) { + char2 = val; + } + + int getField1() { + return field1; + } + + void setField1(int val) { + field1 = val; + } + + void method1() { + char2 = 'a'; + } + + void method3() { + } + + void method4() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18A.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18A.java new file mode 100644 index 000000000000..9d1267993f26 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18A.java @@ -0,0 +1,35 @@ +public class RearrangementTest18 { + int field1; + + int getField1() { + return field1; + } + + void setField1(int val) { + field1 = val; + } + + char char2; + + char getChar2() { + return char2; + } + + void setChar2(char val) { + char2 = val; + } + + RearrangementTest18() { + field1 = 10; + } + + void method1() { + char2 = 'a'; + } + + void method3() { + } + + void method4() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18B.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18B.java new file mode 100644 index 000000000000..491581297451 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult18B.java @@ -0,0 +1,29 @@ +public class MethodEntry { + private boolean isSetter; + + public boolean isIsSetter() { + return isSetter; + } + + // Getters/Setters + public String getCustomizedPrecedingComment() { + if (customizedPrecedingComment == null) { + return ""; + } + return "comment"; + } + + public boolean isGetter() { + return isGetter; + } + + public boolean isSetter() { + return isSetter; + } + + // Other Methods + public DefaultMutableTreeNode addToPopupTree() { + if (isSetter()) return null; + return null; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19A.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19A.java new file mode 100644 index 000000000000..b65c27c7af2a --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19A.java @@ -0,0 +1,24 @@ +public class RearrangementTest19 { + RearrangementTest19() { + } + + RearrangementTest19(int x, int y) { + } + + RearrangementTest19(int oneParam) { + } + + void overloadedMethod1(int x, int y, int z) { + } + + void overloadedMethod1(int x) { + overloadedMethod1(x, 0, 0); + } + + void overloadedMethod1(int x, int y) { + overloadedMethod1(x, y, 0); + } + + void unoverloadedMethod() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19B.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19B.java new file mode 100644 index 000000000000..f9d161a504ee --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19B.java @@ -0,0 +1,24 @@ +public class RearrangementTest19 { + RearrangementTest19() { + } + + RearrangementTest19(int oneParam) { + } + + RearrangementTest19(int x, int y) { + } + + void overloadedMethod1(int x) { + overloadedMethod1(x, 0, 0); + } + + void overloadedMethod1(int x, int y) { + overloadedMethod1(x, y, 0); + } + + void overloadedMethod1(int x, int y, int z) { + } + + void unoverloadedMethod() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19C.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19C.java new file mode 100644 index 000000000000..9231cd2e03f6 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult19C.java @@ -0,0 +1,25 @@ +public class RearrangementTest19 { + + RearrangementTest19(int x, int y) { + } + + RearrangementTest19(int oneParam) { + } + + RearrangementTest19() { + } + + void overloadedMethod1(int x, int y, int z) { + } + + void overloadedMethod1(int x, int y) { + overloadedMethod1(x, y, 0); + } + + void overloadedMethod1(int x) { + overloadedMethod1(x, 0, 0); + } + + void unoverloadedMethod() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult1A.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult1A.java new file mode 100644 index 000000000000..66788594ffdd --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult1A.java @@ -0,0 +1,58 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + + NoRearrangementTest() { + // constructor body + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + void anotherMethod(int j) { + // anotherMethod body + } + + /** field 1. */ + private int field1; + private int field2; + public static final int field3 = 3; + public static final int field4 = 4; + final int field5 = 5; + protected int field6 = 6; + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java new file mode 100644 index 000000000000..186f0581ef94 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java @@ -0,0 +1,57 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + public static final int field3 = 3; + public static final int field4 = 4; + /** field 1. */ + private int field1; + private int field2; + final int field5 = 5; + protected int field6 = 6; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + NoRearrangementTest() { + // constructor body + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + void anotherMethod(int j) { + // anotherMethod body + } + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult20.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult20.java new file mode 100644 index 000000000000..cb18ad6e24db --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult20.java @@ -0,0 +1,18 @@ +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class RearrangementTest20 { + + public static void Father(final Object event) { + JCheckBox box = new JCheckBox("text"); + box.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + ChildA(e); + } + }; + } + + private static void ChildA(final Object event) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult21.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult21.java new file mode 100644 index 000000000000..5d70f209a297 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult21.java @@ -0,0 +1,3 @@ +public class RearrangementTest21 { + int v, u; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult22.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult22.java new file mode 100644 index 000000000000..d7c2e1347fbd --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult22.java @@ -0,0 +1,11 @@ +public class RearrangementTest22 { + public int getMyValue() { + return 0; + } + + public void setMyValue(int x) { + // does nothing + } + + int i; +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23BNNANXME.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23BNNANXME.java new file mode 100644 index 000000000000..4e7bf76cd622 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23BNNANXME.java @@ -0,0 +1,39 @@ +public class RearrangementTest23 + implements IFace2, IFace1 +{ + public int getY() { + return 6; + } + + public int getX() { + return getA() ? 5 : 3; + } + + int method1() { + return 4; + } + + public boolean getB() { + return false; + } + + public boolean getA() { + return true; + } + + int method2() { + return 7; + } +} + +interface IFace2 { + public boolean getA(); + + public boolean getB(); +} + +interface IFace1 { + public int getY(); + + public int getX(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNIANXME.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNIANXME.java new file mode 100644 index 000000000000..73e08795186f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNIANXME.java @@ -0,0 +1,42 @@ +public class RearrangementTest23 + implements IFace2, IFace1 +{ + /** * Interface IFace1 Header *** */ + public int getY() { + return 6; + } + + public int getX() { + return getA() ? 5 : 3; + } +/**** Interface IFace1 Trailer ***/ + /** * Interface IFace2 Header *** */ + public boolean getB() { + return false; + } + + public boolean getA() { + return true; + } + + /** * Interface IFace2 Trailer ** */ + int method1() { + return 4; + } + + int method2() { + return 7; + } +} + +interface IFace2 { + public boolean getA(); + + public boolean getB(); +} + +interface IFace1 { + public int getY(); + + public int getX(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXMA.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXMA.java new file mode 100644 index 000000000000..22a6c10e38e7 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXMA.java @@ -0,0 +1,42 @@ +public class RearrangementTest23 + implements IFace2, IFace1 +{ + /** * Interface IFace2 Header *** */ + public boolean getA() { + return true; + } + + public boolean getB() { + return false; + } +/**** Interface IFace2 Trailer ***/ + /** * Interface IFace1 Header *** */ + public int getX() { + return getA() ? 5 : 3; + } + + public int getY() { + return 6; + } + + /** * Interface IFace1 Trailer ** */ + int method1() { + return 4; + } + + int method2() { + return 7; + } +} + +interface IFace2 { + public boolean getA(); + + public boolean getB(); +} + +interface IFace1 { + public int getY(); + + public int getX(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXME.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXME.java new file mode 100644 index 000000000000..f903e3e5cc05 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXME.java @@ -0,0 +1,42 @@ +public class RearrangementTest23 + implements IFace2, IFace1 +{ + /** * Interface IFace2 Header *** */ + public boolean getB() { + return false; + } + + public boolean getA() { + return true; + } +/**** Interface IFace2 Trailer ***/ + /** * Interface IFace1 Header *** */ + public int getY() { + return 6; + } + + public int getX() { + return getA() ? 5 : 3; + } + + /** * Interface IFace1 Trailer ** */ + int method1() { + return 4; + } + + int method2() { + return 7; + } +} + +interface IFace2 { + public boolean getA(); + + public boolean getB(); +} + +interface IFace1 { + public int getY(); + + public int getX(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXMI.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXMI.java new file mode 100644 index 000000000000..8088b74fa28a --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult23NNNANXMI.java @@ -0,0 +1,42 @@ +public class RearrangementTest23 + implements IFace2, IFace1 +{ + /** * Interface IFace2 Header *** */ + public boolean getA() { + return true; + } + + public boolean getB() { + return false; + } +/**** Interface IFace2 Trailer ***/ + /** * Interface IFace1 Header *** */ + public int getY() { + return 6; + } + + public int getX() { + return getA() ? 5 : 3; + } + + /** * Interface IFace1 Trailer ** */ + int method1() { + return 4; + } + + int method2() { + return 7; + } +} + +interface IFace2 { + public boolean getA(); + + public boolean getB(); +} + +interface IFace1 { + public int getY(); + + public int getX(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult25.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult25.java new file mode 100644 index 000000000000..900ae758c11e --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult25.java @@ -0,0 +1,24 @@ +public class RearrangementTest25 { + // ... + + private double getHorizontalstrecke() { + // ... + Double meanValue = new Double(4.0f); + if (meanValue != null) { + return meanValue.getValue(); + } + // ... + return 0.0f; + } + + private double getRichtungErrorLimit(double sr, double sz, double s) { + if (s == 0f) { // (!G2Null.isValid(s)) { + return sr; + } + return Math.sqrt(QMath.square(sr) + QMath.square(sz / s)); + } + + private void checkDoubleMessung(double messung) { + + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult26.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult26.java new file mode 100644 index 000000000000..fd22dd84a491 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult26.java @@ -0,0 +1,16 @@ +class RearrangementTest26 { + + public int getValue() { + return value; + } + + public void setValue(int i) { + value = i; + } + + int value; + + { + value = 2; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult27.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult27.java new file mode 100644 index 000000000000..2eaffda7d564 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult27.java @@ -0,0 +1,45 @@ +public class RearrangerTest27 { + private boolean constructorMethodType; + private boolean getterSetterMethodType; + private int i; + + public MethodAttributes() { + init(); + } + + private void init() { + i = 1; + } + + public MethodAttributes(int i) { + init(); + this.i = i; + } + + private boolean isConstructorMethodType() { + return constructorMethodType; + } + + public final void setConstructorMethodType(final boolean constructorMethodType) { + this.constructorMethodType = constructorMethodType; + } + + private boolean isGetterSetterMethodType() { + return getterSetterMethodType; + } + + public final void setGetterSetterMethodType(final boolean getterSetterMethodType) { + this.getterSetterMethodType = getterSetterMethodType; + } + + private Object getMethodTypePanel() { + return getMethodTypeInnerPanel(); + } + + private JPanel getMethodTypeInnerPanel() { + setConstructorMethodType(true); + setGetterSetterMethodType(false); + return new Object(); + } +} + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult28.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult28.java new file mode 100644 index 000000000000..f7382377292c --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult28.java @@ -0,0 +1,50 @@ +public class RearrangementTest28 + implements InterfaceName, InterfaceName2 +{ + // start of fields + int i; + + // end of fields +// start of interface InterfaceName +// Level 1 methods + public int getTime() { + return getAnother(); + } + + // Level 2 methods + public int getAnother() { + return 0; + } + + // end Level 2 methods +// end Level 1 methods +// end of interface InterfaceName +// start of interface InterfaceName2 + public int getDate() { + return 0; + } + + // end of interface InterfaceName2 +// Level 1 methods + public void m1() { + m2(); + m3(); + } + + // Level 2 methods + public void m2() { + } + + public void m3() { + } +// end Level 2 methods +// end Level 1 methods +} + +interface InterfaceName { + public int getTime(); +} + +interface InterfaceName2 { + public int getDate(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult3.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult3.java new file mode 100644 index 000000000000..3da9daf9be25 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult3.java @@ -0,0 +1,57 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + /** field 1. */ + private int field1; + private int field2; + final int field5 = 5; + protected int field6 = 6; + public static final int field3 = 3; + public static final int field4 = 4; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + NoRearrangementTest() { + // constructor body + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + void anotherMethod(int j) { + // anotherMethod body + } + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult30.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult30.java new file mode 100644 index 000000000000..fb4989f57275 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult30.java @@ -0,0 +1,328 @@ +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import org.apache.log4j.Logger; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +/** Handles right-click in project view; applies rearrangement to a directory and its files recursively. */ +public final class ProjectTreeActionHandler + extends AnAction +{ + private static final Logger logger = Logger.getLogger("com.wrq.rearranger.ProjectTreeActionHandler"); + + + public final void actionPerformed(final AnActionEvent anActionEvent) { + logger.debug("entered actionPerformed"); + // we're being called on the Swing event dispatch thread. Spin off another thread to do the + // rearranging and let Swing's thread go. +// Thread t = new Thread(new Runnable() { +// public void run() +// { +// //To change body of implemented methods use Options | File Templates. + final Application application = ApplicationManager.getApplication(); + application.runWriteAction(new RearrangeIt(anActionEvent.getDataContext())); +// } +// }, "RearrangerThread"); +// t.start(); +// new RearrangeIt(anActionEvent.getDataContext()).run(); + } + + /** + * Test progress bar functionality. Read 10 "filenames" from console, pausing between each to update the + * progress bar dialog. Handle cancel button and dialog window close button properly. + * + * @param args + */ + public static void main(final String[] args) { + org.apache.log4j.BasicConfigurator.configure(); + // test the progress bar. + final BufferedReader reader; + final ProjectTreeActionHandler ptah = new ProjectTreeActionHandler(); + final RearrangeIt ri = ptah.new RearrangeIt(null); + final RearrangeIt.IntHolder cancelled = ri.new IntHolder(); + + reader = new BufferedReader(new InputStreamReader(System.in)); + final Cancellable c = new Cancellable() { + public void setCancel() { + System.out.println("cancel test"); + cancelled.n = 1; + } + }; + + final JDialog dialog = ri.getProgressFrame(c, 10); + int count = 0; + dialog.pack(); + dialog.setVisible(true); + while (count <= 10 && cancelled.n == 0) { + String s = null; + try { + s = reader.readLine(); + } + catch (IOException e) { + e.printStackTrace(); + } + if (cancelled.n == 0) { + ri.filename.setText(s); + count++; + ri.bar.setValue(count); + } + } + dialog.setVisible(false); + dialog.hide(); + dialog.dispose(); + System.exit(0); + } + + interface Cancellable { + void setCancel(); + } + + abstract class VirtualFileVisitor implements Cancellable { + volatile boolean cancel = false; + + public final void setCancel() { + logger.debug("VirtualFileVisitor.setCancel called"); + cancel = true; + } + + abstract void visitVirtualFile(VirtualFile f); + + final void accept(final VirtualFile f) { + if (f != null) { + visitVirtualFile(f); + } + final VirtualFile[] vfa = f.getChildren(); + if (vfa != null) { + for (int i = 0; i < vfa.length; i++) { + if (!cancel) { + accept(vfa[i]); + } + } + } + } + } + + final class RearrangeIt implements Runnable { + final class IntHolder { + public int n; + } + + final DataContext dc; + final Project project; + final JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL); + final JLabel filename = new JLabel(); + + public RearrangeIt(final DataContext dc) { + this.dc = dc; + this.project = (Project)dc.getData(DataConstants.PROJECT); + } + + public final void run() { + final VirtualFile virtualFile = (VirtualFile)dc.getData(DataConstants.VIRTUAL_FILE); + final IntHolder count = new IntHolder(); + final VirtualFileVisitor counter = new VirtualFileVisitor() { + void visitVirtualFile(final VirtualFile f) { + if (!f.isDirectory()) count.n++; + } + }; + + counter.accept(virtualFile); + logger.debug("counted " + count.n + " files"); + + final RearrangerActionHandler rah = new RearrangerActionHandler(); + final PsiDocumentManager dm = PsiDocumentManager.getInstance(project); + final PsiManager pm = PsiManager.getInstance(project); + final VirtualFileVisitor executor = new VirtualFileVisitor() { + int currentCount = 0; + + void visitVirtualFile(final VirtualFile f) { + try { + final PsiFile psiFile = pm.findFile(f); + if (psiFile != null && psiFile.canContainJavaCode()) { + logger.debug("rearrange psiFile=" + psiFile.toString()); + if (SwingUtilities.isEventDispatchThread()) { + logger.debug("event dispatch thread setting filename to " + psiFile.getName()); + filename.setText(psiFile.getName()); + } + else { + logger.debug("invokeAndWait to set filename to " + psiFile.getName()); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + logger.debug("event dispatch thread within invokeAndWait setting filename to " + + psiFile.getName()); + filename.setText(psiFile.getName()); + } + }); + } + filename.repaint(); +// filename.setText(psiFile.getName()); +// filename.paint(filename.getGraphics()); + filename.paintImmediately(filename.getVisibleRect()); + Thread.sleep(8000); + final Document document = dm.getDocument(psiFile); + if (document == null) { + logger.debug("document was null"); + } + else { +// Thread t = new Thread(new Runnable() { +// public void run() +// { + //To change body of implemented methods use Options | File Templates. + rah.runWriteActionRearrangement(project, document, psiFile); +// } +// } ); +// t.start(); + } + logger.debug("done rearranging psiFile=" + psiFile.toString()); + } + if (SwingUtilities.isEventDispatchThread()) { + logger.debug("EventDispatchThread updating progress bar value to " + currentCount); + bar.setValue(currentCount); + } + else { + logger.debug("invokeAndWait to set progress bar value to " + currentCount); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + logger.debug("EventDispatchThread within InvokeAndWait setting progress bar value to " + + currentCount); + bar.setValue(currentCount); + } + }); + } + bar.repaint(); + bar.paintImmediately(bar.getVisibleRect()); + bar.paint(bar.getGraphics()); + currentCount++; + Thread.sleep(5000); + } + catch (InterruptedException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + } + }; + + final JDialog dialog = getProgressFrame(executor, count.n); + + dialog.show(); + dialog.setVisible(true); + dialog.paint(dialog.getGraphics()); + executor.accept(virtualFile); + dialog.setVisible(false); + dialog.hide(); + dialog.dispose(); + } + + final JDialog getProgressFrame(final Cancellable cancellableObject, final int max) { + final Object parent = WindowManager.getInstance().suggestParentWindow(project); + logger.debug("suggested parent window=" + parent); + final JDialog dialog = parent == null ? + new JDialog() : (parent instanceof JDialog ? + new JDialog((JDialog)parent) : new JDialog((JFrame)parent)); + final Container pane = dialog.getContentPane(); + final JLabel rearrangingLabel = new JLabel("Rearranging files, please wait..."); +// rearrangingLabel.setFont(new Font("dialog", Font.PLAIN, 12)); + final JPanel progressPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 1; + constraints.weightx = 1; + constraints.insets = new Insets(15, 15, 0, 0); + progressPanel.add(rearrangingLabel, constraints); + constraints.gridwidth = 1; + constraints.gridy = 1; + bar.setMinimum(0); + bar.setMaximum(max); + bar.setPreferredSize(new Dimension(500, 15)); + bar.setMinimumSize(new Dimension(500, 15)); + bar.setStringPainted(true); + constraints.insets = new Insets(15, 15, 5, 15); + progressPanel.add(bar, constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 1; + constraints.insets = new Insets(9, 0, 5, 15); + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + logger.debug("cancel button pressed"); + filename.setText("cancelling..."); + cancellableObject.setCancel(); + } + }); + + progressPanel.add(cancelButton, constraints); + constraints.gridx = 0; + constraints.gridy = 2; + constraints.weighty = 1; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.insets = new Insets(0, 15, 15, 0); + filename.setSize(500, 15); + filename.setPreferredSize(new Dimension(500, 15)); +// filename.setFont(new Font("dialog", Font.PLAIN, 12)); + progressPanel.add(filename, constraints); + pane.add(progressPanel, BorderLayout.CENTER); + dialog.setTitle("Rearranger"); + dialog.addWindowListener(new WindowListener() { + public void windowClosed(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowActivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowClosing(final WindowEvent e) { + logger.debug("dialog closed, cancel Rearranger"); + filename.setText("cancelling..."); + cancellableObject.setCancel(); + } + + public void windowDeactivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowDeiconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowIconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowOpened(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + }); + + dialog.pack(); + return dialog; + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult31.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult31.java new file mode 100644 index 000000000000..e6caba257bf6 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult31.java @@ -0,0 +1,176 @@ +/** + * Id$ + * + * Rearranger plugin for IntelliJ IDEA. + * + * Source code may be freely copied and reused. Please copy credits, and send any bug fixes to the author. + * + * @author Dave Kriewall, WRQ, Inc. + * January, 2004 + */ +package com.wrq.rearranger; + +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.CaretModel; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.wrq.rearranger.popup.LiveRearrangerPopup; +import com.wrq.rearranger.rearrangement.Mover; +import com.wrq.rearranger.rearrangement.Parser; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.CommentUtil; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; + +import java.awt.*; +import java.util.ArrayList; + +/** Supports manual rearrangement of a file. */ +public final class LiveRearrangerActionHandler extends EditorActionHandler { + // ------------------------------ FIELDS ------------------------------ + private static final Logger logger = Logger.getLogger("com.wrq.rearranger.LiveRearrangerActionHandler"); + + private static boolean inProgress = false; +// -------------------------- STATIC METHODS -------------------------- + + public static CodeStyleManager getCsm() { + return RearrangerActionHandler.getCsm(); + } + +// -------------------------- OTHER METHODS -------------------------- + + public final void execute(final Editor editor, final DataContext context) { + if (editor == null) { + return; + } + final Project project = (Project)context.getData(DataConstants.PROJECT); + logger.debug("project=" + project); + logger.debug("editor=" + editor); + final Document document = editor.getDocument(); + final CaretModel caret = editor.getCaretModel(); + int cursorOffset = caret.getOffset(); + final PsiFile psiFile = getFile(editor, context); + if (!psiFile.getName().endsWith(".java")) { + logger.debug("not a .java file -- skipping " + psiFile.getName()); + return; + } + if (!psiFile.isWritable()) { + logger.debug("not a writable .java file -- skipping " + psiFile.getName()); + return; + } + logger.debug("inProgress=" + inProgress); + if (inProgress) { + return; + } + + setInProgress(true); + buildLiveRearrangerData(project, document, psiFile, cursorOffset); + } + + private static PsiFile getFile(final Editor editor, + final DataContext context) + { + final Project project = (Project)context.getData(DataConstants.PROJECT); + final Document document = editor.getDocument(); + final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); + final VirtualFile virtualFile = fileDocumentManager.getFile(document); + final PsiManager psiManager = PsiManager.getInstance(project); + return psiManager.findFile(virtualFile); + } + + public static void setInProgress(boolean inProgress) { + logger.debug("set inProgress=" + inProgress); + LiveRearrangerActionHandler.inProgress = inProgress; + } + + /** + * must be called from within an IDEA read-action thread. + * + * @param project + * @param document + * @param psiFile + */ + void buildLiveRearrangerData(final Project project, + final Document document, + final PsiFile psiFile, + final int cursorOffset) + { + /** + * Per instructions from IntelliJ, we have to commit any changes to the document to the Psi + * tree. + */ + final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); + documentManager.commitDocument(document); + final RearrangerSettings settings = new RearrangerSettings(); // use default settings with no rules + settings.setAskBeforeRearranging(true); + final Runnable task = new Runnable() { + public void run() { + logger.debug("liveRearrangeDocument task started"); + liveRearrangeDocument(project, psiFile, settings, document, cursorOffset); + } + }; + + Thread t = new Thread(new Runnable() { + public void run() { + logger.debug("started thread " + Thread.currentThread().getName()); + final Application application = ApplicationManager.getApplication(); + application.runReadAction(new Runnable() { + public void run() { + logger.debug("enter application.runReadAction() on thread " + Thread.currentThread().getName()); + task.run(); + logger.debug("exit application.runReadAction() on thread " + Thread.currentThread().getName()); + } + }); + } + }, "Live Rearranger parser"); + t.start(); + logger.debug("exit buildLiveRearrangerData on thread " + Thread.currentThread().getName()); + } + + public final void liveRearrangeDocument(final Project project, + final PsiFile psiFile, + final RearrangerSettings settings, + final Document document, + final int cursorOffset) + { + logger.setLevel(Level.DEBUG); // TODO - remove debugging flag + logger.debug("enter liveRearrangeDocument on thread " + Thread.currentThread().getName()); + + RearrangerActionHandler.setCsm(CodeStyleManager.getInstance(project)); + new CommentUtil(settings); // create CommentUtil singleton + final Window window = WindowManager.getInstance().suggestParentWindow(project); + LiveRearrangerPopup fsp = new LiveRearrangerPopup(settings, psiFile, document, project, window, cursorOffset); + final Parser p = new Parser(project, settings, psiFile); + final ArrayList outerClasses = p.parseOuterLevel(); + if (outerClasses.size() > 0) { + final Mover m = new Mover(outerClasses, settings); + final ArrayList resultRuleInstances = m.rearrangeOuterClasses(); + fsp.setResultRuleInstances(resultRuleInstances); + fsp.liveRearranger(); + } + logger.debug("exit liveRearrangeDocument on thread " + Thread.currentThread().getName()); + } + + public boolean isFileWritable(PsiElement element) { + VirtualFile file = element.getContainingFile().getVirtualFile(); + if (!file.isWritable()) { + VirtualFileManager.getInstance().fireReadOnlyModificationAttempt(new VirtualFile[]{file}); + return file.isWritable(); + } + return true; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult32.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult32.java new file mode 100644 index 000000000000..e569bbfc433f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult32.java @@ -0,0 +1,11 @@ +public class Temp { +// ------------------------------ FIELDS ------------------------------ + + int field1; + +// -------------------------- OTHER METHODS -------------------------- + + public void finish() { + field1 = 2; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult33.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult33.java new file mode 100644 index 000000000000..095358b63d7b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult33.java @@ -0,0 +1,7 @@ +public class RearrangementTest33 { + double price; + + public final void setPrice(final double price) { + this.price = price; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult34.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult34.java new file mode 100644 index 000000000000..1f0429571f4f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult34.java @@ -0,0 +1,15 @@ +// ----- OUTER CLASS ----- + +public class RearrangementTest34 { +// ------------------------------ FIELDS ------------------------------ + + int i; + +// -------------------------- INNER CLASSES -------------------------- + + class inner { +// ------------------------------ FIELDS ------------------------------ + + int j; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult34B.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult34B.java new file mode 100644 index 000000000000..4a7bde488b96 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult34B.java @@ -0,0 +1,13 @@ +// ----- OUTER CLASS ----- + +public class RearrangementTest34 { +// ------------------------------ FIELDS ------------------------------ + + int i; + +// -------------------------- INNER CLASSES -------------------------- + + class inner { + int j; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult35.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult35.java new file mode 100644 index 000000000000..4075a6afd401 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult35.java @@ -0,0 +1,7 @@ +public class RearrangementTest35 { +// ----- FIELDS ----- + + int field; + + int field2; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult37.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult37.java new file mode 100644 index 000000000000..aae25d07c8c9 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult37.java @@ -0,0 +1,21 @@ +public class RearrangementTest37 { + String productOther; + + String getProductOther() { + return productOther; + } + + boolean isProductOther() { + return productOther.length() > 0; + } + + boolean setProductOther(String s) { + productOther = s; + } + + method interim1() { + } + + method interim2() { + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39.java new file mode 100644 index 000000000000..528f4584ce0b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39.java @@ -0,0 +1,8 @@ +public class RearrangementTest39 { + boolean b0; + boolean b1; + int i2; + String s0; + String s1; + String s2; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39A.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39A.java new file mode 100644 index 000000000000..3ad3bcb20be7 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39A.java @@ -0,0 +1,8 @@ +public class RearrangementTest39 { + boolean b1; + boolean b0; + int i2; + String s1; + String s2; + String s0; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39B.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39B.java new file mode 100644 index 000000000000..b4b41f419928 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39B.java @@ -0,0 +1,8 @@ +public class RearrangementTest39 { + String s0; + String s1; + String s2; + boolean b0; + boolean b1; + int i2; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39C.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39C.java new file mode 100644 index 000000000000..b9b6e21f67df --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult39C.java @@ -0,0 +1,8 @@ +public class RearrangementTest39 { + String s1; + String s2; + String s0; + boolean b1; + boolean b0; + int i2; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java new file mode 100644 index 000000000000..12b241aa0be4 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java @@ -0,0 +1,58 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + + NoRearrangementTest() { + // constructor body + } + + /** field 1. */ + private int field1; + private int field2; + public static final int field3 = 3; + public static final int field4 = 4; + final int field5 = 5; + protected int field6 = 6; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + void anotherMethod(int j) { + // anotherMethod body + } + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult40.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult40.java new file mode 100644 index 000000000000..77d8f4f703d4 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult40.java @@ -0,0 +1,31 @@ +abstract public class TestOverImpl40 + implements Runnable +{ + public String toString() { + // overrides Object.toString() + return super.toString(); //To change body of overridden methods use File | Settings | File Templates. + } + + public void run() { + // implements Runnable.run() + } + + abstract void abstractMethod(); // is implemented + + void overrideableMethod() // is overridden + { + // do nothing + } +} + +class TestOverImpl2 extends TestOverImpl { + void abstractMethod() // implements + { + // implements abstractMethod() + } + + void overrideableMethod() // overrides + { + super.overrideableMethod(); //To change body of overridden methods use File | Settings | File Templates. + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult41.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult41.java new file mode 100644 index 000000000000..899c73d58aea --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult41.java @@ -0,0 +1,5 @@ +public class RearrangementTest41 { + public final void setPrice(final double price) { + this.price = price; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult42.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult42.java new file mode 100644 index 000000000000..2ab26d2f02e5 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult42.java @@ -0,0 +1,5 @@ +public class Foo { + enum Bar {a, b, c} + + ; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult43.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult43.java new file mode 100644 index 000000000000..3c9995a3c124 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult43.java @@ -0,0 +1,13 @@ +public class RearrangementTest43 { + void method2(int a, int b) { + } + + void method3(int a, int b, int c) { + } + + void method1(int a) { + } + + void method0() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult44.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult44.java new file mode 100644 index 000000000000..8a24d11d1a0d --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult44.java @@ -0,0 +1,6 @@ +/** test generated comment with fill. */ +public class RearrangementTest44 { + // -+-+-+-+- METHODS -+-+-+-+- + private void method(int i) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult45.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult45.java new file mode 100644 index 000000000000..98727d9842f9 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult45.java @@ -0,0 +1,59 @@ +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +/** + * Class A implements Externalizable and has its own toString, equals and hashcode methods. + * Class B extends A and has its own toString, equals and hashcode methods. + * Ensure that when rearranging class B, its methods show up under 'canonical' -- not "other methods" (bug). + */ +public class NestedOverridesTest + implements Externalizable +{ +// ------------------------ CANONICAL METHODS ------------------------ + + public boolean equals(Object object) { + return super.equals(object); + } + + public int hashCode() { + return super.hashCode(); + } + + public String toString() { + return ""; + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface Externalizable --------------------- + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + } + + public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException { + } +} + +class B extends NestedOverridesTest { +// ------------------------ CANONICAL METHODS ------------------------ + + public int hashCode() { + return super.hashCode(); + } + + public String toString() { + return super.toString(); + } + +// ------------------------ INTERFACE METHODS ------------------------ + + +// --------------------- Interface Externalizable --------------------- + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + super.writeExternal(objectOutput); + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46A.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46A.java new file mode 100644 index 000000000000..56889ac57281 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46A.java @@ -0,0 +1,19 @@ +import java.util.List; +import java.util.Vector; + +public class RearrangementTest46 { + protected List validator = new Vector(); + protected Object value; + protected final String dbColumnName; + protected boolean isMandatory; + protected final String table; + protected boolean isInvalid; + protected final int sqlType; + protected String invalidText; + + RearrangementTest46() { + dbColumnName = "column"; + table = "table"; + sqlType = 0; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46B.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46B.java new file mode 100644 index 000000000000..92889eb0d9b7 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46B.java @@ -0,0 +1,19 @@ +import java.util.List; +import java.util.Vector; + +public class RearrangementTest46 { + protected List validator = new Vector(); + protected Object value; + protected boolean isMandatory; + protected boolean isInvalid; + protected String invalidText; + protected final String dbColumnName; + protected final String table; + protected final int sqlType; + + RearrangementTest46() { + dbColumnName = "column"; + table = "table"; + sqlType = 0; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46C.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46C.java new file mode 100644 index 000000000000..ad9441dddf20 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46C.java @@ -0,0 +1,19 @@ +import java.util.List; +import java.util.Vector; + +public class RearrangementTest46 { + protected List validator = new Vector(); + protected Object value; + protected final String dbColumnName; + protected final String table; + protected String invalidText; + protected boolean isMandatory; + protected boolean isInvalid; + protected final int sqlType; + + RearrangementTest46() { + dbColumnName = "column"; + table = "table"; + sqlType = 0; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46D.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46D.java new file mode 100644 index 000000000000..3cb5853fa8b2 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46D.java @@ -0,0 +1,19 @@ +import java.util.List; +import java.util.Vector; + +public class RearrangementTest46 { + protected boolean isMandatory; + protected boolean isInvalid; + protected final int sqlType; + protected List validator = new Vector(); + protected Object value; + protected final String dbColumnName; + protected final String table; + protected String invalidText; + + RearrangementTest46() { + dbColumnName = "column"; + table = "table"; + sqlType = 0; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46E.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46E.java new file mode 100644 index 000000000000..4a1b25780ae1 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult46E.java @@ -0,0 +1,19 @@ +import java.util.List; +import java.util.Vector; + +public class RearrangementTest46 { + protected final int sqlType; + protected final String dbColumnName; + protected final String table; + protected boolean isInvalid; + protected boolean isMandatory; + protected List validator = new Vector(); + protected Object value; + protected String invalidText; + + RearrangementTest46() { + dbColumnName = "column"; + table = "table"; + sqlType = 0; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult47.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult47.java new file mode 100644 index 000000000000..b7e52ca2b1b8 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult47.java @@ -0,0 +1,9 @@ +public class RearrangementTest47 { + public final static int CONSTANT1 = 1; + public final static int CONSTANT2 = 2; + + enum suits {CLUBS, DIAMONDS, HEARTS, SPADES} + + int var2 = 2; + int var3 = 3; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult5.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult5.java new file mode 100644 index 000000000000..a87994b91437 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult5.java @@ -0,0 +1,57 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +class AnotherOuterClass { + +} + +/** public class comments. */ +public class RearrangementTest { + /** field 1. */ + private int field1; + private int field2; + public static final int field3 = 3; + public static final int field4 = 4; + final int field5 = 5; + protected int field6 = 6; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + NoRearrangementTest() { + // constructor body + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + void anotherMethod(int j) { + // anotherMethod body + } + + class innerClass { + // inner class definition + } +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java new file mode 100644 index 000000000000..84252bc72ceb --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java @@ -0,0 +1,8 @@ +public class Test { + public static final String sillyField = ""; + public static final String sillyField2 = ""; + private String wibble; + protected String wobble; + public String hitandmiss; + public static int hithere; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult7.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult7.java new file mode 100644 index 000000000000..fcf27e010ae8 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult7.java @@ -0,0 +1,14 @@ +import java.util.Comparator; + +public class RearrangementTest7 { + Comparator c = new Comparator() { + public int compare(Object o, Object o1) { + return 0; //To change body of implemented methods use Options | File Templates. + } + + public boolean equals(Object o) { + return false; //To change body of implemented methods use Options | File Templates. + } + }; + int f; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult8.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult8.java new file mode 100644 index 000000000000..1e8111d0cc4b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult8.java @@ -0,0 +1,58 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + final int field5 = 5; + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + /** field 1. */ + private int field1; + private int field2; + public static final int field3 = 3; + public static final int field4 = 4; + protected int field6 = 6; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + final void method3() { + // method 3 body. + } + + NoRearrangementTest() { + // constructor body + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + void anotherMethod(int j) { + // anotherMethod body + } + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult8A.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult8A.java new file mode 100644 index 000000000000..9979ce1ba98b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult8A.java @@ -0,0 +1,19 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + + static { + // static initializer class. + } + + private int field2; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult9.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult9.java new file mode 100644 index 000000000000..8107c56ad920 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult9.java @@ -0,0 +1,58 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + + void anotherMethod(int j) { + // anotherMethod body + } + + public int getField1() { + return field1; // getter for field1 + } + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + /** field 1. */ + private int field1; + private int field2; + public static final int field3 = 3; + public static final int field4 = 4; + final int field5 = 5; + protected int field6 = 6; + + NoRearrangementTest() { + // constructor body + } + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest.java new file mode 100644 index 000000000000..8882b2f69480 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest.java @@ -0,0 +1,57 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + /** field 1. */ + private int field1; + private int field2; + public static final int field3 = 3; + public static final int field4 = 4; + final int field5 = 5; + protected int field6 = 6; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + /** method 2 comment. */ + public void method2() { + // method 2 body. + } + + final void method3() { + // method 3 body. + } + + NoRearrangementTest() { + // constructor body + } + + public int getField1() { + return field1; // getter for field1 + } + + public int setField1(int f) { + field1 = f; // setter for field1 + } + + void anotherMethod(int j) { + // anotherMethod body + } + + class innerClass { + // inner class definition + } +} + +class AnotherOuterClass { + +} + +/** + * end of file comment. + */ diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest11.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest11.java new file mode 100644 index 000000000000..54df5e39a7d2 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest11.java @@ -0,0 +1,5 @@ +public class RearrangementTest11 { + final int i; + public final int k; + int j; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest12.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest12.java new file mode 100644 index 000000000000..bc950e619355 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest12.java @@ -0,0 +1,20 @@ +class RearrangementTest12 { + int x; + String s; + + void method(int y) { + x = y; + } + + int getX() { + return x; + } + + Object convertX() { + return new Integer(x); + } + + Integer[] convertXs() { + return new Integer[]{new Integer(x), new Integer(0)}; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest13.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest13.java new file mode 100644 index 000000000000..1060fea2f3dd --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest13.java @@ -0,0 +1,28 @@ +public class RearrangerTest13 { + void GF() { // grandfather + F1(); + F2(); + } + + private void F2() { + S2A(); + S2B(); + } + + private void F1() { + S1B(); + S1A(); + } + + void S2B() { + } + + void S1B() { + } + + void S2A() { + } + + void S1A() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest14.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest14.java new file mode 100644 index 000000000000..a4e9e2575e89 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest14.java @@ -0,0 +1,13 @@ +public class RearrangementTest14 { + int doIt(int x) { + return x + 1; + } + + void GF() { + doIt(2, 3); + } + + int doIt(int x, int y) { + return x + y; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest15.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest15.java new file mode 100644 index 000000000000..edf46091b5bd --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest15.java @@ -0,0 +1,15 @@ +// test method inheritance + +public class RearrangementTest15 { + public String toString() { + return "no name"; + } + + public boolean equals(Object o) { + return false; + } + + public void noSuperMethod(boolean b) { + return false; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest16.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest16.java new file mode 100644 index 000000000000..7c021053e037 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest16.java @@ -0,0 +1,18 @@ +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class RearrangementTest16 + implements ActionListener +{ + public void notImplementor(ActionEvent e) { + } + + public void actionPerformed(ActionEvent e) { + } + + public void actionPerformed() { + } + + public void actionPerformed(int i) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest17.xml b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest17.xml new file mode 100644 index 000000000000..e3920d519b7b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest17.xml @@ -0,0 +1,5 @@ + + + Test text. + + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest18.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest18.java new file mode 100644 index 000000000000..09e6b7105016 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest18.java @@ -0,0 +1,34 @@ +public class RearrangementTest18 { + int field1; + char char2; + + RearrangementTest18() { + field1 = 10; + } + + void method1() { + char2 = 'a'; + } + + void setField1(int val) { + field1 = val; + } + + int getField1() { + return field1; + } + + char getChar2() { + return char2; + } + + void method3() { + } + + void setChar2(char val) { + char2 = val; + } + + void method4() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest18B.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest18B.java new file mode 100644 index 000000000000..3306fea0c49b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest18B.java @@ -0,0 +1,27 @@ +public class MethodEntry { + private boolean isSetter; + + public boolean isGetter() { + return isGetter; + } + + public boolean isIsSetter() { + return isSetter; + } + + public String getCustomizedPrecedingComment() { + if (customizedPrecedingComment == null) { + return ""; + } + return "comment"; + } + + public DefaultMutableTreeNode addToPopupTree() { + if (isSetter()) return null; + return null; + } + + public boolean isSetter() { + return isSetter; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest19.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest19.java new file mode 100644 index 000000000000..eebda377975b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest19.java @@ -0,0 +1,24 @@ +public class RearrangementTest19 { + RearrangementTest19() { + } + + void overloadedMethod1(int x, int y, int z) { + } + + RearrangementTest19(int x, int y) { + } + + void unoverloadedMethod() { + } + + void overloadedMethod1(int x) { + overloadedMethod1(x, 0, 0); + } + + void overloadedMethod1(int x, int y) { + overloadedMethod1(x, y, 0); + } + + RearrangementTest19(int oneParam) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java new file mode 100644 index 000000000000..c94e9d4546f9 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java @@ -0,0 +1,8 @@ +public class Test { + private String wibble; + protected String wobble; + public static final String sillyField = ""; + public String hitandmiss; + public static int hithere; + public static final String sillyField2 = ""; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest20.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest20.java new file mode 100644 index 000000000000..fc60ba8199b5 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest20.java @@ -0,0 +1,17 @@ +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class RearrangementTest20 { + private static void ChildA(final Object event) { + } + + public static void Father(final Object event) { + JCheckBox box = new JCheckBox("text"); + box.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + ChildA(e); + } + }; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest21.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest21.java new file mode 100644 index 000000000000..5d70f209a297 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest21.java @@ -0,0 +1,3 @@ +public class RearrangementTest21 { + int v, u; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest22.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest22.java new file mode 100644 index 000000000000..681b6b9ba008 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest22.java @@ -0,0 +1,11 @@ +public class RearrangementTest22 { + int i; + + public void setMyValue(int x) { + // does nothing + } + + public int getMyValue() { + return 0; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest23.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest23.java new file mode 100644 index 000000000000..ffce2e34a321 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest23.java @@ -0,0 +1,39 @@ +public class RearrangementTest23 + implements IFace2, IFace1 +{ + int method1() { + return 4; + } + + public boolean getB() { + return false; + } + + public int getY() { + return 6; + } + + public int getX() { + return getA() ? 5 : 3; + } + + public boolean getA() { + return true; + } + + int method2() { + return 7; + } +} + +interface IFace2 { + public boolean getA(); + + public boolean getB(); +} + +interface IFace1 { + public int getY(); + + public int getX(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest24.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest24.java new file mode 100644 index 000000000000..8075cdde140b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest24.java @@ -0,0 +1,137 @@ +/** + * Submitted by Nathan Brown. Causes NPE in Rearranger 1.7. (Modified to compile in test directory.) + */ + + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +/** + * @author Nathan Brown + * @version $Revision: $ $Date: $ + * @todo : doc this Copyright (c) 2001-2004 UReason. All Rights Reserved. + */ +public abstract class TestClass extends JPanel { + private JComponent _component; + private boolean _initialized; + + protected TestClass() { + this(new BorderLayout()); + } + + protected TestClass(java.awt.LayoutManager layoutManager) { + super(layoutManager); + setOpaque(false); + add(getComponent(), BorderLayout.CENTER); + getComponent().addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + componentFocusGained(e); + } + + public void focusLost(FocusEvent e) { + componentFocusLost(e); + } + }); + _initialized = true; + } + + protected void componentFocusGained(FocusEvent e) { + } + + protected void componentFocusLost(FocusEvent e) { + } + + protected JComponent getComponent() { + if (_component == null) { + _component = createComponent(); + } + return _component; + } + + protected abstract JComponent createComponent(); + + public Dimension getPreferredSize() { + return getComponent().getPreferredSize(); + } + + public Dimension getMaximumSize() { + return getComponent().getMaximumSize(); + } + + public Dimension getMinimumSize() { + return getComponent().getMinimumSize(); + } + + public void setPreferredSize(Dimension preferredSize) { + getComponent().setPreferredSize(preferredSize); + } + + public void setMaximumSize(Dimension maximumSize) { + getComponent().setMaximumSize(maximumSize); + } + + public void setMinimumSize(Dimension minimumSize) { + getComponent().setMinimumSize(minimumSize); + } + + public void updateUI() { + // we're purely a container, we don't want any defaults set on us + } + + public synchronized void addFocusListener(FocusListener l) { + getComponent().addFocusListener(l); + } + + public synchronized void removeFocusListener(FocusListener l) { + getComponent().removeFocusListener(l); + } + + public void setBorder(Border border) { + if (_initialized) { + getComponent().setBorder(border); + } + else { + super.setBorder(border); + } + } + + public Border getBorder() { + return getComponent().getBorder(); + } + + public void setToolTipText(String text) { + getComponent().setToolTipText(text); + } + + public Color getBackground() { + return getComponent().getBackground(); + } + + public Color getForeground() { + return getComponent().getForeground(); + } + + public Font getFont() { + return getComponent().getFont(); + } + + public void setForeground(Color fg) { + getComponent().setForeground(fg); + } + + public void setBackground(Color bg) { + getComponent().setBackground(bg); + } + + public void setFont(Font font) { + getComponent().setFont(font); + } + + public void setEnabled(boolean enabled) { + getComponent().setEnabled(enabled); + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest25.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest25.java new file mode 100644 index 000000000000..cdf3e7d06b6a --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest25.java @@ -0,0 +1,25 @@ +public class RearrangementTest25 { + // ... + + private double getHorizontalstrecke() { + // ... + Double meanValue = new Double(4.0f); + if (meanValue != null) { + return meanValue.getValue(); + } + // ... + return 0.0f; + } + + private double getRichtungErrorLimit(double sr, double sz, double s) { + if (s == 0f) { // (!G2Null.isValid(s)) { + + return sr; + } + return Math.sqrt(QMath.square(sr) + QMath.square(sz / s)); + } + + private void checkDoubleMessung(double messung) { + + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest26.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest26.java new file mode 100644 index 000000000000..157e4f143f8d --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest26.java @@ -0,0 +1,15 @@ +class RearrangementTest26 { + int value; + + { + value = 2; + } + + public int getValue() { + return value; + } + + public void setValue(int i) { + value = i; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest27.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest27.java new file mode 100644 index 000000000000..f51c2f9cec12 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest27.java @@ -0,0 +1,45 @@ +public class RearrangerTest27 { + private boolean constructorMethodType; + private boolean getterSetterMethodType; + private int i; + + public MethodAttributes() { + init(); + } + + private void init() { + i = 1; + } + + public final void setConstructorMethodType(final boolean constructorMethodType) { + this.constructorMethodType = constructorMethodType; + } + + public MethodAttributes(int i) { + init(); + this.i = i; + } + + private boolean isConstructorMethodType() { + return constructorMethodType; + } + + private boolean isGetterSetterMethodType() { + return getterSetterMethodType; + } + + private Object getMethodTypePanel() { + return getMethodTypeInnerPanel(); + } + + public final void setGetterSetterMethodType(final boolean getterSetterMethodType) { + this.getterSetterMethodType = getterSetterMethodType; + } + + private JPanel getMethodTypeInnerPanel() { + setConstructorMethodType(true); + setGetterSetterMethodType(false); + return new Object(); + } +} + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest28.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest28.java new file mode 100644 index 000000000000..5b21dabe1daa --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest28.java @@ -0,0 +1,46 @@ +public class RearrangementTest28 + implements InterfaceName, InterfaceName2 +{ + // start of fields + int i; +// end of fields + + // start of interface InterfaceName + public int getTime() { + return getAnother(); + } + + // end of interface InterfaceName +// start of interface InterfaceName2 + public int getDate() { + return 0; + } + + // end of interface InterfaceName2 + public int getAnother() { + return 0; + } + + // Level 1 methods + public void m1() { + m2(); + m3(); + } + + // Level 2 methods + public void m2() { + } + + public void m3() { + } +// end Level 2 methods +// end Level 1 methods +} + +interface InterfaceName { + public int getTime(); +} + +interface InterfaceName2 { + public int getDate(); +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest29.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest29.java new file mode 100644 index 000000000000..1a3c0f0d6a9b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest29.java @@ -0,0 +1,26 @@ +/** + * Id$ + * + * Rearranger plugin for IntelliJ IDEA. + * + * Source code may be freely copied and reused. Please copy credits, and send any bug fixes to the author. + * + * @author Dave Kriewall, WRQ, Inc. + * January, 2004 + */ +package com.wrq.rearranger; + +/** Illustrates rearrangement by the plugin. */ +abstract public class RearrangeMe { + abstract boolean isGood(); // matches rule 12, "abstract methods" + + /** field1 is documented here. This documentation moves with the field. */ + int field1; // matches rule 3, "non-static fields ..." + + protected RearrangeMe(int field1) // Constructor matches rule 6 + { + this.field1 = field1; + } + + public final static int CONSTANT = 1; // matches rule 1, "... static fields" +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest30.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest30.java new file mode 100644 index 000000000000..fb4989f57275 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest30.java @@ -0,0 +1,328 @@ +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import org.apache.log4j.Logger; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +/** Handles right-click in project view; applies rearrangement to a directory and its files recursively. */ +public final class ProjectTreeActionHandler + extends AnAction +{ + private static final Logger logger = Logger.getLogger("com.wrq.rearranger.ProjectTreeActionHandler"); + + + public final void actionPerformed(final AnActionEvent anActionEvent) { + logger.debug("entered actionPerformed"); + // we're being called on the Swing event dispatch thread. Spin off another thread to do the + // rearranging and let Swing's thread go. +// Thread t = new Thread(new Runnable() { +// public void run() +// { +// //To change body of implemented methods use Options | File Templates. + final Application application = ApplicationManager.getApplication(); + application.runWriteAction(new RearrangeIt(anActionEvent.getDataContext())); +// } +// }, "RearrangerThread"); +// t.start(); +// new RearrangeIt(anActionEvent.getDataContext()).run(); + } + + /** + * Test progress bar functionality. Read 10 "filenames" from console, pausing between each to update the + * progress bar dialog. Handle cancel button and dialog window close button properly. + * + * @param args + */ + public static void main(final String[] args) { + org.apache.log4j.BasicConfigurator.configure(); + // test the progress bar. + final BufferedReader reader; + final ProjectTreeActionHandler ptah = new ProjectTreeActionHandler(); + final RearrangeIt ri = ptah.new RearrangeIt(null); + final RearrangeIt.IntHolder cancelled = ri.new IntHolder(); + + reader = new BufferedReader(new InputStreamReader(System.in)); + final Cancellable c = new Cancellable() { + public void setCancel() { + System.out.println("cancel test"); + cancelled.n = 1; + } + }; + + final JDialog dialog = ri.getProgressFrame(c, 10); + int count = 0; + dialog.pack(); + dialog.setVisible(true); + while (count <= 10 && cancelled.n == 0) { + String s = null; + try { + s = reader.readLine(); + } + catch (IOException e) { + e.printStackTrace(); + } + if (cancelled.n == 0) { + ri.filename.setText(s); + count++; + ri.bar.setValue(count); + } + } + dialog.setVisible(false); + dialog.hide(); + dialog.dispose(); + System.exit(0); + } + + interface Cancellable { + void setCancel(); + } + + abstract class VirtualFileVisitor implements Cancellable { + volatile boolean cancel = false; + + public final void setCancel() { + logger.debug("VirtualFileVisitor.setCancel called"); + cancel = true; + } + + abstract void visitVirtualFile(VirtualFile f); + + final void accept(final VirtualFile f) { + if (f != null) { + visitVirtualFile(f); + } + final VirtualFile[] vfa = f.getChildren(); + if (vfa != null) { + for (int i = 0; i < vfa.length; i++) { + if (!cancel) { + accept(vfa[i]); + } + } + } + } + } + + final class RearrangeIt implements Runnable { + final class IntHolder { + public int n; + } + + final DataContext dc; + final Project project; + final JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL); + final JLabel filename = new JLabel(); + + public RearrangeIt(final DataContext dc) { + this.dc = dc; + this.project = (Project)dc.getData(DataConstants.PROJECT); + } + + public final void run() { + final VirtualFile virtualFile = (VirtualFile)dc.getData(DataConstants.VIRTUAL_FILE); + final IntHolder count = new IntHolder(); + final VirtualFileVisitor counter = new VirtualFileVisitor() { + void visitVirtualFile(final VirtualFile f) { + if (!f.isDirectory()) count.n++; + } + }; + + counter.accept(virtualFile); + logger.debug("counted " + count.n + " files"); + + final RearrangerActionHandler rah = new RearrangerActionHandler(); + final PsiDocumentManager dm = PsiDocumentManager.getInstance(project); + final PsiManager pm = PsiManager.getInstance(project); + final VirtualFileVisitor executor = new VirtualFileVisitor() { + int currentCount = 0; + + void visitVirtualFile(final VirtualFile f) { + try { + final PsiFile psiFile = pm.findFile(f); + if (psiFile != null && psiFile.canContainJavaCode()) { + logger.debug("rearrange psiFile=" + psiFile.toString()); + if (SwingUtilities.isEventDispatchThread()) { + logger.debug("event dispatch thread setting filename to " + psiFile.getName()); + filename.setText(psiFile.getName()); + } + else { + logger.debug("invokeAndWait to set filename to " + psiFile.getName()); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + logger.debug("event dispatch thread within invokeAndWait setting filename to " + + psiFile.getName()); + filename.setText(psiFile.getName()); + } + }); + } + filename.repaint(); +// filename.setText(psiFile.getName()); +// filename.paint(filename.getGraphics()); + filename.paintImmediately(filename.getVisibleRect()); + Thread.sleep(8000); + final Document document = dm.getDocument(psiFile); + if (document == null) { + logger.debug("document was null"); + } + else { +// Thread t = new Thread(new Runnable() { +// public void run() +// { + //To change body of implemented methods use Options | File Templates. + rah.runWriteActionRearrangement(project, document, psiFile); +// } +// } ); +// t.start(); + } + logger.debug("done rearranging psiFile=" + psiFile.toString()); + } + if (SwingUtilities.isEventDispatchThread()) { + logger.debug("EventDispatchThread updating progress bar value to " + currentCount); + bar.setValue(currentCount); + } + else { + logger.debug("invokeAndWait to set progress bar value to " + currentCount); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + logger.debug("EventDispatchThread within InvokeAndWait setting progress bar value to " + + currentCount); + bar.setValue(currentCount); + } + }); + } + bar.repaint(); + bar.paintImmediately(bar.getVisibleRect()); + bar.paint(bar.getGraphics()); + currentCount++; + Thread.sleep(5000); + } + catch (InterruptedException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + } + }; + + final JDialog dialog = getProgressFrame(executor, count.n); + + dialog.show(); + dialog.setVisible(true); + dialog.paint(dialog.getGraphics()); + executor.accept(virtualFile); + dialog.setVisible(false); + dialog.hide(); + dialog.dispose(); + } + + final JDialog getProgressFrame(final Cancellable cancellableObject, final int max) { + final Object parent = WindowManager.getInstance().suggestParentWindow(project); + logger.debug("suggested parent window=" + parent); + final JDialog dialog = parent == null ? + new JDialog() : (parent instanceof JDialog ? + new JDialog((JDialog)parent) : new JDialog((JFrame)parent)); + final Container pane = dialog.getContentPane(); + final JLabel rearrangingLabel = new JLabel("Rearranging files, please wait..."); +// rearrangingLabel.setFont(new Font("dialog", Font.PLAIN, 12)); + final JPanel progressPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 1; + constraints.weightx = 1; + constraints.insets = new Insets(15, 15, 0, 0); + progressPanel.add(rearrangingLabel, constraints); + constraints.gridwidth = 1; + constraints.gridy = 1; + bar.setMinimum(0); + bar.setMaximum(max); + bar.setPreferredSize(new Dimension(500, 15)); + bar.setMinimumSize(new Dimension(500, 15)); + bar.setStringPainted(true); + constraints.insets = new Insets(15, 15, 5, 15); + progressPanel.add(bar, constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 1; + constraints.insets = new Insets(9, 0, 5, 15); + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + logger.debug("cancel button pressed"); + filename.setText("cancelling..."); + cancellableObject.setCancel(); + } + }); + + progressPanel.add(cancelButton, constraints); + constraints.gridx = 0; + constraints.gridy = 2; + constraints.weighty = 1; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.insets = new Insets(0, 15, 15, 0); + filename.setSize(500, 15); + filename.setPreferredSize(new Dimension(500, 15)); +// filename.setFont(new Font("dialog", Font.PLAIN, 12)); + progressPanel.add(filename, constraints); + pane.add(progressPanel, BorderLayout.CENTER); + dialog.setTitle("Rearranger"); + dialog.addWindowListener(new WindowListener() { + public void windowClosed(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowActivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowClosing(final WindowEvent e) { + logger.debug("dialog closed, cancel Rearranger"); + filename.setText("cancelling..."); + cancellableObject.setCancel(); + } + + public void windowDeactivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowDeiconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowIconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowOpened(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + }); + + dialog.pack(); + return dialog; + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest31.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest31.java new file mode 100644 index 000000000000..577103c681d7 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest31.java @@ -0,0 +1,175 @@ +/** + * Id$ + * + * Rearranger plugin for IntelliJ IDEA. + * + * Source code may be freely copied and reused. Please copy credits, and send any bug fixes to the author. + * + * @author Dave Kriewall, WRQ, Inc. + * January, 2004 + */ +package com.wrq.rearranger; + +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.CaretModel; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.wrq.rearranger.popup.LiveRearrangerPopup; +import com.wrq.rearranger.rearrangement.Mover; +import com.wrq.rearranger.rearrangement.Parser; +import com.wrq.rearranger.settings.RearrangerSettings; +import com.wrq.rearranger.util.CommentUtil; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; + +import java.awt.*; +import java.util.ArrayList; + +/** Supports manual rearrangement of a file. */ +public final class LiveRearrangerActionHandler extends EditorActionHandler { + // ------------------------------ FIELDS ------------------------------ + private static final Logger logger = Logger.getLogger("com.wrq.rearranger.LiveRearrangerActionHandler"); + + private static boolean inProgress = false; +// -------------------------- STATIC METHODS -------------------------- + + public static CodeStyleManager getCsm() { + return RearrangerActionHandler.getCsm(); + } +// -------------------------- OTHER METHODS -------------------------- + + public final void execute(final Editor editor, final DataContext context) { + if (editor == null) { + return; + } + final Project project = (Project)context.getData(DataConstants.PROJECT); + logger.debug("project=" + project); + logger.debug("editor=" + editor); + final Document document = editor.getDocument(); + final CaretModel caret = editor.getCaretModel(); + int cursorOffset = caret.getOffset(); + final PsiFile psiFile = getFile(editor, context); + if (!psiFile.getName().endsWith(".java")) { + logger.debug("not a .java file -- skipping " + psiFile.getName()); + return; + } + if (!psiFile.isWritable()) { + logger.debug("not a writable .java file -- skipping " + psiFile.getName()); + return; + } + logger.debug("inProgress=" + inProgress); + if (inProgress) { + return; + } + + setInProgress(true); + buildLiveRearrangerData(project, document, psiFile, cursorOffset); + } + + private static PsiFile getFile(final Editor editor, + final DataContext context) + { + final Project project = (Project)context.getData(DataConstants.PROJECT); + final Document document = editor.getDocument(); + final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); + final VirtualFile virtualFile = fileDocumentManager.getFile(document); + final PsiManager psiManager = PsiManager.getInstance(project); + return psiManager.findFile(virtualFile); + } + + public static void setInProgress(boolean inProgress) { + logger.debug("set inProgress=" + inProgress); + LiveRearrangerActionHandler.inProgress = inProgress; + } + + /** + * must be called from within an IDEA read-action thread. + * + * @param project + * @param document + * @param psiFile + */ + void buildLiveRearrangerData(final Project project, + final Document document, + final PsiFile psiFile, + final int cursorOffset) + { + /** + * Per instructions from IntelliJ, we have to commit any changes to the document to the Psi + * tree. + */ + final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); + documentManager.commitDocument(document); + final RearrangerSettings settings = new RearrangerSettings(); // use default settings with no rules + settings.setAskBeforeRearranging(true); + final Runnable task = new Runnable() { + public void run() { + logger.debug("liveRearrangeDocument task started"); + liveRearrangeDocument(project, psiFile, settings, document, cursorOffset); + } + }; + + Thread t = new Thread(new Runnable() { + public void run() { + logger.debug("started thread " + Thread.currentThread().getName()); + final Application application = ApplicationManager.getApplication(); + application.runReadAction(new Runnable() { + public void run() { + logger.debug("enter application.runReadAction() on thread " + Thread.currentThread().getName()); + task.run(); + logger.debug("exit application.runReadAction() on thread " + Thread.currentThread().getName()); + } + }); + } + }, "Live Rearranger parser"); + t.start(); + logger.debug("exit buildLiveRearrangerData on thread " + Thread.currentThread().getName()); + } + + public final void liveRearrangeDocument(final Project project, + final PsiFile psiFile, + final RearrangerSettings settings, + final Document document, + final int cursorOffset) + { + logger.setLevel(Level.DEBUG); // TODO - remove debugging flag + logger.debug("enter liveRearrangeDocument on thread " + Thread.currentThread().getName()); + + RearrangerActionHandler.setCsm(CodeStyleManager.getInstance(project)); + new CommentUtil(settings); // create CommentUtil singleton + final Window window = WindowManager.getInstance().suggestParentWindow(project); + LiveRearrangerPopup fsp = new LiveRearrangerPopup(settings, psiFile, document, project, window, cursorOffset); + final Parser p = new Parser(project, settings, psiFile); + final ArrayList outerClasses = p.parseOuterLevel(); + if (outerClasses.size() > 0) { + final Mover m = new Mover(outerClasses, settings); + final ArrayList resultRuleInstances = m.rearrangeOuterClasses(); + fsp.setResultRuleInstances(resultRuleInstances); + fsp.liveRearranger(); + } + logger.debug("exit liveRearrangeDocument on thread " + Thread.currentThread().getName()); + } + + public boolean isFileWritable(PsiElement element) { + VirtualFile file = element.getContainingFile().getVirtualFile(); + if (!file.isWritable()) { + VirtualFileManager.getInstance().fireReadOnlyModificationAttempt(new VirtualFile[]{file}); + return file.isWritable(); + } + return true; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest32.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest32.java new file mode 100644 index 000000000000..58d1b54e6d63 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest32.java @@ -0,0 +1,10 @@ +public class Temp { + // ------------------------------ FIELDS ------------------------------ + int field1; + +// -------------------------- OTHER METHODS -------------------------- + + public void finish() { + field1 = 2; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest33.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest33.java new file mode 100644 index 000000000000..33bdc3d43b0a --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest33.java @@ -0,0 +1,9 @@ +public class RearrangementTest33 { + double price; + + public final void setPrice(final double price) + + { + this.price = price; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest34.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest34.java new file mode 100644 index 000000000000..e744780bee40 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest34.java @@ -0,0 +1,10 @@ +// ----- OUTER CLASS ----- + +public class RearrangementTest34 { + int i; + + // -------------------------- INNER CLASSES -------------------------- + class inner { + int j; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest35.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest35.java new file mode 100644 index 000000000000..3bccd71e49d1 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest35.java @@ -0,0 +1,7 @@ +public class RearrangementTest35 { + + + int field; + + int field2; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest36.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest36.java new file mode 100644 index 000000000000..ec9fb7c8d6ca --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest36.java @@ -0,0 +1,48 @@ +public class RearrangementTest36 { + void getRelatedMethodsPane() { + getRelatedMethodsArrangementPane(); + getRelatedMethodsCommentsPane(); + } + + private void getRelatedMethodsArrangementPane() { + getTraversalOrderPanel(); + getOrderingPanel(); + getExtractedPanel(); + getMoveMethodsPanel(); + } + + void getTraversalOrderPanel() { + } + + void getOrderingPanel() { + } + + void getExtractedPanel() { + } + + void getMoveMethodsPanel() { + enableComponents(); + enableOtherComponents(); + } + + private void enableComponents() { + } + + private void enableOtherComponents() { + enablePanel(); + } + + private void enablePanel() { + } + + private void getRelatedMethodsCommentsPane() { + getCommentAreaPanel(); + } + + private void getCommentAreaPanel(final CommentRule comment) { + } + + public static void main(final String[] args) { + new RearrangementTest36().getRelatedMethodsPane(); + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest37.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest37.java new file mode 100644 index 000000000000..1eecd4ba1e45 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest37.java @@ -0,0 +1,21 @@ +public class RearrangementTest37 { + String productOther; + + String getProductOther() { + return productOther; + } + + method interim1() { + } + + boolean isProductOther() { + return productOther.length() > 0; + } + + method interim2() { + } + + boolean setProductOther(String s) { + productOther = s; + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest38.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest38.java new file mode 100644 index 000000000000..39765534b53e --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest38.java @@ -0,0 +1,19 @@ +public class RearrangementTest38 { + + ////////////////////////////////////////////// + // Instance Methods + ////////////////////////////////////////////// + public void createData() throws Exception { + method1(); + + method2(); + } + + + private void method1() { + } + + + private void method2() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest38cfg.xml b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest38cfg.xml new file mode 100644 index 000000000000..d900d4239981 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest38cfg.xml @@ -0,0 +1,274 @@ + + + + \n\ + \ //////////////////////////////////////////////\n\ \ //\ Static\ Vars\n\ \ ////////////////////////////////////////////// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\ + \ //////////////////////////////////////////////\n\ \ //\ Instance\ Vars\n\ \ ////////////////////////////////////////////// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\ \ + //////////////////////////////////////////////\n\ \ //\ CTORS\n\ \ ////////////////////////////////////////////// + + + + + + + + + + + + + + + + + \n\ \ + //////////////////////////////////////////////\n\ \ //\ Getters/Setters\n\ \ ////////////////////////////////////////////// + + + + + + + + + + + + + + + + + \n\ + \ //////////////////////////////////////////////\n\ \ //\ Static\ Methods\n\ \ ////////////////////////////////////////////// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\ + \ //////////////////////////////////////////////\n\ \ //\ Instance\ Methods\n\ \ ////////////////////////////////////////////// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n\ \ + ////////////////////////////////////////////\n\ \ //\ EJB\ methods\n\ \ //////////////////////////////////////////// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest39.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest39.java new file mode 100644 index 000000000000..f460e7c60dd8 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest39.java @@ -0,0 +1,8 @@ +public class RearrangementTest39 { + String s1; + boolean b1; + int i2; + boolean b0; + String s2; + String s0; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest39A.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest39A.java new file mode 100644 index 000000000000..3ad3bcb20be7 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest39A.java @@ -0,0 +1,8 @@ +public class RearrangementTest39 { + boolean b1; + boolean b0; + int i2; + String s1; + String s2; + String s0; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest40.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest40.java new file mode 100644 index 000000000000..77d8f4f703d4 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest40.java @@ -0,0 +1,31 @@ +abstract public class TestOverImpl40 + implements Runnable +{ + public String toString() { + // overrides Object.toString() + return super.toString(); //To change body of overridden methods use File | Settings | File Templates. + } + + public void run() { + // implements Runnable.run() + } + + abstract void abstractMethod(); // is implemented + + void overrideableMethod() // is overridden + { + // do nothing + } +} + +class TestOverImpl2 extends TestOverImpl { + void abstractMethod() // implements + { + // implements abstractMethod() + } + + void overrideableMethod() // overrides + { + super.overrideableMethod(); //To change body of overridden methods use File | Settings | File Templates. + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest41.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest41.java new file mode 100644 index 000000000000..f8fdbe7b7526 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest41.java @@ -0,0 +1,7 @@ +public class RearrangementTest41 { + public final void setPrice(final double price) + + { + this.price = price; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest42.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest42.java new file mode 100644 index 000000000000..2ab26d2f02e5 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest42.java @@ -0,0 +1,5 @@ +public class Foo { + enum Bar {a, b, c} + + ; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest43.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest43.java new file mode 100644 index 000000000000..f474f9d263a2 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest43.java @@ -0,0 +1,13 @@ +public class RearrangementTest43 { + void method0() { + } + + void method1(int a) { + } + + void method2(int a, int b) { + } + + void method3(int a, int b, int c) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest44.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest44.java new file mode 100644 index 000000000000..bd8281b7d800 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest44.java @@ -0,0 +1,5 @@ +/** test generated comment with fill. */ +public class RearrangementTest44 { + private void method(int i) { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest45.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest45.java new file mode 100644 index 000000000000..0bcaf4e06bd7 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest45.java @@ -0,0 +1,45 @@ +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +/** + * Class A implements Externalizable and has its own toString, equals and hashcode methods. + * Class B extends A and has its own toString, equals and hashcode methods. + * Ensure that when rearranging class B, its methods show up under 'canonical' -- not "other methods" (bug). + */ +public class NestedOverridesTest + implements Externalizable +{ + public int hashCode() { + return super.hashCode(); + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + } + + public boolean equals(Object object) { + return super.equals(object); + } + + public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException { + } + + public String toString() { + return ""; + } +} + +class B extends NestedOverridesTest { + public String toString() { + return super.toString(); + } + + public void writeExternal(ObjectOutput objectOutput) throws IOException { + super.writeExternal(objectOutput); + } + + public int hashCode() { + return super.hashCode(); + } +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest46.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest46.java new file mode 100644 index 000000000000..56889ac57281 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest46.java @@ -0,0 +1,19 @@ +import java.util.List; +import java.util.Vector; + +public class RearrangementTest46 { + protected List validator = new Vector(); + protected Object value; + protected final String dbColumnName; + protected boolean isMandatory; + protected final String table; + protected boolean isInvalid; + protected final int sqlType; + protected String invalidText; + + RearrangementTest46() { + dbColumnName = "column"; + table = "table"; + sqlType = 0; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest47.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest47.java new file mode 100644 index 000000000000..e749e4a2f454 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest47.java @@ -0,0 +1,9 @@ +public class RearrangementTest47 { + public final static int CONSTANT1 = 1; + int var2 = 2; + + enum suits {CLUBS, DIAMONDS, HEARTS, SPADES} + + int var3 = 3; + public final static int CONSTANT2 = 2; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest7.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest7.java new file mode 100644 index 000000000000..7993e4a8c4f5 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest7.java @@ -0,0 +1,14 @@ +import java.util.Comparator; + +public class RearrangementTest7 { + int f; + Comparator c = new Comparator() { + public int compare(Object o, Object o1) { + return 0; //To change body of implemented methods use Options | File Templates. + } + + public boolean equals(Object o) { + return false; //To change body of implemented methods use Options | File Templates. + } + }; +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest8.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest8.java new file mode 100644 index 000000000000..37802e109f93 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest8.java @@ -0,0 +1,19 @@ +/** + * leading comments. + */ +package com.wrq.rearranger; + +/** public class comments. */ +public class RearrangementTest { + + private int field2; + + /** method 1 comment. */ + void method1() { + // method 1 body. + } + + static { + // static initializer class. + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult1.java new file mode 100644 index 000000000000..2a93e8f6a92b --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult1.java @@ -0,0 +1,13 @@ +/** class comment */ +public class SpaceTest1 { + /** first field. */ + int firstField; + + /** method */ + void method1() { + int i = 3; + if (i < 3) { + i = 5; + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult2.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult2.java new file mode 100644 index 000000000000..f3a09fc1ab33 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult2.java @@ -0,0 +1,20 @@ +/** class comment */ +public class SpaceTest1 { + + + /** first field. */ + int firstField; + + /** method */ + void method1() { + + + int i = 3; + if (i < 3) { + i = 5; + } + } + + void method2() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult3.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult3.java new file mode 100644 index 000000000000..adbeb6f7725f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult3.java @@ -0,0 +1,18 @@ +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class SpaceTest3 { + void method() { + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + int i = 0; // logger.debug("cancel button pressed"); + String s = "cancelling"; // filename.setText("cancelling..."); + // cancellableObject.setCancel(); + } + }); + JPanel progressPanel = new JPanel(); + progressPanel.add(cancelButton); + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult4.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult4.java new file mode 100644 index 000000000000..6e21c3e5e254 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult4.java @@ -0,0 +1,335 @@ +/** + * Id$ + * + * Rearranger plugin for IntelliJ IDEA. + * + * Source code may be freely copied and reused. Please copy credits, and send any bug fixes to the author. + * + * @author Dave Kriewall, WRQ, Inc. + * October, 2003 + */ +package com.wrq.rearranger; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import org.apache.log4j.Logger; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +/** Handles right-click in project view; applies rearrangement to a directory and its files recursively. */ +public final class ProjectTreeActionHandler + extends AnAction +{ + private static final Logger logger = Logger.getLogger("com.wrq.rearranger.ProjectTreeActionHandler"); + + + public final void actionPerformed(final AnActionEvent anActionEvent) { + logger.debug("entered actionPerformed"); + // we're being called on the Swing event dispatch thread. Spin off another thread to do the + // rearranging and let Swing's thread go. +// Thread t = new Thread(new Runnable() { +// public void run() +// { +// //To change body of implemented methods use Options | File Templates. + final Application application = ApplicationManager.getApplication(); + application.runWriteAction(new RearrangeIt(anActionEvent.getDataContext())); +// } +// }, "RearrangerThread"); +// t.start(); +// new RearrangeIt(anActionEvent.getDataContext()).run(); + } + + /** + * Test progress bar functionality. Read 10 "filenames" from console, pausing between each to update the + * progress bar dialog. Handle cancel button and dialog window close button properly. + * + * @param args + */ + public static void main(final String[] args) { + org.apache.log4j.BasicConfigurator.configure(); + // test the progress bar. + final BufferedReader reader; + final ProjectTreeActionHandler ptah = new ProjectTreeActionHandler(); + final RearrangeIt ri = ptah.new RearrangeIt(null); + final RearrangeIt.IntHolder cancelled = ri.new IntHolder(); + + reader = new BufferedReader(new InputStreamReader(System.in)); + final Cancellable c = new Cancellable() { + public void setCancel() { + System.out.println("cancel test"); + cancelled.n = 1; + } + }; + final JDialog dialog = ri.getProgressFrame(c, 10); + int count = 0; + dialog.pack(); + dialog.setVisible(true); + while (count <= 10 && cancelled.n == 0) { + String s = null; + try { + s = reader.readLine(); + } + catch (IOException e) { + e.printStackTrace(); + } + if (cancelled.n == 0) { + ri.filename.setText(s); + count++; + ri.bar.setValue(count); + } + } + dialog.setVisible(false); + dialog.hide(); + dialog.dispose(); + System.exit(0); + } + + interface Cancellable { + void setCancel(); + } + + abstract class VirtualFileVisitor implements Cancellable { + volatile boolean cancel = false; + + public final void setCancel() { + logger.debug("VirtualFileVisitor.setCancel called"); + cancel = true; + } + + abstract void visitVirtualFile(VirtualFile f); + + final void accept(final VirtualFile f) { + if (f != null) { + visitVirtualFile(f); + } + final VirtualFile[] vfa = f.getChildren(); + if (vfa != null) { + for (int i = 0; i < vfa.length; i++) { + if (!cancel) { + accept(vfa[i]); + } + } + } + } + } + + final class RearrangeIt implements Runnable { + final class IntHolder { + public int n; + } + + final DataContext dc; + final Project project; + final JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL); + final JLabel filename = new JLabel(); + + public RearrangeIt(final DataContext dc) { + this.dc = dc; + this.project = (Project)dc.getData(DataConstants.PROJECT); + } + + public final void run() { + final VirtualFile virtualFile = (VirtualFile)dc.getData(DataConstants.VIRTUAL_FILE); + final IntHolder count = new IntHolder(); + final VirtualFileVisitor counter = new VirtualFileVisitor() { + void visitVirtualFile(final VirtualFile f) { + if (!f.isDirectory()) count.n++; + } + }; + counter.accept(virtualFile); + logger.debug("counted " + count.n + " files"); + + final RearrangerActionHandler rah = new RearrangerActionHandler(); + final PsiDocumentManager dm = PsiDocumentManager.getInstance(project); + final PsiManager pm = PsiManager.getInstance(project); + final VirtualFileVisitor executor = new VirtualFileVisitor() { + int currentCount = 0; + + void visitVirtualFile(final VirtualFile f) { + try { + final PsiFile psiFile = pm.findFile(f); + if (psiFile != null && psiFile.canContainJavaCode()) { + logger.debug("rearrange psiFile=" + psiFile.toString()); + if (SwingUtilities.isEventDispatchThread()) { + logger.debug("event dispatch thread setting filename to " + psiFile.getName()); + filename.setText(psiFile.getName()); + } + else { + logger.debug("invokeAndWait to set filename to " + psiFile.getName()); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + logger.debug("event dispatch thread within invokeAndWait setting filename to " + + psiFile.getName()); + filename.setText(psiFile.getName()); + } + }); + } + filename.repaint(); +// filename.setText(psiFile.getName()); +// filename.paint(filename.getGraphics()); + filename.paintImmediately(filename.getVisibleRect()); + Thread.sleep(8000); + final Document document = dm.getDocument(psiFile); + if (document == null) { + logger.debug("document was null"); + } + else { +// Thread t = new Thread(new Runnable() { +// public void run() +// { + //To change body of implemented methods use Options | File Templates. + rah.runWriteActionRearrangement(project, document, psiFile); +// } +// } ); +// t.start(); + } + logger.debug("done rearranging psiFile=" + psiFile.toString()); + } + if (SwingUtilities.isEventDispatchThread()) { + logger.debug("EventDispatchThread updating progress bar value to " + currentCount); + bar.setValue(currentCount); + } + else { + logger.debug("invokeAndWait to set progress bar value to " + currentCount); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + logger.debug("EventDispatchThread within InvokeAndWait setting progress bar value to " + + currentCount); + bar.setValue(currentCount); + } + }); + } + bar.repaint(); + bar.paintImmediately(bar.getVisibleRect()); + bar.paint(bar.getGraphics()); + currentCount++; + Thread.sleep(5000); + } + catch (InterruptedException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + } + }; + final JDialog dialog = getProgressFrame(executor, count.n); + + dialog.show(); + dialog.setVisible(true); + dialog.paint(dialog.getGraphics()); + executor.accept(virtualFile); + dialog.setVisible(false); + dialog.hide(); + dialog.dispose(); + } + + final JDialog getProgressFrame(final Cancellable cancellableObject, final int max) { + final Object parent = WindowManager.getInstance().suggestParentWindow(project); + logger.debug("suggested parent window=" + parent); + final JDialog dialog = parent == null ? + new JDialog() : (parent instanceof JDialog ? + new JDialog((JDialog)parent) : new JDialog((JFrame)parent)); + final Container pane = dialog.getContentPane(); + final JLabel rearrangingLabel = new JLabel("Rearranging files, please wait..."); +// rearrangingLabel.setFont(new Font("dialog", Font.PLAIN, 12)); + final JPanel progressPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 1; + constraints.weightx = 1; + constraints.insets = new Insets(15, 15, 0, 0); + progressPanel.add(rearrangingLabel, constraints); + constraints.gridwidth = 1; + constraints.gridy = 1; + bar.setMinimum(0); + bar.setMaximum(max); + bar.setPreferredSize(new Dimension(500, 15)); + bar.setMinimumSize(new Dimension(500, 15)); + bar.setStringPainted(true); + constraints.insets = new Insets(15, 15, 5, 15); + progressPanel.add(bar, constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 1; + constraints.insets = new Insets(9, 0, 5, 15); + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + logger.debug("cancel button pressed"); + filename.setText("cancelling..."); + cancellableObject.setCancel(); + } + }); + progressPanel.add(cancelButton, constraints); + constraints.gridx = 0; + constraints.gridy = 2; + constraints.weighty = 1; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.insets = new Insets(0, 15, 15, 0); + filename.setSize(500, 15); + filename.setPreferredSize(new Dimension(500, 15)); +// filename.setFont(new Font("dialog", Font.PLAIN, 12)); + progressPanel.add(filename, constraints); + pane.add(progressPanel, BorderLayout.CENTER); + dialog.setTitle("Rearranger"); + dialog.addWindowListener(new WindowListener() { + public void windowClosed(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowActivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowClosing(final WindowEvent e) { + logger.debug("dialog closed, cancel Rearranger"); + filename.setText("cancelling..."); + cancellableObject.setCancel(); + } + + public void windowDeactivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowDeiconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowIconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowOpened(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + }); + dialog.pack(); + return dialog; + } + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult5.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult5.java new file mode 100644 index 000000000000..7bce95f3b2d6 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult5.java @@ -0,0 +1,41 @@ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. + * User: davek + * Date: Oct 31, 2003 + * Time: 11:48:02 AM + * To change this template use Options | File Templates. + */ +final class SpaceTest5 { +// ------------------------------ FIELDS ------------------------------ + + public static final int CONSTANT3 = 3; + public static final int CONSTANT4 = 4; + /** end of public static final fields */ + private final int privateField5; + +// --------------------------- CONSTRUCTORS --------------------------- + + public TestClass2(final int privateField1) { + this.privateField5 = privateField1; + } + +// -------------------------- INNER CLASSES -------------------------- + + class inner1 { + // test class + } + + + class inner2 { + // test class + } +} + + +class outer1 { + // test class +} + + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult6.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult6.java new file mode 100644 index 000000000000..43a50907c1a5 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult6.java @@ -0,0 +1,37 @@ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. + * User: davek + * Date: Oct 31, 2003 + * Time: 11:48:02 AM + * To change this template use Options | File Templates. + */ +final class TestClass2 { +// ------------------------------ FIELDS ------------------------------ + + public static final int CONSTANT3 = 3; + public static final int CONSTANT4 = 4; + /** end of public static final fields */ + private final int privateField5; + +// --------------------------- CONSTRUCTORS --------------------------- + + public TestClass2(final int privateField1) { + this.privateField5 = privateField1; + } + +// -------------------------- INNER CLASSES -------------------------- + + class inner1 { + // test class + } + + class inner2 { + // test class + } +} + +class outer1 { + // test class +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult7.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult7.java new file mode 100644 index 000000000000..679c93032622 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult7.java @@ -0,0 +1,97 @@ +package com.opsx.bean; + +import com.opsx.exception.EnvironmentsNotDefinedException; +import com.opsx.main.Environment; +import com.opsx.main.EnvironmentManager; +import com.opsx.main.UserManager; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.util.List; + +/** + * @author abrown + * Copyright OpsTechnology Mar 31, 2004 + */ +public class Setup { + + + ******************************FIELDS****************************** + private JTextField environmentName; + private JTextField firstLogFolder; + private JTextField optionalLogFolder; + private JComboBox environmentList; + private JButton save; + private JPanel mainPanel; + private EnvironmentManager environmentManager = null; + private JTextField pathToOutputFile; + + + ******************************CONSTRUCTORS****************************** + + public Setup() throws EnvironmentsNotDefinedException, IOException, ClassNotFoundException { + UserManager userManager = UserManager.getUserManager(); + + environmentManager = EnvironmentManager.getEnvironmentManager(userManager.getUserName()); + + + Environment currentEnvironment = environmentManager.getCurrentEnvironment(); + + environmentName.setText(currentEnvironment.getName()); + firstLogFolder.setText(currentEnvironment.getFirstLogFolder()); + optionalLogFolder.setText(currentEnvironment.getOptionalLogFolder()); + pathToOutputFile.setText(currentEnvironment.getPathToOutputFile()); + + createDropDownList(currentEnvironment.getName()); + + + save.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (Setup.this.environmentName == null || + Setup.this.environmentName.getText().equals("")) + { + JOptionPane dialog = new JOptionPane(); + dialog.showMessageDialog(null, "Environment name can not be blank"); + return; + } + if (Setup.this.firstLogFolder == null || + Setup.this.firstLogFolder.getText().equals("")) + { + JOptionPane dialog = new JOptionPane(); + dialog.showMessageDialog(null, "First log folder can not be blank"); + return; + } + Environment environment = new Environment(Setup.this.environmentName.getText(), + Setup.this.firstLogFolder.getText(), + Setup.this.optionalLogFolder.getText(), + Setup.this.pathToOutputFile.getText()); + try { + Setup.this.environmentManager.saveEnvironment(environment); + Setup.this.createDropDownList(environment.getName()); + } + catch (IOException e1) { + JOptionPane dialog = new JOptionPane(); + dialog.showMessageDialog(null, "Could not persist the environment info: " + e1.getMessage()); + e1.printStackTrace(); + return; + } + } + }); + } + + ******************************METHODS****************************** + + private void createDropDownList(String currentEnvironmentName) { + List envList = environmentManager.getEnvironmentNames(); + String[] names = (String[])envList.toArray(new String[0]); + ComboBoxModel comboModel = new DefaultComboBoxModel(names); + environmentList.setModel(comboModel); + environmentList.setSelectedItem(currentEnvironmentName); + } + + public JPanel getMainPanel() { + return mainPanel; + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult8.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult8.java new file mode 100644 index 000000000000..363ec5485017 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceResult8.java @@ -0,0 +1,11 @@ +public class Tester { +// -------------------------- OTHER METHODS -------------------------- + + void test() { + X x = new X() { + }; + } +} + +interface X { +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest1.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest1.java new file mode 100644 index 000000000000..ebc57ecea80c --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest1.java @@ -0,0 +1,22 @@ +/** class comment */ +public class SpaceTest1 { + + + /** first field. */ + int firstField; + + /** method */ + void method1() { + + + int i = 3; + if (i < 3) { + + i = 5; + } + } +} + + + + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest2.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest2.java new file mode 100644 index 000000000000..d6d7a9d1f144 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest2.java @@ -0,0 +1,16 @@ +/** class comment */ +public class SpaceTest1 { + /** first field. */ + int firstField; + + /** method */ + void method1() { + int i = 3; + if (i < 3) { + i = 5; + } + } + + void method2() { + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest3.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest3.java new file mode 100644 index 000000000000..adbeb6f7725f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest3.java @@ -0,0 +1,18 @@ +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class SpaceTest3 { + void method() { + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + int i = 0; // logger.debug("cancel button pressed"); + String s = "cancelling"; // filename.setText("cancelling..."); + // cancellableObject.setCancel(); + } + }); + JPanel progressPanel = new JPanel(); + progressPanel.add(cancelButton); + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest4.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest4.java new file mode 100644 index 000000000000..c6c6a1e5499f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest4.java @@ -0,0 +1,337 @@ +/** + * Id$ + * + * Rearranger plugin for IntelliJ IDEA. + * + * Source code may be freely copied and reused. Please copy credits, and send any bug fixes to the author. + * + * @author Dave Kriewall, WRQ, Inc. + * October, 2003 + */ +package com.wrq.rearranger; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataConstants; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import org.apache.log4j.Logger; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +/** Handles right-click in project view; applies rearrangement to a directory and its files recursively. */ +public final class ProjectTreeActionHandler + extends AnAction +{ + private static final Logger logger = Logger.getLogger("com.wrq.rearranger.ProjectTreeActionHandler"); + + + public final void actionPerformed(final AnActionEvent anActionEvent) { + logger.debug("entered actionPerformed"); + // we're being called on the Swing event dispatch thread. Spin off another thread to do the + // rearranging and let Swing's thread go. +// Thread t = new Thread(new Runnable() { +// public void run() +// { +// //To change body of implemented methods use Options | File Templates. + final Application application = ApplicationManager.getApplication(); + application.runWriteAction(new RearrangeIt(anActionEvent.getDataContext())); +// } +// }, "RearrangerThread"); +// t.start(); +// new RearrangeIt(anActionEvent.getDataContext()).run(); + } + + /** + * Test progress bar functionality. Read 10 "filenames" from console, pausing between each to update the + * progress bar dialog. Handle cancel button and dialog window close button properly. + * + * @param args + */ + public static void main(final String[] args) { + org.apache.log4j.BasicConfigurator.configure(); + // test the progress bar. + final BufferedReader reader; + final ProjectTreeActionHandler ptah = new ProjectTreeActionHandler(); + final RearrangeIt ri = ptah.new RearrangeIt(null); + final RearrangeIt.IntHolder cancelled = ri.new IntHolder(); + + reader = new BufferedReader(new InputStreamReader(System.in)); + final Cancellable c = new Cancellable() { + public void setCancel() { + System.out.println("cancel test"); + cancelled.n = 1; + } + }; + final JDialog dialog = ri.getProgressFrame(c, 10); + int count = 0; + dialog.pack(); + dialog.setVisible(true); + while (count <= 10 && cancelled.n == 0) { + String s = null; + try { + s = reader.readLine(); + } + catch (IOException e) { + e.printStackTrace(); + } + if (cancelled.n == 0) { + ri.filename.setText(s); + count++; + ri.bar.setValue(count); + } + } + dialog.setVisible(false); + dialog.hide(); + dialog.dispose(); + System.exit(0); + } + + interface Cancellable { + void setCancel(); + } + + abstract class VirtualFileVisitor implements Cancellable { + volatile boolean cancel = false; + + public final void setCancel() { + logger.debug("VirtualFileVisitor.setCancel called"); + cancel = true; + } + + abstract void visitVirtualFile(VirtualFile f); + + final void accept(final VirtualFile f) { + if (f != null) { + visitVirtualFile(f); + } + final VirtualFile[] vfa = f.getChildren(); + if (vfa != null) { + for (int i = 0; i < vfa.length; i++) { + if (!cancel) { + + accept(vfa[i]); + } + } + } + } + } + + final class RearrangeIt implements Runnable { + final class IntHolder { + public int n; + } + + final DataContext dc; + final Project project; + final JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL); + final JLabel filename = new JLabel(); + + public RearrangeIt(final DataContext dc) { + this.dc = dc; + this.project = (Project)dc.getData(DataConstants.PROJECT); + } + + public final void run() { + final VirtualFile virtualFile = (VirtualFile)dc.getData(DataConstants.VIRTUAL_FILE); + final IntHolder count = new IntHolder(); + final VirtualFileVisitor counter = new VirtualFileVisitor() { + void visitVirtualFile(final VirtualFile f) { + if (!f.isDirectory()) count.n++; + } + }; + counter.accept(virtualFile); + logger.debug("counted " + count.n + " files"); + + final RearrangerActionHandler rah = new RearrangerActionHandler(); + final PsiDocumentManager dm = PsiDocumentManager.getInstance(project); + final PsiManager pm = PsiManager.getInstance(project); + final VirtualFileVisitor executor = new VirtualFileVisitor() { + int currentCount = 0; + + void visitVirtualFile(final VirtualFile f) { + try { + final PsiFile psiFile = pm.findFile(f); + if (psiFile != null && psiFile.canContainJavaCode()) { + logger.debug("rearrange psiFile=" + psiFile.toString()); + if (SwingUtilities.isEventDispatchThread()) { + logger.debug("event dispatch thread setting filename to " + psiFile.getName()); + filename.setText(psiFile.getName()); + } + else { + logger.debug("invokeAndWait to set filename to " + psiFile.getName()); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + logger.debug("event dispatch thread within invokeAndWait setting filename to " + + psiFile.getName()); + filename.setText(psiFile.getName()); + } + }); + } + filename.repaint(); +// filename.setText(psiFile.getName()); +// filename.paint(filename.getGraphics()); + filename.paintImmediately(filename.getVisibleRect()); + Thread.sleep(8000); + final Document document = dm.getDocument(psiFile); + if (document == null) { + logger.debug("document was null"); + } + else { +// Thread t = new Thread(new Runnable() { +// public void run() +// { + //To change body of implemented methods use Options | File Templates. + rah.runWriteActionRearrangement(project, document, psiFile); +// } +// } ); +// t.start(); + } + logger.debug("done rearranging psiFile=" + psiFile.toString()); + } + if (SwingUtilities.isEventDispatchThread()) { + logger.debug("EventDispatchThread updating progress bar value to " + currentCount); + bar.setValue(currentCount); + } + else { + logger.debug("invokeAndWait to set progress bar value to " + currentCount); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + logger.debug("EventDispatchThread within InvokeAndWait setting progress bar value to " + + currentCount); + bar.setValue(currentCount); + } + }); + } + bar.repaint(); + bar.paintImmediately(bar.getVisibleRect()); + bar.paint(bar.getGraphics()); + currentCount++; + Thread.sleep(5000); + } + catch (InterruptedException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + catch (InvocationTargetException e) { + e.printStackTrace(); //To change body of catch statement use Options | File Templates. + } + } + }; + final JDialog dialog = getProgressFrame(executor, count.n); + + dialog.show(); + dialog.setVisible(true); + dialog.paint(dialog.getGraphics()); + executor.accept(virtualFile); + dialog.setVisible(false); + dialog.hide(); + dialog.dispose(); + } + + final JDialog getProgressFrame(final Cancellable cancellableObject, final int max) { + final Object parent = WindowManager.getInstance().suggestParentWindow(project); + logger.debug("suggested parent window=" + parent); + final JDialog dialog = parent == null ? + new JDialog() : (parent instanceof JDialog ? + new JDialog((JDialog)parent) : new JDialog((JFrame)parent)); + final Container pane = dialog.getContentPane(); + final JLabel rearrangingLabel = new JLabel("Rearranging files, please wait..."); +// rearrangingLabel.setFont(new Font("dialog", Font.PLAIN, 12)); + final JPanel progressPanel = new JPanel(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.fill = GridBagConstraints.NONE; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = 1; + constraints.weightx = 1; + constraints.insets = new Insets(15, 15, 0, 0); + progressPanel.add(rearrangingLabel, constraints); + constraints.gridwidth = 1; + constraints.gridy = 1; + bar.setMinimum(0); + bar.setMaximum(max); + bar.setPreferredSize(new Dimension(500, 15)); + bar.setMinimumSize(new Dimension(500, 15)); + bar.setStringPainted(true); + constraints.insets = new Insets(15, 15, 5, 15); + progressPanel.add(bar, constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridx = 1; + constraints.insets = new Insets(9, 0, 5, 15); + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + logger.debug("cancel button pressed"); + filename.setText("cancelling..."); + cancellableObject.setCancel(); + } + }); + progressPanel.add(cancelButton, constraints); + constraints.gridx = 0; + constraints.gridy = 2; + constraints.weighty = 1; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.insets = new Insets(0, 15, 15, 0); + filename.setSize(500, 15); + filename.setPreferredSize(new Dimension(500, 15)); +// filename.setFont(new Font("dialog", Font.PLAIN, 12)); + progressPanel.add(filename, constraints); + pane.add(progressPanel, BorderLayout.CENTER); + dialog.setTitle("Rearranger"); + dialog.addWindowListener(new WindowListener() { + public void windowClosed(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowActivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowClosing(final WindowEvent e) { + logger.debug("dialog closed, cancel Rearranger"); + filename.setText("cancelling..."); + cancellableObject.setCancel(); + } + + public void windowDeactivated(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowDeiconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowIconified(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + + public void windowOpened(final WindowEvent e) { + //To change body of implemented methods use Options | File Templates. + } + }); + dialog.pack(); + return dialog; + } + } +} + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest5.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest5.java new file mode 100644 index 000000000000..b3c7b8b14dde --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest5.java @@ -0,0 +1,42 @@ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. + * User: davek + * Date: Oct 31, 2003 + * Time: 11:48:02 AM + * To change this template use Options | File Templates. + */ +final class SpaceTest5 { +// ------------------------------ FIELDS ------------------------------ + + public static final int CONSTANT3 = 3; + public static final int CONSTANT4 = 4; + /** end of public static final fields */ + private final int privateField5; + +// --------------------------- CONSTRUCTORS --------------------------- + + public TestClass2(final int privateField1) { + this.privateField5 = privateField1; + } + + + class inner1 { + // test class + } + + + class inner2 { + // test class + } +} + + +class outer1 { + // test class +} + + + + diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest6.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest6.java new file mode 100644 index 000000000000..86871ec6db2f --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest6.java @@ -0,0 +1,38 @@ +package com.wrq.rearranger.testClasses; + +/** + * Created by IntelliJ IDEA. + * User: davek + * Date: Oct 31, 2003 + * Time: 11:48:02 AM + * To change this template use Options | File Templates. + */ +final class TestClass2 { +// ------------------------------ FIELDS ------------------------------ + + public static final int CONSTANT3 = 3; + public static final int CONSTANT4 = 4; + /** end of public static final fields */ + private final int privateField5; + +// --------------------------- CONSTRUCTORS --------------------------- + + public TestClass2(final int privateField1) { + this.privateField5 = privateField1; + } + +// -------------------------- INNER CLASSES -------------------------- + + class inner1 { + // test class + } + + + class inner2 { + // test class + } +} + +class outer1 { + // test class +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest7.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest7.java new file mode 100644 index 000000000000..f7b849ddf327 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest7.java @@ -0,0 +1,100 @@ +package com.opsx.bean; + +import com.opsx.exception.EnvironmentsNotDefinedException; +import com.opsx.main.Environment; +import com.opsx.main.EnvironmentManager; +import com.opsx.main.UserManager; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.util.List; + +/** + * @author abrown + * Copyright OpsTechnology Mar 31, 2004 + */ + + +public class Setup { + + + private JTextField environmentName; + private JTextField firstLogFolder; + private JTextField optionalLogFolder; + + private JComboBox environmentList; + private JButton save; + + + public JPanel getMainPanel() { + return mainPanel; + } + + + private JPanel mainPanel; + + private EnvironmentManager environmentManager = null; + private JTextField pathToOutputFile; + + + public Setup() throws EnvironmentsNotDefinedException, IOException, ClassNotFoundException { + UserManager userManager = UserManager.getUserManager(); + + environmentManager = EnvironmentManager.getEnvironmentManager(userManager.getUserName()); + + + Environment currentEnvironment = environmentManager.getCurrentEnvironment(); + + environmentName.setText(currentEnvironment.getName()); + firstLogFolder.setText(currentEnvironment.getFirstLogFolder()); + optionalLogFolder.setText(currentEnvironment.getOptionalLogFolder()); + pathToOutputFile.setText(currentEnvironment.getPathToOutputFile()); + + createDropDownList(currentEnvironment.getName()); + + + save.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (Setup.this.environmentName == null || + Setup.this.environmentName.getText().equals("")) + { + JOptionPane dialog = new JOptionPane(); + dialog.showMessageDialog(null, "Environment name can not be blank"); + return; + } + if (Setup.this.firstLogFolder == null || + Setup.this.firstLogFolder.getText().equals("")) + { + JOptionPane dialog = new JOptionPane(); + dialog.showMessageDialog(null, "First log folder can not be blank"); + return; + } + Environment environment = new Environment(Setup.this.environmentName.getText(), + Setup.this.firstLogFolder.getText(), + Setup.this.optionalLogFolder.getText(), + Setup.this.pathToOutputFile.getText()); + try { + Setup.this.environmentManager.saveEnvironment(environment); + Setup.this.createDropDownList(environment.getName()); + } + catch (IOException e1) { + JOptionPane dialog = new JOptionPane(); + dialog.showMessageDialog(null, "Could not persist the environment info: " + e1.getMessage()); + e1.printStackTrace(); + return; + } + } + }); + } + + + private void createDropDownList(String currentEnvironmentName) { + List envList = environmentManager.getEnvironmentNames(); + String[] names = (String[])envList.toArray(new String[0]); + ComboBoxModel comboModel = new DefaultComboBoxModel(names); + environmentList.setModel(comboModel); + environmentList.setSelectedItem(currentEnvironmentName); + } +} diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest7cfg.xml b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest7cfg.xml new file mode 100644 index 000000000000..d46de5f9e532 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest7cfg.xml @@ -0,0 +1,325 @@ + + + + \n + + + ****************************** FIELDS ****************************** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n + + + ****************************** CONSTRUCTORS ****************************** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n + + + ****************************** METHODS ****************************** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n + + + + + + + + + + + + + + + + + \n + + + ****************************** INNER CLASSES ****************************** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest8.java b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest8.java new file mode 100644 index 000000000000..31a55a373d47 --- /dev/null +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/SpaceTest8.java @@ -0,0 +1,9 @@ +public class Tester { + void test() { + X x = new X() { + }; + } +} + +interface X { +} \ No newline at end of file diff --git a/plugins/rearranger/test/testData/defaultConfiguration.xml b/plugins/rearranger/test/testData/defaultConfiguration.xml new file mode 100644 index 000000000000..8a25e6940fc2 --- /dev/null +++ b/plugins/rearranger/test/testData/defaultConfiguration.xml @@ -0,0 +1,262 @@ + + + + + // ------------------------------ FIELDS ------------------------------ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // -------------------------- STATIC METHODS -------------------------- + + + + + + + + + + + + + + + + + + // --------------------------- CONSTRUCTORS --------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // --------------------- GETTER / SETTER METHODS --------------------- + + + + + + + + + + + + + + + + + + // ------------------------ CANONICAL METHODS ------------------------ + + + + + + + + + + + + + + + + + + // ------------------------ INTERFACE METHODS ------------------------ + + + + + + // --------------------- Interface %IF% --------------------- + + + + + + + + // -------------------------- OTHER METHODS -------------------------- + + + + + + + + + + + + + + + + + + // -------------------------- INNER CLASSES -------------------------- + + + + + + + + + + // --------------------------- main() method --------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +