From 3e52bf6b2781857912c7f3140048be31fb76423a Mon Sep 17 00:00:00 2001 From: Brian Remedios Date: Mon, 26 Jul 2010 05:23:43 +0000 Subject: [PATCH] +properties column now highlights non-default values (still a bit buggy) +internals: new visitor pattern for manipulating all selections +able to disable rules from the violation list +grouped rules show all unique priority values +revised filter column icons +revised plugin.xml to export code for other plugins +new opening Rule panel for Rule creation wizard git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@7109 51baf565-9d33-0410-a72c-fc3788e3496d --- .../.classpath | 42 +- .../.settings/org.eclipse.jdt.ui.prefs | 54 + .../CHANGELOG.txt | 1 + .../META-INF/MANIFEST.MF | 24 +- .../icons/btn_diamond_white.png | Bin 0 -> 175 bytes .../icons/btn_dot_white.png | Bin 0 -> 168 bytes .../icons/filter_r.png | Bin 0 -> 391 bytes .../icons/filter_x.png | Bin 562 -> 354 bytes .../icons/icon_filter.png | Bin 0 -> 241 bytes .../icons/icon_spinningArrows.png | Bin 0 -> 382 bytes .../messages.properties | 20 +- .../plugin.xml | 61 +- .../pmd/eclipse/plugin/PMDPlugin.java | 13 + .../eclipse/runtime/builder/MarkerUtil.java | 50 +- .../runtime/cmd/DisableRuleHandler.java | 16 + .../eclipse/runtime/cmd/RenderReportCmd.java | 4 +- .../eclipse/runtime/cmd/ReviewCodeCmd.java | 6 +- .../preferences/impl/PreferenceUIStore.java | 5 +- .../pmd/eclipse/ui/PMDUiConstants.java | 6 +- .../pmd/eclipse/ui/actions/RuleSetUtil.java | 3 +- .../pmd/eclipse/ui/model/FileRecord.java | 8 +- .../pmd/eclipse/ui/nls/StringKeys.java | 12 +- .../ui/preferences/CPDPreferencePage.java | 1 - .../br/AbstractColumnDescriptor.java | 54 + .../br/AbstractPMDPreferencePage.java | 31 +- .../br/AbstractRuleColumnDescriptor.java | 67 +- .../br/AbstractTreeTableManager.java | 466 +++++++++ .../br/BasicRuleFieldAccessor.java | 31 +- .../preferences/br/BasicValueFormatter.java | 25 + .../ui/preferences/br/CellPainterBuilder.java | 2 +- .../ui/preferences/br/ColumnDescriptor.java | 9 + .../ui/preferences/br/EditorFactory.java | 20 +- .../ui/preferences/br/FormatManager.java | 50 + .../preferences/br/IconColumnDescriptor.java | 25 +- .../preferences/br/ImageColumnDescriptor.java | 35 +- .../ui/preferences/br/ImplementationType.java | 12 + .../ui/preferences/br/IndexedString.java | 30 + .../ui/preferences/br/ModifyListener.java | 2 +- .../ui/preferences/br/NewPropertyDialog.java | 156 +-- .../ui/preferences/br/PMDPreferencePage.java | 93 +- .../ui/preferences/br/PMDPreferencePage2.java | 272 +++-- .../br/PropertyChangeListener.java | 2 +- .../ui/preferences/br/RuleCollection.java | 30 + .../preferences/br/RuleColumnDescriptor.java | 8 +- .../ui/preferences/br/RuleFieldAccessor.java | 86 +- .../eclipse/ui/preferences/br/RuleGroup.java | 116 +-- .../ui/preferences/br/RuleLabelProvider.java | 71 +- .../ui/preferences/br/RuleSelection.java | 348 ++++--- .../preferences/br/RuleSelectionListener.java | 2 +- .../br/RuleSetTreeItemProvider.java | 40 +- .../ui/preferences/br/RuleSortListener.java | 2 +- .../ui/preferences/br/RuleTableManager.java | 930 ++++++------------ .../eclipse/ui/preferences/br/RuleUtil.java | 397 ++++++++ .../ui/preferences/br/RuleVisitor.java | 19 + .../ui/preferences/br/SizeChangeListener.java | 3 +- .../pmd/eclipse/ui/preferences/br/TODO items | 12 +- .../preferences/br/TextColumnDescriptor.java | 44 +- .../eclipse/ui/preferences/br/TreeUtil.java | 59 ++ .../preferences/br/ValueChangeListener.java | 5 +- .../ui/preferences/br/ValueFormatter.java | 76 +- .../editors/AbstractEditorFactory.java | 76 +- .../AbstractMultiValueEditorFactory.java | 108 +- .../editors/AbstractNumericEditorFactory.java | 52 +- .../editors/AbstractRealNumberEditor.java | 12 +- .../editors/BooleanEditorFactory.java | 38 +- .../editors/CharacterEditorFactory.java | 48 +- .../editors/DoubleEditorFactory.java | 28 +- .../editors/EnumerationEditorFactory.java | 34 +- .../editors/FloatEditorFactory.java | 28 +- .../editors/IntegerEditorFactory.java | 50 +- .../editors/MethodEditorFactory.java | 44 +- .../ui/preferences/editors/MethodPicker.java | 62 +- .../MultiEnumerationEditorFactory.java | 37 +- .../editors/MultiIntegerEditorFactory.java | 68 +- .../editors/MultiMethodEditorFactory.java | 56 +- .../editors/MultiStringEditorFactory.java | 50 +- .../editors/MultiTypeEditorFactory.java | 70 +- .../ui/preferences/editors/SWTUtil.java | 41 +- .../editors/StringEditorFactory.java | 46 +- .../editors/TypeEditorFactory.java | 44 +- .../ui/preferences/editors/TypeText.java | 58 +- .../AbstractRulePanelManager.java | 281 ++++-- .../panelmanagers/Configuration.java | 8 +- .../panelmanagers/CreateRuleWizard.java | 102 ++ .../DescriptionPanelManager.java | 220 +++-- .../panelmanagers/EditorUsageMode.java | 7 + .../panelmanagers/ExamplePanelManager.java | 76 +- .../panelmanagers/ExclusionPanelManager.java | 126 ++- .../panelmanagers/FormArranger.java | 91 +- .../panelmanagers/ListManager.java | 36 +- .../PerRulePropertyPanelManager.java | 87 +- .../panelmanagers/QuickFixPanelManager.java | 81 +- .../panelmanagers/RulePanelManager.java | 720 ++++++++++++++ .../panelmanagers/RulePropertyManager.java | 2 +- .../preferences/panelmanagers/RuleTarget.java | 13 + .../panelmanagers/XPathPanelManager.java | 145 +-- .../eclipse/ui/views/TableColumnSorter.java | 1 - .../eclipse/ui/views/ViolationOutline.java | 84 +- .../ui/views/ViolationOutlinePage.java | 6 +- .../AbstractViolationSelectionAction.java | 2 +- .../ui/views/actions/DisableRuleAction.java | 45 +- .../ui/views/actions/QuickFixAction.java | 6 +- .../views/actions/RemoveViolationAction.java | 1 - .../pmd/eclipse/util/ColourManager.java | 11 +- .../pmd/eclipse/util/FontBuilder.java | 29 + .../pmd/eclipse/util/ResourceManager.java | 9 +- .../sourceforge/pmd/eclipse/util/Util.java | 362 ++++++- .../ui/preferences/editors/EditorTester.java | 2 - .../editors/NonRuleWithAllPropertyTypes.java | 93 ++ 109 files changed, 5187 insertions(+), 2465 deletions(-) create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/.settings/org.eclipse.jdt.ui.prefs create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/btn_diamond_white.png create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/btn_dot_white.png create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/filter_r.png create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/icon_filter.png create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/icon_spinningArrows.png create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/DisableRuleHandler.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractColumnDescriptor.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractTreeTableManager.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/BasicValueFormatter.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ColumnDescriptor.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/FormatManager.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ImplementationType.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/IndexedString.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleCollection.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleUtil.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleVisitor.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TreeUtil.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/CreateRuleWizard.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/EditorUsageMode.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/RulePanelManager.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/RuleTarget.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/util/FontBuilder.java create mode 100755 pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/test/net/sourceforge/pmd/eclipse/ui/preferences/editors/NonRuleWithAllPropertyTypes.java diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/.classpath b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/.classpath index f2c02e7810..d4fda0e2e8 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/.classpath +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/.classpath @@ -1,18 +1,24 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/.settings/org.eclipse.jdt.ui.prefs b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/.settings/org.eclipse.jdt.ui.prefs new file mode 100755 index 0000000000..7dec1b7e58 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,54 @@ +#Mon Mar 29 02:08:09 CDT 2010 +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=false +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=true +cleanup.correct_indentation=false +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=false +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=true +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=false +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=true +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup_profile=_hatchwater +cleanup_settings_version=2 +eclipse.preferences.version=1 diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/CHANGELOG.txt b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/CHANGELOG.txt index a37e43fd06..d28988859f 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/CHANGELOG.txt +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/CHANGELOG.txt @@ -5,6 +5,7 @@ v4.0.0 - xxx 2010? . Allows users to group/edit rules by multiple criteria . provides ability to enable/disable rules without removing them . larger editors for the various fields +. new rule creation wizard supports new non-Java languages . group editing of filter exclusion rules . Color-tagged expressions in shown in rule table . new property editors are fully type-aware diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/META-INF/MANIFEST.MF b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/META-INF/MANIFEST.MF index 43dfebccee..b9c5a36515 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/META-INF/MANIFEST.MF +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/META-INF/MANIFEST.MF @@ -2,23 +2,21 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %plugin.name Bundle-SymbolicName: net.sourceforge.pmd.eclipse.plugin;singleton:=true -Bundle-Version: 5.0.0.v200810141040 +Bundle-Version: 5.0.0.v20100726 Bundle-Activator: net.sourceforge.pmd.eclipse.plugin.PMDPlugin -Require-Bundle: org.eclipse.core.resources;bundle-version="3.5.0", +Require-Bundle: org.apache.commons.logging;bundle-version="1.0.4", + org.eclipse.core.resources;bundle-version="3.5.0", org.eclipse.core.runtime;bundle-version="3.5.0", org.eclipse.jdt.core;bundle-version="3.5.0", - org.eclipse.jface;bundle-version="3.5.0", org.eclipse.jface.text;bundle-version="3.5.0", org.eclipse.ui;bundle-version="3.5.0", - org.eclipse.ui.editors;bundle-version="3.5.0", org.eclipse.ui.ide;bundle-version="3.5.0", - org.eclipse.help + org.eclipse.ui.editors;bundle-version="3.5.0" Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-Vendor: %plugin.provider Bundle-ClassPath: lib/asm-3.2.jar, lib/castor-1.1.2.1-xml.jar, - lib/commons-logging-1.1.1.jar, lib/jaxen-1.1.1.jar, lib/junit.jar, lib/log4j-1.2.15.jar, @@ -27,12 +25,20 @@ Bundle-ClassPath: lib/asm-3.2.jar, lib/pmd-5.0.jar, lib/xercesImpl-2.6.2.jar, lib/xmlParserAPIs-2.6.2.jar, - pmd-plugin.jar + pmd-plugin.jar, + lib/groupingTree.jar Bundle-Localization: plugin Export-Package: net.sourceforge.pmd, - rulesets, + net.sourceforge.pmd.eclipse.core, net.sourceforge.pmd.eclipse.plugin, net.sourceforge.pmd.eclipse.runtime, net.sourceforge.pmd.eclipse.runtime.builder, net.sourceforge.pmd.eclipse.runtime.properties, - net.sourceforge.pmd.eclipse.runtime.writer + net.sourceforge.pmd.eclipse.runtime.writer, + net.sourceforge.pmd.eclipse.ui, + net.sourceforge.pmd.eclipse.ui.model, + net.sourceforge.pmd.eclipse.ui.nls, + net.sourceforge.pmd.eclipse.ui.preferences.br, + net.sourceforge.pmd.eclipse.ui.views.actions, + net.sourceforge.pmd.util, + rulesets diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/btn_diamond_white.png b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/btn_diamond_white.png new file mode 100755 index 0000000000000000000000000000000000000000..944f752b49079370767aeba744bbcd64d398479f GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5M?jcysy3fAP%zQc z#WBR9ck5+OE(Qe-)(da`m2Y!pPOM{BQOtN)9}t;6zx#TVYuJp+v`&t1N)KB6l^skT za7K5qBuFTlKWH;eVSc#5rAlk5^>bP0l+XkKadS8Z literal 0 HcmV?d00001 diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/btn_dot_white.png b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/btn_dot_white.png new file mode 100755 index 0000000000000000000000000000000000000000..0648e8a9761ac298e33771cf116fb3d1c7059aee GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5M?jcysy3fAP%z5V z#WBR9_v$1=z5@mv%)I~qZ?+C`YIHh$U_yn<^UWfxJM4n)+C04)N6?tAlcSl(o>uK-looBReY!@#3BX4o?{wK>y1`R_oq5sKia)Gum Nc)I$ztaD0e0sxc=I4}SJ literal 0 HcmV?d00001 diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/filter_r.png b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/filter_r.png new file mode 100755 index 0000000000000000000000000000000000000000..90a57f0f7285e43f1f9ec8ca343847951d7290f8 GIT binary patch literal 391 zcmV;20eJq2P)*lRrztKp4iK69+$pgOgvOONVn(&{cGIlqfohi&w;< z(kW6qyJZmRAee3$T>Jvv3l8eq3Q{ePL;i4g$%Uqw`oK%>k~hEi&%FmMrLNmu>ibSF zpv$*REB1>c?{pzh4toCZ%FFvl0>H-lW(FRO-s|$?^7Tx24?F@u=u3vaT&x1Sr>R0; zlC#O&V4-hF5&#BwTRF$=<7WWCpu2~ilSt$o%G7T+`8OHHHXfSm#QL|*(u@lu2Cati z)9mLL`)4-*fTy0q;nmyxnYwx!v>Kd#z0eNkl5XGr-TCmrII^fq{Y7)59eQNQ;6n2OE%FDZX^tL`8{u5lin@yPkN8uv8=~kZp9+L z_4R+!ICOJTfwm+>nD1>=T=Y-nqux=`W!h3_|NpPr`qzF}>JEl;CBH!SY`EcGtk`yt zmzVdy;gQ6bTR@(Ak}@^=qVolYHEc@EUrM^PXCLBG%1}5HkYcC3Z;$_!#w84sV!XN< kcl;2M_AqU37iVCQIk7)z&C1PHz>s3_boFyt=akR{0K8X~r~m)} delta 550 zcmV+>0@?lI0ZKKfSc^5v?T?rMU+s52%@48LJ_6(k5l}6`lJMd4~?`<6Op2* zOI-7TmaN(AZg=na&}K=$a-J?{=A1ioMll19^qhvajjh-@~?!omVtYx4O#T5AAO zsT5%t;&~qb++#ACERN$)sZ^K;Xt!H@{q}=Wsf1w|L{Y@r+8QE49LFf7@O_`rXoUUq zJLz$Od_K?i z_O?ngXnfj}FbsMA?5XPf`YlICN4Ty_9LJ>7X$pk`rfHH=Lbuyxb8}Oj3lX6G`HOTq z9bUbBk?;r2mh9~8ptZ)bENK|po4F&^NR#p%ZipAnN z@wM1LXi4+1EvM&g%Ii08d__Pm_6bPpvK$_kA1L4VdH231y z3Ve^HrA2ba4b)j)0?9NA)U^fxp68J>3{Fl$CW1+A@}6ms$z;%4qt32<)e7^o3~bxR ob=`AKUXpBhA(JxcmMzZ07*qoM6N<$g4hNF5C8xG diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/icon_filter.png b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/icon_filter.png new file mode 100755 index 0000000000000000000000000000000000000000..47ed142d7dd263588703fa6b83264fded2cf4933 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy}!3HFwFZ>e#Qk(@Ik;M!Qd`Cc-ajG_-G*ED{ zr;B5VMeo@u7kLjW@VM}6Hdk(znO$l8T={~6!Gk|rY&khuY~%=(&Q@N`~P5=UCYmwKupwE|{@~ubRVCc_+*HC(k~xz5Bc~v~{wHaq+_D+(`>h zJojX1nix literal 0 HcmV?d00001 diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/icon_spinningArrows.png b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/icons/icon_spinningArrows.png new file mode 100755 index 0000000000000000000000000000000000000000..9b84fe43fd65cbc7812cf7b54ab27d747142b223 GIT binary patch literal 382 zcmV-^0fGLBP)*)8TD{Fc5~}*HH(#O)!&SCh;+e%_NvfdYiaE2s8v* z6e&{G?-#=M!HZA5sO8utRqhrj#m{5g%y#*#QjW?BI?9IfEI9ETC!z!e-n~v9{k; zK8&+d1uF|SjI%>L8bAY>~i@Y6A{FFtnAlppjpNXm>JWQHs~2$pWC)~ zB0{m{Kb}@79;_71Y~f>ACJv6P1VdW z%d8#U#g?uP - + @@ -344,7 +347,22 @@ id="net.sourceforge.pmd.eclipse.ui.pmdFileCheckProjectAction" label="%action.checkpmd" menubarPath="additions"/> - + + + + + + + - + + + + + + + + + + + + + + + + diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/PMDPlugin.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/PMDPlugin.java index 3c476e180a..770b251d99 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/PMDPlugin.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/plugin/PMDPlugin.java @@ -1,8 +1,11 @@ package net.sourceforge.pmd.eclipse.plugin; import java.io.IOException; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSetNotFoundException; @@ -38,6 +41,7 @@ import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.Bundle; @@ -62,6 +66,15 @@ public class PMDPlugin extends AbstractUIPlugin { Integer.valueOf(5) }; + public static final Map colorsByPriority = new HashMap(); + + static { + colorsByPriority.put(RulePriority.LOW, new RGB( 0,0,255) ); // blue + colorsByPriority.put(RulePriority.MEDIUM_LOW, new RGB( 0,255,0) ); // green + colorsByPriority.put(RulePriority.MEDIUM, new RGB( 255,255,0) ); // yellow + colorsByPriority.put(RulePriority.MEDIUM_HIGH, new RGB( 255,0,255) ); // purple + colorsByPriority.put(RulePriority.HIGH, new RGB( 255,0,0) ); // red + } /** * The constructor */ diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/builder/MarkerUtil.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/builder/MarkerUtil.java index 42a1789b26..786d37d065 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/builder/MarkerUtil.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/builder/MarkerUtil.java @@ -1,7 +1,9 @@ package net.sourceforge.pmd.eclipse.runtime.builder; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSet; @@ -12,8 +14,10 @@ import net.sourceforge.pmd.util.StringUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; +import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.CoreException; /** @@ -28,7 +32,7 @@ public class MarkerUtil { public static boolean hasAnyRuleMarkers(IResource resource) throws CoreException { - final boolean foundOne[] = new boolean[] { false }; + final boolean[] foundOne = new boolean[] { false }; IResourceVisitor ruleMarkerFinder = new IResourceVisitor() { @@ -64,6 +68,25 @@ public class MarkerUtil { return foundOne[0]; } + private static IProject projectFor(IResource resource) { + + if (resource instanceof IWorkspaceRoot) return null; + if (resource instanceof IProject) return (IProject)resource; + return projectFor(resource.getParent()); + } + + public static Set commonProjectsOf(IMarker[] markers) { + + Set projects = new HashSet(); + + for (IMarker marker : markers) { + IProject project = projectFor(marker.getResource()); + if (project != null) projects.add(project); + } + + return projects; + } + public static String ruleNameFor(IMarker marker) { return marker.getAttribute(PMDUiConstants.KEY_MARKERATT_RULENAME, ""); } @@ -72,6 +95,31 @@ public class MarkerUtil { return ((Integer)marker.getAttribute(PMDUiConstants.KEY_MARKERATT_PRIORITY)).intValue(); } + public static int deleteViolationsOf(String ruleName, IResource resource) { + + try { + IMarker[] markers = findAllMarkers(resource); + if (markers.length == 0) return 0; + + List matches = new ArrayList(markers.length); + + for (IMarker marker : markers) { + String name = ruleNameFor(marker); + if (ruleName.equals(name)) { + matches.add(marker); + } + } + + markers = new IMarker[matches.size()]; + matches.toArray(markers); + resource.getWorkspace().deleteMarkers(markers); + + return markers.length; + } catch (CoreException ex) { + return 0; + } + } + public static List rulesFor(IMarker[] markers) { List rules = new ArrayList(markers.length); diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/DisableRuleHandler.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/DisableRuleHandler.java new file mode 100755 index 0000000000..0e92f31aee --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/DisableRuleHandler.java @@ -0,0 +1,16 @@ +package net.sourceforge.pmd.eclipse.runtime.cmd; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.handlers.HandlerUtil; + +public class DisableRuleHandler extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + HandlerUtil.getActiveWorkbenchWindow(event).close(); + return null; + } + + +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/RenderReportCmd.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/RenderReportCmd.java index 1286eb8bb6..f936972ea9 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/RenderReportCmd.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/RenderReportCmd.java @@ -198,14 +198,14 @@ public class RenderReportCmd extends AbstractProjectCommand { if (marker.getResource() instanceof IFile) { final ICompilationUnit unit = JavaCore.createCompilationUnitFrom((IFile) marker.getResource()); - final IPackageDeclaration packages[] = unit.getPackageDeclarations(); + final IPackageDeclaration[] packages = unit.getPackageDeclarations(); if (packages.length > 0) { ruleViolation.setPackageName(packages[0].getElementName()); } else { ruleViolation.setPackageName("(default)"); } - IType types[] = unit.getAllTypes(); + IType[] types = unit.getAllTypes(); if (types.length > 0) { ruleViolation.setClassName(types[0].getElementName()); } else { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/ReviewCodeCmd.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/ReviewCodeCmd.java index faae2109a3..17697b5bf8 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/ReviewCodeCmd.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/cmd/ReviewCodeCmd.java @@ -257,7 +257,7 @@ public class ReviewCodeCmd extends AbstractDefaultCommand { if (resources.isEmpty()) { rule = ruleFactory.markerRule(resourceDelta.getResource().getProject()); } else { - ISchedulingRule rules[] = new ISchedulingRule[resources.size()]; + ISchedulingRule[] rules = new ISchedulingRule[resources.size()]; for (int i = 0; i < rules.length; i++) { rules[i] = ruleFactory.markerRule((IResource) resources.get(i)); } @@ -313,6 +313,8 @@ public class ReviewCodeCmd extends AbstractDefaultCommand { fileCount += visitor.getProcessedFilesCount(); pmdDuration += visitor.getActualPmdDuration(); + worked(1); // TODO - temp fix? BR + } catch (PropertiesException e) { throw new CommandException(e); } catch (CoreException e) { @@ -432,7 +434,7 @@ public class ReviewCodeCmd extends AbstractDefaultCommand { currentFile = file.getName(); final Set markerInfoSet = markersByFile.get(file); - MarkerUtil.deleteAllMarkersIn(file); + // MarkerUtil.deleteAllMarkersIn(file); final Iterator j = markerInfoSet.iterator(); while (j.hasNext()) { final MarkerInfo markerInfo = j.next(); diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferenceUIStore.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferenceUIStore.java index 14751cc25f..6449ba44e5 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferenceUIStore.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferenceUIStore.java @@ -35,8 +35,9 @@ public class PreferenceUIStore { private static final char stringSeparator = ','; private static final RuleColumnDescriptor[] defaultHiddenColumns = new RuleColumnDescriptor[] { - TextColumnDescriptor.externalURL, TextColumnDescriptor.minLangVers, - TextColumnDescriptor.exampleCount, TextColumnDescriptor.since + TextColumnDescriptor.externalURL, TextColumnDescriptor.minLangVers, TextColumnDescriptor.fixCount, + TextColumnDescriptor.exampleCount, TextColumnDescriptor.maxLangVers, TextColumnDescriptor.since, + TextColumnDescriptor.modCount }; private static final boolean defaultSortUp = false; diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/PMDUiConstants.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/PMDUiConstants.java index 0ba376ebe2..cf03b57386 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/PMDUiConstants.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/PMDUiConstants.java @@ -74,12 +74,15 @@ public class PMDUiConstants { public static final String ICON_LABEL_ERR5 = "icons/lab_err5.gif"; public static final String ICON_LABEL_ERR_DFA = "icons/lab_errdfa.gif"; - public static final String ICON_FILTER = "icons/filter.gif"; + public static final String ICON_FILTER_R = "icons/filter_r.png"; public static final String ICON_FILTER_X = "icons/filter_x.png"; public static final String ICON_PROJECT = "icons/obj_project.gif"; public static final String ICON_PACKAGE = "icons/obj_package.gif"; public static final String ICON_JAVACU = "icons/obj_javacu.gif"; + + + public static final String ICON_BUTTON_DIAMOND_WHITE = "icons/btn_diamond_white.png"; public static final String ICON_BUTTON_PRIO0 = "icons/btn_prio0.png"; public static final String ICON_BUTTON_PRIO1 = "icons/btn_prio1.gif"; @@ -112,6 +115,7 @@ public class PMDUiConstants { public static final String ICON_BUTTON_EXPORT = "icons/export.gif"; public static final String ICON_BUTTON_EDITOR = "icons/editTool.png"; public static final String ICON_BUTTON_SORT_CHECKED = "icons/sortChecked.png"; + public static final String ICON_BUTTON_RELOAD = "icons/icon_spinningArrows.png"; public static final String ICON_GREEN_CHECK = "icons/icon_greenCheck.png"; public static final String ICON_EMPTY = "icons/icon_empty.png"; diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/RuleSetUtil.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/RuleSetUtil.java index 086624757d..c2e6b9d80a 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/RuleSetUtil.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/RuleSetUtil.java @@ -2,7 +2,6 @@ package net.sourceforge.pmd.eclipse.ui.actions; import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.Set; import net.sourceforge.pmd.Rule; @@ -14,6 +13,8 @@ import net.sourceforge.pmd.RuleSet; */ public class RuleSetUtil { + private RuleSetUtil() {} + public static RuleSet newCopyOf(RuleSet original) { RuleSet rs = new RuleSet(); diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/model/FileRecord.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/model/FileRecord.java index 9bc0a41f67..93107e31f7 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/model/FileRecord.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/model/FileRecord.java @@ -51,7 +51,6 @@ import java.util.StringTokenizer; import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; import net.sourceforge.pmd.eclipse.runtime.PMDRuntimeConstants; import net.sourceforge.pmd.eclipse.runtime.builder.MarkerUtil; -import net.sourceforge.pmd.eclipse.ui.PMDUiConstants; import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; import org.eclipse.core.resources.IMarker; @@ -267,17 +266,16 @@ public class FileRecord extends AbstractPMDRecord { * The Function is adapted from the Eclipse Metrics-Plugin available at: * http://www.sourceforge.net/projects/metrics * - * @return the Lines of Code */ public void calculateLinesOfCode() { - if (this.resource.isAccessible()) { + if (resource.isAccessible()) { // the whole while has to be a String for this operation // so we read the File line-wise into a String - final String source = resourceToString(this.resource); + final String source = resourceToString(resource); - this.numberOfLOC = linesOfCodeIn(source, true); + numberOfLOC = linesOfCodeIn(source, true); } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/nls/StringKeys.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/nls/StringKeys.java index 4c80d73e45..5429acbeb0 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/nls/StringKeys.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/nls/StringKeys.java @@ -95,8 +95,10 @@ public class StringKeys { public static final String MSGKEY_PREF_RULESET_COLUMN_FILTERS_REGEX = "preference.ruleset.column.filters.regex"; public static final String MSGKEY_PREF_RULESET_COLUMN_FILTERS_XPATH = "preference.ruleset.column.filters.xpath"; public static final String MSGKEY_PREF_RULESET_COLUMN_MIN_VER = "preference.ruleset.column.minimum_version"; + public static final String MSGKEY_PREF_RULESET_COLUMN_MAX_VER = "preference.ruleset.column.maximum_version"; public static final String MSGKEY_PREF_RULESET_COLUMN_PRIORITY = "preference.ruleset.column.priority"; public static final String MSGKEY_PREF_RULESET_COLUMN_FIXCOUNT = "preference.ruleset.column.fixCount"; + public static final String MSGKEY_PREF_RULESET_COLUMN_MODCOUNT = "preference.ruleset.column.modCount"; public static final String MSGKEY_PREF_RULESET_COLUMN_PROPERTIES = "preference.ruleset.column.properties"; public static final String MSGKEY_PREF_RULESET_COLUMN_DESCRIPTION = "preference.ruleset.column.description"; public static final String MSGKEY_PREF_RULESET_COLUMN_PROPERTY = "preference.ruleset.column.property"; @@ -126,7 +128,8 @@ public class StringKeys { public static final String MSGKEY_PREF_RULESET_BUTTON_CHECK_ALL = "preference.ruleset.button.tooltip.check.all"; public static final String MSGKEY_PREF_RULESET_BUTTON_UNCHECK_ALL = "preference.ruleset.button.tooltip.uncheck.all"; - + + public static final String MSGKEY_PREF_RULESET_TAB_RULE = "preference.ruleedit.tab.rule"; public static final String MSGKEY_PREF_RULESET_TAB_PROPERTIES = "preference.ruleedit.tab.properties"; public static final String MSGKEY_PREF_RULESET_TAB_DESCRIPTION = "preference.ruleedit.tab.description"; public static final String MSGKEY_PREF_RULESET_TAB_FILTERS = "preference.ruleedit.tab.filters"; @@ -148,7 +151,11 @@ public class StringKeys { public static final String MSGKEY_PREF_RULEEDIT_LABEL_SINCE = "preference.ruleedit.label.since"; public static final String MSGKEY_PREF_RULEEDIT_LABEL_NAME = "preference.ruleedit.label.name"; public static final String MSGKEY_PREF_RULEEDIT_LABEL_IMPLEMENTATION_CLASS = "preference.ruleedit.label.implementation_class"; + public static final String MSGKEY_PREF_RULEEDIT_LABEL_IMPLEMENTED_BY = "preference.ruleedit.label.implemented_by"; public static final String MSGKEY_PREF_RULEEDIT_LABEL_MESSAGE = "preference.ruleedit.label.message"; + public static final String MSGKEY_PREF_RULEEDIT_LABEL_LANGUAGE = "preference.ruleedit.label.language"; + public static final String MSGKEY_PREF_RULEEDIT_LABEL_LANGUAGE_MIN = "preference.ruleedit.label.language.version.min"; + public static final String MSGKEY_PREF_RULEEDIT_LABEL_LANGUAGE_MAX = "preference.ruleedit.label.language.version.max"; public static final String MSGKEY_PREF_RULEEDIT_LABEL_PRIORITY = "preference.ruleedit.label.priority"; public static final String MSGKEY_PREF_RULEEDIT_LABEL_DESCRIPTION = "preference.ruleedit.label.description"; public static final String MSGKEY_PREF_RULEEDIT_LABEL_EXTERNAL_INFO_URL = "preference.ruleedit.label.external_info_url"; @@ -228,7 +235,7 @@ public class StringKeys { public static final String MSGKEY_VIEW_TOOLTIP_CALCULATE_STATS = "view.tooltip.calc_stats"; public static final String MSGKEY_VIEW_TOOLTIP_COMPUTE_METRICS = "view.tooltip.compute_metrics"; public static final String MSGKEY_VIEW_ACTION_PROJECT = "view.action.project"; - public static final String MSGKEY_VIEW_ACTION_DISABLE = "view.action.disable"; + public static final String MSGKEY_VIEW_ACTION_DISABLE_RULE = "view.action.disable.rule"; public static final String MSGKEY_VIEW_ACTION_FILE = "view.action.file"; public static final String MSGKEY_VIEW_ACTION_ERRORHIGH = "view.action.errorhigh"; public static final String MSGKEY_VIEW_ACTION_ERROR = "view.action.error"; @@ -321,6 +328,7 @@ public class StringKeys { public static final String MSGKEY_MONITOR_REMOVE_REVIEWS = "monitor.remove_reviews"; public static final String MSGKEY_MONITOR_CALC_STATS_TASK = "monitor.calc_stats"; public static final String MSGKEY_MONITOR_CALC_STATS_OF_PACKAGE = "monitor.calc_stats.package"; + public static final String MSGKEY_MONITOR_COLLECTING_MARKERS = "monitor.collect_markers"; /** * This class is not meant to be instanciated diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/CPDPreferencePage.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/CPDPreferencePage.java index 41bc3944d4..295d35cffd 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/CPDPreferencePage.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/CPDPreferencePage.java @@ -5,7 +5,6 @@ import net.sourceforge.pmd.eclipse.runtime.preferences.IPreferences; import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; import net.sourceforge.pmd.eclipse.ui.preferences.br.AbstractPMDPreferencePage; -import org.eclipse.jface.preference.PreferencePage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractColumnDescriptor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractColumnDescriptor.java new file mode 100755 index 0000000000..e4e5c5d880 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractColumnDescriptor.java @@ -0,0 +1,54 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +import net.sourceforge.pmd.eclipse.ui.preferences.editors.SWTUtil; +import net.sourceforge.pmd.eclipse.util.ResourceManager; + +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; + +/** + * + * @author Brian Remedios + * + */ +public abstract class AbstractColumnDescriptor implements ColumnDescriptor { + + private final String label; + private final String tooltip; + private final int alignment; + private final int width; + private final boolean isResizable; + private final String imagePath; + + public AbstractColumnDescriptor(String labelKey, int theAlignment, int theWidth, boolean resizableFlag, String theImagePath) { + super(); + + label = SWTUtil.stringFor(labelKey); + tooltip = SWTUtil.tooltipFor(labelKey); + alignment = theAlignment; + width = theWidth; + isResizable = resizableFlag; + imagePath = theImagePath; + } + + /* (non-Javadoc) + * @see net.sourceforge.pmd.eclipse.ui.preferences.br.ColumnDescriptor#label() + */ + public String label() { return label; } + + /* (non-Javadoc) + * @see net.sourceforge.pmd.eclipse.ui.preferences.br.ColumnDescriptor#tooltip() + */ + public String tooltip() { return tooltip; } + + protected TreeColumn buildTreeColumn(Tree parent, final RuleSortListener sortListener) { + + final TreeColumn tc = new TreeColumn(parent, alignment); + tc.setWidth(width); + tc.setResizable(isResizable); + tc.setToolTipText(tooltip); + if (imagePath != null) tc.setImage(ResourceManager.imageFor(imagePath)); + + return tc; + } +} \ No newline at end of file diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractPMDPreferencePage.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractPMDPreferencePage.java index 7eb8aa1d3e..8030bfb7c2 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractPMDPreferencePage.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractPMDPreferencePage.java @@ -4,6 +4,7 @@ import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; import net.sourceforge.pmd.eclipse.runtime.preferences.IPreferences; import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.swt.widgets.Button; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; @@ -12,10 +13,10 @@ public abstract class AbstractPMDPreferencePage extends PreferencePage implement protected IPreferences preferences; private boolean modified; - protected static PMDPlugin plugin = PMDPlugin.getDefault(); - + protected static PMDPlugin plugin = PMDPlugin.getDefault(); + abstract protected String descriptionId(); - + /** * Returns the isModified. * @return boolean @@ -23,7 +24,7 @@ public abstract class AbstractPMDPreferencePage extends PreferencePage implement public boolean isModified() { return modified; } - + public void setModified() { setModified(true); } @@ -33,31 +34,35 @@ public abstract class AbstractPMDPreferencePage extends PreferencePage implement */ public void setModified(boolean isModified) { modified = isModified; + + // can be null for some reason ..argh + Button button = getApplyButton(); + if (button != null) button.setEnabled(modified); - getApplyButton().setEnabled(modified); - getDefaultsButton().setEnabled(!modified); + button = getDefaultsButton(); + if (button != null) button.setEnabled(!modified); } - + /** * Insert the method's description here. * @see PreferencePage#init */ - + public void init(IWorkbench workbench) { setDescription(getMessage(descriptionId())); preferences = PMDPlugin.getDefault().loadPreferences(); - } - + } + /** * @see org.eclipse.jface.preference.IPreferencePage#performOk() */ public boolean performOk() { - + preferences.sync(); return super.performOk(); } - + /** * Helper method to shorten message access * @param key a message key @@ -66,5 +71,5 @@ public abstract class AbstractPMDPreferencePage extends PreferencePage implement protected String getMessage(String key) { return PMDPlugin.getDefault().getStringTable().getString(key); } - + } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractRuleColumnDescriptor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractRuleColumnDescriptor.java index 97abc11d37..1e174f42bb 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractRuleColumnDescriptor.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractRuleColumnDescriptor.java @@ -1,10 +1,9 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.eclipse.ui.preferences.editors.SWTUtil; -import net.sourceforge.pmd.eclipse.util.ResourceManager; import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; @@ -13,59 +12,55 @@ import org.eclipse.swt.widgets.TreeColumn; /** * Retains all values necessary to hydrate a table column for holding a set of rules. Invoke the buildTreeColumn() * method to constitute one. As descriptors they can be held as static items since they they're immutable. - * + * * @author Brian Remedios */ -public abstract class AbstractRuleColumnDescriptor implements RuleColumnDescriptor { +public abstract class AbstractRuleColumnDescriptor extends AbstractColumnDescriptor implements RuleColumnDescriptor { - private final String label; - private final String tooltip; - private final int alignment; - private final int width; private final RuleFieldAccessor accessor; - private final boolean isResizable; - private final String imagePath; - + protected AbstractRuleColumnDescriptor(String labelKey, int theAlignment, int theWidth, RuleFieldAccessor theAccessor, boolean resizableFlag, String theImagePath) { - super(); - - label = SWTUtil.stringFor(labelKey); - tooltip = SWTUtil.tooltipFor(labelKey); - alignment = theAlignment; - width = theWidth; + super(labelKey, theAlignment, theWidth, resizableFlag, theImagePath); + accessor = theAccessor; - isResizable = resizableFlag; - imagePath = theImagePath; } - + protected TreeColumn buildTreeColumn(Tree parent, final RuleSortListener sortListener) { - - final TreeColumn tc = new TreeColumn(parent, alignment); - tc.setWidth(width); - tc.setResizable(isResizable); - tc.setToolTipText(tooltip); - if (imagePath != null) tc.setImage(ResourceManager.imageFor(imagePath)); - + + TreeColumn tc = super.buildTreeColumn(parent, sortListener); + tc.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { sortListener.sortBy(accessor(), e.widget); } - }); - + }); + return tc; } - + protected Object valueFor(Rule rule) { - return accessor.valueFor(rule); + return accessor.valueFor(rule); + } + + protected Object valueFor(RuleCollection collection) { + return accessor.valueFor(collection); } - public String label() { return label; } - - public String tooltip() { return tooltip; } - public RuleFieldAccessor accessor() { return accessor; } - + public String detailStringFor(Rule rule) { return accessor.labelFor(rule); } + + public String detailStringFor(RuleGroup group) { + return "TODO in AbstractRuleColumnDescriptor"; + } + + public Image imageFor(RuleCollection collection) { + return null; // override in subclasses + } + + public String stringValueFor(RuleCollection collection) { + return null; // override in subclasses + } } \ No newline at end of file diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractTreeTableManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractTreeTableManager.java new file mode 100755 index 0000000000..72c5ed5d8f --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/AbstractTreeTableManager.java @@ -0,0 +1,466 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; +import net.sourceforge.pmd.eclipse.runtime.preferences.IPreferences; +import net.sourceforge.pmd.eclipse.runtime.preferences.impl.PreferenceUIStore; +import net.sourceforge.pmd.eclipse.ui.PMDUiConstants; +import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; +import net.sourceforge.pmd.eclipse.util.ResourceManager; + +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; + +/** + * + * @author Brian Remedios + */ +public abstract class AbstractTreeTableManager { + + + protected ContainerCheckedTreeViewer treeViewer; + + protected boolean sortDescending; + + private final Set hiddenColumnNames; + + private Button sortByCheckedButton; + private Button selectAllButton; + private Button unSelectAllButton; + private IPreferences preferences; + + private ModifyListener modifyListener; + + private Label activeCountLabel; + + private Map> paintListeners = new HashMap>(); + + protected static PMDPlugin plugin = PMDPlugin.getDefault(); + + public AbstractTreeTableManager(IPreferences thePreferences) { + super(); + + preferences = thePreferences; + hiddenColumnNames = PreferenceUIStore.instance.hiddenColumnNames(); + } + + protected Map> paintListeners() { + return paintListeners; + } + /** + * Remove all rows, columns, and column painters in preparation + * for new columns. + * + * @return Tree + */ + protected Tree cleanupRuleTree() { + + Tree tree = treeViewer.getTree(); + + tree.clearAll(true); + for(;tree.getColumns().length>0;) { // TODO also dispose any heading icons? + tree.getColumns()[0].dispose(); + } + + // ensure we don't have any previous per-column painters left over + for (Map.Entry> entry : paintListeners.entrySet()) { + int eventCode = entry.getKey().intValue(); + List listeners = entry.getValue(); + for (Listener listener : listeners) { + tree.removeListener(eventCode, listener); + } + listeners.clear(); + } + + return tree; + } + + protected abstract boolean isQualifiedItem(Object item); + + public void saveUIState() { + saveItemSelections(); + } + + protected abstract void saveItemSelections(); + + public int activeItemCount() { + + Object[] checkedItems = treeViewer.getCheckedElements(); + int count = 0; + + for (Object item : checkedItems) { + if (isQualifiedItem(item)) count++; + } + + return count; + } + + protected CheckboxTreeViewer treeViewer() { return treeViewer; } + + protected Button newImageButton(Composite parent, String imageId, String toolTipId) { + + Button button = new Button(parent, SWT.PUSH | SWT.LEFT); + button.setImage(ResourceManager.imageFor(imageId)); + button.setToolTipText(getMessage(toolTipId)); + button.setEnabled(true); + return button; + } + + protected boolean isHidden(String columnName) { + return hiddenColumnNames.contains(columnName); + } + + /** + * @param item TreeItem + * @param checked boolean + */ + private void check(TreeItem item, boolean checked) { + + item.setChecked(checked); + Object itemData = item.getData(); + if (itemData == null || itemData instanceof RuleGroup) return; + + String name = ((Rule)itemData).getName(); + + isActive(name, checked); + + updateCheckControls(); + setModified(); + } + + protected abstract void selectedItems(Object[] items); + + protected abstract void removeSelectedItems(); + + protected abstract void updateTooltipFor(TreeItem item, int columnIndex); + + // TODO move to util + public static int columnIndexAt(TreeItem item, int xPosition) { + + TreeColumn[] cols = item.getParent().getColumns(); + Rectangle bounds = null; + + for(int i = 0; i < cols.length; i++){ + bounds = item.getBounds(i); + if (bounds.x < xPosition && xPosition < (bounds.x + bounds.width)) { + return i; + } + } + return -1; + } + + protected void buildTreeViewer(Composite parent) { + + int treeStyle = SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION | SWT.CHECK; + treeViewer = new ContainerCheckedTreeViewer(parent, treeStyle); + + final Tree tree = treeViewer.getTree(); + tree.setLinesVisible(true); + tree.setHeaderVisible(true); + + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection)event.getSelection(); + selectedItems(selection.toArray()); + } + }); + + tree.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent ev) { + if (ev.character == SWT.DEL) { + removeSelectedItems(); + } + } + }); + + tree.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + if (event.detail == SWT.CHECK) { + TreeItem item = (TreeItem) event.item; + boolean checked = item.getChecked(); + checkItems(item, checked); + checkPath(item.getParentItem(), checked, false); + } + // if (!checkedRules.isEmpty()) System.out.println(checkedRules.iterator().next()); + } + }); + + tree.addListener(SWT.MouseMove, new Listener() { + public void handleEvent(Event event) { + Point point = new Point(event.x, event.y); + TreeItem item = tree.getItem(point); + if (item != null) { + int columnIndex = columnIndexAt(item, event.x); + updateTooltipFor(item, columnIndex); + } + } + }); + } + + public void updated(Object item) { + treeViewer.update(item, null); + } + + /** + * Method checkPath. + * @param item TreeItem + * @param checked boolean + * @param grayed boolean + */ + protected void checkPath(TreeItem item, boolean checked, boolean grayed) { + if (item == null) return; + if (grayed) { + checked = true; + } else { + int index = 0; + TreeItem[] items = item.getItems(); + while (index < items.length) { + TreeItem child = items[index]; + if (child.getGrayed() || checked != child.getChecked()) { + checked = grayed = true; + break; + } + index++; + } + } + check(item, checked); + item.setGrayed(grayed); + checkPath(item.getParentItem(), checked, grayed); + } + + /** + * @param item TreeItem + * @param checked boolean + */ + protected void checkItems(TreeItem item, boolean checked) { + item.setGrayed(false); + check(item, checked); + TreeItem[] items = item.getItems(); + for (TreeItem item2 : items) { + checkItems(item2, checked); + } + updateCheckControls(); + } + + protected void buildActiveCountLabel(Composite parent) { + activeCountLabel = new Label(parent, 0); + activeCountLabel.setText("---"); + GridData data = new GridData(); + data.horizontalAlignment = GridData.FILL; + data.grabExcessHorizontalSpace = true; + activeCountLabel.setAlignment(SWT.RIGHT); + activeCountLabel.setLayoutData(data); + } + + protected void activeCountText(String msg) { + activeCountLabel.setText(msg); + } + + protected abstract String[] columnLabels(); + + protected boolean isActive(String item) { + return preferences.isActive(item); + } + + protected void isActive(String item, boolean flag) { + preferences.isActive(item, flag); + } + + protected void buildCheckButtons(Composite parent) { + + sortByCheckedButton = buildSortByCheckedItemsButton(parent); + selectAllButton = buildSelectAllButton(parent); + unSelectAllButton = buildUnselectAllButton(parent); + } + + protected void addColumnSelectionOptions(Menu menu) { + + MenuItem showMenu = new MenuItem(menu, SWT.CASCADE); + showMenu.setText("Show"); + Menu columnsSubMenu = new Menu(menu); + showMenu.setMenu(columnsSubMenu); + + for (String columnLabel : columnLabels()) { + MenuItem columnItem = new MenuItem(columnsSubMenu, SWT.CHECK); + columnItem.setSelection(!hiddenColumnNames.contains(columnLabel)); + columnItem.setText(columnLabel); + final String nameStr = columnLabel; + columnItem.addSelectionListener( new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + toggleColumnVisiblity(nameStr); + } + } + ); + } + } + + private void toggleColumnVisiblity(String columnName) { + + if (hiddenColumnNames.contains(columnName)) { + hiddenColumnNames.remove(columnName); + } else { + hiddenColumnNames.add(columnName); + } + + PreferenceUIStore.instance.hiddenColumnNames(hiddenColumnNames); + redrawTable(); + } + + protected void redrawTable() { + redrawTable("-", -1); + } + + protected void redrawTable(String sortColumnLabel, int sortDir) { + + TreeColumn sortColumn = columnFor(sortColumnLabel); + treeViewer().getTree().setSortColumn(sortColumn); + treeViewer().getTree().setSortDirection(sortDir); + } + + private TreeColumn columnFor(String tooltipText) { + for (TreeColumn column : treeViewer().getTree().getColumns()) { + if (column.getToolTipText().equals(tooltipText)) return column; + } + return null; + } + + protected void formatValueOn(StringBuilder target, Object value, Class datatype) { + + ValueFormatter formatter = FormatManager.formatterFor(datatype); + if (formatter != null) { + formatter.format(value, target); + return; + } + + target.append(value); // should not get here..breakpoint here + } + + protected Button buildSortByCheckedItemsButton(Composite parent) { + Button button = new Button(parent, SWT.PUSH | SWT.LEFT); + button.setToolTipText("Sort by checked items"); + button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_SORT_CHECKED)); + + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + sortByCheckedItems(); + } + }); + + return button; + } + + protected abstract void sortByCheckedItems(); + + /** + * + * @param parent Composite + * @return Button + */ + protected Button buildSelectAllButton(Composite parent) { + + Button button = new Button(parent, SWT.PUSH | SWT.LEFT); + button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_CHECK_ALL)); + button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_CHECK_ALL)); + + button.setEnabled(true); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + setAllItemsActive(); + } + }); + + return button; + } + + protected abstract void setAllItemsActive(); + + public void modifyListener(ModifyListener theListener) { + modifyListener = theListener; + } + + /** + * Helper method to shorten message access + * @param key a message key + * @return requested message + */ + protected String getMessage(String key) { + return PMDPlugin.getDefault().getStringTable().getString(key); + } + + protected void setModified() { + if (modifyListener != null) modifyListener.setModified(); + } + + protected void updateButtonsFor(int[] selectionRatio) { + + selectAllButton.setEnabled( selectionRatio[0] < selectionRatio[1]); + unSelectAllButton.setEnabled( selectionRatio[0] > 0); + sortByCheckedButton.setEnabled( (selectionRatio[0] != 0) && (selectionRatio[0] != selectionRatio[1])); + } + + protected abstract void updateCheckControls(); + + /** + * Refresh the list + */ + protected void refresh() { + try { + treeViewer().getControl().setRedraw(false); + treeViewer().refresh(); + } catch (ClassCastException e) { + plugin.logError("Ignoring exception while refreshing table", e); + } finally { + treeViewer().getControl().setRedraw(true); + } + } + + /** + * + * @param parent Composite + * @return Button + */ + protected Button buildUnselectAllButton(Composite parent) { + + Button button = new Button(parent, SWT.PUSH | SWT.LEFT); + button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_UNCHECK_ALL)); + button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_UNCHECK_ALL)); + + button.setEnabled(true); + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + preferences.getActiveRuleNames().clear(); + treeViewer().setCheckedElements(new Object[0]); + setModified(); + updateCheckControls(); + } + }); + + return button; + } +} \ No newline at end of file diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/BasicRuleFieldAccessor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/BasicRuleFieldAccessor.java index 85236f8303..545f30df6c 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/BasicRuleFieldAccessor.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/BasicRuleFieldAccessor.java @@ -1,9 +1,12 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; +import java.util.Iterator; +import java.util.Set; + import net.sourceforge.pmd.Rule; /** - * + * * @author Brian Remedios */ public class BasicRuleFieldAccessor implements RuleFieldAccessor { @@ -19,4 +22,30 @@ public class BasicRuleFieldAccessor implements RuleFieldAccessor { public Comparable valueFor(Rule rule) { throw new RuntimeException("unimplemented method"); } + + public Comparable valueFor(RuleCollection collection) { + Comparable aspect = RuleUtil.commonAspect(collection, this); + if (aspect != null) return aspect; + return asString( RuleUtil.uniqueAspects(collection, this) ); + } + + public Set> uniqueValuesFor(RuleCollection collection) { + return RuleUtil.uniqueAspects(collection, this); + } + + protected String format(Object item) { + return item == null ? "" : String.valueOf(item); + } + + protected String asString(Set> items) { + + Iterator> iter = items.iterator(); + if (items.size() == 1) return format(iter.next()); + + StringBuilder sb = new StringBuilder(format(iter.next())); + while (iter.hasNext()) { + sb.append(", ").append(format(iter.next())); + } + return sb.toString(); + } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/BasicValueFormatter.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/BasicValueFormatter.java new file mode 100755 index 0000000000..1604038fc1 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/BasicValueFormatter.java @@ -0,0 +1,25 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +/** + * + * @author Brian Remedios + */ +public class BasicValueFormatter implements ValueFormatter { + + /** + * Override in subclasses + */ + public String format(Object value) { + StringBuilder sb = new StringBuilder(); + format(value, sb); + return sb.toString(); + } + + /** + * Override in subclasses + */ + public void format(Object value, StringBuilder target) { + target.append(value); + } + +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/CellPainterBuilder.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/CellPainterBuilder.java index 26c84283fc..14b8f54ed2 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/CellPainterBuilder.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/CellPainterBuilder.java @@ -6,7 +6,7 @@ import java.util.Map; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; /** - * + * * @author Brian Remedios */ public interface CellPainterBuilder { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ColumnDescriptor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ColumnDescriptor.java new file mode 100755 index 0000000000..e3c885994e --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ColumnDescriptor.java @@ -0,0 +1,9 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +public interface ColumnDescriptor { + + public abstract String label(); + + public abstract String tooltip(); + +} \ No newline at end of file diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/EditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/EditorFactory.java index 8504a532a0..f1998c891b 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/EditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/EditorFactory.java @@ -11,32 +11,32 @@ import org.eclipse.swt.widgets.Label; * @author Brian Remedios */ public interface EditorFactory { - + /** * Have the factory create a descriptor using the name and description provided and use any * of the values in the otherData widgets provided by the createOtherControlsOn method called * earlier. - * + * * @param name * @param optionalDescription * @param otherData * @return PropertyDescriptor */ PropertyDescriptor createDescriptor(String name, String description, Control[] otherData); - + /** * Instantiate and return a label for the descriptor on the parent provided. - * + * * @param parent * @param desc * @return */ Label addLabel(Composite parent, PropertyDescriptor desc); - + /** * Creates a property value editor widget(s) on the parent for the specified descriptor * and rule. It does not perform any layout operations or set form attachments. - * + * * @param parent Composite * @param desc PropertyDescriptor * @param rule Rule @@ -44,13 +44,13 @@ public interface EditorFactory { * @return Control */ Control newEditorOn(Composite parent, PropertyDescriptor desc, Rule rule, ValueChangeListener listener, SizeChangeListener sizeListener); - + /** - * Create an array of label-widget pairs on the parent composite for the - * type managed by the factory. In most cases this will just be a single + * Create an array of label-widget pairs on the parent composite for the + * type managed by the factory. In most cases this will just be a single * widget that captures the default value. Numeric types may also provide * min/max limit widgets. - * + * * @param parent * @param desc * @param rule diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/FormatManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/FormatManager.java new file mode 100755 index 0000000000..930fab6593 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/FormatManager.java @@ -0,0 +1,50 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.pmd.RulePriority; +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.LanguageVersion; + +/** + * + * @author Brian Remedios + */ +public class FormatManager { + + private FormatManager() {} + + private static final Map, ValueFormatter> formattersByType = new HashMap, ValueFormatter>(); + + static { // used to render property values in short form in main table + formattersByType.put(String.class, ValueFormatter.StringFormatter); + formattersByType.put(String[].class, ValueFormatter.MultiStringFormatter); + formattersByType.put(Boolean.class, ValueFormatter.BooleanFormatter); + formattersByType.put(Boolean[].class, ValueFormatter.ObjectArrayFormatter); + formattersByType.put(Integer.class, ValueFormatter.NumberFormatter); + formattersByType.put(Integer[].class, ValueFormatter.ObjectArrayFormatter); + formattersByType.put(Long.class, ValueFormatter.NumberFormatter); + formattersByType.put(Long[].class, ValueFormatter.ObjectArrayFormatter); + formattersByType.put(Float.class, ValueFormatter.NumberFormatter); + formattersByType.put(Float[].class, ValueFormatter.ObjectArrayFormatter); + formattersByType.put(Double.class, ValueFormatter.NumberFormatter); + formattersByType.put(Double[].class, ValueFormatter.ObjectArrayFormatter); + formattersByType.put(Character.class, ValueFormatter.ObjectFormatter); + formattersByType.put(Character[].class, ValueFormatter.ObjectArrayFormatter); + formattersByType.put(Class.class, ValueFormatter.TypeFormatter); + formattersByType.put(Class[].class, ValueFormatter.MultiTypeFormatter); + formattersByType.put(Method.class, ValueFormatter.MethodFormatter); + formattersByType.put(Method[].class, ValueFormatter.MultiMethodFormatter); + formattersByType.put(Object[].class, ValueFormatter.ObjectArrayFormatter); + + formattersByType.put(RulePriority.class, ValueFormatter.PriorityFormatter); + formattersByType.put(Language.class, ValueFormatter.LanguageFormatter); + formattersByType.put(LanguageVersion.class, ValueFormatter.LanguageVersionFormatter); + } + + public static ValueFormatter formatterFor(Class type) { + return formattersByType.get(type); + } +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/IconColumnDescriptor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/IconColumnDescriptor.java index 38292946cd..918e657796 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/IconColumnDescriptor.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/IconColumnDescriptor.java @@ -17,45 +17,50 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; /** - * + * * @author Brian Remedios */ public class IconColumnDescriptor extends AbstractRuleColumnDescriptor { private Map iconsByValue; - + private static final Map iconNamesByPriority = CollectionUtil.mapFrom( - new Object[] { RulePriority.LOW, RulePriority.MEDIUM_LOW, RulePriority.MEDIUM, RulePriority.MEDIUM_HIGH, RulePriority.HIGH }, + new Object[] { RulePriority.LOW, RulePriority.MEDIUM_LOW, RulePriority.MEDIUM, RulePriority.MEDIUM_HIGH, RulePriority.HIGH }, new String[] {PMDUiConstants.ICON_BUTTON_PRIO5, PMDUiConstants.ICON_BUTTON_PRIO4, PMDUiConstants.ICON_BUTTON_PRIO3, PMDUiConstants.ICON_BUTTON_PRIO2, PMDUiConstants.ICON_BUTTON_PRIO1} ); - + private static final Map iconNamesByBoolean = CollectionUtil.mapFrom( - new Object[] { Boolean.TRUE, Boolean.FALSE }, + new Object[] { Boolean.TRUE, Boolean.FALSE }, new String[] { PMDUiConstants.ICON_GREEN_CHECK, PMDUiConstants.ICON_EMPTY} ); - + public static final RuleColumnDescriptor priority = new IconColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PRIORITY, SWT.RIGHT, 53, RuleFieldAccessor.priority, true, PMDUiConstants.ICON_BUTTON_PRIO0, iconNamesByPriority); - + public IconColumnDescriptor(String labelKey, int theAlignment, int theWidth, RuleFieldAccessor theAccessor, boolean resizableFlag, String theImagePath, Map imageNamesByValue) { super(labelKey, theAlignment, theWidth, theAccessor, resizableFlag, theImagePath); iconsByValue = iconsFor(imageNamesByValue); } - + private static Map iconsFor(Map imageNamesByValue) { - + Map imagesByValue = new HashMap(imageNamesByValue.size()); for (Map.Entry entry : imageNamesByValue.entrySet()) { imagesByValue.put(entry.getKey(), ResourceManager.imageFor(entry.getValue())); } return imagesByValue; } - + public Image imageFor(Rule rule) { Object value = valueFor(rule); return iconsByValue.get(value); } + public Image imageFor(RuleCollection collection) { + Object value = valueFor(collection); + return iconsByValue.get(value); + } + public TreeColumn newTreeColumnFor(Tree parent, int columnIndex, RuleSortListener sortListener, Map> paintListeners) { TreeColumn tc = buildTreeColumn(parent, sortListener); return tc; diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ImageColumnDescriptor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ImageColumnDescriptor.java index a5fcda65fe..4487863502 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ImageColumnDescriptor.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ImageColumnDescriptor.java @@ -4,8 +4,10 @@ import java.util.List; import java.util.Map; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; import net.sourceforge.pmd.eclipse.ui.PMDUiConstants; import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; +import net.sourceforge.pmd.eclipse.util.FontBuilder; import net.sourceforge.pmd.eclipse.util.Util; import org.eclipse.swt.SWT; @@ -15,19 +17,38 @@ import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; /** - * + * * @author Brian Remedios */ public class ImageColumnDescriptor extends AbstractRuleColumnDescriptor { private final CellPainterBuilder painterBuilder; - - public static final RuleColumnDescriptor filterViolationRegex = new ImageColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_FILTERS_REGEX, SWT.LEFT, 25, RuleFieldAccessor.violationRegex, false, PMDUiConstants.ICON_FILTER, Util.textAsColorShapeFor(16, 16, Util.shape.square)); + + private static final RuleFieldAccessor propertiesAcc = new BasicRuleFieldAccessor() { + + public Comparable valueFor(Rule rule) { + return PMDPreferencePage2.indexedPropertyStringFrom(rule); + } + public Comparable valueFor(RuleCollection collection) { + return IndexedString.Empty; +// int count = RuleUtil.countNonOccurrencesOf(collection, this, IndexedString.Empty); +// if (count == 0) return IndexedString.Empty; +// return new IndexedString("(rules with properties: " + count + ")"); + } + + }; + + private static final FontBuilder blueBold11 = new FontBuilder("Tahoma", 11, SWT.BOLD, SWT.COLOR_BLUE); + + public static final RuleColumnDescriptor priority = new ImageColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PRIORITY, SWT.LEFT, 50, RuleFieldAccessor.priority, false, PMDUiConstants.ICON_BUTTON_DIAMOND_WHITE, Util.uniqueItemsAsColorShapeFor(12, 12, Util.shape.diamond, SWT.LEFT, PMDPlugin.colorsByPriority)); + public static final RuleColumnDescriptor filterViolationRegex = new ImageColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_FILTERS_REGEX, SWT.LEFT, 25, RuleFieldAccessor.violationRegex, false, PMDUiConstants.ICON_FILTER_R, Util.textAsColorShapeFor(16, 16, Util.shape.square)); public static final RuleColumnDescriptor filterViolationXPath = new ImageColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_FILTERS_XPATH, SWT.LEFT, 25, RuleFieldAccessor.violationXPath, false, PMDUiConstants.ICON_FILTER_X, Util.textAsColorShapeFor(16, 16, Util.shape.circle)); - + public static final RuleColumnDescriptor properties = new ImageColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PROPERTIES, SWT.LEFT, 40, propertiesAcc, false, PMDUiConstants.ICON_BUTTON_DIAMOND_WHITE, Util.styledTextBuilder(blueBold11)); + + public ImageColumnDescriptor(String labelKey, int theAlignment, int theWidth, RuleFieldAccessor theAccessor, boolean resizableFlag, String theImagePath, CellPainterBuilder thePainterBuilder) { super(labelKey, theAlignment, theWidth, theAccessor, resizableFlag, theImagePath); - + painterBuilder = thePainterBuilder; } @@ -37,14 +58,14 @@ public class ImageColumnDescriptor extends AbstractRuleColumnDescriptor { public TreeColumn newTreeColumnFor(Tree parent, int columnIndex, final RuleSortListener sortListener, Map> paintListeners) { TreeColumn tc = buildTreeColumn(parent, sortListener); - if (painterBuilder != null) painterBuilder.addPainterFor(tc.getParent(), columnIndex, accessor(), paintListeners); + if (painterBuilder != null) painterBuilder.addPainterFor(tc.getParent(), columnIndex, accessor(), paintListeners); return tc; } public String stringValueFor(Rule rule) { return ""; } - + public Image imageFor(Rule rule) { return null; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ImplementationType.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ImplementationType.java new file mode 100755 index 0000000000..77f8f0e5dd --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ImplementationType.java @@ -0,0 +1,12 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +/** + * + * @author Brian Remedios + */ +public enum ImplementationType { + + XPath, + Java, + Mixed +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/IndexedString.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/IndexedString.java new file mode 100755 index 0000000000..c643ed556c --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/IndexedString.java @@ -0,0 +1,30 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +import java.util.Collections; +import java.util.List; + +public class IndexedString implements Comparable{ + + public final String string; + public final List indexSpans; + + public IndexedString(String theString) { + this(theString, Collections.EMPTY_LIST); + } + + public IndexedString(String theString, List theSpans) { + string = theString; + indexSpans = theSpans; + } + + public int compareTo(IndexedString other) { + + int deltaLength = other.string.length() - string.length(); + + return deltaLength == 0 ? + other.string.compareTo(string) : + deltaLength; + } + + public static final IndexedString Empty = new IndexedString("", Collections.EMPTY_LIST); +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ModifyListener.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ModifyListener.java index 8528695963..cb6020cca1 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ModifyListener.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ModifyListener.java @@ -1,7 +1,7 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; /** - * + * * @author Brian Remedios */ public interface ModifyListener { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/NewPropertyDialog.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/NewPropertyDialog.java index 95bb295d5c..4885c763a8 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/NewPropertyDialog.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/NewPropertyDialog.java @@ -41,7 +41,7 @@ import org.eclipse.swt.widgets.Text; * @author Brian Remedios */ public class NewPropertyDialog extends Dialog implements SizeChangeListener { - + private Text nameField; private Text labelField; private Combo typeField; @@ -49,24 +49,24 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { private Composite dlgArea; private EditorFactory factory; private ValueChangeListener changeListener; - + private Rule rule; private PropertyDescriptor descriptor; private Map, EditorFactory> editorFactoriesByValueType; - + private Color textColour = new Color(null, 0, 0, 0); - private Color textErrorColour = new Color(null, 255, 0, 0); - + private Color textErrorColour = new Color(null, 255, 0, 0); + // these are the ones we've tested, the others may work but might not make sense in the xpath source context... private static final Class[] validEditorTypes = new Class[] { String.class, Integer.class, Boolean.class }; private static final Class defaultEditorType = validEditorTypes[0]; // first one - + private static final String INITIAL_NAME = "a unique name"; // private static final String INITIAL_DESC = "a description"; // - + public static Map, EditorFactory> withOnly(Map, EditorFactory> factoriesByType, Class[] legalTypeKeys) { Map, EditorFactory> results = new HashMap, EditorFactory>(legalTypeKeys.length); - + for (Class type : legalTypeKeys) { if (factoriesByType.containsKey(type)) { results.put(type, factoriesByType.get(type)); @@ -82,14 +82,14 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { */ public NewPropertyDialog(Shell parent, Map, EditorFactory> theEditorFactoriesByValueType, Rule theRule, ValueChangeListener theChangeListener) { super(parent); - + setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.APPLICATION_MODAL); - + rule = theRule; changeListener = theChangeListener; editorFactoriesByValueType = withOnly(theEditorFactoriesByValueType, validEditorTypes); } - + /** * Constructor for RuleDialog. * @@ -102,13 +102,13 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { } public boolean close() { - + textColour.dispose(); textErrorColour.dispose(); - + return super.close(); } - + /** * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(Composite) */ @@ -124,18 +124,18 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { layout.marginTop = 1; dlgArea.setLayout(layout); dlgArea.setLayoutData(new GridData(GridData.FILL_BOTH)); - + buildLabel(dlgArea, "Name:"); nameField = buildNameText(dlgArea); // TODO i18l label buildLabel(dlgArea, "Datatype:"); typeField = buildTypeField(dlgArea); // TODO i18l label buildLabel(dlgArea, "Label:"); labelField = buildLabelField(dlgArea); // TODO i18l label - + setPreferredName(); setInitialType(); - + validateForm(false); - + dlgArea.pack(); - + return dlgArea; } @@ -147,12 +147,12 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { label.setText(msgKey == null ? "" : SWTUtil.stringFor(msgKey)); return label; } - + /** * Build the rule name text */ private Text buildNameText(Composite parent) { - + final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER); GridData data = new GridData(); data.horizontalSpan = 1; @@ -165,21 +165,21 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { nameChanged(text); } }); - + return text; } - + private boolean isValidNewName(String nameCandidate) { if (StringUtil.isEmpty(nameCandidate)) return false; return rule.getPropertyDescriptor(nameCandidate) == null; } - + private static boolean isValidJavaIdentifier(String candidateName) { - + if (!Character.isJavaIdentifierStart(candidateName.charAt(0))) { return false; } - + for (int i=1; i desc : rule.getPropertyDescriptors()) { if (desc.description().equalsIgnoreCase(labelCandidate)) return false; } return true; } - + private void nameChanged(Text textField) { - String newName = textField.getText().trim(); + String newName = textField.getText().trim(); textField.setForeground( isValidNewName(newName) ? textColour : textErrorColour ); validateForm(false); } - + /** * Build the rule name text */ private Text buildLabelField(Composite parent) { - + final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER); GridData data = new GridData(); data.horizontalSpan = 1; data.horizontalAlignment = GridData.FILL; data.grabExcessHorizontalSpace = true; text.setLayoutData(data); - + text.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { labelChanged(text); } }); - + return text; } - + private void labelChanged(Text textField) { - String newLabel = textField.getText().trim(); + String newLabel = textField.getText().trim(); textField.setForeground( isValidNewLabel(newLabel) ? textColour : textErrorColour ); validateForm(false); } - + private static String labelFor(Class type) { return Util.signatureFor(type, MethodEditorFactory.UnwantedPrefixes); } - + /** * A bit of a hack but this avoids the need to create an alternate lookup structure - * + * * @param label * @return */ private EditorFactory factoryFor(String label) { - + for (Entry, EditorFactory> entry : editorFactoriesByValueType.entrySet()) { if (label.equals( labelFor(entry.getKey()) )) return entry.getValue(); } - + return null; } - + /** * Build the rule name text */ private Combo buildTypeField(final Composite parent) { - + final Combo combo = new Combo(parent, SWT.READ_ONLY); GridData data = new GridData(); data.grabExcessHorizontalSpace = true; data.horizontalAlignment = GridData.FILL; combo.setLayoutData(data); - + String[] labels = new String[editorFactoriesByValueType.size()]; int i=0; for (Entry, EditorFactory> entry : editorFactoriesByValueType.entrySet()) { labels[i++] = labelFor(entry.getKey()); } - Arrays.sort(labels); + Arrays.sort(labels); combo.setItems(labels); - + combo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int selectionIdx = combo.getSelectionIndex(); EditorFactory factory = factoryFor(combo.getItem(selectionIdx)); - + factory( factory ); } - }); - + }); + return combo; } - + private boolean ruleHasPropertyName(String name) { return rule.getPropertyDescriptor(name) != null; } - + /** * Pick the first name in the xpath source the rule doesn't know about */ private void setPreferredName() { - + String xpath = rule.getProperty(XPathRule.XPATH_DESCRIPTOR).trim(); List positions = Util.referencedNamePositionsIn(xpath, '$'); List names = Util.fragmentsWithin(xpath, positions); - + for (String name : names) { if (ruleHasPropertyName(name)) continue; nameField.setText(name); @@ -308,32 +308,32 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { } nameField.setText(INITIAL_NAME); } - + private void setInitialType() { String editorLabel = labelFor(defaultEditorType); typeField.select( Util.indexOf(typeField.getItems(), editorLabel) ); factory( factoryFor(editorLabel)); } - + private void cleanFactoryStuff() { if (factoryControls != null) for (Control control : factoryControls) control.dispose(); } - + private void factory(EditorFactory theFactory) { - + factory = theFactory; - + descriptor = factory.createDescriptor("??", INITIAL_DESC, null); labelField.setText(descriptor.description()); cleanFactoryStuff(); - + factoryControls = factory.createOtherControlsOn(dlgArea, descriptor, rule, changeListener, this); - + dlgArea.pack(); dlgArea.getParent().pack(); } - + // /** // * Helper method to shorten message access // * @@ -371,24 +371,24 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { private boolean validateName(boolean showErrorMessages) { String name = nameField.getText().trim(); - + if (StringUtil.isEmpty(name)) { - if (showErrorMessages) MessageDialog.openWarning(getShell(), + if (showErrorMessages) MessageDialog.openWarning(getShell(), SWTUtil.stringFor(StringKeys.MSGKEY_WARNING_TITLE), SWTUtil.stringFor(StringKeys.MSGKEY_WARNING_NAME_MANDATORY)); nameField.setFocus(); return false; } - + if (ruleHasPropertyName(name)) { - if (showErrorMessages) MessageDialog.openWarning(getShell(), + if (showErrorMessages) MessageDialog.openWarning(getShell(), SWTUtil.stringFor(StringKeys.MSGKEY_WARNING_TITLE), "'" + name + "' is already used by another property" ); nameField.setFocus(); return false; } - + return true; } @@ -398,28 +398,28 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { private boolean validateLabel(boolean showErrorMessages) { String label = labelField.getText().trim(); - + if (StringUtil.isEmpty(label)) { - if (showErrorMessages) MessageDialog.openWarning(getShell(), + if (showErrorMessages) MessageDialog.openWarning(getShell(), SWTUtil.stringFor(StringKeys.MSGKEY_WARNING_TITLE), "A proper label is required" ); labelField.setFocus(); return false; } - + if (!isValidNewLabel(label)) { - if (showErrorMessages) MessageDialog.openWarning(getShell(), + if (showErrorMessages) MessageDialog.openWarning(getShell(), SWTUtil.stringFor(StringKeys.MSGKEY_WARNING_TITLE), "Label text must differ from other label text" ); labelField.setFocus(); return false; } - + return true; } - + /** * Returns the descriptor. * @@ -430,14 +430,14 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { } private PropertyDescriptor newDescriptor() { - + return factory.createDescriptor( - nameField.getText().trim(), + nameField.getText().trim(), labelField.getText().trim(), factoryControls ); } - + /** * @see org.eclipse.jface.dialogs.Dialog#cancelPressed() */ @@ -446,11 +446,11 @@ public class NewPropertyDialog extends Dialog implements SizeChangeListener { // courierFont.dispose(); super.cancelPressed(); } - + public void addedRows(int newRowCount) { dlgArea.pack(); dlgArea.getParent().pack(); - + System.out.println("rows added: " + newRowCount); } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage.java index 1f10b1360a..44812b3ca5 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage.java @@ -24,8 +24,10 @@ import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; import net.sourceforge.pmd.eclipse.ui.preferences.RuleDialog; import net.sourceforge.pmd.eclipse.ui.preferences.RuleSetSelectionDialog; import net.sourceforge.pmd.eclipse.ui.preferences.editors.SWTUtil; +import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.AbstractRulePanelManager; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.Configuration; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.DescriptionPanelManager; +import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.EditorUsageMode; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.ExamplePanelManager; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.ExclusionPanelManager; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.PerRulePropertyPanelManager; @@ -106,7 +108,8 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu TextColumnDescriptor.since, TextColumnDescriptor.ruleSetName, TextColumnDescriptor.ruleType, - TextColumnDescriptor.minLangVers, + TextColumnDescriptor.minLangVers, + TextColumnDescriptor.maxLangVers, TextColumnDescriptor.language, ImageColumnDescriptor.filterViolationRegex, // regex text -> compact color squares (for comparison) ImageColumnDescriptor.filterViolationXPath, // xpath text -> compact color circles (for comparison) @@ -125,29 +128,6 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu }; // private static final int RuleTableFraction = 55; // percent of screen height vs property tabs - private static final Map, ValueFormatter> formattersByType = new HashMap, ValueFormatter>(); - - static { // used to render property values in short form in main table - formattersByType.put(String.class, ValueFormatter.StringFormatter); - formattersByType.put(String[].class, ValueFormatter.MultiStringFormatter); - formattersByType.put(Boolean.class, ValueFormatter.BooleanFormatter); - formattersByType.put(Boolean[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Integer.class, ValueFormatter.NumberFormatter); - formattersByType.put(Integer[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Long.class, ValueFormatter.NumberFormatter); - formattersByType.put(Long[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Float.class, ValueFormatter.NumberFormatter); - formattersByType.put(Float[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Double.class, ValueFormatter.NumberFormatter); - formattersByType.put(Double[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Character.class, ValueFormatter.ObjectFormatter); - formattersByType.put(Character[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Class.class, ValueFormatter.TypeFormatter); - formattersByType.put(Class[].class, ValueFormatter.MultiTypeFormatter); - formattersByType.put(Method.class, ValueFormatter.MethodFormatter); - formattersByType.put(Method[].class, ValueFormatter.MultiMethodFormatter); - formattersByType.put(Object[].class, ValueFormatter.ObjectArrayFormatter); - } private ContainerCheckedTreeViewer ruleTreeViewer; private Button addRuleButton; @@ -415,42 +395,6 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu data.right = new FormAttachment(100, 0); propertySection.setLayoutData(data); } - - public static void formatValueOn(StringBuilder target, Object value, Class datatype) { - - ValueFormatter formatter = formattersByType.get(datatype); - if (formatter != null) { - formatter.format(value, target); - return; - } - - target.append(value); // should not get here..breakpoint here - } - - /** - * @param rule Rule - * @return String - */ - public static String propertyStringFrom(Rule rule) { - - Map, Object> valuesByProp = Configuration.filteredPropertiesOf(rule); - - if (valuesByProp.isEmpty()) return ""; - StringBuilder sb = new StringBuilder(); - - Iterator> iter = valuesByProp.keySet().iterator(); - - PropertyDescriptor desc = iter.next(); - sb.append(desc.name()).append(": "); - formatValueOn(sb, rule.getProperty(desc), desc.type()); - - while (iter.hasNext()) { - desc = iter.next(); - sb.append(", ").append(desc.name()).append(": "); - formatValueOn(sb, rule.getProperty(desc), desc.type()); - } - return sb.toString(); - } public static String ruleSetNameFrom(Rule rule) { return ruleSetNameFrom( rule.getRuleSetName() ); @@ -535,8 +479,8 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu tabFolder = new TabFolder(parent, SWT.TOP); rulePropertyManagers = new RulePropertyManager[] { - buildPropertyTab(tabFolder, 0, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_PROPERTIES)), - buildDescriptionTab(tabFolder, 1, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_DESCRIPTION)), + buildDescriptionTab(tabFolder, 0, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_DESCRIPTION)), + buildPropertyTab(tabFolder, 1, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_PROPERTIES)), buildUsageTab(tabFolder, 2, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_FILTERS)), buildXPathTab(tabFolder, 3, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_XPATH)), buildQuickFixTab(tabFolder, 4, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_FIXES)), @@ -556,9 +500,9 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - PerRulePropertyPanelManager manager = new PerRulePropertyPanelManager(this); + PerRulePropertyPanelManager manager = new PerRulePropertyPanelManager(title, EditorUsageMode.Editing, this); tab.setControl( - manager.setupOn(parent, this) + manager.setupOn(parent) ); manager.tab(tab); return manager; @@ -573,7 +517,7 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - DescriptionPanelManager manager = new DescriptionPanelManager(this); + DescriptionPanelManager manager = new DescriptionPanelManager(title, EditorUsageMode.Editing, this); tab.setControl( manager.setupOn(parent) ); @@ -590,7 +534,7 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - XPathPanelManager manager = new XPathPanelManager(this); + XPathPanelManager manager = new XPathPanelManager(title, EditorUsageMode.Editing, this); tab.setControl( manager.setupOn(parent) ); @@ -607,7 +551,7 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - ExamplePanelManager manager = new ExamplePanelManager(this); + ExamplePanelManager manager = new ExamplePanelManager(title, EditorUsageMode.Editing, this); tab.setControl( manager.setupOn(parent) ); @@ -624,7 +568,7 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - QuickFixPanelManager manager = new QuickFixPanelManager(this); + QuickFixPanelManager manager = new QuickFixPanelManager(title, EditorUsageMode.Editing, this); tab.setControl( manager.setupOn(parent) ); @@ -643,13 +587,10 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - ExclusionPanelManager manager = new ExclusionPanelManager(this); + ExclusionPanelManager manager = new ExclusionPanelManager(title, EditorUsageMode.Editing, this, true); tab.setControl( manager.setupOn( - parent, - SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_EXCLUSION_REGEX), - SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_XPATH_EXCLUSION), - SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_COLOUR_CODE) + parent ) ); manager.tab(tab); @@ -794,7 +735,7 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu private boolean currentSelectionHasNonDefaultValues() { return ruleSelection == null ? - false : ruleSelection.allSelectedRulesUseDefaultValues(); + false : RuleUtil.allUseDefaultValues(ruleSelection); } private Menu createMenuFor(Control control) { @@ -930,7 +871,7 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu // then check that item and disable it, do the reverse for all others. private void adjustMenuRulesetSettings() { - String rulesetName = ruleSetNameFrom(ruleSelection.commonRuleset()); + String rulesetName = ruleSetNameFrom(RuleUtil.commonRuleset(ruleSelection)); Iterator> iter = rulesetMenusByName.entrySet().iterator(); while (iter.hasNext()) { @@ -953,7 +894,7 @@ public class PMDPreferencePage extends AbstractPMDPreferencePage implements Valu private void adjustMenuPrioritySettings() { - RulePriority priority = ruleSelection.commonPriority(); + RulePriority priority = RuleUtil.commonPriority(ruleSelection); Iterator> iter = priorityMenusByPriority.entrySet().iterator(); while (iter.hasNext()) { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage2.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage2.java index c67b610d06..f60a9ce45a 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage2.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage2.java @@ -1,8 +1,8 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -13,11 +13,14 @@ import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; import net.sourceforge.pmd.eclipse.runtime.preferences.impl.PreferenceUIStore; import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; import net.sourceforge.pmd.eclipse.ui.preferences.editors.SWTUtil; +import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.Configuration; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.DescriptionPanelManager; +import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.EditorUsageMode; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.ExamplePanelManager; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.ExclusionPanelManager; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.PerRulePropertyPanelManager; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.QuickFixPanelManager; +import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.RulePanelManager; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.RulePropertyManager; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.XPathPanelManager; import net.sourceforge.pmd.eclipse.util.Util; @@ -50,26 +53,30 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul private TabFolder tabFolder; private RulePropertyManager[] rulePropertyManagers; private RuleTableManager tableManager; - + // columns shown in the rule treetable in the desired order private static final RuleColumnDescriptor[] availableColumns = new RuleColumnDescriptor[] { TextColumnDescriptor.name, //TextColumnDescriptor.priorityName, - IconColumnDescriptor.priority, + // IconColumnDescriptor.priority, + ImageColumnDescriptor.priority, TextColumnDescriptor.fixCount, TextColumnDescriptor.since, TextColumnDescriptor.ruleSetName, TextColumnDescriptor.ruleType, - TextColumnDescriptor.minLangVers, + TextColumnDescriptor.minLangVers, + TextColumnDescriptor.maxLangVers, TextColumnDescriptor.language, ImageColumnDescriptor.filterViolationRegex, // regex text -> compact color squares (for comparison) ImageColumnDescriptor.filterViolationXPath, // xpath text -> compact color circles (for comparison) - TextColumnDescriptor.properties, + TextColumnDescriptor.modCount, + // TextColumnDescriptor.properties + ImageColumnDescriptor.properties }; // last item in this list is the grouping used at startup private static final Object[][] groupingChoices = new Object[][] { - { TextColumnDescriptor.ruleSetName, StringKeys.MSGKEY_PREF_RULESET_COLUMN_RULESET}, + { TextColumnDescriptor.ruleSetName, StringKeys.MSGKEY_PREF_RULESET_COLUMN_RULESET}, { TextColumnDescriptor.since, StringKeys.MSGKEY_PREF_RULESET_GROUPING_PMD_VERSION }, { TextColumnDescriptor.priorityName, StringKeys.MSGKEY_PREF_RULESET_COLUMN_PRIORITY }, { TextColumnDescriptor.ruleType, StringKeys.MSGKEY_PREF_RULESET_COLUMN_RULE_TYPE }, @@ -77,62 +84,124 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul { ImageColumnDescriptor.filterViolationRegex, StringKeys.MSGKEY_PREF_RULESET_GROUPING_REGEX }, { null, StringKeys.MSGKEY_PREF_RULESET_GROUPING_NONE } }; - - private static final Map, ValueFormatter> formattersByType = new HashMap, ValueFormatter>(); - static { // used to render property values in short form in main table - formattersByType.put(String.class, ValueFormatter.StringFormatter); - formattersByType.put(String[].class, ValueFormatter.MultiStringFormatter); - formattersByType.put(Boolean.class, ValueFormatter.BooleanFormatter); - formattersByType.put(Boolean[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Integer.class, ValueFormatter.NumberFormatter); - formattersByType.put(Integer[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Long.class, ValueFormatter.NumberFormatter); - formattersByType.put(Long[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Float.class, ValueFormatter.NumberFormatter); - formattersByType.put(Float[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Double.class, ValueFormatter.NumberFormatter); - formattersByType.put(Double[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Character.class, ValueFormatter.ObjectFormatter); - formattersByType.put(Character[].class, ValueFormatter.ObjectArrayFormatter); - formattersByType.put(Class.class, ValueFormatter.TypeFormatter); - formattersByType.put(Class[].class, ValueFormatter.MultiTypeFormatter); - formattersByType.put(Method.class, ValueFormatter.MethodFormatter); - formattersByType.put(Method[].class, ValueFormatter.MultiMethodFormatter); - formattersByType.put(Object[].class, ValueFormatter.ObjectArrayFormatter); + public PMDPreferencePage2() { + + } + + /** + * @param rule Rule + * @return String + */ + public static String propertyStringFrom(Rule rule, String modifiedTag) { + + Map, Object> valuesByProp = Configuration.filteredPropertiesOf(rule); + + if (valuesByProp.isEmpty()) return ""; + StringBuilder sb = new StringBuilder(); + + Iterator, Object>> iter = valuesByProp.entrySet().iterator(); + + Map.Entry, Object> entry = iter.next(); + sb.append(entry.getKey().name()).append(": "); + formatValueOn(sb, entry, modifiedTag); + + while (iter.hasNext()) { + entry = iter.next(); + sb.append(", ").append(entry.getKey().name()).append(": "); + formatValueOn(sb, entry, modifiedTag); + } + return sb.toString(); } - public PMDPreferencePage2() { + private static int formatValueOn(StringBuilder target, Map.Entry, Object> entry, String modifiedTag) { + + Object value = entry.getValue(); + Class datatype = entry.getKey().type(); + boolean isModified = !RuleUtil.isDefaultValue(entry); + if (isModified) target.append(modifiedTag); + + ValueFormatter formatter = FormatManager.formatterFor(datatype); + if (formatter != null) { + String output = formatter.format(value); + target.append(output); + return isModified ? output.length() : 0; + } + + String out = String.valueOf(value); + target.append(out); // should not get here..breakpoint here + return isModified ? out.length() : 0; + } + + public static String ruleSetNameFrom(Rule rule) { + return ruleSetNameFrom( rule.getRuleSetName() ); + } + + public static String ruleSetNameFrom(String rulesetName) { + + int pos = rulesetName.toUpperCase().indexOf("RULES"); + return pos < 0 ? rulesetName : rulesetName.substring(0, pos-1); + } + + /** + * @param rule Rule + * @return String + */ + public static IndexedString indexedPropertyStringFrom(Rule rule) { + + Map, Object> valuesByProp = Configuration.filteredPropertiesOf(rule); + + if (valuesByProp.isEmpty()) return IndexedString.Empty; + StringBuilder sb = new StringBuilder(); + + Iterator, Object>> iter = valuesByProp.entrySet().iterator(); + + List modValueIndexes = new ArrayList(valuesByProp.size()); + + Map.Entry, Object> entry = iter.next(); + sb.append(entry.getKey().name()).append(": "); + int start = sb.length(); + int stop = start + formatValueOn(sb, entry, ""); + if (stop > start) modValueIndexes.add(new int[] { start, stop }); + + while (iter.hasNext()) { + entry = iter.next(); + sb.append(", ").append(entry.getKey().name()).append(": "); + start = sb.length(); + stop = start + formatValueOn(sb, entry, ""); + if (stop > start) modValueIndexes.add(new int[] { start, stop }); + } + return new IndexedString(sb.toString(), modValueIndexes); } protected String descriptionId() { return StringKeys.MSGKEY_PREF_RULESET_TITLE; } - + @Override protected Control createContents(Composite parent) { - - tableManager = new RuleTableManager(availableColumns, formattersByType, PMDPlugin.getDefault().loadPreferences()); + + tableManager = new RuleTableManager(availableColumns, PMDPlugin.getDefault().loadPreferences()); tableManager.modifyListener(this); tableManager.selectionListener(this); - - populateRuleset(); - + + populateRuleset(); + Composite composite = new Composite(parent, SWT.NULL); layoutControls(composite); - + tableManager.populateRuleTable(); int i = PreferenceUIStore.instance.selectedPropertyTab() ; tabFolder.setSelection( i ); - + return composite; } - + public void createControl(Composite parent) { super.createControl(parent); - - setModified(false); + + setModified(false); } /** * Create buttons for rule properties table management @@ -149,17 +218,17 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul return composite; } - + private Composite createRuleSection(Composite parent) { - + Composite ruleSection = new Composite(parent, SWT.NULL); - + // Create the controls (order is important !) Composite groupCombo = tableManager.buildGroupCombo(ruleSection, StringKeys.MSGKEY_PREF_RULESET_RULES_GROUPED_BY, groupingChoices); - + Tree ruleTree = tableManager.buildRuleTreeViewer(ruleSection); tableManager.groupBy(null); - + Composite ruleTableButtons = tableManager.buildRuleTableButtons(ruleSection); Composite rulePropertiesTableButtons = buildRulePropertiesTableButtons(ruleSection); @@ -187,10 +256,10 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul data.horizontalSpan = 1; data.horizontalAlignment = GridData.FILL; data.verticalAlignment = GridData.FILL; rulePropertiesTableButtons.setLayoutData(data); - + return ruleSection; } - + /** * Method buildTabFolder. * @param parent Composite @@ -201,18 +270,36 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul tabFolder = new TabFolder(parent, SWT.TOP); rulePropertyManagers = new RulePropertyManager[] { - buildPropertyTab(tabFolder, 0, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_PROPERTIES)), + buildRuleTab(tabFolder, 0, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_RULE)), buildDescriptionTab(tabFolder, 1, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_DESCRIPTION)), - buildUsageTab(tabFolder, 2, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_FILTERS)), - buildXPathTab(tabFolder, 3, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_XPATH)), - buildQuickFixTab(tabFolder, 4, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_FIXES)), - buildExampleTab(tabFolder, 5, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_EXAMPLES)), + buildPropertyTab(tabFolder, 2, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_PROPERTIES)), + buildUsageTab(tabFolder, 3, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_FILTERS)), + buildXPathTab(tabFolder, 4, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_XPATH)), + buildQuickFixTab(tabFolder, 5, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_FIXES)), + buildExampleTab(tabFolder, 6, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_EXAMPLES)), }; tabFolder.pack(); return tabFolder; } + /** + * @param parent TabFolder + * @param index int + */ + private RulePropertyManager buildRuleTab(TabFolder parent, int index, String title) { + + TabItem tab = new TabItem(parent, 0, index); + tab.setText(title); + + RulePanelManager manager = new RulePanelManager(title, EditorUsageMode.Editing, this, null); + tab.setControl( + manager.setupOn(parent) + ); + manager.tab(tab); + return manager; + } + /** * @param parent TabFolder * @param index int @@ -222,9 +309,9 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - PerRulePropertyPanelManager manager = new PerRulePropertyPanelManager(this); + PerRulePropertyPanelManager manager = new PerRulePropertyPanelManager(title, EditorUsageMode.Editing, this); tab.setControl( - manager.setupOn(parent, this) + manager.setupOn(parent) ); manager.tab(tab); return manager; @@ -239,7 +326,7 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - DescriptionPanelManager manager = new DescriptionPanelManager(this); + DescriptionPanelManager manager = new DescriptionPanelManager(title, EditorUsageMode.Editing, this); tab.setControl( manager.setupOn(parent) ); @@ -256,14 +343,14 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - XPathPanelManager manager = new XPathPanelManager(this); + XPathPanelManager manager = new XPathPanelManager(title, EditorUsageMode.Editing, this); tab.setControl( manager.setupOn(parent) ); manager.tab(tab); return manager; } - + /** * @param parent TabFolder * @param index int @@ -273,14 +360,14 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - ExamplePanelManager manager = new ExamplePanelManager(this); + ExamplePanelManager manager = new ExamplePanelManager(title, EditorUsageMode.Editing, this); tab.setControl( manager.setupOn(parent) ); manager.tab(tab); return manager; - } - + } + /** * @param parent TabFolder * @param index int @@ -290,14 +377,14 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - QuickFixPanelManager manager = new QuickFixPanelManager(this); + QuickFixPanelManager manager = new QuickFixPanelManager(title, EditorUsageMode.Editing, this); tab.setControl( manager.setupOn(parent) ); manager.tab(tab); return manager; } - + /** * * @param parent TabFolder @@ -309,41 +396,36 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul TabItem tab = new TabItem(parent, 0, index); tab.setText(title); - ExclusionPanelManager manager = new ExclusionPanelManager(this); + ExclusionPanelManager manager = new ExclusionPanelManager(title, EditorUsageMode.Editing, this, true); tab.setControl( - manager.setupOn( - parent, - SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_EXCLUSION_REGEX), - SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_XPATH_EXCLUSION), - SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_COLOUR_CODE) - ) + manager.setupOn(parent) ); manager.tab(tab); return manager; } - + public void changed(Rule rule, PropertyDescriptor desc, Object newValue) { // TODO enhance to recognize default values - setModified(); + setModified(); tableManager.updated(rule); } - + public void changed(RuleSelection selection, PropertyDescriptor desc, Object newValue) { // TODO enhance to recognize default values - + for (Rule rule : selection.allRules()) { if (newValue != null) { // non-reliable update behaviour, alternate trigger option - weird - // ruleTreeViewer.getTree().redraw(); + tableManager.changed(selection, desc, newValue); // System.out.println("doing redraw"); } else { - // ruleTreeViewer.update(rule, null); + tableManager.changed(rule, desc, newValue); // System.out.println("viewer update"); } } for (RulePropertyManager manager : rulePropertyManagers) { manager.validate(); } - + setModified(); } @@ -355,7 +437,7 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul parent.setLayout(new FormLayout()); int ruleTableFraction = 55; //PreferenceUIStore.instance.tableFraction(); - + // Create the sash first, so the other controls can be attached to it. final Sash sash = new Sash(parent, SWT.HORIZONTAL); FormData data = new FormData(); @@ -396,9 +478,9 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul */ @Override public boolean performOk() { - + saveUIState(); - + if (isModified()) { updateRuleSet(); rebuildProjects(); @@ -407,14 +489,14 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul return super.performOk(); } - + @Override public boolean performCancel() { - saveUIState(); + saveUIState(); return super.performCancel(); } - + /** * @see org.eclipse.jface.preference.PreferencePage#performDefaults() */ @@ -423,9 +505,9 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul tableManager.populateRuleTable(); super.performDefaults(); } - + private void populateRuleset() { - + RuleSet defaultRuleSet = plugin.getPreferencesManager().getRuleSet(); RuleSet ruleSet = new RuleSet(); ruleSet.addRuleSet(defaultRuleSet); @@ -433,18 +515,18 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul ruleSet.setDescription(Util.asCleanString(defaultRuleSet.getDescription())); ruleSet.addExcludePatterns(defaultRuleSet.getExcludePatterns()); ruleSet.addIncludePatterns(defaultRuleSet.getIncludePatterns()); - + tableManager.useRuleSet(ruleSet); } - + public void selection(RuleSelection selection) { - + for (RulePropertyManager manager : rulePropertyManagers) { manager.manage(selection); manager.validate(); } } - + /** * If user wants to, rebuild all projects */ @@ -467,25 +549,25 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul } } } - + private void saveUIState() { tableManager.saveUIState(); int i = tabFolder.getSelectionIndex(); PreferenceUIStore.instance.selectedPropertyTab( i ); PreferenceUIStore.instance.save(); } - - private void storeActiveRules() { - + + private void storeActiveRules() { + List chosenRules = tableManager.activeRules(); for (Rule rule : chosenRules) { preferences.isActive(rule.getName(), true); } - + System.out.println("Active rules: " + preferences.getActiveRuleNames()); } - + /** * Update the configured rule set * Update also all configured projects diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PropertyChangeListener.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PropertyChangeListener.java index 4a6e43c04e..304ace57a8 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PropertyChangeListener.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/PropertyChangeListener.java @@ -3,7 +3,7 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; import net.sourceforge.pmd.PropertyDescriptor; /** - * + * * @author Brian Remedios */ public interface PropertyChangeListener { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleCollection.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleCollection.java new file mode 100755 index 0000000000..619c391ecb --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleCollection.java @@ -0,0 +1,30 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +import net.sourceforge.pmd.Rule; + + +/** + * + * @author Brian Remedios + */ +public interface RuleCollection { + + boolean isEmpty(); + + /** + * Return the only rule in the receiver or null if empty + * or more than one is found. + * + * @return + */ + Rule soleRule(); + + /** + * Iterate through all the rules while the visitor returns + * true. Returns the result of the last rule visited. + * + * @param visitor + * @return + */ + boolean rulesDo(RuleVisitor visitor); +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleColumnDescriptor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleColumnDescriptor.java index 5a74c25f30..39ebb9b3fd 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleColumnDescriptor.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleColumnDescriptor.java @@ -11,15 +11,17 @@ import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; /** - * + * * @author Brian Remedios */ -public interface RuleColumnDescriptor { +public interface RuleColumnDescriptor extends ColumnDescriptor { - String label(); RuleFieldAccessor accessor(); Image imageFor(Rule rule); + Image imageFor(RuleCollection collection); String stringValueFor(Rule rule); + String stringValueFor(RuleCollection collection); String detailStringFor(Rule rule); + String detailStringFor(RuleGroup group); TreeColumn newTreeColumnFor(Tree parent, int columnIndex, RuleSortListener sortListener, Map> paintListeners); } \ No newline at end of file diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleFieldAccessor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleFieldAccessor.java index e1e1c1f840..d8bf8571aa 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleFieldAccessor.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleFieldAccessor.java @@ -2,6 +2,7 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; import java.util.ArrayList; import java.util.List; +import java.util.Set; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.eclipse.ui.quickfix.PMDResolutionGenerator; @@ -13,26 +14,31 @@ import net.sourceforge.pmd.lang.rule.XPathRule; /** * A value and label extractor interface for anything implementing the Rule interface * and may be real fields or values held as properties. - * - * Value returned are typed as comparable to facilitate sorting. Never return null, + * + * Value returned are typed as comparable to facilitate sorting. Never return null, * return an empty string instead. - * + * * @author Brian Remedios */ public interface RuleFieldAccessor { - + // NOTE: If you update these values then you also need to update // the tooltip that references them: 'preference.ruleset.column.rule_type.tooltip' - - String ruleTypeXPath[] = new String[] { "X", "XPath" }; - String ruleTypeDFlow[] = new String[] { "D", "Dataflow" }; - String ruleTypeTypeRes[]= new String[] { "T", "Type resolving" }; - + + String[] ruleTypeXPath = new String[] { "X", "XPath" }; + String[] ruleTypeDFlow = new String[] { "D", "Dataflow" }; + String[] ruleTypeTypeRes= new String[] { "T", "Type resolving" }; + /** * @param rule Rule * @return Comparable */ Comparable valueFor(Rule rule); + + Comparable valueFor(RuleCollection collection); + + Set> uniqueValuesFor(RuleCollection collection); + String labelFor(Rule rule); RuleFieldAccessor since = new BasicRuleFieldAccessor() { @@ -40,62 +46,68 @@ public interface RuleFieldAccessor { return rule.getSince(); } }; - + RuleFieldAccessor priority = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return rule.getPriority(); } + public Comparable valueFor(RuleCollection collection) { + return RuleUtil.commonPriority(collection); + } }; - + RuleFieldAccessor priorityName = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return rule.getPriority().getName(); } }; - + RuleFieldAccessor fixCount = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return PMDResolutionGenerator.fixCountFor(rule); } }; - + RuleFieldAccessor name = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return rule.getName(); } }; - + RuleFieldAccessor description = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return rule.getDescription(); } }; - + RuleFieldAccessor usesDFA = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { - return rule.usesDFA() ? Boolean.TRUE : Boolean.FALSE; + return rule.usesDFA(); + } + public Comparable valueFor(RuleCollection collection) { + return RuleUtil.allUseDfa(collection); } }; - + RuleFieldAccessor message = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return rule.getMessage(); } }; - + RuleFieldAccessor url = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return rule.getExternalInfoUrl(); } }; - + RuleFieldAccessor exampleCount = new BasicRuleFieldAccessor() { - public Comparable valueFor(Rule rule) { + public Comparable valueFor(Rule rule) { int count = rule.getExamples().size(); return count > 0 ? Integer.toString(count) : ""; } }; - + RuleFieldAccessor ruleType = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { StringBuilder sb = new StringBuilder(3); @@ -112,36 +124,44 @@ public interface RuleFieldAccessor { return Util.asString(types, ", "); } }; - + RuleFieldAccessor language = new BasicRuleFieldAccessor() { - public Comparable valueFor(Rule rule) { - Language language = rule.getLanguage(); - return language == null ? "" : language.getTerseName(); + public Comparable valueFor(Rule rule) { + return rule.getLanguage(); } + + protected String format(Object item) { + return ((Language)item).getName(); + } }; - + RuleFieldAccessor minLanguageVersion = new BasicRuleFieldAccessor() { - public Comparable valueFor(Rule rule) { - LanguageVersion version = rule.getMinimumLanguageVersion(); - return version == null ? "" : version.getTerseName(); + public Comparable valueFor(Rule rule) { + return rule.getMinimumLanguageVersion(); } }; - + RuleFieldAccessor maxLanguageVersion = new BasicRuleFieldAccessor() { - public Comparable valueFor(Rule rule) { + public Comparable valueFor(Rule rule) { return rule.getMaximumLanguageVersion(); } }; - + RuleFieldAccessor violationRegex = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return rule.getProperty(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR); } }; - + RuleFieldAccessor violationXPath = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { return rule.getProperty(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR); } }; + + RuleFieldAccessor nonDefaultProperyCount = new BasicRuleFieldAccessor() { + public Comparable valueFor(Rule rule) { + return RuleUtil.modifiedPropertiesIn(rule).size(); + } + }; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleGroup.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleGroup.java index 1687521d1c..858334637b 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleGroup.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleGroup.java @@ -6,22 +6,21 @@ import java.util.Comparator; import java.util.List; import net.sourceforge.pmd.Rule; -import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.lang.rule.properties.StringProperty; import net.sourceforge.pmd.util.StringUtil; /** * Holds a collection of rules as assembled by the tree widget manager. - * + * * @author Brian Remedios */ -public class RuleGroup implements Comparable { +public class RuleGroup implements RuleCollection, Comparable { private Comparable id; private String label; private String description; private List rules = new ArrayList(); - + /** * @param theId Object * @param theDescription String @@ -32,144 +31,103 @@ public class RuleGroup implements Comparable { description = theDescription; } + public boolean isEmpty() { return rules == null || rules.isEmpty(); } + /** * If the receiver holds just a single rule then return * it, otherwise return null. - * + * * @return Rule */ public Rule soleRule() { return rules.size() == 1 ? rules.get(0) : null; } + + public boolean rulesDo(RuleVisitor visitor) { + + for (Rule rule : rules) { + if (!visitor.accept(rule)) return false; + } + + return true; + } /** * @return Comparable */ public Comparable id() { return id; } - + /** * @return String */ public String description() { return description; } - + /** * @return String */ public String label() { - + if (label != null) return label; return id == null ? "" : id.toString(); } - + public void sortBy(Comparator ruleComparator) { - + if (!hasRules()) return; - + Object[] sortedRules = rules.toArray(); - + Arrays.sort(sortedRules, ruleComparator); rules.clear(); for (Object rule : sortedRules) rules.add((Rule)rule); } - + /** * @return int */ public int ruleCount() { return rules.size(); } - + /** * @param ref Rule */ public void add(Rule ref) { rules.add(ref); } - + /** * @return Rule[] */ - public Rule[] rules() { - return rules.toArray(new Rule[rules.size()]); + public Rule[] rules() { + return rules.toArray(new Rule[rules.size()]); } - - public void setPriority(RulePriority priority) { - for (Rule rule : rules) rule.setPriority(priority); - } - - - public boolean allRulesUseDefaultValues() { - - for (Rule rule : rules) { - if (!rule.usesDefaultValues()) return false; - } - - return true; - } - - /** - * Returns the name of the ruleset common to all rules - * held by the receiver, returns null if they differ. - * - * @return String - */ - public String commonRuleset() { - - if (rules.isEmpty()) return null; - - String rulesetName = rules.get(0).getRuleSetName(); - for (int i=1; i 0 ? rawLabel.substring(0, rulesPos) : rawLabel; - + return filteredLabel + " (" + count + ")"; } - + } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleSelection.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleSelection.java index 31d8a9efc4..6761ebe587 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleSelection.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleSelection.java @@ -2,204 +2,290 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.LanguageVersion; +import net.sourceforge.pmd.lang.rule.RuleReference; +import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.properties.StringProperty; +import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; /** * Represents a set of selected rules in a rule selection widget. Provides useful metrics * and determines common properties (if any). - * + * * @author Brian Remedios */ -public class RuleSelection { +public class RuleSelection implements RuleCollection { private Object[] ruleItems; + public RuleSelection(Rule soleRule) { + this(new Object[] {soleRule} ); + } + + public boolean isEmpty() { return ruleItems == null || ruleItems.length == 0; } + public RuleSelection(Object[] theRuleItems) { ruleItems = theRuleItems; } + public void soleRule(Rule theRule) { + ruleItems = new Object[] { theRule }; + } + + /** + * Iterate through all the rules ultimately held by the receiver. + * Returns true if it went through every one, false if it stopped + * along the way. + * + * @param visitor + * @return + */ + public boolean rulesDo(RuleVisitor visitor) { + + for (Object item : ruleItems) { + if (item instanceof Rule) { + if (!visitor.accept((Rule)item)) return false; + continue; + } + if (item instanceof RuleGroup) { + if (!((RuleGroup)item).rulesDo(visitor)) return false; + } + } + + return true; + } + + public ImplementationType implementationType() { + + if (ruleItems == null || ruleItems.length == 0) return ImplementationType.Mixed; + + final Set types = new HashSet(); + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + types.add( implementationType(rule) ); + return types.size() < 2; + } + }; + + rulesDo(visitor); + + return types.size() > 1 ? + ImplementationType.Mixed : + types.iterator().next(); + } + + /** + * Returns whether all the elements match by equality and position + * including any possible children they may have. + * + * @param thisArray Object[] + * @param thatArray Object[] + * @return boolean + */ + public static final boolean valuesAreTransitivelyEqual(Object[] thisArray, Object[] thatArray) { + if (thisArray == thatArray) return true; + if ((thisArray == null) || (thatArray == null)) return false; + if (thisArray.length != thatArray.length) return false; + for (int i = 0; i < thisArray.length; i++) { + if (!CollectionUtil.areEqual(thisArray[i], thatArray[i])) return false; // recurse if req'd + } + return true; + } + + public boolean haveDefaultValues() { + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + return rule.usesDefaultValues(); + } + }; + + return rulesDo(visitor); + } + public boolean hasOneRule() { - + if (ruleItems.length > 1) return false; return allRules().size() == 1; } - + public boolean hasMultipleRules() { return ruleItems != null && allRules().size() > 1; } - + public Rule soleRule() { - + if (ruleItems == null || ruleItems.length != 1) return null; if (ruleItems[0] instanceof Rule) return (Rule)ruleItems[0]; if (ruleItems[0] instanceof RuleGroup) { return ((RuleGroup)ruleItems[0]).soleRule(); } - + return null; // should not get here } - - private boolean hasDefaultValues(Rule rule) { - - return true; - } - - - private boolean allHaveDefaultValues(RuleGroup group) { - - return true; - } - - public boolean allSelectedRulesUseDefaultValues() { - - if (ruleItems == null || ruleItems.length == 0) return true; - - if (ruleItems[0] instanceof Rule) return hasDefaultValues((Rule)ruleItems[0]); - if (ruleItems[0] instanceof RuleGroup) { - return allHaveDefaultValues((RuleGroup)ruleItems[0]); - } - // should never get here - return true; + private static void useDefaultValues(Rule rule) { + + for (Map.Entry, Object> entry : rule.getPropertiesByPropertyDescriptor().entrySet()) { + //rule.useDefaultValueFor(entry.getKey()); + System.out.println("TODO: Setting default for: " + entry.getKey().name() ); + // TODO filter out 'hidden' properties such as violationSuppressRegex..etc. + } } public void useDefaultValues() { - // TODO + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + useDefaultValues(rule); + return true; + } + }; + + rulesDo(visitor); } - private RulePriority commonPriorityFor(Object item) { - - return item instanceof Rule ? - ((Rule)item).getPriority() : - ((RuleGroup)item).commonPriority(); + public static ImplementationType implementationType(Rule rule) { + + if (rule instanceof RuleReference) { + return ((RuleReference)rule).getRule() instanceof XPathRule ? ImplementationType.XPath : ImplementationType.Java; + } else { + return rule instanceof XPathRule ? ImplementationType.XPath : ImplementationType.Java; + } } - private String commonRulesetFor(Object item) { - - return item instanceof Rule ? - ((Rule)item).getRuleSetName() : - ((RuleGroup)item).commonRuleset(); - } - - private String commonStringValueFor(Object item, StringProperty desc) { - + public static String commonStringValueFor(Object item, StringProperty desc) { + return item instanceof Rule ? ((Rule)item).getProperty(desc) : ((RuleGroup)item).commonStringProperty(desc); } - - public void setPriority(RulePriority priority) { - + + public void setLanguage(final Language language) { + if (ruleItems == null) return; - - for (Object ruleItem : ruleItems) { - if (ruleItem instanceof Rule) { - ((Rule)ruleItem).setPriority(priority); - } - if (ruleItem instanceof RuleGroup) { - ((RuleGroup)ruleItem).setPriority(priority); - } - } + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + rule.setLanguage(language); + return true; + } + }; + + rulesDo(visitor); } + public void setMinLanguageVersion(final LanguageVersion version) { + + if (ruleItems == null) return; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + rule.setMinimumLanguageVersion(version); + return true; + } + }; + + rulesDo(visitor); + } + + public void setMaxLanguageVersion(final LanguageVersion version) { + + if (ruleItems == null) return; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + rule.setMaximumLanguageVersion(version); + return true; + } + }; + + rulesDo(visitor); + } + + public void setPriority(final RulePriority priority) { + + if (ruleItems == null) return; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + rule.setPriority(priority); + return true; + } + }; + + rulesDo(visitor); + } + public int removeAllFrom(RuleSet ruleSet) { - + List rules = allRules(); if (rules.isEmpty()) return 0; - + Collection currentRules = ruleSet.getRules(); - for (Rule rule : rules) currentRules.remove(rule); - + for (Rule rule : rules) currentRules.remove(rule); + return currentRules.size(); } - + public List allRules() { - - List selections = new ArrayList(); - - if (ruleItems == null || ruleItems.length == 0) { - return selections; + + if (ruleItems == null || ruleItems.length == 0) { + return Collections.emptyList(); } - - for (Object ruleItem : ruleItems) { - if (ruleItem instanceof Rule) { - selections.add((Rule)ruleItem); - continue; - } else { - Rule[] rules = ((RuleGroup)ruleItem).rules(); - for (Rule rule : rules) selections.add(rule); - } - } - - return selections; + + final List rules = new ArrayList(ruleItems.length); + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + rules.add( rule ); + return true; + } + }; + + rulesDo(visitor); + + return rules; } - - /** - * Iterates through the currently selected rules and returns - * their common priority setting or null if they differ. - */ - public RulePriority commonPriority() { - - if (ruleItems == null || ruleItems.length == 0) return null; - - RulePriority priority = commonPriorityFor(ruleItems[0]); - if (priority == null) return null; - - for (int i=1; i ruleColl) { Object[] rules = ruleColl.toArray(); if (comparator == null) return rules; - + Arrays.sort(rules, comparator); return rules; } - + /** * * @param parentElement Object @@ -56,20 +56,20 @@ public class RuleSetTreeItemProvider implements ITreeContentProvider { * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(Object) */ public Object[] getChildren(Object parentElement) { - + if (parentElement instanceof RuleSet) { RuleSet ruleSet = (RuleSet) parentElement; return fieldAccessor == null ? sort(ruleSet.getRules()) : asRuleGroups(ruleSet.getRules()); } - + if (parentElement instanceof RuleGroup) { RuleGroup ruleGroup = (RuleGroup) parentElement; return ruleGroup.rules(); } - - return Util.EMPTY_ARRAY; + + return Util.EMPTY_ARRAY; } /** @@ -78,14 +78,14 @@ public class RuleSetTreeItemProvider implements ITreeContentProvider { * @return RuleGroup[] */ private RuleGroup[] asRuleGroups(Collection rules) { - + Iterator iter = rules.iterator(); Map ruleGroups = new HashMap(); while (iter.hasNext()) { Rule rule = iter.next(); - + Comparable groupId = fieldAccessor.valueFor(rule); - + RuleGroup group = ruleGroups.get(groupId); if (group != null) { group.add(rule); @@ -99,16 +99,16 @@ public class RuleSetTreeItemProvider implements ITreeContentProvider { ruleGroups.put(groupId, group); } } - + RuleGroup[] groups = ruleGroups.values().toArray(new RuleGroup[ruleGroups.size()]); - + // TODO sort within groups for (RuleGroup group : groups) group.sortBy(comparator); - + Arrays.sort(groups); return groups; } - + /** * Method getParent. * @param element Object @@ -127,16 +127,16 @@ public class RuleSetTreeItemProvider implements ITreeContentProvider { * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(Object) */ public boolean hasChildren(Object element) { - + if (element instanceof RuleSet) { RuleSet ruleSet = (RuleSet) element; return ruleSet.getRules().size() > 0; } - + if (element instanceof RuleGroup) { return ((RuleGroup)element).hasRules(); } - + return false; } @@ -158,11 +158,11 @@ public class RuleSetTreeItemProvider implements ITreeContentProvider { * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(Viewer, Object, Object) */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - + } public void dispose() { - // TODO Auto-generated method stub + // TODO Auto-generated method stub } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleSortListener.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleSortListener.java index 706eb4ce21..d9ef369d6f 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleSortListener.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleSortListener.java @@ -1,7 +1,7 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; /** - * + * * @author Brian Remedios */ public interface RuleSortListener { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleTableManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleTableManager.java index 1ea765927c..1eeacc477e 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleTableManager.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleTableManager.java @@ -1,7 +1,9 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; @@ -15,17 +17,15 @@ import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; import net.sourceforge.pmd.eclipse.runtime.preferences.IPreferences; import net.sourceforge.pmd.eclipse.runtime.preferences.impl.PreferenceUIStore; import net.sourceforge.pmd.eclipse.runtime.writer.IRuleSetWriter; +import net.sourceforge.pmd.eclipse.runtime.writer.WriterException; import net.sourceforge.pmd.eclipse.ui.PMDUiConstants; import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; -import net.sourceforge.pmd.eclipse.ui.preferences.RuleDialog; import net.sourceforge.pmd.eclipse.ui.preferences.RuleSetSelectionDialog; import net.sourceforge.pmd.eclipse.ui.preferences.editors.SWTUtil; -import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.Configuration; -import net.sourceforge.pmd.eclipse.util.ResourceManager; +import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.CreateRuleWizard; import net.sourceforge.pmd.eclipse.util.Util; import net.sourceforge.pmd.util.FileUtil; import net.sourceforge.pmd.util.StringUtil; @@ -33,18 +33,14 @@ import net.sourceforge.pmd.util.designer.Designer; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.ICheckStateProvider; -import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; @@ -57,202 +53,116 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; /** * Instantiates and manages a tree table widget holding all the rules in a ruleset. - * + * * @author Brian Remedios */ -public class RuleTableManager implements RuleSortListener, ValueChangeListener { +public class RuleTableManager extends AbstractTreeTableManager implements RuleSortListener, ValueChangeListener { private RuleSet ruleSet; - - private ContainerCheckedTreeViewer ruleTreeViewer; - - private boolean sortDescending; - private RuleFieldAccessor columnSorter = RuleFieldAccessor.name; // initial sort - private RuleColumnDescriptor groupingColumn; - private Set hiddenColumnNames = new HashSet(); - private Map> paintListeners = new HashMap>(); - + private RuleFieldAccessor columnSorter = RuleFieldAccessor.name; + private RuleColumnDescriptor groupingColumn; + private RuleFieldAccessor checkedColumnAccessor; private Map priorityMenusByPriority; private Map rulesetMenusByName; - - private RuleFieldAccessor checkedColumnAccessor; - private RuleSelection ruleSelection; // may hold rules and/or group nodes + private RuleSelection ruleSelection; // may hold rules and/or group nodes + private Menu ruleListMenu; +private MenuItem useDefaultsItem; private Button addRuleButton; private Button removeRuleButton; - private Button sortByCheckedButton; - private Button selectAllButton; - private Button unSelectAllButton; - private Label activeCountLabel; - + private final RuleColumnDescriptor[] availableColumns; // columns shown in the rule treetable in the desired order - private final Map, ValueFormatter> formattersByType; - private final IPreferences preferences; - - private ModifyListener modifyListener; private RuleSelectionListener ruleSelectionListener; - - protected static PMDPlugin plugin = PMDPlugin.getDefault(); - + public static String ruleSetNameFrom(Rule rule) { return ruleSetNameFrom( rule.getRuleSetName() ); } - public List activeRules() { - - Object[] checkedItems = ruleTreeViewer.getCheckedElements(); - List activeOnes = new ArrayList(checkedItems.length); - - for (Object item : checkedItems) { - if (item instanceof Rule) { - activeOnes.add((Rule)item); - } - } - - return activeOnes; - } - - public int activeRuleCount() { - - Object[] checkedItems = ruleTreeViewer.getCheckedElements(); - int count = 0; - - for (Object item : checkedItems) { - if (item instanceof Rule) count++; - } - - return count; - } - - public void modifyListener(ModifyListener theListener) { - modifyListener = theListener; - } - - public void selectionListener(RuleSelectionListener theListener) { - ruleSelectionListener = theListener; - } - public static String ruleSetNameFrom(String rulesetName) { + if (rulesetName == null) return null; + int pos = rulesetName.toUpperCase().indexOf("RULES"); return pos < 0 ? rulesetName : rulesetName.substring(0, pos-1); } - - public void formatValueOn(StringBuilder target, Object value, Class datatype) { - - ValueFormatter formatter = formattersByType.get(datatype); - if (formatter != null) { - formatter.format(value, target); - return; - } - - target.append(value); // should not get here..breakpoint here - } - - /** - * @param rule Rule - * @return String - */ - public String propertyStringFrom(Rule rule) { - - Map, Object> valuesByProp = Configuration.filteredPropertiesOf(rule); - - if (valuesByProp.isEmpty()) return ""; - StringBuilder sb = new StringBuilder(); - - Iterator> iter = valuesByProp.keySet().iterator(); - - PropertyDescriptor desc = iter.next(); - sb.append(desc.name()).append(": "); - formatValueOn(sb, rule.getProperty(desc), desc.type()); - - while (iter.hasNext()) { - desc = iter.next(); - sb.append(", ").append(desc.name()).append(": "); - formatValueOn(sb, rule.getProperty(desc), desc.type()); - } - return sb.toString(); - } - public RuleTableManager(RuleColumnDescriptor[] theColumns, Map, ValueFormatter> theFormattersByType, IPreferences thePreferences) { + public RuleTableManager(RuleColumnDescriptor[] theColumns, IPreferences thePreferences) { + super(thePreferences); availableColumns = theColumns; - formattersByType = theFormattersByType; - preferences = thePreferences; - - hiddenColumnNames = PreferenceUIStore.instance.hiddenColumnNames(); checkedColumnAccessor = createCheckedItemAccessor(); } + protected boolean isQualifiedItem(Object item) { + return item instanceof Rule; + } + + public List activeRules() { + + Object[] checkedItems = treeViewer.getCheckedElements(); + List activeOnes = new ArrayList(checkedItems.length); + + for (Object item : checkedItems) { + if (isQualifiedItem(item)) { + activeOnes.add((Rule)item); + } + } + + return activeOnes; + } + + public void selectionListener(RuleSelectionListener theListener) { + ruleSelectionListener = theListener; + } + private RuleFieldAccessor createCheckedItemAccessor() { - + return new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { - return preferences.isActive(rule.getName()); + return isActive(rule.getName()); } }; } - - private void addColumnSelectionOptions(Menu menu) { - - MenuItem showMenu = new MenuItem(menu, SWT.CASCADE); - showMenu.setText("Show"); - Menu columnsSubMenu = new Menu(menu); - showMenu.setMenu(columnsSubMenu); - - for (String columnLabel : columnLabels()) { - MenuItem columnItem = new MenuItem(columnsSubMenu, SWT.CHECK); - columnItem.setSelection(!hiddenColumnNames.contains(columnLabel)); - columnItem.setText(columnLabel); - final String nameStr = columnLabel; - columnItem.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - toggleColumnVisiblity(nameStr); - } - } - ); - } - } - + private void addRulesetMenuOptions(Menu menu) { - + MenuItem rulesetMenu = new MenuItem(menu, SWT.CASCADE); rulesetMenu.setText("Ruleset"); Menu rulesetSubMenu = new Menu(menu); rulesetMenu.setMenu(rulesetSubMenu); rulesetMenusByName = new HashMap(); - + MenuItem demoItem = new MenuItem(rulesetSubMenu, SWT.PUSH); demoItem.setText("---demo only---"); // NO API to re-parent rules to other rulesets (yet) - + for (String rulesetName : rulesetNames()) { MenuItem rulesetItem = new MenuItem(rulesetSubMenu, SWT.RADIO); rulesetMenusByName.put(rulesetName, rulesetItem); rulesetItem.setText(rulesetName); final String rulesetStr = rulesetName; - rulesetItem.addSelectionListener( new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - setRuleset(rulesetStr); + rulesetItem.addSelectionListener( new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + setRuleset(rulesetStr); } } ); - } + } } - + private void adjustMenuPrioritySettings() { - - RulePriority priority = ruleSelection == null ? null : ruleSelection.commonPriority(); + + RulePriority priority = ruleSelection == null ? null : RuleUtil.commonPriority(ruleSelection); Iterator> iter = priorityMenusByPriority.entrySet().iterator(); - + while (iter.hasNext()) { Map.Entry entry = iter.next(); MenuItem item = entry.getValue(); @@ -265,14 +175,14 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { } } } - + // if all the selected rules/ruleGroups reference a common ruleset name // then check that item and disable it, do the reverse for all others. private void adjustMenuRulesetSettings() { - - String rulesetName = ruleSelection == null ? null : ruleSetNameFrom(ruleSelection.commonRuleset()); + + String rulesetName = ruleSelection == null ? null : ruleSetNameFrom(RuleUtil.commonRuleset(ruleSelection)); Iterator> iter = rulesetMenusByName.entrySet().iterator(); - + while (iter.hasNext()) { Map.Entry entry = iter.next(); MenuItem item = entry.getValue(); @@ -292,52 +202,51 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { } private void adjustMenuUseDefaultsOption() { - + useDefaultsItem.setEnabled( ! ruleSelection.haveDefaultValues() ); } - + /** * Build the edit rule button * @param parent Composite * @return Button */ public Button buildAddRuleButton(final Composite parent) { - Button button = new Button(parent, SWT.PUSH | SWT.LEFT); - button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_ADD)); - button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_ADDRULE)); - button.setEnabled(true); - + + Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_ADD, StringKeys.MSGKEY_PREF_RULESET_BUTTON_ADDRULE); + button.addSelectionListener(new SelectionAdapter() { - @Override public void widgetSelected(SelectionEvent event) { - RuleDialog dialog = new RuleDialog(parent.getShell()); - int result = dialog.open(); - if (result == RuleDialog.OK) { - Rule addedRule = dialog.getRule(); - ruleSet.addRule(addedRule); - setModified(); - try { - refresh(); - } catch (Throwable t) { - plugin.logError("Exception when refreshing the rule table", t); - } + createRule(parent.getShell()); } - } - }); + }); return button; } - /** - * Helper method to shorten message access - * @param key a message key - * @return requested message - */ - protected String getMessage(String key) { - return PMDPlugin.getDefault().getStringTable().getString(key); - } - - private void setModified() { - if (modifyListener != null) modifyListener.setModified(); + private void createRule(Shell shell) { +// RuleDialog dialog = new RuleDialog(parent.getShell()); +// int result = dialog.open(); + + try { + CreateRuleWizard wiz = new CreateRuleWizard(); + WizardDialog dialog = new WizardDialog(shell, wiz); + int result = dialog.open(); + + if (result == Window.OK) { + Rule addedRule = wiz.rule(); + ruleSet.addRule(addedRule); + setModified(); + try { + refresh(); + treeViewer.reveal(addedRule); + } catch (Throwable t) { + plugin.logError("Exception when refreshing the rule table", t); + } + } + + } catch (Exception ex) { + ex.printStackTrace(); + } } /** @@ -346,89 +255,92 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { * @return Button */ public Button buildRemoveRuleButton(Composite parent) { - - Button button = new Button(parent, SWT.PUSH | SWT.LEFT); - button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_DELETE)); - button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_REMOVERULE)); + + Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_DELETE, StringKeys.MSGKEY_PREF_RULESET_BUTTON_REMOVERULE); button.addSelectionListener(new SelectionAdapter() { - @Override public void widgetSelected(SelectionEvent event) { - removeSelectedRules(); - } - }); + removeSelectedItems(); + } + }); return button; } - - private void removeSelectedRules() { - + + protected void removeSelectedItems() { + if (ruleSelection == null) return; - + int removeCount = ruleSelection.removeAllFrom(ruleSet); if (removeCount == 0) return; - + setModified(); - + try { refresh(); } catch (Throwable t) { - ruleTreeViewer.setSelection(null); + treeViewer.setSelection(null); } } - + /** * Build the export rule set button * @param parent Composite * @return Button */ private Button buildExportRuleSetButton(final Composite parent) { - Button button = new Button(parent, SWT.PUSH | SWT.LEFT); - button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_EXPORT)); - button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_EXPORTRULESET)); - button.setEnabled(true); + + Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_EXPORT, StringKeys.MSGKEY_PREF_RULESET_BUTTON_EXPORTRULESET); + button.addSelectionListener(new SelectionAdapter() { - @Override + public void widgetSelected(SelectionEvent event) { FileDialog dialog = new FileDialog(parent.getShell(), SWT.SAVE); String fileName = dialog.open(); if (fileName != null) { try { - File file = new File(fileName); - boolean flContinue = true; - if (file.exists()) { - flContinue = MessageDialog.openConfirm(parent.getShell(), - getMessage(StringKeys.MSGKEY_CONFIRM_TITLE), - getMessage(StringKeys.MSGKEY_CONFIRM_RULESET_EXISTS)); - } - - InputDialog input = null; - if (flContinue) { - input = new InputDialog(parent.getShell(), - getMessage(StringKeys.MSGKEY_PREF_RULESET_DIALOG_TITLE), - getMessage(StringKeys.MSGKEY_PREF_RULESET_DIALOG_RULESET_DESCRIPTION), - ruleSet.getDescription() == null ? "" : ruleSet.getDescription().trim(), null); - flContinue = input.open() == InputDialog.OK; - } - - if (flContinue) { - ruleSet.setName(FileUtil.getFileNameWithoutExtension(file.getName())); - ruleSet.setDescription(input.getValue()); - OutputStream out = new FileOutputStream(fileName); - IRuleSetWriter writer = plugin.getRuleSetWriter(); - writer.write(out, ruleSet); - out.close(); - MessageDialog.openInformation(parent.getShell(), getMessage(StringKeys.MSGKEY_INFORMATION_TITLE), - getMessage(StringKeys.MSGKEY_INFORMATION_RULESET_EXPORTED)); - } + exportTo(fileName, parent.getShell()); } catch (Exception e) { plugin.showError(getMessage(StringKeys.MSGKEY_ERROR_EXPORTING_RULESET), e); } } } + }); return button; } + + private void exportTo(String fileName, Shell shell) throws FileNotFoundException, WriterException, IOException { + + File file = new File(fileName); + boolean flContinue = true; + + if (file.exists()) { + flContinue = MessageDialog.openConfirm(shell, + getMessage(StringKeys.MSGKEY_CONFIRM_TITLE), + getMessage(StringKeys.MSGKEY_CONFIRM_RULESET_EXISTS)); + } + + InputDialog input = null; + if (flContinue) { + input = new InputDialog(shell, + getMessage(StringKeys.MSGKEY_PREF_RULESET_DIALOG_TITLE), + getMessage(StringKeys.MSGKEY_PREF_RULESET_DIALOG_RULESET_DESCRIPTION), + ruleSet.getDescription() == null ? "" : ruleSet.getDescription().trim(), null); + flContinue = input.open() == Window.OK; + } + + if (flContinue) { + ruleSet.setName(FileUtil.getFileNameWithoutExtension(file.getName())); + ruleSet.setDescription(input.getValue()); + OutputStream out = new FileOutputStream(fileName); + IRuleSetWriter writer = plugin.getRuleSetWriter(); + writer.write(out, ruleSet); + out.close(); + MessageDialog.openInformation(shell, getMessage(StringKeys.MSGKEY_INFORMATION_TITLE), + getMessage(StringKeys.MSGKEY_INFORMATION_RULESET_EXPORTED)); + } + } /** * Build the import ruleset button @@ -436,40 +348,16 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { * @return Button */ private Button buildImportRuleSetButton(final Composite parent) { - - Button button = new Button(parent, SWT.PUSH | SWT.LEFT); - button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_IMPORT)); - button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_IMPORTRULESET)); - button.setEnabled(true); + + Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_IMPORT, StringKeys.MSGKEY_PREF_RULESET_BUTTON_IMPORTRULESET); button.addSelectionListener(new SelectionAdapter() { - @Override + public void widgetSelected(SelectionEvent event) { RuleSetSelectionDialog dialog = new RuleSetSelectionDialog(parent.getShell()); dialog.open(); - if (dialog.getReturnCode() == RuleSetSelectionDialog.OK) { - try { - RuleSet selectedRuleSet = dialog.getSelectedRuleSet(); - if (dialog.isImportByReference()) { - ruleSet.addRuleSetByReference(selectedRuleSet, false); - } else { - // Set pmd-eclipse as new RuleSet name and add the Rule - Iterator iter = selectedRuleSet.getRules().iterator(); - while (iter.hasNext()) { - Rule rule = iter.next(); - rule.setRuleSetName("pmd-eclipse"); - ruleSet.addRule(rule); - } - } - setModified(); - try { - refresh(); - } catch (Throwable t) { - plugin.logError("Exception when refreshing the rule table", t); - } - } catch (RuntimeException e) { - plugin.showError(getMessage(StringKeys.MSGKEY_ERROR_IMPORTING_RULESET), e); - } + if (dialog.getReturnCode() == Window.OK) { + doImport(dialog.getSelectedRuleSet(), dialog.isImportByReference()); } } }); @@ -477,15 +365,38 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { return button; } + private void doImport(RuleSet selectedRuleSet, boolean doByReference) { + + try { + if (doByReference) { + ruleSet.addRuleSetByReference(selectedRuleSet, false); + } else { + // Set pmd-eclipse as new RuleSet name and add the Rule + Iterator iter = selectedRuleSet.getRules().iterator(); + while (iter.hasNext()) { + Rule rule = iter.next(); + rule.setRuleSetName("pmd-eclipse"); + ruleSet.addRule(rule); + } + } + setModified(); + try { + refresh(); + } catch (Throwable t) { + plugin.logError("Exception when refreshing the rule table", t); + } + } catch (RuntimeException e) { + plugin.showError(getMessage(StringKeys.MSGKEY_ERROR_IMPORTING_RULESET), e); + } + } + public Composite buildGroupCombo(Composite parent, String comboLabelKey, final Object[][] groupingChoices) { Composite panel = new Composite(parent, 0); GridLayout layout = new GridLayout(6, false); panel.setLayout(layout); - sortByCheckedButton = buildSortByCheckedItemsButton(panel); - selectAllButton = buildSelectAllButton(panel); - unSelectAllButton = buildUnselectAllButton(panel); + buildCheckButtons(panel); Label label = new Label(panel, 0); GridData data = new GridData(); @@ -493,11 +404,11 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { data.verticalAlignment = SWT.CENTER; label.setLayoutData(data); label.setText(SWTUtil.stringFor(comboLabelKey)); - + final Combo combo = new Combo(panel, SWT.READ_ONLY); - combo.setItems(SWTUtil.i18lLabelsIn(groupingChoices, 1)); + combo.setItems(SWTUtil.i18lLabelsIn(groupingChoices, 1)); combo.select(groupingChoices.length - 1); // picks last one by default TODO make it a persistent preference - + combo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int selectionIdx = combo.getSelectionIndex(); @@ -505,31 +416,24 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { groupingColumn = (RuleColumnDescriptor)choice[0]; redrawTable(); } - }); - - activeCountLabel = new Label(panel, 0); - activeCountLabel.setText("---"); - data = new GridData(); - data.horizontalAlignment = GridData.FILL; - data.grabExcessHorizontalSpace = true; - data.horizontalAlignment = SWT.RIGHT; - activeCountLabel.setLayoutData(data); - + }); + + buildActiveCountLabel(panel); + return panel; } - + /** * Build the Rule Designer button * @param parent Composite * @return Button */ private Button buildRuleDesignerButton(Composite parent) { - Button button = new Button(parent, SWT.PUSH | SWT.LEFT); - button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_EDITOR)); - button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_RULEDESIGNER)); - button.setEnabled(true); + + Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_EDITOR, StringKeys.MSGKEY_PREF_RULESET_BUTTON_RULEDESIGNER); + button.addSelectionListener(new SelectionAdapter() { - @Override + public void widgetSelected(SelectionEvent event) { // TODO Is this cool from Eclipse? Is there a nicer way to spawn a J2SE Application? new Thread(new Runnable() { @@ -542,14 +446,14 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { return button; } - + /** * Create buttons for rule table management * @param parent Composite * @return Composite */ public Composite buildRuleTableButtons(Composite parent) { - + Composite composite = new Composite(parent, SWT.NULL); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 1; @@ -587,263 +491,75 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { */ public Tree buildRuleTreeViewer(Composite parent) { - int treeStyle = SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION | SWT.CHECK; - ruleTreeViewer = new ContainerCheckedTreeViewer(parent, treeStyle); - - final Tree ruleTree = ruleTreeViewer.getTree(); - ruleTree.setLinesVisible(true); - ruleTree.setHeaderVisible(true); - - ruleTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection)event.getSelection(); - selectedItems(selection.toArray()); - } - }); + buildTreeViewer(parent); + Tree ruleTree = treeViewer.getTree(); + ruleListMenu = createMenuFor(ruleTree); ruleTree.setMenu(ruleListMenu); - ruleTree.addListener(SWT.MenuDetect, new Listener () { + ruleTree.addListener(SWT.MenuDetect, new Listener () { public void handleEvent (Event event) { popupRuleSelectionMenu(event); } - }); - - ruleTree.addListener(SWT.Selection, new Listener() { - public void handleEvent(Event event) { - if (event.detail == SWT.CHECK) { - TreeItem item = (TreeItem) event.item; - boolean checked = item.getChecked(); - checkItems(item, checked); - checkPath(item.getParentItem(), checked, false); - } - // if (!checkedRules.isEmpty()) System.out.println(checkedRules.iterator().next()); - } }); - ruleTree.addListener(SWT.MouseMove, new Listener() { - public void handleEvent(Event event) { - Point point = new Point(event.x, event.y); - TreeItem item = ruleTree.getItem(point); - if (item != null) { - int columnIndex = columnIndexAt(item, event.x); - updateTooltipFor(item, columnIndex); - } - } - }); - - ruleTreeViewer.setCheckStateProvider(createCheckStateProvider()); - + treeViewer.setCheckStateProvider(createCheckStateProvider()); + return ruleTree; } - /** - * - * @param parent Composite - * @return Button - */ - private Button buildSelectAllButton(Composite parent) { - Button button = new Button(parent, SWT.PUSH | SWT.LEFT); - button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_CHECK_ALL)); - button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_CHECK_ALL)); - - button.setEnabled(true); - button.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent event) { - setAllRulesActive(); - } - }); - - return button; - } - - private Button buildSortByCheckedItemsButton(Composite parent) { - Button button = new Button(parent, SWT.PUSH | SWT.LEFT); - button.setToolTipText("Sort by checked items"); - button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_SORT_CHECKED)); - - button.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent event) { - sortByCheckedItems(); - } - }); - - return button; - } - - /** - * - * @param parent Composite - * @return Button - */ - private Button buildUnselectAllButton(Composite parent) { - Button button = new Button(parent, SWT.PUSH | SWT.LEFT); - button.setToolTipText(getMessage(StringKeys.MSGKEY_PREF_RULESET_BUTTON_UNCHECK_ALL)); - button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_UNCHECK_ALL)); - - button.setEnabled(true); - button.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent event) { - preferences.getActiveRuleNames().clear(); - treeViewer().setCheckedElements(new Object[0]); - setModified(); - updateCheckControls(); - } - }); - - return button; - } - public void changed(Rule rule, PropertyDescriptor desc, Object newValue) { - // TODO enhance to recognize default values - ruleTreeViewer.update(rule, null); + // TODO enhance to recognize default values + // RuleUtil.modifiedPropertiesIn(rule); + + treeViewer.update(rule, null); setModified(); } - + public void changed(RuleSelection selection, PropertyDescriptor desc, Object newValue) { // TODO enhance to recognize default values - + for (Rule rule : selection.allRules()) { if (newValue != null) { // non-reliable update behaviour, alternate trigger option - weird - ruleTreeViewer.getTree().redraw(); - // System.out.println("doing redraw"); + treeViewer.getTree().redraw(); +// System.out.println("doing redraw"); } else { - ruleTreeViewer.update(rule, null); - // System.out.println("viewer update"); + treeViewer.update(rule, null); +// System.out.println("viewer update"); } } setModified(); } - - /** - * Method checkPath. - * @param item TreeItem - * @param checked boolean - * @param grayed boolean - */ - private void checkPath(TreeItem item, boolean checked, boolean grayed) { - if (item == null) return; - if (grayed) { - checked = true; - } else { - int index = 0; - TreeItem[] items = item.getItems(); - while (index < items.length) { - TreeItem child = items[index]; - if (child.getGrayed() || checked != child.getChecked()) { - checked = grayed = true; - break; - } - index++; - } - } - check(item, checked); - item.setGrayed(grayed); - checkPath(item.getParentItem(), checked, grayed); - } - /** - * @param item TreeItem - * @param checked boolean - */ - private void checkItems(TreeItem item, boolean checked) { - item.setGrayed(false); - check(item, checked); - TreeItem[] items = item.getItems(); - for (TreeItem item2 : items) { - checkItems(item2, checked); - } - updateCheckControls(); - } - /** - * @param item TreeItem - * @param checked boolean - */ - private void check(TreeItem item, boolean checked) { - - item.setChecked(checked); - Object itemData = item.getData(); - if (itemData == null || itemData instanceof RuleGroup) return; - - String name = ((Rule)itemData).getName(); - - preferences.isActive(name, checked); - - updateCheckControls(); - setModified(); - } - private void checkSelections() { - + // List activeRules = new ArrayList(); -// +// // for (Rule rule : ruleSet.getRules()) { // if (preferences.isActive(rule.getName())) { // activeRules.add(rule); // } // } -// +// // ruleTreeViewer.setCheckedElements(activeRules.toArray()); } - - /** - * Remove all rows, columns, and column painters in preparation - * for new columns. - * - * @return Tree - */ - private Tree cleanupRuleTree() { - - Tree ruleTree = ruleTreeViewer.getTree(); - ruleTree.clearAll(true); - for(;ruleTree.getColumns().length>0;) { // TODO also dispose any heading icons? - ruleTree.getColumns()[0].dispose(); - } - - // ensure we don't have any previous per-column painters left over - for (Map.Entry> entry : paintListeners.entrySet()) { - int eventCode = entry.getKey().intValue(); - List listeners = entry.getValue(); - for (Listener listener : listeners) { - ruleTree.removeListener(eventCode, listener); - } - listeners.clear(); - } - - return ruleTree; - } - - private int columnIndexAt(TreeItem item, int xPosition) { - - TreeColumn[] cols = ruleTreeViewer.getTree().getColumns(); - Rectangle bounds = null; - - for(int i = 0; i < cols.length; i++){ - bounds = item.getBounds(i); - if (bounds.x < xPosition && xPosition < (bounds.x + bounds.width)) { - return i; - } - } - return -1; - } - - private String[] columnLabels() { + protected String[] columnLabels() { String[] names = new String[availableColumns.length]; for (int i=0; i(RulePriority.values().length); - + for (RulePriority priority : RulePriority.values()) { MenuItem priorityItem = new MenuItem (subMenu, SWT.RADIO); priorityMenusByPriority.put(priority, priorityItem); priorityItem.setText(priority.getName()); // TODO need to internationalize? // priorityItem.setImage(imageFor(priority)); not visible with radiobuttons final RulePriority pri = priority; - priorityItem.addSelectionListener( new SelectionListener() { - public void widgetSelected(SelectionEvent e) { - setPriority(pri); + priorityItem.addSelectionListener( new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + setPriority(pri); } - public void widgetDefaultSelected(SelectionEvent e) { }} + } ); } - + // MenuItem removeItem = new MenuItem(menu, SWT.PUSH); // removeItem.setText("Remove"); // removeItem.addSelectionListener(new SelectionAdapter() { @@ -897,130 +613,102 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { // removeSelectedRules(); // } // }); - - MenuItem useDefaultsItem = new MenuItem(menu, SWT.PUSH); + + useDefaultsItem = new MenuItem(menu, SWT.PUSH); useDefaultsItem.setText("Use defaults"); useDefaultsItem.setEnabled(false); useDefaultsItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { - // useDefaultValues(); + ruleSelection.useDefaultValues(); } }); - + return menu; } - - private TreeColumn columnFor(String tooltipText) { - for (TreeColumn column : ruleTreeViewer.getTree().getColumns()) { - if (column.getToolTipText().equals(tooltipText)) return column; - } - return null; - } - + /** * Method groupBy. * @param chosenColumn RuleColumnDescriptor */ public void groupBy(RuleColumnDescriptor chosenColumn) { - + List visibleColumns = new ArrayList(availableColumns.length); for (RuleColumnDescriptor desc : availableColumns) { if (desc == chosenColumn) continue; // redundant, don't include it - if (hiddenColumnNames.contains(desc.label())) continue; + if (isHidden(desc.label())) continue; visibleColumns.add(desc); } - + setupTreeColumns( - visibleColumns.toArray(new RuleColumnDescriptor[visibleColumns.size()]), + visibleColumns.toArray(new RuleColumnDescriptor[visibleColumns.size()]), chosenColumn == null ? null : chosenColumn.accessor() ); } - + private boolean hasPriorityGrouping() { - return - groupingColumn == TextColumnDescriptor.priorityName || + return + groupingColumn == TextColumnDescriptor.priorityName || groupingColumn == TextColumnDescriptor.priority; } - + /** * Populate the rule table */ - public void populateRuleTable() { - ruleTreeViewer.setInput(ruleSet); + public void populateRuleTable() { + treeViewer.setInput(ruleSet); checkSelections(); - + restoreSavedRuleSelections(); updateCheckControls(); } - + private void popupRuleSelectionMenu(Event event) { - + // have to do it here or else the ruleset var is null in the menu setup - timing issue if (rulesetMenusByName == null) { addRulesetMenuOptions(ruleListMenu); new MenuItem(ruleListMenu, SWT.SEPARATOR); addColumnSelectionOptions(ruleListMenu); } - + adjustMenuPrioritySettings(); adjustMenuRulesetSettings(); adjustMenuUseDefaultsOption(); ruleListMenu.setLocation(event.x, event.y); ruleListMenu.setVisible(true); } - - private void redrawTable() { - redrawTable("-", -1); - } - - private void redrawTable(String sortColumnLabel, int sortDir) { - groupBy(groupingColumn); - - TreeColumn sortColumn = columnFor(sortColumnLabel); - ruleTreeViewer.getTree().setSortColumn(sortColumn); - ruleTreeViewer.getTree().setSortDirection(sortDir); - } - - /** - * Refresh the list - */ - protected void refresh() { - try { - ruleTreeViewer.getControl().setRedraw(false); - ruleTreeViewer.refresh(); - } catch (ClassCastException e) { - plugin.logError("Ignoring exception while refreshing table", e); - } finally { - ruleTreeViewer.getControl().setRedraw(true); - } + protected void redrawTable(String sortColumnLabel, int sortDir) { + groupBy(groupingColumn); + + super.redrawTable(sortColumnLabel, sortDir); } - + private void restoreSavedRuleSelections() { - + Set names = PreferenceUIStore.instance.selectedRuleNames(); List rules = new ArrayList(); for (String name : names) rules.add(ruleSet.getRuleByName(name)); - + IStructuredSelection selection = new StructuredSelection(rules); - ruleTreeViewer.setSelection(selection); + treeViewer.setSelection(selection); } - + public RuleSet ruleSet() { return ruleSet; } - + private String[] rulesetNames() { - + Set names = new HashSet(); for (Rule rule : ruleSet.getRules()) { names.add(ruleSetNameFrom(rule)); // if we strip out the 'Rules' portions then we don't get matches...need to rename rulesets } return names.toArray(new String[names.size()]); } - - private void saveRuleSelections() { - - IStructuredSelection selection = (IStructuredSelection)ruleTreeViewer.getSelection(); - + + protected void saveItemSelections() { + + IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection(); + List ruleNames = new ArrayList(); for (Object item : selection.toList()) { if (item instanceof Rule) @@ -1029,142 +717,118 @@ public class RuleTableManager implements RuleSortListener, ValueChangeListener { PreferenceUIStore.instance.selectedRuleNames(ruleNames); } - - public void saveUIState() { - saveRuleSelections(); - } - + /** * @param item Object[] */ - private void selectedItems(Object[] items) { + protected void selectedItems(Object[] items) { ruleSelection = new RuleSelection(items); if (ruleSelectionListener != null) { ruleSelectionListener.selection(ruleSelection); } - + if (removeRuleButton != null) removeRuleButton.setEnabled(items.length > 0); } - + private int[] selectionRatioIn(Rule[] rules) { - + int selectedCount = 0; for (Rule rule : rules) { - if (preferences.isActive(rule.getName())) selectedCount++; + if (isActive(rule.getName())) selectedCount++; } return new int[] { selectedCount , rules.length }; } - - private void setAllRulesActive() { + + protected void setAllItemsActive() { for (Rule rule : ruleSet.getRules()) { - preferences.isActive(rule.getName(), true); + isActive(rule.getName(), true); } - + treeViewer().setCheckedElements(ruleSet.getRules().toArray()); - + updateCheckControls(); setModified(); } - + private void setPriority(RulePriority priority) { - + if (ruleSelection == null) return; - + ruleSelection.setPriority(priority); - + if (hasPriorityGrouping()) { redrawTable(); } else { - ruleTreeViewer.update(ruleSelection.allRules().toArray(), null); + treeViewer.update(ruleSelection.allRules().toArray(), null); } - + setModified(); } - + private void setRuleset(String rulesetName) { // TODO - awaiting support in PMD itself } /** - * Method setupTreeColumns. + * * @param columnDescs RuleColumnDescriptor[] * @param groupingField RuleFieldAccessor */ private void setupTreeColumns(RuleColumnDescriptor[] columnDescs, RuleFieldAccessor groupingField) { Tree ruleTree = cleanupRuleTree(); - - for (int i=0; i 0); - sortByCheckedButton.setEnabled( (selectionRatio[0] != 0) && (selectionRatio[0] != selectionRatio[1])); + + updateButtonsFor(selectionRatio); String label = SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_ACTIVE_RULE_COUNT); - activeCountLabel.setText(label + " " + activeRuleCount() + " / " + ruleSet.size()); + activeCountText(label + " " + activeItemCount() + " / " + ruleSet.size()); } - - private void updateTooltipFor(TreeItem item, int columnIndex) { - - RuleLabelProvider provider = (RuleLabelProvider)ruleTreeViewer.getLabelProvider(); - String txt = provider.getDetailText(item.getData(), columnIndex); - ruleTreeViewer.getTree().setToolTipText(txt); + + protected void updateTooltipFor(TreeItem item, int columnIndex) { + + RuleLabelProvider provider = (RuleLabelProvider)treeViewer.getLabelProvider(); + String txt = provider.getDetailText(item.getData(), columnIndex); + treeViewer.getTree().setToolTipText(txt); } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleUtil.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleUtil.java new file mode 100755 index 0000000000..dcbcf97d73 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleUtil.java @@ -0,0 +1,397 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RulePriority; +import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.Configuration; +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.LanguageVersion; +import net.sourceforge.pmd.lang.rule.RuleReference; +import net.sourceforge.pmd.lang.rule.properties.AbstractProperty; +import net.sourceforge.pmd.util.CollectionUtil; + + +/** + * + * @author Brian Remedios + */ +public class RuleUtil { + + private RuleUtil() {} + + + public static boolean isDefaultValue(Map.Entry, Object> entry) { + PropertyDescriptor desc = entry.getKey(); + Object value = entry.getValue(); + return CollectionUtil.areEqual(desc.defaultValue(), value); + } + + public static boolean hasDefaultValues(Rule rule) { + + Map, Object> valuesByProperty = Configuration.filteredPropertiesOf(rule); + for (Map.Entry, Object> entry : valuesByProperty.entrySet()) { + if (!isDefaultValue(entry)) return false; + } + return true; + } + + public static Set> modifiedPropertiesIn(Rule rule) { + + Set> descs = new HashSet>(); + + for (Map.Entry, Object> entry: Configuration.filteredPropertiesOf(rule).entrySet() ) { + if (isDefaultValue(entry)) continue; + descs.add(entry.getKey()); + } + + return descs; + } + + /** + * Sometimes references reference references ! + * + * @param reference + * @return + */ + private static Class rootImplementationClassOf(RuleReference reference) { + + Rule rule = reference.getRule(); + + while (rule.getClass() == RuleReference.class) { + rule = ((RuleReference)rule).getRule(); + } + + return (Class)rule.getClass(); + } + + public static Class implementationClassOf(Rule rule) { + + if (rule instanceof RuleReference) { + return rootImplementationClassOf((RuleReference)rule); + } else { + return (Class)rule.getClass(); + } + } + + public static boolean allUseDefaultValues(RuleCollection collection) { + + if (collection.isEmpty()) return false; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + return rule.usesDefaultValues(); + } + }; + + return collection.rulesDo(visitor); + } + + public static boolean allUseDfa(RuleCollection collection) { + + if (collection.isEmpty()) return false; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + return rule.usesDFA(); + } + }; + + return collection.rulesDo(visitor); + } + + public static boolean allUseTypeResolution(RuleCollection collection) { + + if (collection.isEmpty()) return false; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + return rule.usesTypeResolution(); + } + }; + + return collection.rulesDo(visitor); + } + + /** + * Iterates through the currently selected rules and returns + * their common priority setting or null if they differ. + */ + public static RulePriority commonPriority(RuleCollection collection) { + + if (collection.isEmpty()) return null; + + final RulePriority[] prio = new RulePriority[1]; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + if (prio[0] == null) { + prio[0] = rule.getPriority(); + } + if (prio[0] != rule.getPriority()) { + prio[0] = null; + return false; + } + return true; + } + }; + + collection.rulesDo(visitor); + + return prio[0]; + } + + private static String format(Object item) { + return item == null ? "" : String.valueOf(item); // TODO custom format per type + } + + public static String asString(Set> items) { + + Iterator> iter = items.iterator(); + if (items.size() == 1) return format(iter.next()); + + StringBuilder sb = new StringBuilder(format(iter.next())); + while (iter.hasNext()) { + sb.append(", ").append(format(iter.next())); + } + return sb.toString(); + } + + /** + */ + public static Map fractionsByPriority(RuleCollection collection) { + + if (collection.isEmpty()) return Collections.emptyMap(); + + final Map priorityCounts = new HashMap(5); + final int[] count = new int[1]; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + RulePriority priority = rule.getPriority(); + count[0] = count[0] + 1; + Integer count = priorityCounts.get(priority); + if (count == null) { + priorityCounts.put(priority, Integer.valueOf(1)); + } else { + priorityCounts.put(priority, Integer.valueOf(count + 1)); + } + + return true; + } + }; + + collection.rulesDo(visitor); + + int total = count[0]; + + Map priorityFractions = new HashMap(); + for (Map.Entry entry : priorityCounts.entrySet()) { + float fraction = (float)entry.getValue() / total; + priorityFractions.put(entry.getKey(), fraction); + } + + return priorityFractions; + } + + + /** + * Iterates through the currently selected rules and returns + * their common ruleset name or null if they differ. + */ + public static String commonRuleset(RuleCollection collection) { + + if (collection.isEmpty()) return null; + + final Set names = new HashSet(2); + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + names.add( rule.getRuleSetName().trim() ); + return names.size() < 2; + } + }; + + collection.rulesDo(visitor); + + return names.size() > 1 ? + null : + names.iterator().next(); + } + + public static Class commonImplementationClass(RuleCollection collection) { + + if (collection.isEmpty()) return null; + + // TODO use array[1] approach like the others + final Set> types = new HashSet>(2); + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + types.add( implementationClassOf(rule) ); + return types.size() < 2; + } + }; + + collection.rulesDo(visitor); + + return types.size() > 1 ? + null : + types.iterator().next(); + } + + private static boolean areEqual(Object a, Object b) { + return AbstractProperty.areEqual(a, b); + } + + public static Comparable commonAspect(RuleCollection collection, final RuleFieldAccessor accessor) { + + if (collection.isEmpty()) return null; + + final Comparable[] aspect = new Comparable[1]; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + if (aspect[0] == null) { + aspect[0] = accessor.valueFor(rule); + return true; + } + if (areEqual(aspect[0], accessor.valueFor(rule)) ) { + aspect[0] = null; + return false; + } + return true; + } + }; + + collection.rulesDo(visitor); + + return aspect[0]; + } + + /** + * + */ + public static int countNonOccurrencesOf(RuleCollection collection, final RuleFieldAccessor accessor, final Object item) { + + if (collection.isEmpty()) return 0; + + final int[] count = new int[] {0}; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + Object value = accessor.valueFor(rule); + if (value != item) count[0] = count[0]+1; + return true; + } + }; + + collection.rulesDo(visitor); + + return count[0]; + } + + /** + * Iterates through the currently selected rules and returns + * the set of unique aspect values. + */ + public static Set> uniqueAspects(RuleCollection collection, final RuleFieldAccessor accessor) { + + if (collection.isEmpty()) return Collections.emptySet(); + + final Set> aspects = new HashSet>(); + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + aspects.add( accessor.valueFor(rule) ); + return true; + } + }; + + collection.rulesDo(visitor); + + return aspects; + } + + public static Language commonLanguage(RuleCollection collection) { + + if (collection.isEmpty()) return null; + + final Language[] type = new Language[1]; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + if (type[0] == null) { + type[0] = rule.getLanguage(); + return true; + } + if (type[0] != rule.getLanguage() ) { + type[0] = null; + return false; + } + return true; + } + }; + + collection.rulesDo(visitor); + + return type[0]; + } + + public static LanguageVersion commonLanguageMinVersion(RuleCollection collection) { + + if (collection.isEmpty()) return null; + + final LanguageVersion[] version = new LanguageVersion[1]; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + if (version[0] == null) { + version[0] = rule.getMinimumLanguageVersion(); + return true; + } + if (version[0] != rule.getMinimumLanguageVersion() ) { + version[0] = null; + return false; + } + return true; + } + }; + + collection.rulesDo(visitor); + + return version[0]; + } + + + public static LanguageVersion commonLanguageMaxVersion(RuleCollection collection) { + + if (collection.isEmpty()) return null; + + final LanguageVersion[] version = new LanguageVersion[1]; + + RuleVisitor visitor = new RuleVisitor() { + public boolean accept(Rule rule) { + if (version[0] == null) { + version[0] = rule.getMaximumLanguageVersion(); + return true; + } + if (version[0] != rule.getMaximumLanguageVersion() ) { + version[0] = null; + return false; + } + return true; + } + }; + + collection.rulesDo(visitor); + + return version[0]; + } +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleVisitor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleVisitor.java new file mode 100755 index 0000000000..2a0076065b --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/RuleVisitor.java @@ -0,0 +1,19 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +import net.sourceforge.pmd.Rule; + +/** + * + * @author Brian Remedios + */ +public interface RuleVisitor { + + /** + * Process the rule provided and return whether to continue + * processing other rules. + * + * @param rule + * @return boolean + */ + public boolean accept(Rule rule); +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/SizeChangeListener.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/SizeChangeListener.java index 514ff85a9e..d79f52440c 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/SizeChangeListener.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/SizeChangeListener.java @@ -3,9 +3,10 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; /** * A callback f'n that informs a parent panel to adjust its layout or reset its minimum * size and thus its scrollable limits. - * + * * @author Brian Remedios */ public interface SizeChangeListener { + void addedRows(int newRowCount); } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TODO items b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TODO items index ccc4525f82..74f43fabc0 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TODO items +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TODO items @@ -1,21 +1,25 @@ ToDo items: March 21st 2010 Finish remaining editors and the Add Property dialog -Highlight non-default values in editors and/or summary column -Enable 'Use defaults' option in popup menu +Enable 'Use defaults' option in popup menu (need support in properties/PMD) Add selection column selected rules in per-project rule settings table Rework context menu - build on-demand, not before Markup violations using priority icons rather than the yellow yield signs or red Xs +Work on support for fixes +Format example & description text +Should we add support for Date properties? (i.e. to reference file timestamp?) Cleanup icons Remember settings for: chosen grouping selection (or none) sort column & order rule table screen fraction - +Fix: + new property dialog, use JFace dialog + Items needing support in PMD itself: Enable non-intrinsic property field removal -Enable/disable rules w/out removing from ruleset +Null-out property values to default Enable rule reassignment to different rulesets Add support for creating new rulesets & descriptions for same For multi-value properties, decide whether to allow unique or duplicate values (default to Set behaviour) diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TextColumnDescriptor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TextColumnDescriptor.java index ff8fda5c12..4c38feb3ef 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TextColumnDescriptor.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TextColumnDescriptor.java @@ -13,39 +13,41 @@ import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; /** - * + * * @author Brian Remedios */ public class TextColumnDescriptor extends AbstractRuleColumnDescriptor { private static final RuleFieldAccessor ruleSetNameAcc = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { - return PMDPreferencePage.ruleSetNameFrom(rule); + return PMDPreferencePage2.ruleSetNameFrom(rule); } }; - + private static final RuleFieldAccessor propertiesAcc = new BasicRuleFieldAccessor() { public Comparable valueFor(Rule rule) { - return PMDPreferencePage.propertyStringFrom(rule); + return PMDPreferencePage2.propertyStringFrom(rule, "*"); } }; - - public static final RuleColumnDescriptor name = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_RULE_NAME, SWT.LEFT, 210, RuleFieldAccessor.name, true, null); - public static final RuleColumnDescriptor ruleSetName = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_RULESET_NAME,SWT.LEFT, 160, ruleSetNameAcc, true, null); - public static final RuleColumnDescriptor priority = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PRIORITY, SWT.RIGHT,53, RuleFieldAccessor.priority, false, null); - public static final RuleColumnDescriptor priorityName = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PRIORITY, SWT.LEFT, 80, RuleFieldAccessor.priorityName, true, null); - public static final RuleColumnDescriptor since = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_SINCE, SWT.RIGHT,46, RuleFieldAccessor.since, false, null); - public static final RuleColumnDescriptor usesDFA = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_DATAFLOW, SWT.LEFT, 60, RuleFieldAccessor.usesDFA, false, null); + + public static final RuleColumnDescriptor name = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_RULE_NAME, SWT.LEFT, 210, RuleFieldAccessor.name, true, null); + public static final RuleColumnDescriptor ruleSetName = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_RULESET_NAME,SWT.LEFT, 160, ruleSetNameAcc, true, null); + public static final RuleColumnDescriptor priority = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PRIORITY, SWT.RIGHT,53, RuleFieldAccessor.priority, false, null); + public static final RuleColumnDescriptor priorityName = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PRIORITY, SWT.LEFT, 80, RuleFieldAccessor.priorityName, true, null); + public static final RuleColumnDescriptor since = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_SINCE, SWT.RIGHT,46, RuleFieldAccessor.since, false, null); + public static final RuleColumnDescriptor usesDFA = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_DATAFLOW, SWT.LEFT, 60, RuleFieldAccessor.usesDFA, false, null); public static final RuleColumnDescriptor externalURL = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_URL, SWT.LEFT, 100, RuleFieldAccessor.url, true, null); public static final RuleColumnDescriptor properties = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PROPERTIES, SWT.LEFT, 40, propertiesAcc, true, null); public static final RuleColumnDescriptor language = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_LANGUAGE, SWT.LEFT, 32, RuleFieldAccessor.language, false, null); public static final RuleColumnDescriptor ruleType = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_RULE_TYPE, SWT.LEFT, 20, RuleFieldAccessor.ruleType, false, null); public static final RuleColumnDescriptor minLangVers = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_MIN_VER, SWT.LEFT, 30, RuleFieldAccessor.minLanguageVersion, false, null); + public static final RuleColumnDescriptor maxLangVers = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_MAX_VER, SWT.LEFT, 30, RuleFieldAccessor.maxLanguageVersion, false, null); public static final RuleColumnDescriptor exampleCount = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_EXAMPLE_CNT, SWT.RIGHT, 20, RuleFieldAccessor.exampleCount, false, null); public static final RuleColumnDescriptor fixCount = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_FIXCOUNT, SWT.RIGHT, 25, RuleFieldAccessor.fixCount, false, null); + public static final RuleColumnDescriptor modCount = new TextColumnDescriptor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_MODCOUNT, SWT.RIGHT, 25, RuleFieldAccessor.nonDefaultProperyCount, false, null); // public static final RuleColumnDescriptor violateXPath = new TextColumnDescriptor("Filter", SWT.RIGHT, 20, RuleFieldAccessor.violationXPath, true); - + /** * @param theLabel String * @param theAlignment int @@ -56,7 +58,7 @@ public class TextColumnDescriptor extends AbstractRuleColumnDescriptor { public TextColumnDescriptor(String theLabel, int theAlignment, int theWidth, RuleFieldAccessor theAccessor, boolean resizableFlag, String theImagePath) { super(theLabel, theAlignment,theWidth,theAccessor,resizableFlag, theImagePath); } - + /* (non-Javadoc) * @see net.sourceforge.pmd.eclipse.ui.preferences.br.IRuleColumnDescriptor#newTreeColumnFor(org.eclipse.swt.widgets.Tree, int, net.sourceforge.pmd.eclipse.ui.preferences.br.RuleSortListener, java.util.Map) */ @@ -65,12 +67,24 @@ public class TextColumnDescriptor extends AbstractRuleColumnDescriptor { tc.setText(label()); return tc; } + + private String asString(Object value) { + if (value == null) return ""; + if (value instanceof String) return value.toString(); + ValueFormatter formatter = FormatManager.formatterFor(value.getClass()); + return formatter == null ? value.toString() : formatter.format(value); + } public String stringValueFor(Rule rule) { Object value = valueFor(rule); - return value == null ? "" : value.toString(); + return asString(value); } - + + public String stringValueFor(RuleCollection collection) { + Object value = valueFor(collection); + return asString(value); + } + public Image imageFor(Rule rule) { return null; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TreeUtil.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TreeUtil.java new file mode 100755 index 0000000000..dafd01c79e --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/TreeUtil.java @@ -0,0 +1,59 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.br; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; + +/** + * + * @author Brian Remedios + */ +public class TreeUtil { + + private TreeUtil() {} + + public static String getSelectionAsString(TreeViewer viewer, String columnSeparator, String lineSeparator) { + + String[][] data = getStringContents(viewer); + StringBuilder sb = new StringBuilder(); + + for (int r=0; r desc, Object newValue); - + /** * Method changed. * @param rule Rule diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ValueFormatter.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ValueFormatter.java index 3f95fc359a..433e349b3b 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ValueFormatter.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/br/ValueFormatter.java @@ -2,60 +2,68 @@ package net.sourceforge.pmd.eclipse.ui.preferences.br; import java.lang.reflect.Method; +import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.eclipse.ui.preferences.editors.MethodEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.MultiTypeEditorFactory; import net.sourceforge.pmd.eclipse.util.Util; +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.util.ClassUtil; /** - * + * * @author Brian Remedios */ public interface ValueFormatter { - void format(Object value, StringBuilder target); + String format(Object value); - ValueFormatter StringFormatter = new ValueFormatter() { + void format(Object value, StringBuilder target); + + ValueFormatter StringFormatter = new BasicValueFormatter() { public void format(Object value, StringBuilder target) { target.append(value == null ? "" : value); } + public String format(Object value) { + return value == null ? "" : value.toString(); + } }; - - ValueFormatter MultiStringFormatter = new ValueFormatter() { + + ValueFormatter MultiStringFormatter = new BasicValueFormatter() { public void format(Object value, StringBuilder target) { target.append('['); Util.asString((Object[])value, ", ", target); target.append(']'); } }; - - ValueFormatter NumberFormatter = new ValueFormatter() { + + ValueFormatter NumberFormatter = new BasicValueFormatter() { public void format(Object value, StringBuilder target) { target.append(value == null ? "?" : value); } }; - - ValueFormatter BooleanFormatter = new ValueFormatter() { + + ValueFormatter BooleanFormatter = new BasicValueFormatter() { public void format(Object value, StringBuilder target) { target.append(value == null ? "?" : value); } }; - - ValueFormatter TypeFormatter = new ValueFormatter() { - public void format(Object value, StringBuilder target) { + + ValueFormatter TypeFormatter = new BasicValueFormatter() { + public void format(Object value, StringBuilder target) { target.append(value == null ? "" : ClassUtil.asShortestName((Class)value)); } }; - - ValueFormatter MultiTypeFormatter = new ValueFormatter() { + + ValueFormatter MultiTypeFormatter = new BasicValueFormatter() { public void format(Object value, StringBuilder target) { target.append('['); Util.asString(MultiTypeEditorFactory.shortNamesFor((Class[])value), ", ", target); target.append(']'); } }; - - ValueFormatter MethodFormatter = new ValueFormatter() { + + ValueFormatter MethodFormatter = new BasicValueFormatter() { public void format(Object value, StringBuilder target) { if (value == null) return; target.append( @@ -63,8 +71,8 @@ public interface ValueFormatter { ); } }; - - ValueFormatter MultiMethodFormatter = new ValueFormatter() { + + ValueFormatter MultiMethodFormatter = new BasicValueFormatter() { public void format(Object value, StringBuilder target) { target.append('['); Object[] methods = ((Object[])value); @@ -80,18 +88,38 @@ public interface ValueFormatter { target.append(']'); } }; - - ValueFormatter ObjectFormatter = new ValueFormatter() { - public void format(Object value, StringBuilder target) { + + ValueFormatter ObjectFormatter = new BasicValueFormatter() { + public void format(Object value, StringBuilder target) { target.append(value == null ? "" : value); } }; - - ValueFormatter ObjectArrayFormatter = new ValueFormatter() { - public void format(Object value, StringBuilder target) { + + ValueFormatter ObjectArrayFormatter = new BasicValueFormatter() { + public void format(Object value, StringBuilder target) { target.append('['); Util.asString((Object[])value, ", ", target); target.append(']'); } }; + +// ================================================================= + + ValueFormatter PriorityFormatter = new BasicValueFormatter() { + public String format(Object value) { + return ((RulePriority)value).getName(); + } + }; + + ValueFormatter LanguageFormatter = new BasicValueFormatter() { + public String format(Object value) { + return ((Language)value).getName(); + } + }; + + ValueFormatter LanguageVersionFormatter = new BasicValueFormatter() { + public String format(Object value) { + return ((LanguageVersion)value).getName(); + } + }; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractEditorFactory.java index 1ff3ec3da1..28b84a01b1 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractEditorFactory.java @@ -18,37 +18,37 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; /** - * + * * @author Brian Remedios */ public abstract class AbstractEditorFactory implements EditorFactory { - + protected static ColourManager colourManager; protected static Color overriddenColour; - + protected AbstractEditorFactory() { } - private static ColourManager managerFor(Display display) { - + private static ColourManager colourManager() { + if (colourManager != null) return colourManager; - colourManager = ColourManager.managerFor(display); + colourManager = ColourManager.managerFor(Display.getCurrent()); return colourManager; } - - private Color overriddenColour(Display display) { - + + private Color overriddenColour() { + if (overriddenColour != null) return overriddenColour; - - overriddenColour = managerFor(display).colourFor(AbstractRulePanelManager.overridenColourValues); + + overriddenColour = colourManager().colourFor(AbstractRulePanelManager.overridenColourValues); return overriddenColour; } - + protected Label newLabel(Composite parent, String text) { Label label = new Label(parent, SWT.None); label.setText(text); return label; } - + /** * Generic control that provides a label/widget pair for the default value. Subclasses can override this to provide additional * labels & widgets as necessary but must be able to extract the values held by them when the property is created. @@ -56,19 +56,19 @@ public abstract class AbstractEditorFactory implements EditorFactory { public Control[] createOtherControlsOn(Composite parent, PropertyDescriptor desc, Rule rule, ValueChangeListener listener, SizeChangeListener sizeListener) { return new Control[] { newLabel(parent,"Default"), - newEditorOn(parent, desc, rule, listener, sizeListener) + newEditorOn(parent, desc, rule, listener, sizeListener) }; - } - + } + protected abstract Object valueFrom(Control valueControl); - + protected Object valueFor(Rule rule, PropertyDescriptor desc) { - + return rule.hasDescriptor(desc) ? - rule.getProperty(desc) : + rule.getProperty(desc) : desc.defaultValue(); } - + /** * Method addLabel. * @param parent Composite @@ -76,7 +76,7 @@ public abstract class AbstractEditorFactory implements EditorFactory { * @return Label */ public Label addLabel(Composite parent, PropertyDescriptor desc) { - + Label label = new Label(parent, SWT.NONE); label.setText(desc.description()); GridData data = new GridData(); @@ -85,7 +85,7 @@ public abstract class AbstractEditorFactory implements EditorFactory { label.setLayoutData(data); return label; } - + /** * Return the value as a string that can be easily recognized and parsed * when we see it again. @@ -96,34 +96,34 @@ public abstract class AbstractEditorFactory implements EditorFactory { protected static String asString(Object value) { return value == null ? "" : value.toString(); } - + /** - * Adjust the display of the control to denote whether it holds + * Adjust the display of the control to denote whether it holds * onto the default value or not. - * + * * @param control * @param hasDefaultValue */ protected void adjustRendering(Control control, boolean hasDefaultValue) { - + Display display = control.getDisplay(); - - control.setBackground( - display.getSystemColor(hasDefaultValue ? SWT.COLOR_WHITE : SWT.COLOR_CYAN) + + control.setBackground( + display.getSystemColor(hasDefaultValue ? SWT.COLOR_WHITE : SWT.COLOR_CYAN) ); } - + protected void adjustRendering(Rule rule, PropertyDescriptor desc, Control control) { - - if (!(rule instanceof RuleReference)) return; + + if (!(rule instanceof RuleReference)) return; boolean isOverridden = ((RuleReference)rule).hasOverriddenProperty(desc); Display display = control.getDisplay(); - Color clr = isOverridden ? overriddenColour(display) : display.getSystemColor(SWT.COLOR_WHITE); + Color clr = isOverridden ? overriddenColour() : display.getSystemColor(SWT.COLOR_WHITE); control.setBackground(clr); } - + /** * Return the specified values as a single string using the delimiter. * @param values Object @@ -132,11 +132,11 @@ public abstract class AbstractEditorFactory implements EditorFactory { * @see net.sourceforge.pmd.PropertyDescriptor#asDelimitedString(Object) */ public static String asDelimitedString(Object values, char delimiter) { - + if (values == null) { return ""; } - + if (values instanceof Object[]) { Object[] valueSet = (Object[])values; if (valueSet.length == 0) { @@ -145,14 +145,14 @@ public abstract class AbstractEditorFactory implements EditorFactory { if (valueSet.length == 1) { return asString(valueSet[0]); } - + StringBuilder sb = new StringBuilder(asString(valueSet[0])); for (int i=1; i desc, Rule rule, ValueChangeListener listener); - + protected abstract void setValue(Control widget, Object value); protected abstract void update(Rule rule, PropertyDescriptor desc, List newValues); protected abstract Object addValueIn(Control widget, PropertyDescriptor desc, Rule rule); - + protected abstract Control addWidget(Composite parent, Object value, PropertyDescriptor desc, Rule rule); - + /** - * + * * @param parent Composite * @param desc PropertyDescriptor * @param rule Rule @@ -73,16 +73,16 @@ public abstract class AbstractMultiValueEditorFactory extends AbstractEditorFact * @see net.sourceforge.pmd.ui.preferences.br.EditorFactory#newEditorOn(Composite, PropertyDescriptor, Rule, ValueChangeListener, SizeChangeListener) */ public Control newEditorOn(final Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener changeListener, final SizeChangeListener sizeListener) { - + final Composite panel = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(3, false); layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; panel.setLayout(layout); - + final Text textWidget = new Text(panel, SWT.SINGLE | SWT.BORDER); - final Button butt = new Button(panel, SWT.BORDER); + final Button butt = new Button(panel, SWT.PUSH); butt.setText("..."); // TODO use triangle icon & rotate 90deg when clicked butt.addListener(SWT.Selection, new Listener() { boolean itemsVisible = false; @@ -91,7 +91,7 @@ public abstract class AbstractMultiValueEditorFactory extends AbstractEditorFact if (itemsVisible) { hideCollection(items); sizeListener.addedRows(items.size() / -WidgetsPerRow); - } else { + } else { items = openCollection(panel, desc, rule, textWidget, changeListener, sizeListener); sizeListener.addedRows(items.size() / WidgetsPerRow); } @@ -101,41 +101,41 @@ public abstract class AbstractMultiValueEditorFactory extends AbstractEditorFact } }); GridData data = new GridData(GridData.FILL_HORIZONTAL); - data.horizontalSpan = 2; + data.horizontalSpan = 2; textWidget.setLayoutData(data); panel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - + fillWidget(textWidget, desc, rule); configure(textWidget, desc, rule, changeListener); return panel; } - + private void hideCollection(List controls) { for (Control control : controls) control.dispose(); } - + private void delete(Control number, Control widget, Control button, List controlList, Object deleteValue, PropertyDescriptor desc, Rule rule) { - + controlList.remove(number); number.dispose(); controlList.remove(widget); widget.dispose(); controlList.remove(button); button.dispose(); renumberLabelsIn(controlList); - + Object[] values = (Object[])valueFor(rule, desc); List newValues = new ArrayList(values.length - 1); for (Object value : values) { if (value.equals(deleteValue)) continue; newValues.add(value); } - + update(rule, desc, newValues); } - + private List openCollection(final Composite parent, final PropertyDescriptor desc, final Rule rule, final Text textWidget, final ValueChangeListener changeListener, final SizeChangeListener sizeListener) { - + final List newControls = new ArrayList(); - + int i=0; Object[] values = (Object[])valueFor(rule, desc); for (i=0; i desc, final Rule rule) { return true; } - + private void addNewValueRow(final Composite parent, final PropertyDescriptor desc, final Rule rule, final Text parentWidget, final ValueChangeListener changeListener, final SizeChangeListener sizeListener, final List newControls, int i) { - + if (!canAddNewRowFor(desc, rule)) return; - + final Label number = new Label(parent, SWT.NONE); number.setText(Integer.toString(i+1)); newControls.add(number); final Control widget = addWidget(parent, null, desc, rule); widget.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); newControls.add(widget); - final Button butt = new Button(parent, SWT.BORDER); + final Button butt = new Button(parent, SWT.PUSH); butt.setText("+"); // TODO use icon for consistent width newControls.add(butt); - Listener addListener = new Listener() { + Listener addListener = new Listener() { public void handleEvent(Event event) { // add new value handler // add the new value to the property set // set the value in the widget to the cleaned up one, disable it @@ -196,12 +196,12 @@ public abstract class AbstractMultiValueEditorFactory extends AbstractEditorFact // add listener for new button Object newValue = addValueIn(widget, desc, rule); if (newValue == null) return; - + addNewValueRow(parent, desc, rule, parentWidget, changeListener, sizeListener, newControls, -1); convertToDelete(butt, newValue, parent, newControls, desc, rule, parentWidget, number, widget, changeListener, sizeListener); widget.setEnabled(false); setValue(widget, newValue); - + renumberLabelsIn(newControls); fillWidget(parentWidget, desc, rule); adjustRendering(rule, desc, parentWidget); @@ -214,11 +214,11 @@ public abstract class AbstractMultiValueEditorFactory extends AbstractEditorFact widget.addListener(SWT.DefaultSelection, addListener); // allow for CR on entry widgets themselves, no need to click the '+' button widget.setFocus(); } - + private void convertToDelete(final Button button, final Object toDeleteValue, final Composite parent, final List newControls, final PropertyDescriptor desc, final Rule rule, final Text parentWidget, final Label number, final Control widget, final ValueChangeListener changeListener, final SizeChangeListener sizeListener) { button.setText("-"); Util.removeListeners(button,SWT.Selection); - button.addListener(SWT.Selection, new Listener() { + button.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { delete(number, widget, button, newControls, toDeleteValue, desc, rule); fillWidget(parentWidget, desc, rule); @@ -228,7 +228,7 @@ public abstract class AbstractMultiValueEditorFactory extends AbstractEditorFact } } ); } - + private static void renumberLabelsIn(List controls) { int i=1; for (Control control : controls) { @@ -237,28 +237,28 @@ public abstract class AbstractMultiValueEditorFactory extends AbstractEditorFact } } } - + protected void fillWidget(Text textWidget, PropertyDescriptor desc, Rule rule) { - + Object[] values = (Object[])valueFor(rule, desc); textWidget.setText(values == null ? "" : StringUtil.asString(values, delimiter + ' ')); adjustRendering(rule, desc, textWidget); } - + protected String[] textWidgetValues(Text textWidget) { - + String values = textWidget.getText().trim(); - + if (StringUtil.isEmpty(values)) return StringUtil.EMPTY_STRINGS; - + String[] valueSet = values.split(delimiter); List valueList = new ArrayList(valueSet.length); - + for (String value : valueSet) { String str = value.trim(); if (str.length() > 0) valueList.add(str); } - - return (String[])valueList.toArray(new String[valueList.size()]); + + return valueList.toArray(new String[valueList.size()]); } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractNumericEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractNumericEditorFactory.java index 06fc6c7003..db57d6e9a9 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractNumericEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractNumericEditorFactory.java @@ -15,101 +15,101 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Spinner; /** - * + * * @author Brian Remedios */ public abstract class AbstractNumericEditorFactory extends AbstractEditorFactory { - + public static final int defaultMinimum = 0; public static final int defaultMaximum = 1000; - + protected AbstractNumericEditorFactory() { } - + protected static Spinner newSpinnerFor(Composite parent, int digits) { - + Spinner spinner = new Spinner(parent, SWT.SINGLE | SWT.BORDER); - spinner.setDigits(digits); + spinner.setDigits(digits); return spinner; } - + protected int digitPrecision() { return 0; } - + public Control[] createOtherControlsOn(Composite parent, PropertyDescriptor desc, Rule rule, ValueChangeListener listener, SizeChangeListener sizeListener) { - + Label defaultLabel = newLabel(parent, SWTUtil.stringFor(StringKeys.MSGKEY_RULEEDIT_LABEL_DEFAULT)); Control valueControl = newEditorOn(parent, desc, rule, listener, sizeListener); - + Label minLabel = newLabel(parent, SWTUtil.stringFor(StringKeys.MSGKEY_RULEEDIT_LABEL_MIN)); Spinner minWidget = newSpinnerFor(parent, digitPrecision()); Label maxLabel = newLabel(parent, SWTUtil.stringFor(StringKeys.MSGKEY_RULEEDIT_LABEL_MAX)); Spinner maxWidget = newSpinnerFor(parent, digitPrecision()); - + linkup(minWidget, (Spinner)valueControl, maxWidget); - + return new Control[] { defaultLabel, valueControl, minLabel, minWidget, maxLabel, maxWidget }; } - + private void linkup(final Spinner minWidget, final Spinner valueWidget, final Spinner maxWidget) { minWidget.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { adjustForMin(minWidget, valueWidget, maxWidget); } }); - + valueWidget.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { adjustForValue(minWidget, valueWidget, maxWidget); } - }); - + }); + maxWidget.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { adjustForMax(minWidget, valueWidget, maxWidget); } - }); + }); } - + private void adjustForMin(Spinner minWidget, Spinner valueWidget, Spinner maxWidget) { int min = minWidget.getSelection(); if (valueWidget.getSelection() < min) valueWidget.setSelection(min); if (maxWidget.getSelection() < min) maxWidget.setSelection(min); } - + private void adjustForValue(Spinner minWidget, Spinner valueWidget, Spinner maxWidget) { int value = valueWidget.getSelection(); if (minWidget.getSelection() > value) minWidget.setSelection(value); if (maxWidget.getSelection() < value) maxWidget.setSelection(value); } - + private void adjustForMax(Spinner minWidget, Spinner valueWidget, Spinner maxWidget) { int max = maxWidget.getSelection(); if (valueWidget.getSelection() > max) valueWidget.setSelection(max); if (minWidget.getSelection() > max) minWidget.setSelection(max); } - + protected Number defaultIn(Control[] controls) { - + return controls == null ? Integer.valueOf(defaultMinimum) : (Number)valueFrom(controls[1]); } - + protected Number minimumIn(Control[] controls) { - + return controls == null ? Integer.valueOf(0) : (Number)valueFrom(controls[3]); } - + protected Number maximumIn(Control[] controls) { - + return controls == null ? Integer.valueOf(defaultMaximum) : (Number)valueFrom(controls[5]); diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractRealNumberEditor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractRealNumberEditor.java index 51eae28fd3..f7492ce42d 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractRealNumberEditor.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/AbstractRealNumberEditor.java @@ -7,32 +7,32 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Spinner; /** - * + * * @author Brian Remedios */ public abstract class AbstractRealNumberEditor extends AbstractNumericEditorFactory { protected static final int digits = 3; - + protected static final double scale = Math.pow(10, digits); - + protected AbstractRealNumberEditor() { } protected Spinner newSpinnerFor(Composite parent, Rule rule, NumericPropertyDescriptor numDesc) { - + Spinner spinner = newSpinnerFor(parent, digits); int min = (int)(numDesc.lowerLimit().doubleValue() * scale); int max = (int)(numDesc.upperLimit().doubleValue() * scale); spinner.setMinimum(min); spinner.setMaximum(max); - + Number value = ((Number)valueFor(rule, numDesc)); if (value != null) { int intVal = (int)(value.doubleValue() * scale); spinner.setSelection(intVal); } - + return spinner; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/BooleanEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/BooleanEditorFactory.java index 0f39dfa8d9..2182e8127a 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/BooleanEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/BooleanEditorFactory.java @@ -21,53 +21,53 @@ public class BooleanEditorFactory extends AbstractEditorFactory { public static final BooleanEditorFactory instance = new BooleanEditorFactory(); - + private BooleanEditorFactory() { } - + public PropertyDescriptor createDescriptor(String name, String description, Control[] otherData) { - + return new BooleanProperty( - name, - description, - otherData == null ? Boolean.FALSE : valueFrom(otherData[1]), + name, + description, + otherData == null ? Boolean.FALSE : valueFrom(otherData[1]), 0 ); - } - + } + private static BooleanProperty booleanPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (BooleanProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (BooleanProperty)desc; } } - + protected Boolean valueFrom(Control valueControl) { return ((Button)valueControl).getSelection() ? Boolean.TRUE : Boolean.FALSE; } - + public Control newEditorOn(Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { - + final Button butt = new Button(parent, SWT.CHECK); butt.setText(""); - + final BooleanProperty bp = booleanPropertyFrom(desc); // TODO - do I really have to do this? - + boolean set = ((Boolean)valueFor(rule, desc)).booleanValue(); butt.setSelection(set); - + butt.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { boolean selected = butt.getSelection(); if (selected == (((Boolean)valueFor(rule, bp))).booleanValue()) return; - + rule.setProperty(bp, Boolean.valueOf(selected)); listener.changed(rule, desc, Boolean.valueOf(selected)); adjustRendering(rule, desc, butt); } }); - + return butt; - } + } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/CharacterEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/CharacterEditorFactory.java index 9572f820af..e83ada43f2 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/CharacterEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/CharacterEditorFactory.java @@ -16,33 +16,33 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; /** - * + * * @author Brian Remedios */ public class CharacterEditorFactory extends AbstractEditorFactory { public static final CharacterEditorFactory instance = new CharacterEditorFactory(); - + private CharacterEditorFactory() { } public PropertyDescriptor createDescriptor(String name, String description, Control[] otherData) { - + return new CharacterProperty( - name, - description, - 'a', + name, + description, + 'a', 0); - } - + } + protected Object valueFrom(Control valueControl) { - + String value = ((Text)valueControl).getText().trim(); - - return (StringUtil.isEmpty(value) || value.length() > 1) ? - null : + + return (StringUtil.isEmpty(value) || value.length() > 1) ? + null : Character.valueOf(value.charAt(0)); } - + /** * Method fillWidget. * @param textWidget Text @@ -53,36 +53,36 @@ public class CharacterEditorFactory extends AbstractEditorFactory { Character val = (Character)valueFor(rule, desc); textWidget.setText(val == null ? "" : val.toString()); } - + private static Character charValueIn(Text textControl) { String newValue = textControl.getText().trim(); if (newValue.length() == 0) return null; return Character.valueOf(newValue.charAt(0)); } - + private static CharacterProperty characterPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (CharacterProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (CharacterProperty)desc; } } - + public Control newEditorOn(Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { - + final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER); fillWidget(text, desc, rule); - + final CharacterProperty cp = characterPropertyFrom(desc); // TODO - really necessary? - + text.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { Character newValue = charValueIn(text); - Character existingValue = (Character)valueFor(rule, cp); - if (existingValue.equals(newValue)) return; - + Character existingValue = (Character)valueFor(rule, cp); + if (existingValue.equals(newValue)) return; + rule.setProperty(cp, newValue); listener.changed(rule, cp, newValue); adjustRendering(rule, desc, text); diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/DoubleEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/DoubleEditorFactory.java index 39aaaebf25..fdc31100cf 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/DoubleEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/DoubleEditorFactory.java @@ -14,19 +14,19 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Spinner; /** - * + * * @author Brian Remedios */ public class DoubleEditorFactory extends AbstractRealNumberEditor { public static final DoubleEditorFactory instance = new DoubleEditorFactory(); - + private DoubleEditorFactory() { } public PropertyDescriptor createDescriptor(String name, String description, Control[] otherData) { - + return new DoubleProperty( - name, + name, description, defaultIn(otherData).doubleValue(), minimumIn(otherData).doubleValue(), @@ -34,38 +34,38 @@ public class DoubleEditorFactory extends AbstractRealNumberEditor { 0.0f ); } - + private static DoubleProperty doublePropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (DoubleProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (DoubleProperty)desc; } } - + protected Object valueFrom(Control valueControl) { - + return Double.valueOf(((Spinner)valueControl).getSelection() / scale); } - + public Control newEditorOn(Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { - final DoubleProperty dp = doublePropertyFrom(desc); + final DoubleProperty dp = doublePropertyFrom(desc); final Spinner spinner = newSpinnerFor(parent, rule, dp); - + spinner.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { Double newValue = Double.valueOf(spinner.getSelection() / scale); if (newValue.equals(valueFor(rule, dp))) return; - + rule.setProperty(dp, newValue); listener.changed(rule, dp, newValue); adjustRendering(rule, desc, spinner); } }); - + return spinner; } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/EnumerationEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/EnumerationEditorFactory.java index e98730b47a..91aec697c2 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/EnumerationEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/EnumerationEditorFactory.java @@ -15,7 +15,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** - * + * * @author Brian Remedios */ public class EnumerationEditorFactory extends AbstractEditorFactory { @@ -23,54 +23,54 @@ public class EnumerationEditorFactory extends AbstractEditorFactory { public static final EnumerationEditorFactory instance = new EnumerationEditorFactory(); private EnumerationEditorFactory() { } - + private static EnumeratedProperty enumerationPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (EnumeratedProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (EnumeratedProperty)desc; } } - - + + protected Object valueFrom(Control valueControl) { - + int index = ((Combo)valueControl).getSelectionIndex(); return null; // TODO ??? } - + public PropertyDescriptor createDescriptor(String name, String optionalDescription, Control[] otherData) { return new EnumeratedProperty(name, "Value set " + name, null, null, 0, 0.0f); } - + public static int indexOf(Object item, Object[][] items) { for (int i=0; i desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { - + final Combo combo = new Combo(parent, SWT.READ_ONLY); - + final EnumeratedProperty ep = enumerationPropertyFrom(desc); Object value = valueFor(rule, desc); combo.setItems(SWTUtil.labelsIn(ep.choices(), 0)); int selectionIdx = indexOf(value, ep.choices()); if (selectionIdx >= 0) combo.select(selectionIdx); - + combo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int selectionIdx = combo.getSelectionIndex(); - Object newValue = ep.choices()[selectionIdx][1]; + Object newValue = ep.choices()[selectionIdx][1]; if (newValue == valueFor(rule, desc)) return; - + rule.setProperty(ep, newValue); listener.changed(rule, desc, newValue); adjustRendering(rule, desc, combo); } - }); - + }); + return combo; } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/FloatEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/FloatEditorFactory.java index 04047f4a52..66369836f8 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/FloatEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/FloatEditorFactory.java @@ -14,19 +14,19 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Spinner; /** - * + * * @author Brian Remedios */ public class FloatEditorFactory extends AbstractRealNumberEditor { public static final FloatEditorFactory instance = new FloatEditorFactory(); - + private FloatEditorFactory() { } - + public PropertyDescriptor createDescriptor(String name, String description, Control[] otherData) { - + return new FloatProperty( - name, + name, description, defaultIn(otherData).floatValue(), minimumIn(otherData).floatValue(), @@ -34,38 +34,38 @@ public class FloatEditorFactory extends AbstractRealNumberEditor { 0.0f ); } - + private static FloatProperty floatPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (FloatProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (FloatProperty)desc; } } - + protected Object valueFrom(Control valueControl) { - + return new Float(((Spinner)valueControl).getSelection() / scale); } - + public Control newEditorOn(Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { final FloatProperty fp = floatPropertyFrom(desc); final Spinner spinner = newSpinnerFor(parent, rule, fp); - + spinner.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { Float newValue = new Float(spinner.getSelection() / scale); if (newValue.equals(valueFor(rule, fp))) return; - + rule.setProperty(fp, newValue); listener.changed(rule, fp, newValue); adjustRendering(rule, desc, spinner); } }); - + return spinner; } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/IntegerEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/IntegerEditorFactory.java index 71103dc97c..7ee4d7a34b 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/IntegerEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/IntegerEditorFactory.java @@ -15,77 +15,77 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Spinner; /** - * + * * @author Brian Remedios */ public class IntegerEditorFactory extends AbstractNumericEditorFactory { public static final IntegerEditorFactory instance = new IntegerEditorFactory(); - + private IntegerEditorFactory() { } - + public PropertyDescriptor createDescriptor(String name, String description, Control[] otherData) { - + return new IntegerProperty( - name, + name, description, minimumIn(otherData).intValue(), maximumIn(otherData).intValue(), defaultIn(otherData).intValue(), 0.0f ); - } - + } + protected Object valueFrom(Control valueControl) { - - int value = ((Spinner)valueControl).getSelection(); + + int value = ((Spinner)valueControl).getSelection(); return Integer.valueOf(value); } - + private static IntegerProperty intPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (IntegerProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (IntegerProperty)desc; } } - + public static Spinner newSpinner(Composite parent, NumericPropertyDescriptor desc, Object valueIn) { - + Spinner spinner = newSpinnerFor(parent, 0); - + spinner.setMinimum(desc.lowerLimit().intValue()); spinner.setMaximum(desc.upperLimit().intValue()); - + int value = valueIn == null ? spinner.getMinimum() : ((Number)valueIn).intValue(); spinner.setSelection(value); return spinner; } protected void setValue(Rule rule, IntegerProperty desc, Integer value) { - + // if (!rule.hasDescriptor(desc)) return; rule.setProperty(desc, value); } - + public Control newEditorOn(Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { - - final IntegerProperty ip = intPropertyFrom(desc); // TODO - do I really have to do this? + + final IntegerProperty ip = intPropertyFrom(desc); // TODO - do I really have to do this? final Spinner spinner = newSpinner(parent, ip, valueFor(rule, desc)); - + spinner.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { Integer newValue = Integer.valueOf(spinner.getSelection()); if (newValue.equals(valueFor(rule, ip))) return; - + setValue(rule, ip, newValue); listener.changed(rule, desc, newValue); adjustRendering(rule, desc, spinner); } - }); - + }); + return spinner; - } + } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MethodEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MethodEditorFactory.java index 1d8503e526..105b79be6f 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MethodEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MethodEditorFactory.java @@ -18,7 +18,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** - * + * * @author Brian Remedios */ public class MethodEditorFactory extends AbstractEditorFactory { @@ -29,53 +29,53 @@ public class MethodEditorFactory extends AbstractEditorFactory { "java.lang.", "java.util." }; - + public static final Method stringLength = ClassUtil.methodFor(String.class, "length", ClassUtil.EMPTY_CLASS_ARRAY); - - private MethodEditorFactory() { } - + + private MethodEditorFactory() { } + public PropertyDescriptor createDescriptor(String name, String optionalDescription, Control[] otherData) { return new MethodProperty(name, "Method value " + name, stringLength, new String[] { "java.lang" }, 0.0f); - } - + } + protected Object valueFrom(Control valueControl) { - + return ((MethodPicker)valueControl).getMethod(); } - + protected void fillWidget(MethodPicker widget, PropertyDescriptor desc, Rule rule) { - + Method method = (Method)valueFor(rule, desc); widget.setMethod(method); adjustRendering(rule, desc, widget); } - + private static MethodProperty methodPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (MethodProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (MethodProperty)desc; } } - + public Control newEditorOn(Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { - + final MethodPicker picker = new MethodPicker(parent, SWT.SINGLE | SWT.BORDER, UnwantedPrefixes); picker.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fillWidget(picker, desc, rule); - + final MethodProperty mp = methodPropertyFrom(desc); - + picker.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Method newValue = picker.getMethod(); if (newValue == null) return; - - Method existingValue = (Method)valueFor(rule, mp); - if (existingValue == newValue) return; - + + Method existingValue = (Method)valueFor(rule, mp); + if (existingValue == newValue) return; + rule.setProperty(mp, newValue); fillWidget(picker, desc, rule); // redraw listener.changed(rule, desc, newValue); @@ -83,5 +83,5 @@ public class MethodEditorFactory extends AbstractEditorFactory { }); return picker; - } + } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MethodPicker.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MethodPicker.java index a260e30ec5..0c1584a6f9 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MethodPicker.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MethodPicker.java @@ -20,31 +20,31 @@ import org.eclipse.swt.widgets.Listener; /** * A general purpose selection widget that deals with methods. Once the user types in a valid type * in the left-most text field, all methods that are part of it are listed in the combobox on the - * right. - * + * right. + * * Note: Uses the default class loader to lookup the class, we'll probably want to supply an * external one in the future? - * + * * @author Brian Remedios */ public class MethodPicker extends Composite { private TypeText typeText; - private Combo methodList; - private Method[] methods; + private Combo methodList; + private Method[] methods; private String[] unwantedPrefixes; - + public MethodPicker(Composite parent, int style, String[] theUnwantedPrefixes) { super(parent, SWT.None); - + unwantedPrefixes = theUnwantedPrefixes == null ? StringUtil.EMPTY_STRINGS : theUnwantedPrefixes; - + GridLayout layout = new GridLayout(2, true); layout.verticalSpacing = 0; layout.horizontalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; this.setLayout(layout); - + typeText = new TypeText(this, style, false, "Enter a type name"); // TODO i18l typeText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); typeText.addListener(SWT.FocusOut, new Listener() { @@ -52,65 +52,65 @@ public class MethodPicker extends Composite { reviseMethodListFor(typeText.getType(true)); } }); - + typeText.addListener(SWT.Modify, new Listener() { public void handleEvent(Event event) { reviseMethodListFor(typeText.getType(false)); // no cleanup, avoid event loop & overflow } }); - + methodList = new Combo(this, style); methodList.setLayoutData(new GridData(GridData.FILL_BOTH)); } - + private void reviseMethodListFor(Class cls) { - + if (cls == null) { methodList.removeAll(); methodList.setEnabled(false); return; } - + methodList.setEnabled(true); methods = cls.getMethods(); Arrays.sort(methods, Util.MethodNameComparator); String[] items = new String[methods.length]; for (int i=0; i cls) { + + public void setType(Class cls) { typeText.setType(cls); } - + public void setEnabled(boolean flag) { super.setEnabled(flag); typeText.setEnabled(flag); methodList.setEnabled(flag); } - + public void setEditable(boolean flag) { typeText.setEditable(flag); } - - public Class getType(boolean doCleanup) { + + public Class getType(boolean doCleanup) { return typeText.getType(doCleanup); } - + private int indexOf(Method method) { if (methods == null) return -1; for (int i=0; i enumerationPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (EnumeratedMultiProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (EnumeratedMultiProperty)desc; } } - + @Override protected Object addValueIn(Control widget, PropertyDescriptor desc, Rule rule) { - + int idx = ((Combo)widget).getSelectionIndex(); if (idx < 0) return null; - + String newValue = ((Combo)widget).getItem(idx); - + String[] currentValues = (String[])valueFor(rule, desc); String[] newValues = CollectionUtil.addWithoutDuplicates(currentValues, newValue); if (currentValues.length == newValues.length) return null; - + rule.setProperty((EnumeratedMultiProperty)desc, newValues); return newValue; } @@ -63,25 +62,25 @@ public class MultiEnumerationEditorFactory extends AbstractMultiValueEditorFacto */ @Override protected boolean canAddNewRowFor(PropertyDescriptor desc, Rule rule) { - + Object[] choices = desc.choices(); Object[] values = (Object[])rule.getProperty(desc); - + return choices.length > values.length; } - + @Override protected Control addWidget(Composite parent, Object value, PropertyDescriptor desc, Rule rule) { - + final Combo combo = new Combo(parent, SWT.READ_ONLY); - + final EnumeratedMultiProperty ep = enumerationPropertyFrom(desc); - + // TODO remove all choices already chosen by previous widgets combo.setItems(SWTUtil.labelsIn(ep.choices(), 0)); int selectionIdx = EnumerationEditorFactory.indexOf(value, ep.choices()); if (selectionIdx >= 0) combo.select(selectionIdx); - + return combo; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiIntegerEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiIntegerEditorFactory.java index 2744fa8cbc..9c51efcb57 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiIntegerEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiIntegerEditorFactory.java @@ -22,39 +22,39 @@ import org.eclipse.swt.widgets.Text; /** * Behaviour: * Provide a set of widgets that allows the user to pick a range of integer values. The selected values can only exist once. - * + * * Provide a spin box for each value selected while ensuring that their choices only contain unselected values. If the last spin box holds the only * remaining choice then ensure it gets disabled, the user can only delete it or the previous ones. If the user deletes a previous one then re-enable * the last one and add the deleted value to its set of choices. - * + * * @author Brian Remedios */ public class MultiIntegerEditorFactory extends AbstractMultiValueEditorFactory { public static final MultiIntegerEditorFactory instance = new MultiIntegerEditorFactory(); - + private static final Integer[] emptyIntSet = new Integer[0]; - + private MultiIntegerEditorFactory() { } - + public PropertyDescriptor createDescriptor(String name, String optionalDescription, Control[] otherData) { return new IntegerMultiProperty(name, "Integer values " + name, NumericConstants.ZERO, Integer.valueOf(10), new Integer[] {NumericConstants.ZERO}, 0.0f); } - + protected Object valueFrom(Control valueControl) { - + return currentIntegers((Text)valueControl); } - + private Integer[] currentIntegers(Text textWidget) { - + String[] numberStrings = textWidgetValues(textWidget); if (numberStrings.length == 0) return emptyIntSet; - + List ints = new ArrayList(numberStrings.length); - + Integer intrg = null; - + for (String numString : numberStrings) { try { intrg = Integer.parseInt(numString); @@ -63,61 +63,61 @@ public class MultiIntegerEditorFactory extends AbstractMultiValueEditorFactory { } if (intrg != null) ints.add(intrg); } - return (Integer[]) ints.toArray(new Integer[ints.size()]); + return ints.toArray(new Integer[ints.size()]); } - + private static NumericPropertyDescriptor numericPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (NumericPropertyDescriptor) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (NumericPropertyDescriptor)desc; } } - + protected Control addWidget(Composite parent, Object value, PropertyDescriptor desc, Rule rule) { - - NumericPropertyDescriptor ip = numericPropertyFrom(desc); // TODO - do I really have to do this? + + NumericPropertyDescriptor ip = numericPropertyFrom(desc); // TODO - do I really have to do this? return IntegerEditorFactory.newSpinner(parent, ip, value); - } - + } + protected void setValue(Control widget, Object valueIn) { - + Spinner spinner = (Spinner)widget; int value = valueIn == null ? spinner.getMinimum() : ((Number)valueIn).intValue(); spinner.setSelection(value); } - + protected void configure(final Text textWidget, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener) { - + final IntegerMultiProperty imp = (IntegerMultiProperty)numericPropertyFrom(desc); - + textWidget.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { - Integer[] newValue = currentIntegers(textWidget); - Integer[] existingValue = (Integer[])valueFor(rule, imp); - if (CollectionUtil.areSemanticEquals(existingValue, newValue)) return; - + Integer[] newValue = currentIntegers(textWidget); + Integer[] existingValue = (Integer[])valueFor(rule, imp); + if (CollectionUtil.areSemanticEquals(existingValue, newValue)) return; + rule.setProperty(imp, newValue); fillWidget(textWidget, desc, rule); // display the accepted values listener.changed(rule, desc, newValue); } }); } - + protected void update(Rule rule, PropertyDescriptor desc, List newValues) { rule.setProperty((IntegerMultiProperty)desc, newValues.toArray(new Integer[newValues.size()])); } - + @Override protected Object addValueIn(Control widget, PropertyDescriptor desc, Rule rule) { - + Integer newValue= Integer.valueOf(((Spinner)widget).getSelection()); - + Integer[] currentValues = (Integer[])valueFor(rule, desc); Integer[] newValues = CollectionUtil.addWithoutDuplicates(currentValues, newValue); if (currentValues.length == newValues.length) return null; - + rule.setProperty((IntegerMultiProperty)desc, newValues); return newValue; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiMethodEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiMethodEditorFactory.java index 5431f932bc..ceb0e16743 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiMethodEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiMethodEditorFactory.java @@ -20,19 +20,19 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Text; /** - * + * * @author Brian Remedios */ public class MultiMethodEditorFactory extends AbstractMultiValueEditorFactory { public static final MultiMethodEditorFactory instance = new MultiMethodEditorFactory(); - + private MultiMethodEditorFactory() { } - + public PropertyDescriptor createDescriptor(String name, String optionalDescription, Control[] otherData) { return new MethodMultiProperty(name, "Method value " + name, new Method[] {MethodEditorFactory.stringLength}, new String[] { "java.lang" }, 0.0f); } - + public static String[] signaturesFor(Method[] methods) { String[] typeNames = new String[methods.length]; for (int i=0; i> methodGroups) { - + if (methodGroups.isEmpty()) return ""; - + StringBuilder sb = new StringBuilder(); Iterator>> iter = methodGroups.entrySet().iterator(); Entry> entry = iter.next(); - + sb.append(entry.getKey()).append('['); allSignaturesOn(sb, entry.getValue(), ","); sb.append(']'); - + while (iter.hasNext()) { entry = iter.next(); sb.append(" ").append(entry.getKey()).append('['); allSignaturesOn(sb, entry.getValue(), ", "); - sb.append(']'); + sb.append(']'); } - + return sb.toString(); } - + private static void allSignaturesOn(StringBuilder sb, List methods, String delimiter) { - + sb.append( Util.signatureFor(methods.get(0), MethodEditorFactory.UnwantedPrefixes) ); - + for (int i=1; i desc, Rule rule) { - + Method[] values = (Method[])valueFor(rule, desc); if (values == null) { textWidget.setText(""); return; } - - Map> methodMap = ClassUtil.asMethodGroupsByTypeName(values); + + Map> methodMap = ClassUtil.asMethodGroupsByTypeName(values); textWidget.setText(values == null ? "" : asString(methodMap)); adjustRendering(rule, desc, textWidget); } - + protected Control addWidget(Composite parent, Object value, PropertyDescriptor desc, Rule rule) { MethodPicker widget = new MethodPicker(parent, SWT.SINGLE | SWT.BORDER, MethodEditorFactory.UnwantedPrefixes); setValue(widget, value); return widget; } - + protected void setValue(Control widget, Object value) { Method method = value == null ? null : (Method)value; ((MethodPicker)widget).setMethod(method); } - + protected void configure(final Text textWidget, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener) { textWidget.setEditable(false); } - + protected void update(Rule rule, PropertyDescriptor desc, List newValues) { rule.setProperty((MethodMultiProperty)desc, newValues.toArray(new Method[newValues.size()])); } - + @Override protected Object addValueIn(Control widget, PropertyDescriptor desc, Rule rule) { - + Method newValue = ((MethodPicker)widget).getMethod(); if (newValue == null) return null; - + Method[] currentValues = (Method[])valueFor(rule, desc); Method[] newValues = CollectionUtil.addWithoutDuplicates(currentValues, newValue); if (currentValues.length == newValues.length) return null; // nothing changed - + rule.setProperty((MethodMultiProperty)desc, newValues); return newValue; } - + protected Object valueFrom(Control valueControl) { // not necessary for this type - return null; + return null; } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiStringEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiStringEditorFactory.java index 50434fc43a..9cb63d8a10 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiStringEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiStringEditorFactory.java @@ -18,54 +18,54 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; /** - * + * * @author Brian Remedios */ public class MultiStringEditorFactory extends AbstractMultiValueEditorFactory { public static final MultiStringEditorFactory instance = new MultiStringEditorFactory(); - + private MultiStringEditorFactory() { } - + public PropertyDescriptor createDescriptor(String name, String optionalDescription, Control[] otherData) { return new StringMultiProperty(name, "String value " + name, new String[] {""}, 0.0f, StringMultiProperty.DEFAULT_DELIMITER); } - + private static StringMultiProperty multiStringPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (StringMultiProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (StringMultiProperty)desc; } } - + protected Control addWidget(Composite parent, Object value, PropertyDescriptor desc, Rule rule) { Text textWidget = new Text(parent, SWT.SINGLE | SWT.BORDER); setValue(textWidget,value); return textWidget; - } - + } + protected void setValue(Control widget, Object value) { ((Text)widget).setText(value == null ? "" : value.toString()); } - + protected void configure(final Text textWidget, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener) { - + final StringMultiProperty smp = multiStringPropertyFrom(desc); - + Listener widgetListener = new Listener() { public void handleEvent(Event event) { - String[] newValues = textWidgetValues(textWidget); - String[] existingValues = (String[])valueFor(rule, smp); - if (CollectionUtil.areSemanticEquals(existingValues, newValues)) return; - - rule.setProperty(smp, newValues); - fillWidget(textWidget, desc, rule); // reload with latest scrubbed values + String[] newValues = textWidgetValues(textWidget); + String[] existingValues = (String[])valueFor(rule, smp); + if (CollectionUtil.areSemanticEquals(existingValues, newValues)) return; + + rule.setProperty(smp, newValues); + fillWidget(textWidget, desc, rule); // reload with latest scrubbed values listener.changed(rule, desc, newValues); } }; - + textWidget.addListener(SWT.FocusOut, widgetListener); // textWidget.addListener(SWT.DefaultSelection, widgetListener); } @@ -74,22 +74,22 @@ public class MultiStringEditorFactory extends AbstractMultiValueEditorFactory { protected void update(Rule rule, PropertyDescriptor desc, List newValues) { rule.setProperty((StringMultiProperty)desc, newValues.toArray(new String[newValues.size()])); } - + @Override protected Object addValueIn(Control widget, PropertyDescriptor desc, Rule rule) { - + String newValue = ((Text)widget).getText().trim(); if (StringUtil.isEmpty(newValue)) return null; - + String[] currentValues = (String[])valueFor(rule, desc); String[] newValues = CollectionUtil.addWithoutDuplicates(currentValues, newValue); if (currentValues.length == newValues.length) return null; - + rule.setProperty((StringMultiProperty)desc, newValues); return newValue; } - + protected Object valueFrom(Control valueControl) { // not necessary for this type - return null; + return null; } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiTypeEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiTypeEditorFactory.java index 5001f3f963..eb9b71ed95 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiTypeEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/MultiTypeEditorFactory.java @@ -21,19 +21,19 @@ import org.eclipse.swt.widgets.Text; /** * TODO - use new TypeText widget - * + * * @author Brian Remedios */ public class MultiTypeEditorFactory extends AbstractMultiValueEditorFactory { public static final MultiTypeEditorFactory instance = new MultiTypeEditorFactory(); - + private MultiTypeEditorFactory() { } - + public PropertyDescriptor createDescriptor(String name, String optionalDescription, Control[] otherData) { return new TypeMultiProperty(name, "Type value " + name, new Class[] {String.class}, new String[] { "java.lang" } , 0.0f); } - + public static String[] shortNamesFor(Class[] types) { String[] typeNames = new String[types.length]; for (int i=0; i desc, Rule rule) { - + Class[] values = (Class[])valueFor(rule, desc); if (values == null) { textWidget.setText(""); return; } - + textWidget.setText(values == null ? "" : asString(values)); adjustRendering(rule, desc, textWidget); } - + private String asString(Class[] types) { String[] typeNames = shortNamesFor(types); return StringUtil.asString(typeNames, delimiter + ' '); } - + private Class[] currentTypes(Text textWidget) { - + String[] typeNames = textWidgetValues(textWidget); if (typeNames.length == 0) return ClassUtil.EMPTY_CLASS_ARRAY; - + List> types = new ArrayList>(typeNames.length); - + for (String typeName : typeNames) { Class newType = TypeEditorFactory.typeFor(typeName); if (newType != null) types.add(newType); } - return (Class[]) types.toArray(new Class[types.size()]); + return types.toArray(new Class[types.size()]); } - + private static TypeMultiProperty multiTypePropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (TypeMultiProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (TypeMultiProperty)desc; } } - + protected Control addWidget(Composite parent, Object value, PropertyDescriptor desc, Rule rule) { TypeText typeWidget = new TypeText(parent, SWT.SINGLE | SWT.BORDER, true, "Enter type name"); setValue(typeWidget, value); return typeWidget; } - + protected void setValue(Control widget, Object value) { - - Class type = (Class)value; + + Class type = (Class)value; ((TypeText)widget).setType(type); } - + protected void configure(final Text textWidget, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener) { - + final TypeMultiProperty tmp = multiTypePropertyFrom(desc); // TODO - really necessary? - + textWidget.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { - Class[] newValue = currentTypes(textWidget); - Class[] existingValue = (Class[])valueFor(rule, tmp); - if (CollectionUtil.areSemanticEquals(existingValue, newValue)) return; - + Class[] newValue = currentTypes(textWidget); + Class[] existingValue = (Class[])valueFor(rule, tmp); + if (CollectionUtil.areSemanticEquals(existingValue, newValue)) return; + rule.setProperty(tmp, newValue); fillWidget(textWidget, desc, rule); // display the accepted values listener.changed(rule, desc, newValue); - + adjustRendering(rule, desc, textWidget); } }); } - + protected void update(Rule rule, PropertyDescriptor desc, List newValues) { rule.setProperty((TypeMultiProperty)desc, newValues.toArray(new Class[newValues.size()])); } - + @Override protected Object addValueIn(Control widget, PropertyDescriptor desc, Rule rule) { - + Class enteredValue = ((TypeText) widget).getType(true); if (enteredValue == null) return null; - + Class[] currentValues = (Class[])valueFor(rule, desc); Class[] newValues = CollectionUtil.addWithoutDuplicates(currentValues, enteredValue); if (currentValues.length == newValues.length) return null; - + rule.setProperty((TypeMultiProperty)desc, newValues); return enteredValue; } - + protected Object valueFrom(Control valueControl) { // not necessary for this type - return null; + return null; } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/SWTUtil.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/SWTUtil.java index f3c5a594cb..e44e608166 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/SWTUtil.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/SWTUtil.java @@ -11,35 +11,36 @@ import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Listener; /** - * + * * @author Brian Remedios */ public class SWTUtil { - + + private SWTUtil() {} + private static PMDPlugin plugin = PMDPlugin.getDefault(); - + private static final String TOOLTIP_SUFFIX = ".tooltip"; - + public static void logInfo(String message) { plugin.logInformation(message); } public static void logError(String message, Throwable error) { plugin.logError(message, error); - } - - + } + // TODO move this to to Collections utility public static Set asStringSet(String input, char separator) { List values = Arrays.asList(input.split(""+separator)); return new HashSet(values); } - + // TODO move this to to Collections utility public static String asString(Collection values, char separator) { - + if (values == null || values.isEmpty()) return ""; - + String[] strings = values.toArray(new String[values.size()]); StringBuilder sb = new StringBuilder(strings[0]); @@ -47,35 +48,35 @@ public class SWTUtil { sb.append(separator).append(strings[i]); } return sb.toString(); - } - + } + public static String stringFor(String key) { return plugin.getStringTable().getString(key); - } - + } + public static String tooltipFor(String key) { String ttKey = key + TOOLTIP_SUFFIX; String tooltip = stringFor(ttKey); return ttKey.equals(tooltip) ? stringFor(key) : tooltip; } - + public static void releaseListeners(Control control, int listenerType) { Listener[] listeners = control.getListeners(listenerType); for (Listener listener : listeners) control.removeListener(listenerType, listener); } - + public static String[] labelsIn(Object[][] items, int columnIndex) { - + String[] labels = new String[items.length]; for (int i=0; i createDescriptor(String name, String description, Control[] otherData) { - + return new StringProperty( - name, - description, - otherData == null ? "" : (String)valueFrom(otherData[1]), + name, + description, + otherData == null ? "" : (String)valueFrom(otherData[1]), 0.0f ); } - - + + protected Object valueFrom(Control valueControl) { return ((Text)valueControl).getText(); } - + /** * Method fillWidget. * @param textWidget Text @@ -52,10 +52,10 @@ public class StringEditorFactory extends AbstractEditorFactory { textWidget.setText(val == null ? "" : val); adjustRendering(rule, desc, textWidget); } - + private static StringProperty stringPropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (StringProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (StringProperty)desc; @@ -63,26 +63,26 @@ public class StringEditorFactory extends AbstractEditorFactory { } private void setValue(Rule rule, StringProperty desc, String value) { - + if (!rule.hasDescriptor(desc)) return; rule.setProperty(desc, value); } - + public Control newEditorOn(Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { - + final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fillWidget(text, desc, rule); - + final StringProperty sp = stringPropertyFrom(desc); // TODO - really necessary? - + text.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { - String newValue = text.getText().trim(); - String existingValue = (String)valueFor(rule, sp); - if (StringUtil.areSemanticEquals(existingValue, newValue)) return; - + String newValue = text.getText().trim(); + String existingValue = (String)valueFor(rule, sp); + if (StringUtil.areSemanticEquals(existingValue, newValue)) return; + setValue(rule, sp, newValue); fillWidget(text, desc, rule); // redraw listener.changed(rule, desc, newValue); @@ -90,5 +90,5 @@ public class StringEditorFactory extends AbstractEditorFactory { }); return text; - } + } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/TypeEditorFactory.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/TypeEditorFactory.java index 6581cadacf..749a65b246 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/TypeEditorFactory.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/TypeEditorFactory.java @@ -17,7 +17,7 @@ import org.eclipse.swt.widgets.Listener; /** - * + * * @author Brian Remedios */ public class TypeEditorFactory extends AbstractEditorFactory { @@ -27,18 +27,18 @@ public class TypeEditorFactory extends AbstractEditorFactory { private TypeEditorFactory() { } public PropertyDescriptor createDescriptor(String name, String description, Control[] otherData) { - + return new TypeProperty( - name, + name, description, - String.class, + String.class, new String[] { "java.lang" }, 0.0f ); } - + public static Class typeFor(String typeName) { - + Class newType = ClassUtil.getTypeFor(typeName); // try for well-known types first if (newType != null) return newType; @@ -48,20 +48,20 @@ public class TypeEditorFactory extends AbstractEditorFactory { return null; } } - - protected Object valueFrom(Control valueControl) { + + protected Object valueFrom(Control valueControl) { return ((TypeText)valueControl).getType(false); } - + protected void fillWidget(TypeText textWidget, PropertyDescriptor desc, Rule rule) { - + Class type = (Class)valueFor(rule, desc); textWidget.setType(type); } - + private static TypeProperty typePropertyFrom(PropertyDescriptor desc) { - - if (desc instanceof PropertyDescriptorWrapper) { + + if (desc instanceof PropertyDescriptorWrapper) { return (TypeProperty) ((PropertyDescriptorWrapper)desc).getPropertyDescriptor(); } else { return (TypeProperty)desc; @@ -69,32 +69,32 @@ public class TypeEditorFactory extends AbstractEditorFactory { } public Control newEditorOn(Composite parent, final PropertyDescriptor desc, final Rule rule, final ValueChangeListener listener, SizeChangeListener sizeListener) { - + final TypeText typeText = new TypeText(parent, SWT.SINGLE | SWT.BORDER, true, "Enter a type name"); // TODO i18l typeText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fillWidget(typeText, desc, rule); - + final TypeProperty tp = typePropertyFrom(desc); - + Listener wereDoneListener = new Listener() { public void handleEvent(Event event) { Class newValue = typeText.getType(true); if (newValue == null) return; - - Class existingValue = (Class)valueFor(rule, tp); - if (existingValue == newValue) return; - + + Class existingValue = (Class)valueFor(rule, tp); + if (existingValue == newValue) return; + rule.setProperty(tp, newValue); listener.changed(rule, desc, newValue); adjustRendering(rule, desc, typeText); } }; - + typeText.addListener(SWT.FocusOut, wereDoneListener); typeText.addListener(SWT.DefaultSelection, wereDoneListener); return typeText; } - + } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/TypeText.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/TypeText.java index aa3f432983..b85ffdaff3 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/TypeText.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/editors/TypeText.java @@ -19,9 +19,9 @@ import org.eclipse.swt.widgets.Text; * when the widget loses focus, if the text represents a recognized class then it is * re-rendered with its full package name. If it isn't recognized or is a disallowed * primitive then the entry is cleared. - * + * * TODO - add a grey prompt within the field when it is empty, remove when user starts typing - * + * * @author Brian Remedios */ public class TypeText extends Composite { @@ -29,103 +29,103 @@ public class TypeText extends Composite { private Text text; private boolean acceptPrimitives; private String promptText; - + public TypeText(Composite parent, int style, boolean primitivesOK, String thePromptText) { super(parent, SWT.None); - + promptText = thePromptText; - + GridLayout layout = new GridLayout(1, false); layout.verticalSpacing = 0; layout.horizontalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; setLayout(layout); - + text = new Text(this, style); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - + text.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { + public void modifyText(ModifyEvent e) { // adjust to remove prompt text if necessary //TODO - } + } }); - + acceptPrimitives = primitivesOK; } - + private boolean hasRealText() { String textValue = text.getText(); if (StringUtil.isEmpty(textValue)) return false; if (text.equals(promptText)) return false; - + return true; } - + private void adjustFieldContents() { - + // text.setForeground( // hasRealText() ? Color. // ); } - + public void addListener(int eventType, Listener listener) { text.addListener(eventType, listener); } - + public void removeListener(int eventType, Listener listener) { text.removeListener(eventType, listener); } - + public Point computeSize(int wHint, int hHint, boolean changed) { return text.computeSize(wHint, hHint, changed); } - + public void setType(Class cls) { - + if (cls == null) { text.setText(""); return; } - + if (cls.isPrimitive() && !acceptPrimitives) { setType(null); return; } - + text.setText(cls.getName()); } - + public void setBackground(Color clr) { text.setBackground(clr); } - + public void setEnabled(boolean flag) { super.setEnabled(flag); text.setEnabled(flag); } - + public void setEditable(boolean flag) { text.setEditable(flag); } - + public Class getType(boolean doCleanup) { - + String typeStr = text.getText().trim(); if (StringUtil.isEmpty(typeStr)) { if (doCleanup) setType(null); return null; } - + Class cls = ClassUtil.getTypeFor(typeStr); if (cls != null && cls.isPrimitive() && !acceptPrimitives) { cls = null; } - + if (cls != null) { if (doCleanup) setType(cls); return cls; } - + try { return Class.forName(typeStr); } catch (Exception ex) { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/AbstractRulePanelManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/AbstractRulePanelManager.java index 3c0a021a70..17c6339994 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/AbstractRulePanelManager.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/AbstractRulePanelManager.java @@ -1,20 +1,29 @@ package net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers; +import java.util.Collections; +import java.util.List; + import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.eclipse.ui.PMDUiConstants; import net.sourceforge.pmd.eclipse.ui.preferences.br.RuleSelection; import net.sourceforge.pmd.eclipse.ui.preferences.br.ValueChangeListener; +import net.sourceforge.pmd.eclipse.ui.preferences.editors.TypeText; import net.sourceforge.pmd.eclipse.util.ColourManager; import net.sourceforge.pmd.eclipse.util.ResourceManager; import net.sourceforge.pmd.lang.rule.properties.StringProperty; -import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; +import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Listener; @@ -22,200 +31,308 @@ import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Text; /** - * + * Concrete subclasses can also be used as tab folders outside of a wizard dialog via the setupOn(Composite) method. + * * @author Brian Remedios */ -public abstract class AbstractRulePanelManager implements RulePropertyManager { +public abstract class AbstractRulePanelManager extends WizardPage implements RulePropertyManager { private TabItem tab; private String tabText; private boolean isActive; protected RuleSelection rules; protected final ValueChangeListener changeListener; + protected final EditorUsageMode usageMode; protected static Color textColour; protected static Color errorColour; protected static Color disabledColour; protected static Color overridenColour; - + private static final String disabledTabText = "-------"; - - public static final int[] overridenColourValues = new int[] {196, 196, 255}; // light blue - - public AbstractRulePanelManager(ValueChangeListener theListener) { + + public static final RGB overridenColourValues = new RGB(236, 236, 255); // light blue + + public AbstractRulePanelManager(String theId, String theTitle, EditorUsageMode theMode, ValueChangeListener theListener) { + super(theId, theTitle, null); + changeListener = theListener; + usageMode = theMode; } - public void tab(TabItem theTab) { - tab = theTab; + public abstract Control setupOn(Composite panel); + + public EditorUsageMode mode() { return usageMode; } + + /** + * For use by wizards only.. + */ + public void createControl(Composite panel) { + + Control childPanel = setupOn(panel); + + setControl(childPanel); + + setPageComplete(true); + } + + public void tab(TabItem theTab) { + tab = theTab; tabText = theTab.getText(); } - + public boolean isActive() { return isActive; } - + + protected String asCleanString(String original) { + if (original == null) return ""; + return original.trim(); + } + public void manage(RuleSelection theRules) { - + rules = theRules; - - isActive = + + isActive = (rules.hasOneRule() && canWorkWith(rules.soleRule())) || (rules.hasMultipleRules() && canManageMultipleRules()); - - setVisible(isActive); - tab.setText(isActive ? tabText : disabledTabText); - + + showControls(isActive); + if (tab != null) tab.setText(isActive ? tabText : disabledTabText); + if (isActive) { adapt(); } else { clearControls(); } - - updateTabUI(); - } - - protected void valueChanged(PropertyDescriptor optionalDesc, Object newValue) { - changeListener.changed(rules, optionalDesc, newValue); + updateUI(); } - + + protected void valueChanged(PropertyDescriptor optionalDesc, Object newValue) { + changeListener.changed(rules, optionalDesc, newValue); + updateUI(); + } + protected void updateUI() { - updateTabUI(); + List warnings = fieldWarnings(); + List errors = fieldErrors(); + if (tab != null) updateTabUI(warnings, errors); updateOverridenFields(); } - + protected void updateOverridenFields() { - + } - + protected boolean canWorkWith(Rule rule) { return true; } // override as necessary - - protected String[] fieldErrors() { // override as necessary - return StringUtil.EMPTY_STRINGS; + + protected List fieldErrors() { // override as necessary + return Collections.emptyList(); } - - protected String[] fieldWarnings() { // override as necessary - return StringUtil.EMPTY_STRINGS; + + protected List fieldWarnings() { // override as necessary + return Collections.emptyList(); } - - public void validate() { - updateTabUI(); - } - - protected void updateTabUI() { + + public boolean validate() { + + List warnings = fieldWarnings(); + List errors = fieldErrors(); + + if (tab != null) { + updateTabUI(warnings, errors); + } + String errorText = errors.isEmpty() ? null : StringUtil.asString(errors.toArray(), ", "); + + setErrorMessage(errorText); + + setPageComplete(StringUtil.isEmpty(errorText)); + + return errorText == null; + } + + protected void updateTabUI(List warnings, List errors) { + if (!isActive) { tab.setToolTipText(""); tab.setImage(null); return; } - - boolean hasIssues = updateTab(fieldErrors(), PMDUiConstants.ICON_ERROR); + + boolean hasIssues = updateTab(errors, PMDUiConstants.ICON_ERROR); if (hasIssues) return; - + updateTab(fieldWarnings(), PMDUiConstants.ICON_WARN); } - - private boolean updateTab(String[] issues, String iconName) { - - boolean hasIssues = !CollectionUtil.isEmpty(issues); - + + private boolean updateTab(List issues, String iconName) { + + boolean hasIssues = !issues.isEmpty(); + tab.setImage( hasIssues ? ResourceManager.imageFor(iconName) : null ); - + tab.setToolTipText(hasIssues ? issues.toString() : ""); - + return hasIssues; } - + protected abstract boolean canManageMultipleRules(); - + protected abstract void adapt(); - + protected abstract void clearControls(); - - protected abstract void setVisible(boolean flag); - + + public abstract void showControls(boolean flag); + protected Rule soleRule() { return rules.soleRule(); } - + protected void addTextListeners(final Text control, final StringProperty desc) { - + control.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { changed(desc, control.getText()); } }); } - + protected void initializeOn(Composite parent) { - + if (errorColour != null) return; - + ColourManager clrMgr = ColourManager.managerFor(parent.getDisplay()); - errorColour = clrMgr.colourFor(new int[] { 255, 0, 0 }); // red - textColour = clrMgr.colourFor(new int[] { 0, 0, 0 }); // black - disabledColour = clrMgr.colourFor(new int[] {128, 128, 128}); // grey + errorColour = clrMgr.colourFor(new RGB( 255, 0, 0 )); // red + textColour = clrMgr.colourFor(new RGB( 0, 0, 0 )); // black + disabledColour = clrMgr.colourFor(new RGB( 128, 128, 128)); // grey overridenColour = clrMgr.colourFor(overridenColourValues); } - + +// protected void valueChanged() { +// changeListener.changed(rules, null, ""); +// } + /** * @param property StringProperty * @param newValue String */ protected void changed(StringProperty property, String newValue) { - + if (rules == null) return; - + String cleanValue = newValue.trim(); String existingValue = rules.commonStringValue(property); - + if (StringUtil.areSemanticEquals(existingValue, cleanValue)) return; - + rules.setValue(property, cleanValue); valueChanged(property, newValue); } - + protected void shutdown(Text control) { control.setText(""); control.setEnabled(false); } - + protected void shutdown(StyledText control) { control.setText(""); control.setEnabled(false); } - + protected void shutdown(Link control) { control.setText(""); control.setEnabled(false); } - + + protected void show(TypeText control, Class type) { + control.setType(type); +// control.setEnabled(usageMode == EditorUsageMode.CreateNew); + } + + protected void show(Button checkbox, boolean checked) { + checkbox.setSelection(checked); +// checkbox.setEnabled(usageMode == EditorUsageMode.CreateNew); + } + protected void show(Text control, String value) { control.setText(value == null ? "" : value); - control.setEnabled(true); +// control.setEnabled(usageMode == EditorUsageMode.CreateNew); } - + protected void show(StyledText control, String value) { control.setText(value == null ? "" : value); - control.setEnabled(true); +// control.setEnabled(usageMode == EditorUsageMode.CreateNew); + } + + protected void show(Combo control, String value) { + +// control.setEnabled(usageMode == EditorUsageMode.CreateNew); + + if (StringUtil.isEmpty(value)) { + control.deselectAll(); + return; + } + + String[] choices = control.getItems(); + + int index = -1; + for (int i=0; i, Object> filteredPropertiesOf(Rule rule) { Map, Object> valuesByProp = rule.getPropertiesByPropertyDescriptor(); - for (PropertyDescriptor excludedRulePropertie : excludedRuleProperties) { - valuesByProp.remove(excludedRulePropertie); + for (PropertyDescriptor excludedRuleProperty : excludedRuleProperties) { + valuesByProp.remove(excludedRuleProperty); } return valuesByProp; diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/CreateRuleWizard.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/CreateRuleWizard.java new file mode 100755 index 0000000000..7527a97567 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/CreateRuleWizard.java @@ -0,0 +1,102 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers; + +import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.eclipse.ui.preferences.br.RuleSelection; +import net.sourceforge.pmd.eclipse.ui.preferences.br.ValueChangeListener; +import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.util.StringUtil; + +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; + +/** + * A wizard that encapsulates a succession of rule panel managers to collect the + * required info for a new rule. + * + * @author Brian Remedios + */ +public class CreateRuleWizard extends Wizard implements ValueChangeListener, RuleTarget { + + private Rule rule; + + public CreateRuleWizard() { + super(); + } + + public Rule rule() { + return rule; + } + + public void rule(Rule theRule) { + rule = theRule; + } + + public void addPages() { + addPage(new RulePanelManager("rule", EditorUsageMode.CreateNew, this, this)); + addPage(new DescriptionPanelManager("description", EditorUsageMode.CreateNew, this)); + addPage(new PerRulePropertyPanelManager("properties", EditorUsageMode.CreateNew, this)); + addPage(new XPathPanelManager("xpath", EditorUsageMode.CreateNew, this)); + addPage(new ExclusionPanelManager("exclusion", EditorUsageMode.CreateNew, this, false)); + addPage(new QuickFixPanelManager("fixes", EditorUsageMode.CreateNew, this)); + addPage(new ExamplePanelManager("examples", EditorUsageMode.CreateNew, this)); + } + + public boolean performFinish() { + return true; + } + + private boolean isXPathRule() { + return rule instanceof XPathRule; + } + + public boolean performCancel() { + System.out.println("Perform Cancel called"); + return true; + } + + private IWizardPage getAndPrepare(String pageId) { + + AbstractRulePanelManager rulePanel = (AbstractRulePanelManager)getPage(pageId); + RuleSelection rs = new RuleSelection(rule); + rulePanel.manage(rs); + return rulePanel; + } + + public IWizardPage getNextPage(IWizardPage currentPage) { + + if (rule == null) { + return null; + } + + if (currentPage instanceof RulePanelManager) { + return getAndPrepare(DescriptionPanelManager.ID); + } + if (currentPage instanceof DescriptionPanelManager) { + if (StringUtil.isEmpty( rule.getDescription() )) return null; + return getAndPrepare(PerRulePropertyPanelManager.ID); + } + if (currentPage instanceof PerRulePropertyPanelManager) { + return isXPathRule() ? + getAndPrepare(XPathPanelManager.ID) : + getAndPrepare(ExclusionPanelManager.ID); + } + if (currentPage instanceof ExclusionPanelManager || currentPage instanceof XPathPanelManager) { + return getAndPrepare(QuickFixPanelManager.ID); + } + if (currentPage instanceof QuickFixPanelManager) { + return getAndPrepare(ExamplePanelManager.ID); + } + return null; + } + + public void changed(RuleSelection rule, PropertyDescriptor desc, Object newValue) { + // TODO Auto-generated method stub + + } + + public void changed(Rule rule, PropertyDescriptor desc, Object newValue) { + // TODO Auto-generated method stub + + } +} \ No newline at end of file diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/DescriptionPanelManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/DescriptionPanelManager.java index e07d226068..2fcdf685e6 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/DescriptionPanelManager.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/DescriptionPanelManager.java @@ -2,6 +2,8 @@ package net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.List; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; @@ -29,31 +31,35 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.browser.IWebBrowser; /** - * + * * @author Brian Remedios */ public class DescriptionPanelManager extends AbstractRulePanelManager { private Text descriptionBox; - private Text externalURLField; + private Text externalURLField; private Label extURLLabel; private Button browseButton; private Label messageLabel; private Text messageField; - - public DescriptionPanelManager(ValueChangeListener theListener) { - super(theListener); + + private static final int MIN_MESSAGE_LENGTH = 10; //chars + + public static final String ID = "description"; + + public DescriptionPanelManager(String theTitle, EditorUsageMode theMode, ValueChangeListener theListener) { + super(ID, theTitle, theMode, theListener); } protected boolean canManageMultipleRules() { return false; } - + protected void clearControls() { descriptionBox.setText(""); externalURLField.setText(""); } - - protected void setVisible(boolean flag) { - + + public void showControls(boolean flag) { + descriptionBox.setVisible(flag); externalURLField.setVisible(flag); browseButton.setVisible(flag); @@ -61,11 +67,11 @@ public class DescriptionPanelManager extends AbstractRulePanelManager { messageLabel.setVisible(flag); messageField.setVisible(flag); } - + protected void updateOverridenFields() { - + Rule rule = soleRule(); - + if (rule instanceof RuleReference) { RuleReference ruleReference = (RuleReference)rule; messageField.setBackground(ruleReference.getOverriddenMessage() != null ? overridenColour: null); @@ -73,126 +79,137 @@ public class DescriptionPanelManager extends AbstractRulePanelManager { externalURLField.setBackground(ruleReference.getOverriddenExternalInfoUrl() != null ? overridenColour: null); } } - + public Control setupOn(Composite parent) { - + initializeOn(parent); - + GridData gridData = new GridData(GridData.FILL_HORIZONTAL); - + Composite panel = new Composite(parent, 0); GridLayout layout = new GridLayout(3, false); panel.setLayout(layout); - - descriptionBox = newTextField(panel); + + descriptionBox = newTextField(panel); gridData = new GridData(GridData.FILL_BOTH); gridData.grabExcessHorizontalSpace = true; gridData.horizontalSpan = 3; - descriptionBox.setLayoutData(gridData); - - descriptionBox.addListener(SWT.FocusOut, new Listener() { - public void handleEvent(Event event) { - + descriptionBox.setLayoutData(gridData); + + descriptionBox.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent event) { + Rule soleRule = soleRule(); - - String cleanValue = descriptionBox.getText().trim(); + if (soleRule == null) return; + + String cleanValue = asCleanString(descriptionBox.getText()); String existingValue = soleRule.getDescription(); - + if (StringUtil.areSemanticEquals(existingValue, cleanValue)) return; - + soleRule.setDescription(cleanValue); - valueChanged(null, cleanValue); + valueChanged(null, cleanValue); + validateRuleParams(); // TODO hang off of valueChanged instead? } - }); - - buildExternalUrlPanel(panel, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULEEDIT_LABEL_EXTERNAL_INFO_URL)); + }); + + buildExternalUrlPanel(panel, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULEEDIT_LABEL_EXTERNAL_INFO_URL)); buildMessagePanel(panel, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULEEDIT_LABEL_MESSAGE)); - - return panel; + + return panel; } - + + private void validateRuleParams() { + + validate(); + + boolean urlOK = StringUtil.isEmpty(externalURLField.getText()) || hasValidURL(); + adjustBrowseButton(urlOK); + } + private void buildExternalUrlPanel(Composite parent, String urlLabel) { - + GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - + extURLLabel = new Label(parent, 0); extURLLabel.setText(urlLabel); gridData.horizontalSpan = 1; gridData.grabExcessHorizontalSpace = false; - extURLLabel.setLayoutData(gridData); - + extURLLabel.setLayoutData(gridData); + externalURLField = new Text(parent, SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 1; gridData.grabExcessHorizontalSpace = true; externalURLField.setLayoutData(gridData); - + browseButton = buildExternalInfoUrlButton(parent); gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); gridData.horizontalSpan = 1; browseButton.setLayoutData(gridData); - + externalURLField.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event e) { handleExternalURLChange(); } - }); + }); externalURLField.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - adjustBrowseButton(); - } + public void modifyText(ModifyEvent e) { + validateRuleParams(); + } }); } - + private void buildMessagePanel(Composite parent, String messageLbl) { - + GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - + messageLabel = new Label(parent, 0); messageLabel.setText(messageLbl); gridData.horizontalSpan = 1; gridData.grabExcessHorizontalSpace = false; - messageLabel.setLayoutData(gridData); - + messageLabel.setLayoutData(gridData); + messageField = new Text(parent, SWT.BORDER); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 2; gridData.grabExcessHorizontalSpace = true; messageField.setLayoutData(gridData); - - messageField.addListener(SWT.FocusOut, new Listener() { - public void handleEvent(Event e) { + + messageField.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { handleMessageChange(); + validateRuleParams(); } }); } - + private void handleExternalURLChange() { - - String newURL = externalURLField.getText().trim(); + + String newURL = asCleanString(externalURLField.getText()); Rule rule = soleRule(); - - if (!StringUtil.areSemanticEquals(rule.getExternalInfoUrl().trim(), newURL)) { + + if (!StringUtil.areSemanticEquals(asCleanString(rule.getExternalInfoUrl()), newURL)) { rule.setExternalInfoUrl(newURL); valueChanged(null, newURL); } - - adjustBrowseButton(); + + adjustBrowseButton( hasValidURL() ); } - + private void handleMessageChange() { - - String newMessage = messageField.getText().trim(); + + String newMessage = asCleanString(messageField.getText()); Rule rule = soleRule(); - - if (!StringUtil.areSemanticEquals(rule.getMessage().trim(), newMessage)) { + + if (!StringUtil.areSemanticEquals(asCleanString(rule.getMessage()), newMessage)) { rule.setMessage(newMessage); updateUI(); } } - + private Button buildExternalInfoUrlButton(Composite parent) { - + final Button button = new Button(parent, SWT.PUSH); button.setText(SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULEEDIT_BUTTON_OPEN_EXTERNAL_INFO_URL)); @@ -215,57 +232,76 @@ public class DescriptionPanelManager extends AbstractRulePanelManager { return button; } - + protected void adapt() { - + Rule soleRule = soleRule(); - + if (soleRule == null) { shutdown(descriptionBox); shutdown(externalURLField); shutdown(messageField); } else { - show(descriptionBox, soleRule.getDescription().trim()); - show(externalURLField, soleRule.getExternalInfoUrl().trim()); - show(messageField, soleRule.getMessage().trim()); + show(descriptionBox, asCleanString(soleRule.getDescription())); + show(externalURLField, asCleanString(soleRule.getExternalInfoUrl())); + show(messageField, asCleanString(soleRule.getMessage())); } - - adjustBrowseButton(); + + boolean isValid = hasValidURL(); + adjustBrowseButton(isValid); } public static boolean isValidURL(String url) { - + if (StringUtil.isEmpty(url)) return false; - - String urlUC = url.toUpperCase(); + + String urlUC = url.toUpperCase(); if (!urlUC.startsWith("HTTP")) return false; - + for (int i=0; i MIN_MESSAGE_LENGTH); + } + + private boolean hasValidDescription() { + String description = descriptionBox.getText().trim(); + return (!StringUtil.isEmpty(description) && description.length() > MIN_MESSAGE_LENGTH); + } + + private void adjustBrowseButton(boolean hasValidURL) { + + browseButton.setEnabled(hasValidURL); externalURLField.setForeground( - isValid ? textColour : errorColour + hasValidURL ? textColour : errorColour ); } - protected String[] fieldErrors() { - - return hasValidURL() ? - StringUtil.EMPTY_STRINGS : - new String[] { "Invalid external URL" }; + protected List fieldErrors() { + + List errors = new ArrayList(3); + + if (StringUtil.isEmpty(descriptionBox.getText().trim())) { + errors.add("Missing description"); + } + if (StringUtil.isEmpty(messageField.getText().trim())) { + errors.add("Missing message"); + } + + if (!hasValidURL()) errors.add("Invalid external URL"); + + return errors; } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/EditorUsageMode.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/EditorUsageMode.java new file mode 100755 index 0000000000..b1f574286b --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/EditorUsageMode.java @@ -0,0 +1,7 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers; + +public enum EditorUsageMode { + + CreateNew, + Editing +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/ExamplePanelManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/ExamplePanelManager.java index 9fb18a90fe..6f24e8971f 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/ExamplePanelManager.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/ExamplePanelManager.java @@ -19,79 +19,81 @@ import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; /** - * + * * @author Brian Remedios */ public class ExamplePanelManager extends AbstractRulePanelManager { private Text exampleField; - - public ExamplePanelManager(ValueChangeListener theListener) { - super(theListener); + + public static final String ID = "example"; + + public ExamplePanelManager(String theTitle, EditorUsageMode theMode, ValueChangeListener theListener) { + super(ID, theTitle, theMode, theListener); } protected boolean canManageMultipleRules() { return false; } - + protected void clearControls() { exampleField.setText(""); } - - protected void setVisible(boolean flag) { - + + public void showControls(boolean flag) { + exampleField.setVisible(flag); } - + protected void updateOverridenFields() { - + Rule rule = soleRule(); - + if (rule instanceof RuleReference) { RuleReference ruleReference = (RuleReference)rule; exampleField.setBackground(ruleReference.getOverriddenExamples() != null ? overridenColour: null); } } - + public Control setupOn(Composite parent) { - + GridData gridData = new GridData(GridData.FILL_HORIZONTAL); - + Composite panel = new Composite(parent, 0); GridLayout layout = new GridLayout(2, false); panel.setLayout(layout); - - exampleField = newTextField(panel); + + exampleField = newTextField(panel); gridData = new GridData(GridData.FILL_BOTH); gridData.grabExcessHorizontalSpace = true; gridData.horizontalSpan = 1; - exampleField.setLayoutData(gridData); - + exampleField.setLayoutData(gridData); + exampleField.addListener(SWT.FocusOut, new Listener() { public void handleEvent(Event event) { - + Rule soleRule = soleRule(); - + String cleanValue = exampleField.getText().trim(); String existingValue = soleRule.getDescription(); - + if (StringUtil.areSemanticEquals(existingValue, cleanValue)) return; - + soleRule.setDescription(cleanValue); - valueChanged(null, cleanValue); + valueChanged(null, cleanValue); } - }); - - return panel; + }); + + return panel; } - + private void formatExampleOn(StringBuilder sb, String example) { // TODO - adjust for common leading whitespace on all lines - see StringUtil facilities // sb.append(example.trim()); - + String[] lines = example.split("\n"); List realLines = new ArrayList(lines.length); for (String line : lines) if (!StringUtil.isEmpty(line)) realLines.add(line); lines = realLines.toArray(new String[realLines.size()]); - + int trimDepth = StringUtil.maxCommonLeadingWhitespaceForAll(lines); if (trimDepth > 0) { lines = StringUtil.trimStartOn(lines, trimDepth); @@ -100,27 +102,27 @@ public class ExamplePanelManager extends AbstractRulePanelManager { sb.append(line).append(PMD.EOL); } } - + private String examples(Rule rule) { - + List examples = rule.getExamples(); if (examples.isEmpty()) return ""; - + StringBuilder sb = new StringBuilder(); formatExampleOn(sb, examples.get(0)); - + for (int i=1; i fieldErrors() { + return Collections.emptyList(); } - + private void addListeners(final Text control, final StringProperty desc, final Control colourWindow) { - + addTextListeners(control, desc); - + control.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { String newText = control.getText(); - colourWindow.setBackground( - colourManager.colourFor(newText) - ); - + if (colourWindow != null) { + colourWindow.setBackground( + colourManager.colourFor(newText) + ); + } changed(desc, newText); - } + } }); } - + private Composite newColourPanel(Composite parent, String label) { - + Composite panel = new Composite(parent, SWT.None); - + GridLayout layout = new GridLayout(2, false); layout.verticalSpacing = 0; layout.horizontalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; panel.setLayout(layout); - + Label labelWidget = new Label(panel, SWT.None); labelWidget.setText(label); - + Composite clrPanel = new Composite(panel, SWT.BORDER); GridData gridData = new GridData(); gridData.horizontalSpan = 1; @@ -88,45 +98,51 @@ public class ExclusionPanelManager extends AbstractRulePanelManager { gridData.widthHint = 15; gridData.grabExcessHorizontalSpace = false; clrPanel.setLayoutData(gridData); - + return clrPanel; } - + /** * @param parent Composite * @param regexExclusionLabel String * @param xpathExclusionLabel String * @return Control */ - public Control setupOn(Composite parent, String regexExclusionLabel, String xpathExclusionLabel, String colourBoxLabel) { - + public Control setupOn(Composite parent) { + + String regexExclusionLabel = SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_EXCLUSION_REGEX); + String xpathExclusionLabel = SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_XPATH_EXCLUSION); + String colourBoxLabel = SWTUtil.stringFor(StringKeys.MSGKEY_LABEL_COLOUR_CODE); + colourManager = ColourManager.managerFor(parent.getDisplay()); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); - + Composite panel = new Composite(parent, 0); GridLayout layout = new GridLayout(2, false); panel.setLayout(layout); - + Label labelA = new Label(panel, 0); labelA.setText(regexExclusionLabel); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.horizontalSpan = 1; gridData.grabExcessHorizontalSpace = true; labelA.setLayoutData(gridData); - - // labelAIcon.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_FILTER)); - - excludeColour = newColourPanel(panel, colourBoxLabel); - + + // labelAIcon.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_FILTER)); + + if (showColourBoxes) { + excludeColour = newColourPanel(panel, colourBoxLabel); + } + excludeWidget = newTextField(panel); gridData = new GridData(GridData.FILL_BOTH); gridData.grabExcessHorizontalSpace = true; gridData.horizontalSpan = 2; excludeWidget.setLayoutData(gridData); - + addListeners(excludeWidget, Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR, excludeColour); - + Label labelB = new Label(panel, 0); labelB.setText(xpathExclusionLabel); gridData = new GridData(GridData.FILL_HORIZONTAL); @@ -134,30 +150,32 @@ public class ExclusionPanelManager extends AbstractRulePanelManager { labelB.setLayoutData(gridData); // labelAIcon.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_FILTER_X)); - - xPathColour = newColourPanel(panel, colourBoxLabel); - + + if (showColourBoxes) { + xPathColour = newColourPanel(panel, colourBoxLabel); + } + gridData = new GridData(GridData.FILL_BOTH); gridData.horizontalSpan = 2; gridData.grabExcessHorizontalSpace = true; xpathWidget = newTextField(panel); xpathWidget.setLayoutData(gridData); - + addListeners(xpathWidget, Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR, xPathColour); - + panel.pack(); - + return panel; } - + protected void adapt() { - + if (rules == null) { shutdown(excludeWidget); shutdown(xpathWidget); return; } - + show(excludeWidget, rules.commonStringValue(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR)); show(xpathWidget, rules.commonStringValue(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR)); } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/FormArranger.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/FormArranger.java index fa1cc55da6..d404cee62b 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/FormArranger.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/FormArranger.java @@ -8,7 +8,6 @@ import java.util.Map; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.eclipse.ui.PMDUiConstants; -import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; import net.sourceforge.pmd.eclipse.ui.preferences.br.EditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.br.NewPropertyDialog; import net.sourceforge.pmd.eclipse.ui.preferences.br.SizeChangeListener; @@ -17,7 +16,7 @@ import net.sourceforge.pmd.eclipse.util.ResourceManager; import net.sourceforge.pmd.eclipse.util.Util; import net.sourceforge.pmd.lang.rule.XPathRule; -import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; @@ -30,7 +29,7 @@ import org.eclipse.swt.widgets.Control; * Takes in a rule instance, extracts its properties, creates a series of type-specific editors for each, and then populates them with * the current values. As some types can hold multiple values the vertical span can grow to accommodate additional widgets and does so * by broadcasting this through the SizeChange listener. The ValueChange listener can be used to update any outside UIs as necessary. - * + * * @author Brian Remedios */ public class FormArranger { @@ -41,7 +40,7 @@ public class FormArranger { private final SizeChangeListener sizeChangeListener; private Rule rule; private Control[][] widgets; - + /** * Constructor for FormArranger. * @param theParent Composite @@ -55,7 +54,6 @@ public class FormArranger { } /** - * Method factoryFor. * @param desc PropertyDescriptor * @return EditorFactory */ @@ -65,14 +63,13 @@ public class FormArranger { public void clearChildren() { Control[] kids = parent.getChildren(); - for (Control kid : kids) + for (Control kid : kids) kid.dispose(); parent.pack(); rule = null; } /** - * Method arrangeFor. * @param theRule Rule */ public int arrangeFor(Rule theRule) { @@ -80,28 +77,28 @@ public class FormArranger { if (rule == theRule) return -1; return rearrangeFor(theRule); } - - private int rearrangeFor(Rule theRule) { - + + private int rearrangeFor(Rule theRule) { + clearChildren(); - + rule = theRule; - + if (rule == null) return -1; - + Map, Object> valuesByDescriptor = Configuration.filteredPropertiesOf(rule); - + if (valuesByDescriptor.isEmpty()) { if (rule.hasDescriptor(XPathRule.XPATH_DESCRIPTOR)) { - addAddButton(); + addAddButton(); parent.pack(); return 1; } return 0; } - - PropertyDescriptor[] orderedDescs = (PropertyDescriptor[])valuesByDescriptor.keySet().toArray(new PropertyDescriptor[valuesByDescriptor.size()]); - + + PropertyDescriptor[] orderedDescs = valuesByDescriptor.keySet().toArray(new PropertyDescriptor[valuesByDescriptor.size()]); + int rowCount = 0; // count up the actual rows with widgets needed, not all have editors yet for (PropertyDescriptor desc: orderedDescs) { EditorFactory factory = factoryFor(desc); @@ -114,45 +111,45 @@ public class FormArranger { boolean isXPathRule = rule.hasDescriptor(XPathRule.XPATH_DESCRIPTOR); int columnCount = isXPathRule ? 3 : 2; // xpath descriptors have a column of delete buttons - + GridLayout layout = new GridLayout(columnCount, false); layout.verticalSpacing = 2; layout.marginTop = 1; parent.setLayout(layout); - + widgets = new Control[rowCount][columnCount]; - + int rowsAdded = 0; - + for (PropertyDescriptor desc: orderedDescs) { if (addRowWidgets(factoryFor(desc), rowsAdded, desc, isXPathRule)) rowsAdded++; } - + if (rule.hasDescriptor(XPathRule.XPATH_DESCRIPTOR)) { addAddButton(); rowsAdded++; } - + if (rowsAdded > 0) { parent.pack(); } - + return rowsAdded; } private void addAddButton() { - - Button button = new Button(parent, SWT.BORDER); + + Button button = new Button(parent, SWT.PUSH); button.setText("Add new..."); button.addSelectionListener( new SelectionListener(){ public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { NewPropertyDialog dialog = new NewPropertyDialog(parent.getShell(), editorFactoriesByValueType, rule, changeListener); - if (dialog.open() == Dialog.OK) { + if (dialog.open() == Window.OK) { PropertyDescriptor desc = dialog.descriptor(); rule.definePropertyDescriptor(desc); rearrangeFor(rule); - }; + } } }); } @@ -166,67 +163,67 @@ public class FormArranger { private boolean addRowWidgets(EditorFactory factory, int rowIndex, PropertyDescriptor desc, boolean isXPathRule) { if (factory == null) return false; - + // add all the labels & controls necessary on each row widgets[rowIndex][0] = factory.addLabel(parent, desc); - widgets[rowIndex][1] = factory.newEditorOn(parent, desc, rule, changeListener, sizeChangeListener); - + widgets[rowIndex][1] = factory.newEditorOn(parent, desc, rule, changeListener, sizeChangeListener); + if (isXPathRule) { widgets[rowIndex][2] = addDeleteButton(parent, desc, rule, sizeChangeListener); } - + return true; } private Control addDeleteButton(Composite parent, final PropertyDescriptor desc, final Rule rule, final SizeChangeListener sizeChangeListener) { - - Button button = new Button(parent, SWT.BORDER); + + Button button = new Button(parent, SWT.PUSH); button.setData(desc.name()); // for later reference button.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_DELETE)); - + button.addSelectionListener( new SelectionListener(){ public void widgetDefaultSelected(SelectionEvent e) { } - public void widgetSelected(SelectionEvent e) { + public void widgetSelected(SelectionEvent e) { // rule.undefine(desc); rearrangeFor(rule); updateDeleteButtons(); // sizeChangeListener.addedRows(-1); not necessary apres rearrange? }}); - + return button; } - + /** - * Flag the delete buttons linked to property variables that are not referenced in the + * Flag the delete buttons linked to property variables that are not referenced in the * Xpath source or clear any images they may have. Returns the names of any unreferenced * variables are found; */ public List updateDeleteButtons() { - + if (rule == null || !rule.hasDescriptor(XPathRule.XPATH_DESCRIPTOR)) { return Collections.emptyList(); } - + String source = rule.getProperty(XPathRule.XPATH_DESCRIPTOR); List refPositions = Util.referencedNamePositionsIn(source, '$'); if (refPositions.isEmpty()) return Collections.emptyList(); - List unreferenced = new ArrayList(refPositions.size()); + List unreferenced = new ArrayList(refPositions.size()); List varNames = Util.fragmentsWithin(source, refPositions); - + for (Control[] widgetRow : widgets) { Button butt = (Button)widgetRow[2]; String buttonName = (String)butt.getData(); boolean isReferenced = varNames.contains(buttonName); butt.setToolTipText( - isReferenced ? - "Delete variable: $" + buttonName : + isReferenced ? + "Delete variable: $" + buttonName : "Delete unreferenced variable: $" + buttonName ); if (!isReferenced) unreferenced.add((String) butt.getData()); } - + return unreferenced; }; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/ListManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/ListManager.java index e6a4ca2ec1..2b92061828 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/ListManager.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/ListManager.java @@ -9,7 +9,7 @@ import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Listener; /** - * + * * @author Brian Remedios */ public class ListManager { @@ -18,14 +18,14 @@ public class ListManager { private final Button upButton; private final Button downButton; private final Button deleteButton; - + public ListManager(List theList, Button theUpButton, Button theDownButton, Button theDeleteButton) { - + list = theList; upButton = theUpButton; downButton = theDownButton; deleteButton = theDeleteButton; - + registerListeners(); updateButtonStates(); } @@ -36,38 +36,38 @@ public class ListManager { public void handleEvent(Event arg0) { updateButtonStates(); } - + }); upButton.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent arg0) { shiftUp(); } + public void widgetSelected(SelectionEvent arg0) { shiftUp(); } }); downButton.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent arg0) { shiftDown(); } + public void widgetSelected(SelectionEvent arg0) { shiftDown(); } }); deleteButton.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent arg0) { delete(); } + public void widgetSelected(SelectionEvent arg0) { delete(); } }); } - + private void shiftUp() { - // TODO + // TODO updateButtonStates(); } - + private void shiftDown() { // TODO updateButtonStates(); } - + private void delete() { int[] indices = list.getSelectionIndices(); list.remove(indices); - + updateButtonStates(); } - + private void updateButtonStates() { - + if (!hasSelection()) { upButton.setEnabled(false); downButton.setEnabled(false); @@ -79,14 +79,14 @@ public class ListManager { downButton.setEnabled(hasSelectionIndex(list.getItemCount()-1)); deleteButton.setEnabled(true); } - + private boolean hasSelection() { return list.getSelectionCount() > 0; } - + private boolean hasSelectionIndex(int index) { - + for (int i : list.getSelectionIndices()) { if (i == index) return false; } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/PerRulePropertyPanelManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/PerRulePropertyPanelManager.java index 759624aa0f..8ab9fea8db 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/PerRulePropertyPanelManager.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/PerRulePropertyPanelManager.java @@ -1,6 +1,7 @@ package net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -25,16 +26,14 @@ import net.sourceforge.pmd.eclipse.ui.preferences.editors.MultiTypeEditorFactory import net.sourceforge.pmd.eclipse.ui.preferences.editors.StringEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.TypeEditorFactory; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.util.StringUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.TabFolder; /** - * + * * @author Brian Remedios */ public class PerRulePropertyPanelManager extends AbstractRulePanelManager implements SizeChangeListener { @@ -44,13 +43,14 @@ public class PerRulePropertyPanelManager extends AbstractRulePanelManager implem private ScrolledComposite sComposite; private int widgetRowCount; private List unreferencedVariables; - + private static final int MaxWidgetHeight = 30; // TODO derive this instead - + public static final String ID = "perRuleProperties"; + public static final Map, EditorFactory> editorFactoriesByPropertyType; - + static { - Map, EditorFactory> factoriesByPropertyType = new HashMap, EditorFactory>(); + Map, EditorFactory> factoriesByPropertyType = new HashMap, EditorFactory>(); factoriesByPropertyType.put(Boolean.class, BooleanEditorFactory.instance); factoriesByPropertyType.put(String.class, StringEditorFactory.instance); @@ -59,7 +59,7 @@ public class PerRulePropertyPanelManager extends AbstractRulePanelManager implem factoriesByPropertyType.put(Double.class, DoubleEditorFactory.instance); factoriesByPropertyType.put(Object.class, EnumerationEditorFactory.instance); factoriesByPropertyType.put(Character.class, CharacterEditorFactory.instance); - + factoriesByPropertyType.put(Class.class, TypeEditorFactory.instance); factoriesByPropertyType.put(Class[].class, MultiTypeEditorFactory.instance); factoriesByPropertyType.put(Method.class, MethodEditorFactory.instance); @@ -67,71 +67,80 @@ public class PerRulePropertyPanelManager extends AbstractRulePanelManager implem factoriesByPropertyType.put(String[].class, MultiStringEditorFactory.instance); factoriesByPropertyType.put(Integer[].class, MultiIntegerEditorFactory.instance); factoriesByPropertyType.put(Object[].class, MultiEnumerationEditorFactory.instance); - + editorFactoriesByPropertyType = Collections.unmodifiableMap(factoriesByPropertyType); } - - public PerRulePropertyPanelManager(ValueChangeListener theListener) { - super(theListener); + + public PerRulePropertyPanelManager(String theTitle, EditorUsageMode theMode, ValueChangeListener theListener) { + super(ID, theTitle, theMode, theListener); } protected boolean canManageMultipleRules() { return false; } - + protected boolean canWorkWith(Rule rule) { if (rule.hasDescriptor(XPathRule.XPATH_DESCRIPTOR)) return true; return !Configuration.filteredPropertiesOf(rule).isEmpty(); } - + protected void clearControls() { formArranger.clearChildren(); } - - protected void setVisible(boolean flag) { + + public void showControls(boolean flag) { + clearControls(); } - - public Control setupOn(TabFolder parent, ValueChangeListener changeListener) { - - sComposite = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); - composite = new Composite(sComposite, SWT.NONE); + + public Control setupOn(Composite parent) { + + sComposite = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); + composite = new Composite(sComposite, SWT.NONE); sComposite.setContent(composite); sComposite.setExpandHorizontal(true); sComposite.setExpandVertical(true); - + formArranger = new FormArranger(composite, editorFactoriesByPropertyType, changeListener, this); - + return sComposite; } - + public void addedRows(int rowCountDelta) { widgetRowCount += rowCountDelta; adjustMinimumHeight(); } - + private void adjustMinimumHeight() { sComposite.setMinSize(composite.computeSize(500, widgetRowCount * MaxWidgetHeight)); } - + protected void adapt() { - + widgetRowCount = formArranger.arrangeFor(soleRule()); validate(); - + if (widgetRowCount < 0) return; - + adjustMinimumHeight(); } - - public void validate() { - super.validate(); - unreferencedVariables = formArranger.updateDeleteButtons(); - } - - protected String[] fieldWarnings() { + + public boolean validate() { + if (!super.validate()) return false; - return unreferencedVariables == null || unreferencedVariables.isEmpty()? - StringUtil.EMPTY_STRINGS : - (String[]) unreferencedVariables.toArray(new String[unreferencedVariables.size()]); + unreferencedVariables = formArranger.updateDeleteButtons(); // any unref'd vars are not real errors + + return true; + } + + protected List fieldWarnings() { + + if (unreferencedVariables == null || unreferencedVariables.isEmpty()) { + return Collections.emptyList(); + } + + List warnings = new ArrayList(2); + warnings.add("Unreferences variables: " + unreferencedVariables.toArray(new String[unreferencedVariables.size()])); + + return warnings; } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/QuickFixPanelManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/QuickFixPanelManager.java index 681fad33d7..f5019a07b7 100755 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/QuickFixPanelManager.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/QuickFixPanelManager.java @@ -22,31 +22,33 @@ public class QuickFixPanelManager extends AbstractRulePanelManager { private org.eclipse.swt.widgets.List fixerList; private ListManager listManager; - - public QuickFixPanelManager(ValueChangeListener theListener) { - super(theListener); + + public static final String ID = "fixes"; + + public QuickFixPanelManager(String theTitle, EditorUsageMode theMode, ValueChangeListener theListener) { + super(ID, theTitle, theMode, theListener); } - + protected List commonFixes() { // TODO finish this List theRules = rules.allRules(); List fixes = new ArrayList(); - + Fix[] fixSet = PMDResolutionGenerator.fixesFor(theRules.get(0)); if (fixSet != null) { for (Fix fix : fixSet) fixes.add(fix); } - + return fixes; } - + @Override protected void adapt() { - + fixerList.removeAll(); - + List fixes = commonFixes(); - + for (Fix fix : fixes) fixerList.add(fix.getLabel()); } @@ -57,14 +59,15 @@ public class QuickFixPanelManager extends AbstractRulePanelManager { fixerList.removeAll(); } - protected void setVisible(boolean flag) { + public void showControls(boolean flag) { + fixerList.setVisible(flag); } public static List shift(List items, int[] indices, int shiftAmt) { - + int[] indexArr = new int[items.size()]; - + int currentIdx = 0; for (int i=0; i out = new ArrayList(indexArr.length); - for (int i=0; i List shift(List items, int index, int shiftAmt) { - + int start = Math.min(index, index + shiftAmt); int end = Math.max(index, index + shiftAmt); - + Collections.rotate(items.subList(start, end), shiftAmt); - + return items; } - + public Control setupOn(Composite parent) { - + GridData gridData = new GridData(GridData.FILL_HORIZONTAL); - + Composite panel = new Composite(parent, 0); GridLayout layout = new GridLayout(2, false); panel.setLayout(layout); - - fixerList = new org.eclipse.swt.widgets.List(panel, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); + + fixerList = new org.eclipse.swt.widgets.List(panel, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL); gridData = new GridData(GridData.FILL_BOTH); gridData.grabExcessHorizontalSpace = true; gridData.horizontalSpan = 1; - fixerList.setLayoutData(gridData); + fixerList.setLayoutData(gridData); Composite buttonPanel = new Composite(panel, 0); layout = new GridLayout(1, false); @@ -112,37 +115,37 @@ public class QuickFixPanelManager extends AbstractRulePanelManager { gridData = new GridData(); gridData.horizontalSpan = 1; gridData.grabExcessHorizontalSpace = false; - buttonPanel.setLayoutData(gridData); - + buttonPanel.setLayoutData(gridData); + Button shiftUpButton = new Button(buttonPanel, SWT.PUSH); shiftUpButton.setToolTipText("Shift up"); shiftUpButton.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_UPARROW)); - + Button addButton = new Button(buttonPanel, SWT.PUSH); addButton.setToolTipText("Add"); addButton.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_ADD)); - + Button removeButton = new Button(buttonPanel, SWT.PUSH); removeButton.setToolTipText("Remove"); removeButton.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_DELETE)); - + Button shiftDownButton = new Button(buttonPanel, SWT.PUSH); shiftDownButton.setToolTipText("Shift down"); shiftDownButton.setImage(ResourceManager.imageFor(PMDUiConstants.ICON_BUTTON_DOWNARROW)); - + listManager = new ListManager(fixerList, shiftUpButton, shiftDownButton, removeButton); - - return panel; + + return panel; } - + public static void main(String[] args) { - + List numbers = new ArrayList(); Collections.addAll(numbers, 0,1,2,3,4,5,6,7,8,9,10); // int[] shiftSet = new int[] { 4, 6 }; - + List newNumbers = shift(numbers, 5, 3); - + System.out.println(newNumbers); } } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/RulePanelManager.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/RulePanelManager.java new file mode 100755 index 0000000000..4fdc72dad5 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/panelmanagers/RulePanelManager.java @@ -0,0 +1,720 @@ +package net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RulePriority; +import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; +import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; +import net.sourceforge.pmd.eclipse.ui.preferences.br.ImplementationType; +import net.sourceforge.pmd.eclipse.ui.preferences.br.RuleFieldAccessor; +import net.sourceforge.pmd.eclipse.ui.preferences.br.RuleSelection; +import net.sourceforge.pmd.eclipse.ui.preferences.br.RuleUtil; +import net.sourceforge.pmd.eclipse.ui.preferences.br.RuleVisitor; +import net.sourceforge.pmd.eclipse.ui.preferences.br.ValueChangeListener; +import net.sourceforge.pmd.eclipse.ui.preferences.editors.SWTUtil; +import net.sourceforge.pmd.eclipse.ui.preferences.editors.TypeText; +import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.LanguageVersion; +import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.util.StringUtil; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +/** + * + * @author Brian Remedios + */ +public class RulePanelManager extends AbstractRulePanelManager { + + private RuleTarget target; + + private Text nameField; + private TypeText implementationClassField; + private Combo ruleSetNameField; + + private Button ruleReferenceButton; + private Combo languageCombo; + private CCombo priorityCombo; + + private Label minLanguageLabel; + private Label maxLanguageLabel; + private Combo minLanguageVersionCombo; + private Combo maxLanguageVersionCombo; + + private Combo implementationTypeCombo; + + private Button usesTypeResolutionButton; + private Button usesDfaButton; + private List