Changeset 19201 in josm for trunk/src


Ignore:
Timestamp:
2024-08-19T23:47:08+02:00 (5 months ago)
Author:
taylor.smock
Message:

Fix #23290: Exclude incomplete relations from region checks

Also rework TagCheckerTest to use parameterized tests.

File:
1 edited

Legend:

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

    r19195 r19201  
    184184    private static final int MAX_LEVENSHTEIN_DISTANCE = 2;
    185185
     186    /* Common string values */
     187    private static final String FIXME_STR = marktr("fixme");
     188    private static final String MULTIPOLYGON_TAGS = marktr("Multipolygon tags");
     189    private static final String SEAMARK_TYPE = "seamark:type";
     190
    186191    protected boolean includeOtherSeverity;
    187192
     
    293298                BufferedReader reader = cf.getContentReader()
    294299            ) {
    295                 String okValue = null;
    296                 boolean tagcheckerfile = false;
    297                 boolean ignorefile = false;
    298                 boolean isFirstLine = true;
    299                 String line;
    300                 while ((line = reader.readLine()) != null) {
    301                     if (line.isEmpty()) {
    302                         // ignore
    303                     } else if (line.startsWith("#")) {
    304                         if (line.startsWith("# JOSM TagChecker")) {
    305                             tagcheckerfile = true;
    306                             Logging.error(tr("Ignoring {0}. Support was dropped", source));
    307                         } else
    308                         if (line.startsWith("# JOSM IgnoreTags")) {
    309                             ignorefile = true;
    310                             if (!DEFAULT_SOURCES.contains(source)) {
    311                                 Logging.info(tr("Adding {0} to ignore tags", source));
    312                             }
    313                         }
    314                     } else if (ignorefile) {
    315                         parseIgnoreFileLine(source, line);
    316                     } else if (tagcheckerfile) {
    317                         // ignore
    318                     } else if (line.charAt(0) == '+') {
    319                         okValue = line.substring(1);
    320                     } else if (line.charAt(0) == '-' && okValue != null) {
    321                         String hk = harmonizeKey(line.substring(1));
    322                         if (!okValue.equals(hk) && harmonizedKeys.put(hk, okValue) != null && Logging.isDebugEnabled()) {
    323                             Logging.debug("Line was ignored: " + line);
    324                         }
    325                     } else {
    326                         Logging.error(tr("Invalid spellcheck line: {0}", line));
    327                     }
    328                     if (isFirstLine) {
    329                         isFirstLine = false;
    330                         if (!(tagcheckerfile || ignorefile) && !DEFAULT_SOURCES.contains(source)) {
    331                             Logging.info(tr("Adding {0} to spellchecker", source));
    332                         }
    333                     }
    334                 }
     300                parseSource(source, reader);
    335301            } catch (IOException e) {
    336302                Logging.error(e);
     
    343309                    "Could not access data file:\n{0}",
    344310                    "Could not access data files:\n{0}", errorSources.length(), errorSources));
     311    }
     312
     313    private static void parseSource(String source, BufferedReader reader) throws IOException {
     314        String okValue = null;
     315        boolean tagcheckerfile = false;
     316        boolean ignorefile = false;
     317        boolean isFirstLine = true;
     318        String line;
     319        while ((line = reader.readLine()) != null) {
     320            if (line.isEmpty()) {
     321                // ignore
     322            } else if (line.startsWith("#")) {
     323                if (line.startsWith("# JOSM TagChecker")) {
     324                    tagcheckerfile = true;
     325                    Logging.error(tr("Ignoring {0}. Support was dropped", source));
     326                } else
     327                if (line.startsWith("# JOSM IgnoreTags")) {
     328                    ignorefile = true;
     329                    if (!DEFAULT_SOURCES.contains(source)) {
     330                        Logging.info(tr("Adding {0} to ignore tags", source));
     331                    }
     332                }
     333            } else if (ignorefile) {
     334                parseIgnoreFileLine(source, line);
     335            } else if (tagcheckerfile) {
     336                // ignore
     337            } else if (line.charAt(0) == '+') {
     338                okValue = line.substring(1);
     339            } else if (line.charAt(0) == '-' && okValue != null) {
     340                String hk = harmonizeKey(line.substring(1));
     341                if (!okValue.equals(hk) && harmonizedKeys.put(hk, okValue) != null && Logging.isDebugEnabled()) {
     342                    Logging.debug("Line was ignored: " + line);
     343                }
     344            } else {
     345                Logging.error(tr("Invalid spellcheck line: {0}", line));
     346            }
     347            if (isFirstLine) {
     348                isFirstLine = false;
     349                if (!(tagcheckerfile || ignorefile) && !DEFAULT_SOURCES.contains(source)) {
     350                    Logging.info(tr("Adding {0} to spellchecker", source));
     351                }
     352            }
     353        }
    345354    }
    346355
     
    435444        additionalPresetsValueData.addAll(Config.getPref().getList(
    436445                ValidatorPrefHelper.PREFIX + ".knownkeys",
    437                 Arrays.asList("is_in", "int_ref", "fixme", "population")));
     446                Arrays.asList("is_in", "int_ref", FIXME_STR, "population")));
    438447    }
    439448
     
    584593     * @deprecated since 18281 -- use {@link TaggingPresets#isKeyInPresets(String)} instead
    585594     */
    586     @Deprecated
     595    @Deprecated(since = "18281", forRemoval = true)
    587596    public static boolean isKeyInPresets(String key) {
    588597        return TaggingPresets.isKeyInPresets(key);
     
    667676            if (checkFixmes && key != null && !Utils.isEmpty(value) && isFixme(key, value) && !withErrors.contains(p, "FIXME")) {
    668677                errors.add(TestError.builder(this, Severity.OTHER, FIXME)
    669                         .message(tr("fixme"))
     678                        .message(tr(FIXME_STR))
    670679                        .primitives(p)
    671680                        .build());
     
    867876            return ((IWay<?>) primitive).getNodes().stream().anyMatch(n -> primitiveInRegions(n, regions, excludeRegions));
    868877        } else if (primitive instanceof IRelation) {
    869             return ((IRelation<?>) primitive).getMemberPrimitivesList().stream().anyMatch(p -> primitiveInRegions(p, regions, excludeRegions));
     878            final IRelation<?> relation = (IRelation<?>) primitive;
     879            if (relation.hasIncompleteMembers()) {
     880                return true; // Assume that the relation has members in a valid area. See #23290.
     881            }
     882            return relation.getMemberPrimitivesList().stream().anyMatch(p -> primitiveInRegions(p, regions, excludeRegions));
    870883        }
    871884        throw new IllegalArgumentException("Unknown primitive type: " + primitive);
     
    904917            // accept often used tag surface=* as area tag
    905918            builder = TestError.builder(this, Severity.OTHER, MULTIPOLYGON_INCOMPLETE)
    906                     .message(tr("Multipolygon tags"), marktr("only {0} tag"), "surface");
     919                    .message(tr(MULTIPOLYGON_TAGS), marktr("only {0} tag"), "surface");
    907920        } else {
    908921            Map<String, String> filteredTags = p.getInterestingTags();
     
    913926            if (filteredTags.isEmpty()) {
    914927                builder = TestError.builder(this, Severity.ERROR, MULTIPOLYGON_NO_AREA)
    915                         .message(tr("Multipolygon tags"), marktr("tag describing the area is missing"), new Object());
     928                        .message(tr(MULTIPOLYGON_TAGS), marktr("tag describing the area is missing"), new Object());
    916929
    917930            }
     
    920933            // multipolygon has either no area tag or a rarely used one
    921934            builder = TestError.builder(this, Severity.WARNING, MULTIPOLYGON_MAYBE_NO_AREA)
    922                     .message(tr("Multipolygon tags"), marktr("tag describing the area might be missing"), new Object());
     935                    .message(tr(MULTIPOLYGON_TAGS), marktr("tag describing the area might be missing"), new Object());
    923936        }
    924937        errors.add(builder.primitives(p).build());
     
    984997                || p.hasTag("indoor", "corridor", "room", "area")
    985998                || p.hasTag("power", "substation", "generator", "plant", "switchgear", "converter", "sub_station")
    986                 || p.hasTag("seamark:type", "harbour", "fairway", "anchorage", "landmark", "berth", "harbour_basin",
     999                || p.hasTag(SEAMARK_TYPE, "harbour", "fairway", "anchorage", "landmark", "berth", "harbour_basin",
    9871000                        "separation_zone")
    988                 || (p.get("seamark:type") != null && p.get("seamark:type").matches(".*\\_(area|zone)$")))
     1001                || (p.get(SEAMARK_TYPE) != null && p.get(SEAMARK_TYPE).matches(".*\\_(area|zone)$")))
    9891002            return true;
    9901003        return p.hasTag("harbour", OsmUtils.TRUE_VALUE)
     
    12591272
    12601273    private static boolean isFixme(String key, String value) {
    1261         return key.toLowerCase(Locale.ENGLISH).contains("fixme") || key.contains("todo")
    1262           || value.toLowerCase(Locale.ENGLISH).contains("fixme") || value.contains("check and delete");
     1274        return key.toLowerCase(Locale.ENGLISH).contains(FIXME_STR) || key.contains("todo")
     1275          || value.toLowerCase(Locale.ENGLISH).contains(FIXME_STR) || value.contains("check and delete");
    12631276    }
    12641277
Note: See TracChangeset for help on using the changeset viewer.