Changeset 16784 in josm


Ignore:
Timestamp:
2020-07-17T17:12:54+02:00 (3 weeks ago)
Author:
GerdP
Message:

see #19180: false positives from tagchecker with single letter differences

  • avoid to produce "Value 'y' for key 'x' is unknown, maybe 'z' is meant?" when x=z produces a deprecated message. It uses all *.mapcss rules which are stored in files ending with deprecated.mapcss, so this will fail if user changed the name to something else, but it should work with e.g. my_deprecated.mapcss
Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    r16445 r16784  
    939939
    940940        if (partialSelection && !tested.isEmpty()) {
    941             // #14287: see https://josm.openstreetmap.de/ticket/14287#comment:15
    942             // execute tests for objects which might contain or cross previously tested elements
    943 
    944             // rebuild index with a reduced set of rules (those that use ChildOrParentSelector) and thus may have left selectors
    945             // matching the previously tested elements
    946             indexData = createMapCSSTagCheckerIndex(currentCheck, includeOtherSeverityChecks(), ONLY_SELECTED_TESTS);
    947 
    948             if (surrounding.isEmpty()) {
    949                 for (OsmPrimitive p : tested) {
    950                     if (p.getDataSet() != null) {
    951                         surrounding.addAll(p.getDataSet().searchWays(p.getBBox()));
    952                         surrounding.addAll(p.getDataSet().searchRelations(p.getBBox()));
    953                     }
    954                 }
    955             }
    956 
    957             final boolean includeOtherSeverity = includeOtherSeverityChecks();
    958             for (OsmPrimitive p : surrounding) {
    959                 if (tested.contains(p))
    960                     continue;
    961                 Collection<TestError> additionalErrors = getErrorsForPrimitive(p, includeOtherSeverity);
    962                 for (TestError e : additionalErrors) {
    963                     if (e.getPrimitives().stream().anyMatch(tested::contains))
    964                         addIfNotSimilar(e, errors);
    965                 }
    966             }
    967         }
     941            testPartial(currentCheck, tested, surrounding);
     942        }
     943    }
     944
     945    private void testPartial(MultiMap<String, TagCheck> currentCheck, Set<OsmPrimitive> tested,
     946            Set<OsmPrimitive> surrounding) {
     947
     948        // #14287: see https://josm.openstreetmap.de/ticket/14287#comment:15
     949        // execute tests for objects which might contain or cross previously tested elements
     950
     951        final boolean includeOtherSeverity = includeOtherSeverityChecks();
     952        // rebuild index with a reduced set of rules (those that use ChildOrParentSelector) and thus may have left selectors
     953        // matching the previously tested elements
     954        indexData = createMapCSSTagCheckerIndex(currentCheck, includeOtherSeverity, ONLY_SELECTED_TESTS);
     955        if (indexData.isEmpty())
     956            return; // performance: some *.mapcss rule files don't use ChildOrParentSelector
     957
     958        if (surrounding.isEmpty()) {
     959            for (OsmPrimitive p : tested) {
     960                if (p.getDataSet() != null) {
     961                    surrounding.addAll(p.getDataSet().searchWays(p.getBBox()));
     962                    surrounding.addAll(p.getDataSet().searchRelations(p.getBBox()));
     963                }
     964            }
     965        }
     966
     967        for (OsmPrimitive p : surrounding) {
     968            if (tested.contains(p))
     969                continue;
     970            Collection<TestError> additionalErrors = getErrorsForPrimitive(p, includeOtherSeverity);
     971            for (TestError e : additionalErrors) {
     972                if (e.getPrimitives().stream().anyMatch(tested::contains))
     973                    addIfNotSimilar(e, errors);
     974            }
     975        }
     976
     977    }
     978
     979    /**
     980     * Execute only the rules for the rules matching the given file name. See #19180
     981     * @param ruleFile the name of the mapcss file, e.g. deprecated.mapcss
     982     * @param selection collection of primitives
     983     * @since 16784
     984     */
     985    public void runOnly(String ruleFile, Collection<OsmPrimitive> selection) {
     986        mpAreaCache.clear();
     987
     988        Set<OsmPrimitive> surrounding = new HashSet<>();
     989        for (Entry<String, Set<TagCheck>> entry : checks.entrySet()) {
     990            if (isCanceled()) {
     991                break;
     992            }
     993            if (entry.getKey().endsWith(ruleFile)) {
     994                visit(entry.getKey(), entry.getValue(), selection, surrounding);
     995            }
     996        }
     997
    968998    }
    969999}
  • trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

    r16630 r16784  
    1818import java.util.HashMap;
    1919import java.util.HashSet;
     20import java.util.Iterator;
    2021import java.util.LinkedHashMap;
    2122import java.util.LinkedHashSet;
     
    4546import org.openstreetmap.josm.data.osm.Tagged;
    4647import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper;
     48import org.openstreetmap.josm.data.validation.OsmValidator;
    4749import org.openstreetmap.josm.data.validation.Severity;
    4850import org.openstreetmap.josm.data.validation.Test.TagTest;
     
    100102    /** The preferences prefix */
    101103    protected static final String PREFIX = ValidatorPrefHelper.PREFIX + "." + TagChecker.class.getSimpleName();
     104
     105    MapCSSTagChecker deprecatedChecker;
    102106
    103107    /**
     
    894898            // use Levenshtein distance to find typical typos
    895899            int minDist = MAX_LEVENSHTEIN_DISTANCE + 1;
    896             String closest = null;
    897900            for (Set<String> possibleValues: sets) {
    898901                for (String possibleVal : possibleValues) {
     
    911914                    }
    912915                    if (dist < minDist) {
    913                         closest = possibleVal;
    914916                        minDist = dist;
    915917                        fixVals.clear();
     
    920922                }
    921923            }
    922 
     924            filterDeprecatedTags(p, key, fixVals);
    923925            if (minDist <= MAX_LEVENSHTEIN_DISTANCE && maxPresetValueLen > MAX_LEVENSHTEIN_DISTANCE
     926                    && !fixVals.isEmpty()
    924927                    && (harmonizedValue.length() > 3 || minDist < MAX_LEVENSHTEIN_DISTANCE)) {
    925928                if (fixVals.size() < 2) {
    926                     fixedValue = closest;
     929                    fixedValue = fixVals.get(0);
    927930                } else {
    928931                    Collections.sort(fixVals);
     
    958961    }
    959962
     963    // see #19180
     964    private void filterDeprecatedTags(OsmPrimitive p, String key, List<String> fixVals) {
     965        if (fixVals.isEmpty() || deprecatedChecker == null)
     966            return;
     967
     968        String origVal = p.get(key);
     969        try {
     970            int unchangedDeprecated = countDeprecated(p);
     971            Iterator<String> iter = fixVals.iterator();
     972            while (iter.hasNext()) {
     973                p.put(key, iter.next());
     974                if (countDeprecated(p) > unchangedDeprecated)
     975                    iter.remove();
     976            }
     977        } finally {
     978            // restore original value
     979            p.put(key, origVal);
     980        }
     981    }
     982
     983    private int countDeprecated(OsmPrimitive p) {
     984        if (deprecatedChecker == null)
     985            return 0;
     986        deprecatedChecker.getErrors().clear();
     987        deprecatedChecker.runOnly("deprecated.mapcss", Collections.singleton(p));
     988        return deprecatedChecker.getErrors().size();
     989    }
     990
    960991    private static boolean isNum(String harmonizedValue) {
    961992        try {
     
    10081039            checkPresetsTypes = checkPresetsTypes && Config.getPref().getBoolean(PREF_CHECK_PRESETS_TYPES_BEFORE_UPLOAD, true);
    10091040        }
     1041        deprecatedChecker = OsmValidator.getTest(MapCSSTagChecker.class);
     1042    }
     1043
     1044    @Override
     1045    public void endTest() {
     1046        deprecatedChecker = null;
     1047        super.endTest();
    10101048    }
    10111049
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRuleIndex.java

    r16357 r16784  
    247247        remaining.clear();
    248248    }
     249
     250    /**
     251     * Check if this index is empty.
     252     * @return true if this index is empty.
     253     * @since 16784
     254     */
     255    public boolean isEmpty() {
     256        return rules.isEmpty();
     257    }
    249258}
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleIndex.java

    r16357 r16784  
    173173        return get(osm).getRuleCandidates(osm);
    174174    }
     175
     176    /**
     177     * Check if this index is empty.
     178     * @return true if this index is empty.
     179     * @since 16784
     180     */
     181    public boolean isEmpty() {
     182        return nodeRules.isEmpty() && wayRules.isEmpty() && wayNoAreaRules.isEmpty() && relationRules.isEmpty()
     183                && multipolygonRules.isEmpty() && canvasRules.isEmpty();
     184    }
    175185}
Note: See TracChangeset for help on using the changeset viewer.