Skip to content

Commit 9ba7180

Browse files
committed
Rework properties handling in rule table in preferences
Fixes #191
1 parent 63fe212 commit 9ba7180

File tree

11 files changed

+183
-226
lines changed

11 files changed

+183
-226
lines changed

ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ This is a minor release.
1616
### Fixed Issues
1717
* [#192](https://github.com/pmd/pmd-eclipse-plugin/pull/192): Add japicmp
1818

19+
* [#191](https://github.com/pmd/pmd-eclipse-plugin/issues/191): Rule Configuration Pref Page - PropertyDescriptor cannot be cast to Comparable
20+
1921
### API Changes
2022

2123
### External Contributions

net.sourceforge.pmd.eclipse.plugin/src/main/java/net/sourceforge/pmd/eclipse/ui/dialogs/NewPropertyDialog.java

Lines changed: 45 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44

55
package net.sourceforge.pmd.eclipse.ui.dialogs;
66

7-
import java.lang.reflect.Method;
87
import java.util.Arrays;
98
import java.util.HashMap;
109
import java.util.List;
1110
import java.util.Map;
12-
import java.util.Map.Entry;
1311

1412
import org.apache.commons.lang3.StringUtils;
1513
import org.eclipse.jface.dialogs.IDialogConstants;
@@ -34,6 +32,7 @@
3432
import net.sourceforge.pmd.eclipse.ui.preferences.br.SizeChangeListener;
3533
import net.sourceforge.pmd.eclipse.ui.preferences.br.ValueChangeListener;
3634
import net.sourceforge.pmd.eclipse.ui.preferences.editors.SWTUtil;
35+
import net.sourceforge.pmd.eclipse.ui.preferences.internal.PropertyEditorFactory;
3736
import net.sourceforge.pmd.eclipse.util.Util;
3837
import net.sourceforge.pmd.lang.rule.Rule;
3938
import net.sourceforge.pmd.lang.rule.RuleReference;
@@ -42,16 +41,14 @@
4241
import net.sourceforge.pmd.properties.PropertySource;
4342

4443
/**
45-
* Implements a dialog for adding or editing a rule property. As the user
46-
* changes the specified type, each type's associated editor factory will
47-
* provide additional labels & widgets intended to capture other metadata.
44+
* Implements a dialog for adding or editing a rule property.
4845
*
4946
* @author Brian Remedios
5047
*/
5148
public class NewPropertyDialog extends TitleAreaDialog implements SizeChangeListener {
5249

5350
private Text nameField;
54-
private Text labelField;
51+
private Text descriptionField;
5552
private Combo typeField;
5653
private Control[] factoryControls;
5754
private Composite dlgArea;
@@ -60,43 +57,56 @@ public class NewPropertyDialog extends TitleAreaDialog implements SizeChangeList
6057

6158
private PropertySource propertySource;
6259
private PropertyDescriptor<?> descriptor;
63-
private Map<Class<?>, EditorFactory<?>> editorFactoriesByValueType;
6460

6561
// these are the ones we've tested, the others may work but might not make
6662
// sense in the xpath source context...
67-
private static final Class<?>[] VALID_EDITOR_TYPES = new Class[] { String.class, Integer.class, Boolean.class,
68-
Class.class, Method.class };
63+
private static final Class<?>[] VALID_EDITOR_TYPES = new Class[] { String.class, Integer.class, Boolean.class };
6964
private static final Class<?> DEFAULT_EDITOR_TYPE = VALID_EDITOR_TYPES[0]; // first one
7065

7166
/**
7267
* Constructor for RuleDialog. Supply a working descriptor with name &
7368
* description values we expect the user to change.
74-
*
75-
* @param parentdlgArea
7669
*/
77-
public NewPropertyDialog(Shell parent, Map<Class<?>, EditorFactory<?>> theEditorFactoriesByValueType,
78-
PropertySource theSource, ValueChangeListener theChangeListener) {
70+
public NewPropertyDialog(Shell parent, PropertySource theSource, ValueChangeListener theChangeListener) {
7971
super(parent);
8072

8173
setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.APPLICATION_MODAL);
8274

8375
propertySource = theSource;
8476
changeListener = theChangeListener;
85-
editorFactoriesByValueType = withOnly(theEditorFactoriesByValueType, VALID_EDITOR_TYPES);
77+
}
78+
79+
/**
80+
* Constructor for RuleDialog. Supply a working descriptor with name &
81+
* description values we expect the user to change.
82+
*
83+
* @param parentdlgArea
84+
* @deprecated use {@link #NewPropertyDialog(Shell, PropertySource, ValueChangeListener)} instead.
85+
*/
86+
@Deprecated // for removal
87+
public NewPropertyDialog(Shell parent, Map<Class<?>, EditorFactory<?>> theEditorFactoriesByValueType,
88+
PropertySource theSource, ValueChangeListener theChangeListener) {
89+
this(parent, theSource, theChangeListener);
8690
}
8791

8892
/**
8993
* Constructor for RuleDialog.
9094
*
9195
* @param parentdlgArea
96+
* @deprecated This ctor is not used and will be removed
9297
*/
98+
@Deprecated // for removal
9399
public NewPropertyDialog(Shell parent, Map<Class<?>, EditorFactory<?>> theEditorFactoriesByValueType, Rule theRule,
94100
PropertyDescriptor<?> theDescriptor, ValueChangeListener theChangeListener) {
95101
this(parent, theEditorFactoriesByValueType, theRule, theChangeListener);
96102

97103
descriptor = theDescriptor;
98104
}
99105

106+
/**
107+
* @deprecated This was a helper method that should have been private
108+
*/
109+
@Deprecated // for removal
100110
public static Map<Class<?>, EditorFactory<?>> withOnly(Map<Class<?>, EditorFactory<?>> factoriesByType,
101111
Class<?>[] legalTypeKeys) {
102112
Map<Class<?>, EditorFactory<?>> results = new HashMap<>(legalTypeKeys.length);
@@ -125,8 +135,8 @@ protected Control createDialogArea(Composite parent) {
125135
nameField = buildNameText(dlgArea); // TODO i18l label
126136
buildLabel(dlgArea, "Datatype:");
127137
typeField = buildTypeField(dlgArea); // TODO i18l label
128-
buildLabel(dlgArea, "Label:");
129-
labelField = buildLabelField(dlgArea); // TODO i18l label
138+
buildLabel(dlgArea, "Description:");
139+
descriptionField = buildDescriptionField(dlgArea); // TODO i18l label
130140

131141
setPreferredName();
132142
setInitialType();
@@ -182,24 +192,21 @@ public void handleEvent(Event event) {
182192
return text;
183193
}
184194

185-
private boolean isValidNewLabel(String labelCandidate) {
186-
return StringUtils.isNotBlank(labelCandidate);
195+
private boolean isValidNewDescription(String descriptionCandidate) {
196+
return StringUtils.isNotBlank(descriptionCandidate);
187197
}
188198

189-
private boolean isPreExistingLabel(String labelCandidate) {
199+
private boolean isPreExistingDescription(String descriptionCandidate) {
190200

191201
for (PropertyDescriptor<?> desc : propertySource.getPropertyDescriptors()) {
192-
if (desc.description().equalsIgnoreCase(labelCandidate)) {
202+
if (desc.description().equalsIgnoreCase(descriptionCandidate)) {
193203
return false;
194204
}
195205
}
196206
return true;
197207
}
198208

199-
/**
200-
* Build the rule name text.
201-
*/
202-
private Text buildLabelField(Composite parent) {
209+
private Text buildDescriptionField(Composite parent) {
203210

204211
final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
205212
setFieldLayoutData(text);
@@ -220,24 +227,6 @@ private static String labelFor(Class<?> type) {
220227
return Util.signatureFor(type, new String[0]);
221228
}
222229

223-
/**
224-
* A bit of a hack but this avoids the need to create an alternate lookup
225-
* structure.
226-
*
227-
* @param label
228-
* @return
229-
*/
230-
private EditorFactory<?> factoryFor(String label) {
231-
232-
for (Entry<Class<?>, EditorFactory<?>> entry : editorFactoriesByValueType.entrySet()) {
233-
if (label.equals(labelFor(entry.getKey()))) {
234-
return entry.getValue();
235-
}
236-
}
237-
238-
return null;
239-
}
240-
241230
/**
242231
* Build the rule name text.
243232
*/
@@ -246,20 +235,17 @@ private Combo buildTypeField(final Composite parent) {
246235
final Combo combo = new Combo(parent, SWT.READ_ONLY);
247236
setFieldLayoutData(combo);
248237

249-
String[] labels = new String[editorFactoriesByValueType.size()];
250-
int i = 0;
251-
for (Entry<Class<?>, EditorFactory<?>> entry : editorFactoriesByValueType.entrySet()) {
252-
labels[i++] = labelFor(entry.getKey());
238+
String[] labels = new String[VALID_EDITOR_TYPES.length];
239+
for (int i = 0; i < labels.length; i++) {
240+
labels[i] = VALID_EDITOR_TYPES[i].getSimpleName();
253241
}
254242
Arrays.sort(labels);
255243
combo.setItems(labels);
256244

257245
combo.addSelectionListener(new SelectionAdapter() {
258246
@Override
259247
public void widgetSelected(SelectionEvent e) {
260-
int selectionIdx = combo.getSelectionIndex();
261-
EditorFactory<?> factory = factoryFor(combo.getItem(selectionIdx));
262-
248+
EditorFactory<?> factory = PropertyEditorFactory.INSTANCE;
263249
factory(factory);
264250
}
265251
});
@@ -309,10 +295,9 @@ private void setPreferredName() {
309295
}
310296

311297
private void setInitialType() {
312-
313298
String editorLabel = labelFor(DEFAULT_EDITOR_TYPE);
314299
typeField.select(Util.indexOf(typeField.getItems(), editorLabel));
315-
factory(factoryFor(editorLabel));
300+
factory(PropertyEditorFactory.INSTANCE);
316301
}
317302

318303
private void cleanFactoryStuff() {
@@ -323,13 +308,11 @@ private void cleanFactoryStuff() {
323308
}
324309
}
325310

326-
private <T> void factory(EditorFactory<T> theFactory) {
327-
311+
private void factory(EditorFactory<?> theFactory) {
328312
factory = theFactory;
329-
// dummy values (??) that will be replaced
330-
PropertyDescriptor<T> theDescriptor = theFactory.createDescriptor("??", "??", null);
313+
PropertyDescriptor theDescriptor = theFactory.createDescriptor("propertyName", "The description", null);
331314
descriptor = theDescriptor;
332-
labelField.setText(theDescriptor.description());
315+
descriptionField.setText(theDescriptor.description());
333316
cleanFactoryStuff();
334317

335318
factoryControls = theFactory.createOtherControlsOn(dlgArea, theDescriptor, propertySource, changeListener, this);
@@ -339,16 +322,6 @@ private <T> void factory(EditorFactory<T> theFactory) {
339322
dlgArea.getParent().pack();
340323
}
341324

342-
// /**
343-
// * Helper method to shorten message access
344-
// *
345-
// * @param key a message key
346-
// * @return requested message
347-
// */
348-
// private String getMessage(String key) {
349-
// return PMDPlugin.getDefault().getStringTable().getString(key);
350-
// }
351-
352325
/**
353326
* @see org.eclipse.jface.dialogs.Dialog#okPressed()
354327
*/
@@ -364,7 +337,7 @@ protected void okPressed() {
364337
* Perform the form validation
365338
*/
366339
private boolean validateForm() {
367-
boolean isOk = validateName() && validateLabel();
340+
boolean isOk = validateName() && validateDescription();
368341
Control button = getButton(IDialogConstants.OK_ID);
369342
if (button != null) {
370343
button.setEnabled(isOk);
@@ -394,24 +367,21 @@ private boolean validateName() {
394367
return true;
395368
}
396369

397-
/**
398-
* Perform the label validation
399-
*/
400-
private boolean validateLabel() {
370+
private boolean validateDescription() {
401371

402-
String label = labelField.getText().trim();
372+
String label = descriptionField.getText().trim();
403373

404374
if (StringUtils.isBlank(label)) {
405375
setErrorMessage("A descriptive label is required");
406376
return false;
407377
}
408378

409-
if (!isValidNewLabel(label)) {
379+
if (!isValidNewDescription(label)) {
410380
setErrorMessage("Invalid label");
411381
return false;
412382
}
413383

414-
if (!isPreExistingLabel(label)) {
384+
if (!isPreExistingDescription(label)) {
415385
setErrorMessage("Label text must differ from other label text");
416386
return false;
417387
}
@@ -431,8 +401,7 @@ public PropertyDescriptor<?> descriptor() {
431401
}
432402

433403
private PropertyDescriptor<?> newDescriptor() {
434-
435-
return factory.createDescriptor(nameField.getText().trim(), labelField.getText().trim(), factoryControls);
404+
return factory.createDescriptor(nameField.getText().trim(), descriptionField.getText().trim(), factoryControls);
436405
}
437406

438407
@Override

net.sourceforge.pmd.eclipse.plugin/src/main/java/net/sourceforge/pmd/eclipse/ui/preferences/br/ImageColumnDescriptor.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ public class ImageColumnDescriptor extends AbstractRuleColumnDescriptor {
2525

2626
public static final RuleFieldAccessor PROPERTIES_ACCESSOR = new BasicRuleFieldAccessor() {
2727
@Override
28-
public Comparable<?> valueFor(Rule rule) {
28+
public String labelFor(Rule rule) {
29+
IndexedString value = valueFor(rule);
30+
return value == null ? "" : value.string;
31+
}
32+
33+
@Override
34+
public IndexedString valueFor(Rule rule) {
2935
// notes indices of non-default values in the string for emphasis
3036
// during later rendering
3137
return RuleUIUtil.indexedPropertyStringFrom(rule);

net.sourceforge.pmd.eclipse.plugin/src/main/java/net/sourceforge/pmd/eclipse/ui/preferences/br/PMDPreferencePage2.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,18 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage
6464
private Composite contentPanel;
6565

6666
// columns shown in the rule treetable in the desired order
67-
public static final RuleColumnDescriptor[] AVAILABLE_COLUMNS = new RuleColumnDescriptor[] { RuleTableColumns.NAME,
67+
public static final RuleColumnDescriptor[] AVAILABLE_COLUMNS = new RuleColumnDescriptor[] {
68+
RuleTableColumns.NAME,
6869
// PreferenceTableColumns.priorityName,
6970
// IconColumnDescriptor.priority,
7071
RuleTableColumns.IMG_PRIORITY,
7172
// PreferenceTableColumns.fixCount,
72-
RuleTableColumns.SINCE, RuleTableColumns.RULE_SET_NAME, RuleTableColumns.RULE_TYPE, RuleTableColumns.MIN_LANGUAGE_VERSION,
73-
RuleTableColumns.MAX_LANGUAGE_VERSION, RuleTableColumns.LANGUAGE,
73+
RuleTableColumns.SINCE,
74+
RuleTableColumns.RULE_SET_NAME,
75+
RuleTableColumns.RULE_TYPE,
76+
RuleTableColumns.MIN_LANGUAGE_VERSION,
77+
RuleTableColumns.MAX_LANGUAGE_VERSION,
78+
RuleTableColumns.LANGUAGE,
7479
// regex text -> compact color squares (for comparison)
7580
RuleTableColumns.FILTER_VIOLATION_REGEX,
7681
// xpath text -> compact color circles (for comparison)

0 commit comments

Comments
 (0)