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 f7274bd3bd..bff46f9c12 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 @@ -46,5 +46,4 @@ Export-Package: net.sourceforge.pmd, net.sourceforge.pmd.eclipse.ui.preferences.br, net.sourceforge.pmd.eclipse.ui.views.actions, net.sourceforge.pmd.util, - org.apache.log4j, - rulesets + org.apache.log4j diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/messages.properties b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/messages.properties index e8c371d196..b4e6cad592 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/messages.properties +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/messages.properties @@ -114,7 +114,7 @@ preference.rulesetselection.button.copy = Import by Copy preference.ruleedit.tab.rule = Rule preference.ruleedit.tab.properties = Properties preference.ruleedit.tab.description = Description -preference.ruleedit.tab.filters = Filters +preference.ruleedit.tab.exclusions = Exclusions preference.ruleedit.tab.xpath = XPath preference.ruleedit.tab.fixes = Fixes preference.ruleedit.tab.examples = Examples diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/plugin.properties b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/plugin.properties index 5fc55aa8df..e966652a7f 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/plugin.properties +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/plugin.properties @@ -16,6 +16,7 @@ preferences.pmd = PMD preferences.rulesets = Rule Configuration preferences.cpd = CPD Preferences preferences.report = Reports +preferences.filter = File Filters properties.pmd = PMD menu.pmd = PMD diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/plugin.xml b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/plugin.xml index a5ca6ade8d..fb8ea8e90b 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/plugin.xml +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/plugin.xml @@ -198,6 +198,13 @@ id="net.sourceforge.pmd.eclipse.ui.preferences.reportsPreferencePage"> + + + names); + /** + * + */ + Set activeExclusionPatterns(); + + /** + * + * @param names + */ + void activeExclusionPatterns(Set filterPatterns); + + /** + * + */ + Set activeInclusionPatterns(); + + /** + * + * @param names + */ + void activeInclusionPatterns(Set filterPatterns); /** * Synchronize the preferences with the preferences store */ diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferencesImpl.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferencesImpl.java index eadb5a6646..83214c90fe 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferencesImpl.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferencesImpl.java @@ -72,6 +72,8 @@ class PreferencesImpl implements IPreferences { private Level logLevel; private Set activeRuleNames = new HashSet(); private Set activeRendererNames = new HashSet(); + private Set activeExclusionPatterns = new HashSet(); + private Set activeInclusionPatterns = new HashSet(); private Map uiDescriptorsByPriority = new HashMap(5); @@ -251,6 +253,22 @@ class PreferencesImpl implements IPreferences { activeRuleNames = ruleNames; } + public Set activeExclusionPatterns() { + return activeExclusionPatterns; + } + + public void activeExclusionPatterns(Set patterns) { + activeExclusionPatterns = patterns; + } + + public Set activeInclusionPatterns() { + return activeInclusionPatterns; + } + + public void activeInclusionPatterns(Set patterns) { + activeInclusionPatterns = patterns; + } + public void setPriorityDescriptor(RulePriority priority, PriorityDescriptor pd) { uiDescriptorsByPriority.put(priority, pd); } diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferencesManagerImpl.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferencesManagerImpl.java index ec0fe95019..cc9f146310 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferencesManagerImpl.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/runtime/preferences/impl/PreferencesManagerImpl.java @@ -108,6 +108,8 @@ class PreferencesManagerImpl implements IPreferencesManager { private static final String LOG_LEVEL = PMDPlugin.PLUGIN_ID + ".log_level"; private static final String ACTIVE_RULES = PMDPlugin.PLUGIN_ID + ".active_rules"; private static final String ACTIVE_RENDERERS = PMDPlugin.PLUGIN_ID + ".active_renderers"; + private static final String ACTIVE_EXCLUSIONS = PMDPlugin.PLUGIN_ID + ".active_exclusions"; + private static final String ACTIVE_INCLUSIONS = PMDPlugin.PLUGIN_ID + ".active_inclusions"; private static final String OLD_PREFERENCE_PREFIX = "net.sourceforge.pmd.runtime"; private static final String OLD_PREFERENCE_LOCATION = "/.metadata/.plugins/org.eclipse.core.runtime/.settings/net.sourceforge.pmd.runtime.prefs"; @@ -168,6 +170,8 @@ class PreferencesManagerImpl implements IPreferencesManager { loadLogLevel(); loadActiveRules(); loadActiveReportRenderers(); + loadActiveExclusions(); + loadActiveInclusions(); loadRulePriorityDescriptors(); return preferences; @@ -229,6 +233,8 @@ class PreferencesManagerImpl implements IPreferencesManager { storeLogLevel(); storeActiveRules(); storeActiveReportRenderers(); + storeActiveExclusions(); + storeActiveInclusions(); storePriorityDescriptors(); } @@ -312,6 +318,16 @@ class PreferencesManagerImpl implements IPreferencesManager { preferences.activeReportRenderers(asStringSet(loadPreferencesStore.getString(ACTIVE_RENDERERS), ",")); } + private void loadActiveExclusions() { + loadPreferencesStore.setDefault(ACTIVE_EXCLUSIONS, IPreferences.ACTIVE_EXCLUSIONS); + preferences.activeExclusionPatterns(asStringSet(loadPreferencesStore.getString(ACTIVE_EXCLUSIONS), ",")); + } + + private void loadActiveInclusions() { + loadPreferencesStore.setDefault(ACTIVE_INCLUSIONS, IPreferences.ACTIVE_INCLUSIONS); + preferences.activeInclusionPatterns(asStringSet(loadPreferencesStore.getString(ACTIVE_INCLUSIONS), ",")); + } + private void loadRulePriorityDescriptors() { for (Map.Entry entry : StoreKeysByPriority.entrySet()) { @@ -355,6 +371,14 @@ class PreferencesManagerImpl implements IPreferencesManager { private void storeActiveReportRenderers() { storePreferencesStore.setValue(ACTIVE_RENDERERS, asDelimitedString(preferences.activeReportRenderers(), ",")); } + + private void storeActiveExclusions() { + storePreferencesStore.setValue(ACTIVE_EXCLUSIONS, asDelimitedString(preferences.activeExclusionPatterns(), ",")); + } + + private void storeActiveInclusions() { + storePreferencesStore.setValue(ACTIVE_INCLUSIONS, asDelimitedString(preferences.activeInclusionPatterns(), ",")); + } private void storeProjectBuildPathEnabled() { storePreferencesStore.setValue(PROJECT_BUILD_PATH_ENABLED, preferences.isProjectBuildPathEnabled()); diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/PMDCheckAction.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/PMDCheckAction.java index 80328ac005..7dff6ff5d2 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/PMDCheckAction.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/actions/PMDCheckAction.java @@ -145,8 +145,7 @@ public class PMDCheckAction extends AbstractUIAction { for (Iterator i = selection.iterator(); i.hasNext();) { Object element = i.next(); if (element instanceof AbstractPMDRecord) { - final IResource resource = ((AbstractPMDRecord) element) - .getResource(); + IResource resource = ((AbstractPMDRecord) element).getResource(); if (resource != null) { cmd.addResource(resource); } else { diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/BasicAccessor.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/BasicAccessor.java new file mode 100644 index 0000000000..66e1c65b32 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/BasicAccessor.java @@ -0,0 +1,9 @@ +package net.sourceforge.pmd.eclipse.ui.filters; + +import net.sourceforge.pmd.eclipse.ui.filters.FilterHolder.Accessor; + +class BasicAccessor implements Accessor { + + public boolean boolValueFor(FilterHolder fh) { return false; } + public String textValueFor(FilterHolder fh) { return null; } +} \ No newline at end of file diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterColumnUI.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterColumnUI.java new file mode 100644 index 0000000000..de37b76471 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterColumnUI.java @@ -0,0 +1,39 @@ +package net.sourceforge.pmd.eclipse.ui.filters; + +import net.sourceforge.pmd.eclipse.ui.ItemColumnDescriptor; +import net.sourceforge.pmd.eclipse.ui.ItemFieldAccessor; +import net.sourceforge.pmd.eclipse.ui.ItemFieldAccessorAdapter; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; + +/** + * + * @author Brian Remedios + */ +public interface FilterColumnUI { + + ItemFieldAccessor includeAcc = new ItemFieldAccessorAdapter(null) { + public Image imageFor(FilterHolder holder) { return FilterPreferencesPage.typeIconFor(holder); } + }; + + ItemFieldAccessor pmdAcc = new ItemFieldAccessorAdapter(null) { + public String valueFor(FilterHolder holder) { return holder.forPMD ? "Y" : ""; } + }; + + ItemFieldAccessor cpdAcc = new ItemFieldAccessorAdapter(null) { + public String valueFor(FilterHolder holder) { return holder.forCPD ? "Y" : ""; } + }; + + ItemFieldAccessor patternAcc = new ItemFieldAccessorAdapter(null) { + public String valueFor(FilterHolder holder) { return holder.pattern; } + }; + + ItemColumnDescriptor include = new ItemColumnDescriptor("", " Type", SWT.LEFT, 85, false, includeAcc); + ItemColumnDescriptor pmd = new ItemColumnDescriptor("", "PMD", SWT.LEFT, 55, false, pmdAcc); + ItemColumnDescriptor cpd = new ItemColumnDescriptor("", "CPD", SWT.LEFT, 55, false, cpdAcc); + ItemColumnDescriptor pattern = new ItemColumnDescriptor("", "Pattern", SWT.LEFT, 55, true, patternAcc); + + @SuppressWarnings("rawtypes") + ItemColumnDescriptor[] VisibleColumns = new ItemColumnDescriptor[] { include, pmd, cpd, pattern }; +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterHolder.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterHolder.java new file mode 100644 index 0000000000..f2aca0b875 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterHolder.java @@ -0,0 +1,59 @@ +package net.sourceforge.pmd.eclipse.ui.filters; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author Brian Remedios + */ +class FilterHolder { + + public String pattern; + public boolean forPMD; + public boolean forCPD; + public boolean isInclude; + + public static final FilterHolder[] EMPTY_HOLDERS = new FilterHolder[0]; + + public FilterHolder(String thePattern, boolean pmdFlag, boolean cpdFlag, boolean isIncludeFlag) { + pattern = thePattern; + forPMD = pmdFlag; + forCPD = cpdFlag; + isInclude = isIncludeFlag; + } + + public interface Accessor { + boolean boolValueFor(FilterHolder fh); + String textValueFor(FilterHolder fh); + } + + public static final Accessor IncludeAccessor = new BasicAccessor() { + public boolean boolValueFor(FilterHolder fh) { return fh.isInclude; } + }; + + public static final Accessor PMDAccessor = new BasicAccessor() { + public boolean boolValueFor(FilterHolder fh) { return fh.forPMD; } + }; + + public static final Accessor CPDAccessor = new BasicAccessor() { + public boolean boolValueFor(FilterHolder fh) { return fh.forCPD; } + }; + + public static final Accessor PatternAccessor = new BasicAccessor() { + public String textValueFor(FilterHolder fh) { return fh.pattern; } + }; + + public static Boolean boolValueOf(Collection holders, Accessor boolAccessor) { + Set values = new HashSet(); + for (FilterHolder fh : holders) values.add(boolAccessor.boolValueFor(fh)); + return values.size() == 2 ? null : values.iterator().next(); + } + + public static String textValueOf(Collection holders, Accessor textAccessor) { + Set values = new HashSet(); + for (FilterHolder fh : holders) values.add(textAccessor.textValueFor(fh)); + return values.size() > 1 ? "" : values.iterator().next(); + } +} diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterPreferencesPage.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterPreferencesPage.java new file mode 100644 index 0000000000..4932d71015 --- /dev/null +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/filters/FilterPreferencesPage.java @@ -0,0 +1,565 @@ +package net.sourceforge.pmd.eclipse.ui.filters; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.PropertySource; +import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.eclipse.plugin.PMDPlugin; +import net.sourceforge.pmd.eclipse.ui.BasicTableLabelProvider; +import net.sourceforge.pmd.eclipse.ui.PMDUiConstants; +import net.sourceforge.pmd.eclipse.ui.Shape; +import net.sourceforge.pmd.eclipse.ui.ShapePainter; +import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; +import net.sourceforge.pmd.eclipse.ui.preferences.br.AbstractPMDPreferencePage; +import net.sourceforge.pmd.eclipse.ui.preferences.br.BasicTableManager; +import net.sourceforge.pmd.eclipse.ui.preferences.br.RuleSelection; +import net.sourceforge.pmd.eclipse.ui.preferences.br.SizeChangeListener; +import net.sourceforge.pmd.eclipse.ui.preferences.br.ValueChangeListener; +import net.sourceforge.pmd.eclipse.util.ResourceManager; + +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; + +/** + * The available report formats and their properties. + * + * @author Brian Remedios + */ +public class FilterPreferencesPage extends AbstractPMDPreferencePage implements ValueChangeListener, SizeChangeListener { + + private TableViewer tableViewer; + private Button addButton; + private Button removeButton; + + private Button excludeButt; + private Button includeButt; + private Button cpdButt; + private Button pmdButt; + private Text patternField; + private BasicTableManager reportTableMgr; + + + private static Image IncludeIcon; + private static Image ExcludeIcon; + + private static final RGB ProtoTransparentColour = new RGB(1,1,1); // almost full black, unlikely to be used + + public static Image typeIconFor(FilterHolder holder) { + return holder.isInclude ? includeIcon() : excludeIcon(); + } + + private static Image includeIcon() { + + if (IncludeIcon != null) return IncludeIcon; + + IncludeIcon = ShapePainter.newDrawnImage( + Display.getCurrent(), + 16, + 16, + Shape.plus, + ProtoTransparentColour, + new RGB(0,255,0) + ); + + return IncludeIcon; + } + + private static Image excludeIcon() { + + if (ExcludeIcon != null) return ExcludeIcon; + + ExcludeIcon = ShapePainter.newDrawnImage( + Display.getCurrent(), + 16, + 16, + Shape.minus, + ProtoTransparentColour, + new RGB(255,0,0) + ); + + return ExcludeIcon; + } + + /** + * Create and initialize the controls of the page + * + + * @param parent Composite + * @return Control + * @see PreferencePage#createContents */ + @Override + protected Control createContents(Composite parent) { + + // Create parent composite + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.verticalSpacing = 10; + composite.setLayout(layout); + + // Create panels + Composite filterGroup = buildFilterGroup(composite); + Composite buttonPanel = buildTableButtons(composite); + + // Layout children + filterGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); + buttonPanel.setLayoutData(new GridData()); + buildFilterEditor(parent); + + return composite; + } + + private FilterHolder[] currentFilters() { + + List holders = new ArrayList(); + + RuleSet ruleSet = plugin.getPreferencesManager().getRuleSet(); + + for (String pattern : ruleSet.getExcludePatterns() ) { + holders.add( new FilterHolder(pattern, true, false, false) ); + } + for (String pattern : ruleSet.getIncludePatterns() ) { + holders.add( new FilterHolder(pattern, true, false, true) ); + } + return holders.toArray(new FilterHolder[holders.size()]); + } + /** + * Build the group of priority preferences + * @param parent the parent composite + + * @return the group widget */ + private Composite buildFilterGroup(Composite parent) { + + IStructuredContentProvider contentProvider = new IStructuredContentProvider() { + public void dispose() { } + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } + public Object[] getElements(Object inputElement) { return (FilterHolder[])inputElement; } + }; + BasicTableLabelProvider labelProvider = new BasicTableLabelProvider(FilterColumnUI.VisibleColumns); + + reportTableMgr = new BasicTableManager("renderers", null, FilterColumnUI.VisibleColumns); + tableViewer = reportTableMgr.buildTableViewer( + parent, + SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION | SWT.CHECK + ); + reportTableMgr.setupColumns(FilterColumnUI.VisibleColumns); + + Table table = tableViewer.getTable(); + table.setLayoutData( new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1) ); + + tableViewer.setLabelProvider(labelProvider); + tableViewer.setContentProvider(contentProvider); + table.setHeaderVisible(true); + // labelProvider.addColumnsTo(table); + + tableViewer.setInput( currentFilters() ); + + selectCheckedFilters(); + + TableColumn[] columns = table.getColumns(); + for (TableColumn column : columns) column.pack(); + + tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection)event.getSelection(); + selectedPatterns(filtersIn(selection.toList())); + } + }); + + tableViewer.getTable().addListener(SWT.Selection, new Listener () { + public void handleEvent(Event event) { + if (event.detail == SWT.CHECK) { + checked(event.item); + } + } + }); + + return parent; + } + + private void selectedPatterns(Collection holders) { + + setState(holders, includeButt, FilterHolder.IncludeAccessor); + setState(holders, pmdButt, FilterHolder.PMDAccessor); + setState(holders, cpdButt, FilterHolder.CPDAccessor); + setValue(holders, patternField, FilterHolder.PatternAccessor); + } + + private static void setState(Collection holders, Button button, FilterHolder.Accessor accessor) { + + Boolean state = FilterHolder.boolValueOf(holders, accessor); + if (state == null) { + button.setGrayed(true); + return; + } + + button.setSelection(state); + } + + private static void setValue(Collection holders, Text field, FilterHolder.Accessor accessor) { + + String text = FilterHolder.textValueOf(holders, accessor); + field.setText(text); + } + + private void setAllPMD(boolean state) { + for (FilterHolder fh : selectedFilters()) { + fh.forPMD = state; + } + } + + private void setAllCPD(boolean state) { + for (FilterHolder fh : selectedFilters()) { + fh.forCPD = state; + } + } + + private void setAllInclude(boolean state) { + for (FilterHolder fh : selectedFilters()) { + fh.isInclude = state; + } + } + + private void setAllPatterns(String pattern) { + for (FilterHolder fh : selectedFilters()) { + fh.pattern = pattern; + } + } + + private void buildFilterEditor(Composite parent) { + + Composite editorPanel = new Composite(parent, SWT.None); + editorPanel.setLayoutData( new GridData(GridData.FILL, GridData.FILL, false, true) ); + editorPanel.setLayout(new GridLayout(3, false)); + + Label typeLabel = new Label(editorPanel, SWT.None); + typeLabel.setLayoutData( new GridData()); + typeLabel.setText("Type:"); + + excludeButt = createButton(editorPanel, SWT.RADIO, excludeIcon(), "Exclude"); + excludeButt.addSelectionListener( new SelectionAdapter() { + public void widgetSelected(SelectionEvent se) { + setAllInclude(includeButt.getSelection()); + tableViewer.refresh(); + } + }); + + includeButt = createButton(editorPanel, SWT.RADIO, includeIcon(), "Include"); + includeButt.addSelectionListener( new SelectionAdapter() { + public void widgetSelected(SelectionEvent se) { + setAllInclude(includeButt.getSelection()); + tableViewer.refresh(); + } + }); + + Label contextLabel = new Label(editorPanel, SWT.None); + contextLabel.setLayoutData( new GridData()); + contextLabel.setText("Applies to:"); + + pmdButt = createButton(editorPanel, SWT.CHECK, "PMD"); + pmdButt.addSelectionListener( new SelectionAdapter() { + public void widgetSelected(SelectionEvent se) { + setAllPMD(pmdButt.getSelection()); + tableViewer.refresh(); + } + }); + + cpdButt = createButton(editorPanel, SWT.CHECK, "CPD"); + cpdButt.addSelectionListener( new SelectionAdapter() { + public void widgetSelected(SelectionEvent se) { + setAllCPD(cpdButt.getSelection()); + tableViewer.refresh(); + } + }); + + Label patternLabel = new Label(editorPanel, SWT.None); + patternLabel.setLayoutData( new GridData()); + patternLabel.setText("Pattern:"); + + patternField = new Text(editorPanel, SWT.BORDER); + patternField.setLayoutData( new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1) ); + patternField.addFocusListener(new FocusAdapter() { + public void focusLost(FocusEvent fe) { + setAllPatterns(patternField.getText()); + tableViewer.refresh(); + } + }); + } + + private static Button createButton(Composite panel, int type, String label) { + Button butt = new Button(panel, type); + butt.setLayoutData( new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); + butt.setText(label); + return butt; + } + + private static Button createButton(Composite panel, int type, Image image, String tooltip) { + Button butt = new Button(panel, type); + butt.setLayoutData( new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); + butt.setImage(image); + butt.setToolTipText(tooltip); + return butt; + } + + /** + * Create buttons for rule table management + * @param parent Composite + * @return Composite + */ + public Composite buildTableButtons(Composite parent) { + + Composite composite = new Composite(parent, SWT.NULL); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + gridLayout.verticalSpacing = 3; + composite.setLayout(gridLayout); + + addButton = buildAddButton(composite); +addButton.setEnabled(false); + removeButton = buildRemoveButton(composite); +removeButton.setEnabled(false); + + GridData data = new GridData(); + addButton.setLayoutData(data); + + return composite; + } + + /** + * Check the filters as noted from the preferences. + */ + private void selectCheckedFilters() { + + Set activeOnes = preferences.activeExclusionPatterns(); + activeOnes.addAll(preferences.activeInclusionPatterns()); + + for (TableItem item : tableViewer.getTable().getItems()) { + FilterHolder holder = (FilterHolder)item.getData(); + item.setChecked( + activeOnes.contains(holder.pattern) + ); + } + } + + /** + * + * @return Set + */ + private Set currentCheckedFilters() { + + Set holders = new HashSet(); + for (Object holder : checkedItems(tableViewer.getTable())) { + holders.add((FilterHolder) holder); + } + return holders; + } + + /** + * + * @return Set + */ + private Set selectedFilters() { + + Set holders = new HashSet(); + for (Object tItem : tableViewer.getTable().getSelection()) { + holders.add((FilterHolder) (((TableItem)tItem).getData())); + } + return holders; + } + + /** + * + * @return Set + */ + private static Collection filtersIn(List tableItems) { + + Set holders = new HashSet(); + for (Object tItem : tableItems) { + holders.add((FilterHolder) tItem); + } + return holders; + } + + /** + * Method checkedItems. + * @param table Table + * @return Set + */ + private static Set checkedItems(Table table) { + + Set checkedItems = new HashSet(); + + for (TableItem ti : table.getItems()) { + if (ti.getChecked()) checkedItems.add( ti.getData() ); + } + return checkedItems; + } + + /** + * + * @param item Object + */ + private void checked(Object item) { + + //FIXME + boolean matches = currentCheckedFilters().equals(preferences.activeExclusionPatterns()); + + setModified(!matches); + } + + /** + + * @see org.eclipse.jface.preference.PreferencePage#performDefaults() */ + @Override + protected void performDefaults() { + + } + + /** + * + * @return boolean + * @see org.eclipse.jface.preference.IPreferencePage#performCancel() + */ + @Override + public boolean performCancel() { + // clear out any changes for next possible usage + selectCheckedFilters(); + return true; + } + + private static Set patternsIn(Collection holders, boolean getInclusions) { + + if (holders.isEmpty()) return Collections.emptySet(); + + Set patterns = new HashSet(); + for (FilterHolder holder : holders) { + if (holder.isInclude == getInclusions) { + patterns.add(holder.pattern); + } + } + return patterns; + } + + 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; + } + + /** + * Build the edit rule button + * @param parent Composite + * @return Button + */ + public Button buildAddButton(final Composite parent) { + + Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_ADD, StringKeys.PREF_RULESET_BUTTON_ADDRULE); + + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + addNewFilter(); + } + }); + + return button; + } + + private void addNewFilter() { + FilterHolder holder = new FilterHolder("", true, false, false); + + // TODO finish this + } + + /** + * Build the edit rule button + * @param parent Composite + * @return Button + */ + public Button buildRemoveButton(final Composite parent) { + + Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_DELETE, StringKeys.PREF_RULESET_BUTTON_REMOVERULE); + + button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + deleteSelected(); + } + }); + + return button; + } + + private void deleteSelected() { + IStructuredSelection sel = (IStructuredSelection)tableViewer.getSelection(); + if (sel.isEmpty()) return; + + // TODO finish this + } + + /** + * @return boolean + * @see org.eclipse.jface.preference.IPreferencePage#performOk() */ + @Override + public boolean performOk() { + + Set filters = currentCheckedFilters(); + preferences.activeExclusionPatterns( patternsIn(filters, false) ); + preferences.activeInclusionPatterns( patternsIn(filters, true) ); + + preferences.sync(); + PMDPlugin.getDefault().applyLogPreferences(preferences); + + return true; + } + + /** + * Method descriptionId. + * @return String + */ + @Override + protected String descriptionId() { + return "???"; // TODO + } + + public void changed(PropertySource source, PropertyDescriptor desc, Object newValue) { + // TODO enable/disable save/cancel buttons + } + + // ignore these + + public void addedRows(int newRowCount) { } + public void changed(RuleSelection rule, PropertyDescriptor desc, Object newValue) { } + +} 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 11384b1cec..07954a9e36 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 @@ -136,7 +136,7 @@ public class StringKeys { public static final String PREF_RULESET_TAB_RULE = "preference.ruleedit.tab.rule"; public static final String PREF_RULESET_TAB_PROPERTIES = "preference.ruleedit.tab.properties"; public static final String PREF_RULESET_TAB_DESCRIPTION = "preference.ruleedit.tab.description"; - public static final String PREF_RULESET_TAB_FILTERS = "preference.ruleedit.tab.filters"; + public static final String PREF_RULESET_TAB_EXCLUSIONS = "preference.ruleedit.tab.exclusions"; public static final String PREF_RULESET_TAB_XPATH = "preference.ruleedit.tab.xpath"; public static final String PREF_RULESET_TAB_FIXES = "preference.ruleedit.tab.fixes"; public static final String PREF_RULESET_TAB_EXAMPLES = "preference.ruleedit.tab.examples"; diff --git a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/RuleSetSelectionDialog.java b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/RuleSetSelectionDialog.java index 896f901fe8..98a38db8eb 100644 --- a/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/RuleSetSelectionDialog.java +++ b/pmd-eclipse-plugin/plugins/net.sourceforge.pmd.eclipse.plugin/src/net/sourceforge/pmd/eclipse/ui/preferences/RuleSetSelectionDialog.java @@ -32,6 +32,7 @@ import org.eclipse.swt.widgets.Shell; * Implements a dialog for the user to select a rule set to import * * @author Philippe Herlin + * @author Brian Remedios * */ public class RuleSetSelectionDialog extends Dialog { @@ -178,14 +179,12 @@ public class RuleSetSelectionDialog extends Dialog { * Build the reference button */ private Button buildReferenceButton(Composite parent) { - final Button button = new Button(parent, SWT.CHECK); + final Button button = new Button(parent, SWT.RADIO); button.setText(getMessage(StringKeys.PREF_RULESETSELECTION_BUTTON_REFERENCE)); button.setSelection(true); importByReference = true; button.addSelectionListener(new SelectionAdapter() { - @Override public void widgetSelected(SelectionEvent event) { - copyButton.setSelection(false); importByReference = true; } }); @@ -197,13 +196,11 @@ public class RuleSetSelectionDialog extends Dialog { * Build the copy button */ private Button buildCopyButton(Composite parent) { - final Button button = new Button(parent, SWT.CHECK); + final Button button = new Button(parent, SWT.RADIO); button.setText(getMessage(StringKeys.PREF_RULESETSELECTION_BUTTON_COPY)); button.setSelection(false); button.addSelectionListener(new SelectionAdapter() { - @Override public void widgetSelected(SelectionEvent event) { - referenceButton.setSelection(false); importByReference = false; } }); 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 fc6ac76f93..e5034599ad 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 @@ -89,7 +89,7 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul buildRuleTab(folder, 0, SWTUtil.stringFor(StringKeys.PREF_RULESET_TAB_RULE), listener), buildDescriptionTab(folder, 1, SWTUtil.stringFor(StringKeys.PREF_RULESET_TAB_DESCRIPTION), listener), buildPropertyTab(folder, 2, SWTUtil.stringFor(StringKeys.PREF_RULESET_TAB_PROPERTIES), listener), - buildUsageTab(folder, 3, SWTUtil.stringFor(StringKeys.PREF_RULESET_TAB_FILTERS), listener), + buildExclusionTab(folder, 3, SWTUtil.stringFor(StringKeys.PREF_RULESET_TAB_EXCLUSIONS), listener), buildXPathTab(folder, 4, SWTUtil.stringFor(StringKeys.PREF_RULESET_TAB_XPATH), listener), // buildQuickFixTab(folder, 5, SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_TAB_FIXES), listener), buildExampleTab(folder, 5, SWTUtil.stringFor(StringKeys.PREF_RULESET_TAB_EXAMPLES), listener), @@ -326,7 +326,7 @@ public class PMDPreferencePage2 extends AbstractPMDPreferencePage implements Rul * @param index int * @param title String */ - private static RulePropertyManager buildUsageTab(TabFolder parent, int index, String title, ValueChangeListener listener) { + private static RulePropertyManager buildExclusionTab(TabFolder parent, int index, String title, ValueChangeListener listener) { TabItem tab = new TabItem(parent, 0, index); tab.setText(title); 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 0feabed2a7..3652a15d2e 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 @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -138,6 +139,20 @@ public class RuleSelection implements RuleCollection { return null; // should not get here } + public Collection ruleGroupNames() { + + if (ruleItems == null) return Collections.emptyList(); + + Collection names = new ArrayList(); + for (Object item : ruleItems) { + if (item instanceof RuleGroup) { + names.add( ((RuleGroup)item).label() ); + } + } + + return names; + } + private static void useDefaultValues(Rule rule) { for (Map.Entry, Object> entry : Configuration.filteredPropertiesOf(rule).entrySet()) { @@ -234,10 +249,25 @@ public class RuleSelection implements RuleCollection { List rules = allRules(); if (rules.isEmpty()) return 0; - Collection currentRules = ruleSet.getRules(); - for (Rule rule : rules) currentRules.remove(rule); + Set rulesAsSet = new HashSet(); + rulesAsSet.addAll(rules); + + Iterator currentRuleIter = ruleSet.getRules().iterator(); + + int removed = 0; + while (currentRuleIter.hasNext()) { + Rule curRule = currentRuleIter.next(); // could be rule or a ruleReference +// if (curRule instanceof RuleReference) { +// RuleReference rr = (RuleReference)curRule; +// curRule = rr.getRule(); +// } + if (rulesAsSet.contains(curRule)) { + currentRuleIter.remove(); + removed++; + } + } - return currentRules.size(); + return removed; } public List allRules() { @@ -287,4 +317,20 @@ public class RuleSelection implements RuleCollection { rulesDo(visitor); } + + public String toString() { + + StringBuilder sb = new StringBuilder(); + + Collection rgNames = ruleGroupNames(); + if (!rgNames.isEmpty()) { + sb.append("groups: ").append(rgNames.size()); + } + + List rulz = allRules(); + if (!rulz.isEmpty()) { + sb.append(" rules: ").append(rulz.size()); + } + return sb.toString(); + } } 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 f3c566ea89..e2c48361e1 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 @@ -418,6 +418,8 @@ public class RuleTableManager extends AbstractTreeTableManager implements try { if (doByReference) { ruleSet.addRuleSetByReference(selectedRuleSet, false); + ruleSet.addIncludePatterns(selectedRuleSet.getIncludePatterns()); + ruleSet.addExcludePatterns(selectedRuleSet.getExcludePatterns()); } else { add(selectedRuleSet); }