A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/pmd/pmd/issues/785 below:

[java] NPE in DataClass rule · Issue #785 · pmd/pmd · GitHub

Affects Version: 6.0.0
Rule: DataClass

Description:
We're upgrading to PMD 6.0.0 and found a bug in new rule DataClass

Code Sample demonstrating the issue:

// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui.tagging.presets.items;

import static org.openstreetmap.josm.tools.I18n.tr;

import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.SortedSet;
import java.util.TreeSet;

import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.OsmUtils;
import org.openstreetmap.josm.data.preferences.BooleanProperty;
import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItem;

/**
 * Preset item associated to an OSM key.
 */
public abstract class KeyedItem extends TaggingPresetItem {

    /** Translatation of "<different>". Use in combo boxes to display an entry matching several different values. */
    protected static final String DIFFERENT = tr("<different>");

    protected static final BooleanProperty PROP_FILL_DEFAULT = new BooleanProperty("taggingpreset.fill-default-for-tagged-primitives", false);

    /** Last value of each key used in presets, used for prefilling corresponding fields */
    static final Map<String, String> LAST_VALUES = new HashMap<>();

    /** This specifies the property key that will be modified by the item. */
    public String key; // NOSONAR
    /** The text to display */
    public String text; // NOSONAR
    /** The context used for translating {@link #text} */
    public String text_context; // NOSONAR
    /**
     * Allows to change the matching process, i.e., determining whether the tags of an OSM object fit into this preset.
     * If a preset fits then it is linked in the Tags/Membership dialog.<ul>
     * <li>none: neutral, i.e., do not consider this item for matching</li>
     * <li>key: positive if key matches, neutral otherwise</li>
     * <li>key!: positive if key matches, negative otherwise</li>
     * <li>keyvalue: positive if key and value matches, neutral otherwise</li>
     * <li>keyvalue!: positive if key and value matches, negative otherwise</li></ul>
     * Note that for a match, at least one positive and no negative is required.
     * Default is "keyvalue!" for {@link Key} and "none" for {@link Text}, {@link Combo}, {@link MultiSelect} and {@link Check}.
     */
    public String match = getDefaultMatch().getValue(); // NOSONAR

    /**
     * Enum denoting how a match (see {@link TaggingPresetItem#matches}) is performed.
     */
    protected enum MatchType {

        /** Neutral, i.e., do not consider this item for matching. */
        NONE("none"),
        /** Positive if key matches, neutral otherwise. */
        KEY("key"),
        /** Positive if key matches, negative otherwise. */
        KEY_REQUIRED("key!"),
        /** Positive if key and value matches, neutral otherwise. */
        KEY_VALUE("keyvalue"),
        /** Positive if key and value matches, negative otherwise. */
        KEY_VALUE_REQUIRED("keyvalue!");

        private final String value;

        MatchType(String value) {
            this.value = value;
        }

        /**
         * Replies the associated textual value.
         * @return the associated textual value
         */
        public String getValue() {
            return value;
        }

        /**
         * Determines the {@code MatchType} for the given textual value.
         * @param type the textual value
         * @return the {@code MatchType} for the given textual value
         */
        public static MatchType ofString(String type) {
            for (MatchType i : EnumSet.allOf(MatchType.class)) {
                if (i.getValue().equals(type))
                    return i;
            }
            throw new IllegalArgumentException(type + " is not allowed");
        }
    }

    /**
     * Usage information on a key
     */
    protected static class Usage {
        /**
         * A set of values that were used for this key.
         */
        public final SortedSet<String> values = new TreeSet<>();; // NOSONAR
        private boolean hadKeys;
        private boolean hadEmpty;

        /**
         * Check if there is exactly one value for this key.
         * @return <code>true</code> if there was exactly one value.
         */
        public boolean hasUniqueValue() {
            return values.size() == 1 && !hadEmpty;
        }

        /**
         * Check if this key was not used in any primitive
         * @return <code>true</code> if it was unused.
         */
        public boolean unused() {
            return values.isEmpty();
        }

        /**
         * Get the first value available.
         * @return The first value
         * @throws NoSuchElementException if there is no such value.
         */
        public String getFirst() {
            return values.first();
        }

        /**
         * Check if we encountered any primitive that had any keys
         * @return <code>true</code> if any of the primtives had any tags.
         */
        public boolean hadKeys() {
            return hadKeys;
        }
    }

    protected static Usage determineTextUsage(Collection<OsmPrimitive> sel, String key) {
        Usage returnValue = new Usage();
        for (OsmPrimitive s : sel) {
            String v = s.get(key);
            if (v != null) {
                returnValue.values.add(v);
            } else {
                returnValue.hadEmpty = true;
            }
            if (s.hasKeys()) {
                returnValue.hadKeys = true;
            }
        }
        return returnValue;
    }

    protected static Usage determineBooleanUsage(Collection<OsmPrimitive> sel, String key) {
        Usage returnValue = new Usage();
        for (OsmPrimitive s : sel) {
            String booleanValue = OsmUtils.getNamedOsmBoolean(s.get(key));
            if (booleanValue != null) {
                returnValue.values.add(booleanValue);
            }
        }
        return returnValue;
    }

    /**
     * Returns the default match.
     * @return the default match
     */
    public abstract MatchType getDefaultMatch();

    /**
     * Returns the list of values.
     * @return the list of values
     */
    public abstract Collection<String> getValues();

    protected String getKeyTooltipText() {
        return tr("This corresponds to the key ''{0}''", key);
    }

    @Override
    protected Boolean matches(Map<String, String> tags) {
        switch (MatchType.ofString(match)) {
        case NONE:
            return null;
        case KEY:
            return tags.containsKey(key) ? Boolean.TRUE : null;
        case KEY_REQUIRED:
            return tags.containsKey(key);
        case KEY_VALUE:
            return tags.containsKey(key) && getValues().contains(tags.get(key)) ? Boolean.TRUE : null;
        case KEY_VALUE_REQUIRED:
            return tags.containsKey(key) && getValues().contains(tags.get(key));
        default:
            throw new IllegalStateException();
        }
    }

    @Override
    public String toString() {
        return "KeyedItem [key=" + key + ", text=" + text
                + ", text_context=" + text_context + ", match=" + match
                + ']';
    }
}

Running PMD through: Ant

Error

Exception applying rule DataClass on file org\openstreetmap\josm\gui\tagging\presets\items\KeyedItem.java, continuing with next rule
java.lang.NullPointerException
	at net.sourceforge.pmd.lang.ast.AbstractNode.jjtGetChild(AbstractNode.java:104)
	at net.sourceforge.pmd.lang.java.metrics.impl.AbstractJavaClassMetric.getDeclarationsOfType(AbstractJavaClassMetric.java:116)
	at net.sourceforge.pmd.lang.java.metrics.impl.AbstractJavaClassMetric.getMethodsAndConstructors(AbstractJavaClassMetric.java:94)
	at net.sourceforge.pmd.lang.java.metrics.impl.AbstractJavaClassMetric.countMatchingOpSigs(AbstractJavaClassMetric.java:52)
	at net.sourceforge.pmd.lang.java.metrics.impl.WocMetric.computeFor(WocMetric.java:35)
	at net.sourceforge.pmd.lang.java.metrics.impl.WocMetric.computeFor(WocMetric.java:20)
	at net.sourceforge.pmd.lang.metrics.AbstractMetricsComputer.computeForType(AbstractMetricsComputer.java:35)
	at net.sourceforge.pmd.lang.metrics.AbstractMetricsFacade.computeForType(AbstractMetricsFacade.java:67)
	at net.sourceforge.pmd.lang.java.metrics.JavaMetrics.get(JavaMetrics.java:55)
	at net.sourceforge.pmd.lang.java.rule.design.DataClassRule.interfaceRevealsData(DataClassRule.java:48)
	at net.sourceforge.pmd.lang.java.rule.design.DataClassRule.visit(DataClassRule.java:30)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule.visit(AbstractJavaMetricsRule.java:25)
	at net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration.jjtAccept(ASTClassOrInterfaceDeclaration.java:33)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:120)
	at net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration.jjtAccept(ASTClassOrInterfaceBodyDeclaration.java:41)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:116)
	at net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody.jjtAccept(ASTClassOrInterfaceBody.java:21)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule.visit(AbstractJavaMetricsRule.java:42)
	at net.sourceforge.pmd.lang.java.rule.design.DataClassRule.visit(DataClassRule.java:43)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule.visit(AbstractJavaMetricsRule.java:25)
	at net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration.jjtAccept(ASTClassOrInterfaceDeclaration.java:33)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:232)
	at net.sourceforge.pmd.lang.java.ast.ASTTypeDeclaration.jjtAccept(ASTTypeDeclaration.java:35)
	at net.sourceforge.pmd.lang.java.ast.AbstractJavaNode.childrenAccept(AbstractJavaNode.java:56)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:83)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visit(AbstractJavaRule.java:212)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.visitAll(AbstractJavaRule.java:39)
	at net.sourceforge.pmd.lang.java.rule.AbstractJavaRule.apply(AbstractJavaRule.java:27)
	at net.sourceforge.pmd.lang.rule.AbstractDelegateRule.apply(AbstractDelegateRule.java:321)
	at net.sourceforge.pmd.RuleSet.apply(RuleSet.java:502)
	at net.sourceforge.pmd.RuleSets.apply(RuleSets.java:143)
	at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:181)
	at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:95)
	at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:50)
	at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:75)
	at net.sourceforge.pmd.processor.MonoThreadProcessor.runAnalysis(MonoThreadProcessor.java:29)
	at net.sourceforge.pmd.processor.AbstractPMDProcessor.processFiles(AbstractPMDProcessor.java:111)
	at net.sourceforge.pmd.PMD.processFiles(PMD.java:315)
	at net.sourceforge.pmd.ant.internal.PMDTaskImpl.doTask(PMDTaskImpl.java:192)
	at net.sourceforge.pmd.ant.internal.PMDTaskImpl.execute(PMDTaskImpl.java:276)
	at net.sourceforge.pmd.ant.PMDTask.execute(PMDTask.java:49)
	at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
	at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
	at org.apache.tools.ant.Task.perform(Task.java:348)
	at org.apache.tools.ant.Target.execute(Target.java:435)
	at org.apache.tools.ant.Target.performTasks(Target.java:456)
	at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1405)
	at org.apache.tools.ant.Project.executeTarget(Project.java:1376)
	at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
	at org.eclipse.ant.internal.launching.remote.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:36)
	at org.apache.tools.ant.Project.executeTargets(Project.java:1260)
	at org.eclipse.ant.internal.launching.remote.InternalAntRunner.run(InternalAntRunner.java:460)
	at org.eclipse.ant.internal.launching.remote.InternalAntRunner.main(InternalAntRunner.java:142)

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4