Changeset 8435 in josm for trunk/src


Ignore:
Timestamp:
2015-05-31T17:06:27+02:00 (9 years ago)
Author:
Don-vip
Message:

fix #11498 - Warn about obvious misspelled tag values (modified patch by mdk) + javadoc

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

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

    r8378 r8435  
    1414    protected final Command fix;
    1515
     16    /**
     17     * Constructs a new {@code FixableTestError} for a single primitive.
     18     * @param tester The tester
     19     * @param severity The severity of this error
     20     * @param message The error message
     21     * @param code The test error reference code
     22     * @param primitive The affected primitive
     23     * @param fix The command used to fix the error
     24     */
    1625    public FixableTestError(Test tester, Severity severity, String message, int code, OsmPrimitive primitive, Command fix) {
    1726        super(tester, severity, message, code, primitive);
     
    1928    }
    2029
    21     public FixableTestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives, Command fix) {
     30    /**
     31     * Constructs a new {@code FixableTestError} for multiple primitives.
     32     * @param tester The tester
     33     * @param severity The severity of this error
     34     * @param message The error message
     35     * @param code The test error reference code
     36     * @param primitives The affected primitives
     37     * @param fix The command used to fix the error
     38     */
     39    public FixableTestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives,
     40            Command fix) {
    2241        super(tester, severity, message, code, primitives);
    2342        this.fix = fix;
    2443    }
    2544
    26     public FixableTestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives, Collection<?> highlighted, Command fix) {
     45    /**
     46     * Constructs a new {@code FixableTestError} for multiple primitives.
     47     * @param tester The tester
     48     * @param severity The severity of this error
     49     * @param message The error message
     50     * @param code The test error reference code
     51     * @param primitives The affected primitives
     52     * @param highlighted OSM primitives to highlight
     53     * @param fix The command used to fix the error
     54     */
     55    public FixableTestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives,
     56            Collection<?> highlighted, Command fix) {
    2757        super(tester, severity, message, code, primitives, highlighted);
    2858        this.fix = fix;
    2959    }
    3060
    31     public FixableTestError(Test tester, Severity severity, String message, String description, String description_en, int code, OsmPrimitive primitive, Command fix) {
    32         super(tester, severity, message, description, description_en, code, primitive);
     61    /**
     62     * Constructs a new {@code FixableTestError} for a single primitive.
     63     * @param tester The tester
     64     * @param severity The severity of this error
     65     * @param message The error message
     66     * @param description The translated description
     67     * @param descriptionEn The English description
     68     * @param code The test error reference code
     69     * @param primitive The affected primitive
     70     * @param fix The command used to fix the error
     71     */
     72    public FixableTestError(Test tester, Severity severity, String message, String description, String descriptionEn, int code,
     73            OsmPrimitive primitive, Command fix) {
     74        super(tester, severity, message, description, descriptionEn, code, primitive);
    3375        this.fix = fix;
    3476    }
    3577
    36     public FixableTestError(Test tester, Severity severity, String message, String description, String description_en, int code, Collection<? extends OsmPrimitive> primitives, Command fix) {
    37         super(tester, severity, message, description, description_en, code, primitives);
     78    /**
     79     * Constructs a new {@code FixableTestError} for multiple primitives.
     80     * @param tester The tester
     81     * @param severity The severity of this error
     82     * @param message The error message
     83     * @param description The translated description
     84     * @param descriptionEn The English description
     85     * @param code The test error reference code
     86     * @param primitives The affected primitives
     87     * @param fix The command used to fix the error
     88     */
     89    public FixableTestError(Test tester, Severity severity, String message, String description, String descriptionEn, int code,
     90            Collection<? extends OsmPrimitive> primitives, Command fix) {
     91        super(tester, severity, message, description, descriptionEn, code, primitives);
    3892        this.fix = fix;
    3993    }
    4094
    41     public FixableTestError(Test tester, Severity severity, String message, String description, String description_en, int code, Collection<? extends OsmPrimitive> primitives, Collection<?> highlighted, Command fix) {
    42         super(tester, severity, message, description, description_en, code, primitives, highlighted);
     95    /**
     96     * Constructs a new {@code FixableTestError} for multiple primitives.
     97     * @param tester The tester
     98     * @param severity The severity of this error
     99     * @param message The error message
     100     * @param description The translated description
     101     * @param descriptionEn The English description
     102     * @param code The test error reference code
     103     * @param primitives The affected primitives
     104     * @param highlighted OSM primitives to highlight
     105     * @param fix The command used to fix the error
     106     */
     107    public FixableTestError(Test tester, Severity severity, String message, String description, String descriptionEn, int code,
     108            Collection<? extends OsmPrimitive> primitives, Collection<?> highlighted, Command fix) {
     109        super(tester, severity, message, description, descriptionEn, code, primitives, highlighted);
    43110        this.fix = fix;
    44111    }
  • trunk/src/org/openstreetmap/josm/data/validation/TestError.java

    r8390 r8435  
    5757     * @param severity The severity of this error
    5858     * @param message The error message
     59     * @param description The translated description
     60     * @param descriptionEn The English description
    5961     * @param primitives The affected primitives
    6062     * @param code The test error reference code
    61      */
    62     public TestError(Test tester, Severity severity, String message, String description, String description_en,
     63     * @param highlighted OSM primitives to highlight
     64     */
     65    public TestError(Test tester, Severity severity, String message, String description, String descriptionEn,
    6366            int code, Collection<? extends OsmPrimitive> primitives, Collection<?> highlighted) {
    6467        this.tester = tester;
     
    6669        this.message = message;
    6770        this.description = description;
    68         this.descriptionEn = description_en;
     71        this.descriptionEn = descriptionEn;
    6972        this.primitives = primitives;
    7073        this.highlighted = highlighted;
     
    7275    }
    7376
     77    /**
     78     * Constructs a new {@code TestError} without description.
     79     * @param tester The tester
     80     * @param severity The severity of this error
     81     * @param message The error message
     82     * @param primitives The affected primitives
     83     * @param code The test error reference code
     84     * @param highlighted OSM primitives to highlight
     85     */
    7486    public TestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives,
    7587            Collection<?> highlighted) {
     
    7789    }
    7890
    79     public TestError(Test tester, Severity severity, String message, String description, String description_en,
     91    /**
     92     * Constructs a new {@code TestError}.
     93     * @param tester The tester
     94     * @param severity The severity of this error
     95     * @param message The error message
     96     * @param description The translated description
     97     * @param descriptionEn The English description
     98     * @param primitives The affected primitives
     99     * @param code The test error reference code
     100     */
     101    public TestError(Test tester, Severity severity, String message, String description, String descriptionEn,
    80102            int code, Collection<? extends OsmPrimitive> primitives) {
    81         this(tester, severity, message, description, description_en, code, primitives, primitives);
    82     }
    83 
     103        this(tester, severity, message, description, descriptionEn, code, primitives, primitives);
     104    }
     105
     106    /**
     107     * Constructs a new {@code TestError} without description.
     108     * @param tester The tester
     109     * @param severity The severity of this error
     110     * @param message The error message
     111     * @param primitives The affected primitives
     112     * @param code The test error reference code
     113     */
    84114    public TestError(Test tester, Severity severity, String message, int code, Collection<? extends OsmPrimitive> primitives) {
    85115        this(tester, severity, message, null, null, code, primitives, primitives);
    86116    }
    87117
     118    /**
     119     * Constructs a new {@code TestError} without description, for a single primitive.
     120     * @param tester The tester
     121     * @param severity The severity of this error
     122     * @param message The error message
     123     * @param primitive The affected primitive
     124     * @param code The test error reference code
     125     */
    88126    public TestError(Test tester, Severity severity, String message, int code, OsmPrimitive primitive) {
    89127        this(tester, severity, message, null, null, code, Collections.singletonList(primitive), Collections
     
    91129    }
    92130
    93     public TestError(Test tester, Severity severity, String message, String description, String description_en,
     131    /**
     132     * Constructs a new {@code TestError} for a single primitive.
     133     * @param tester The tester
     134     * @param severity The severity of this error
     135     * @param message The error message
     136     * @param description The translated description
     137     * @param descriptionEn The English description
     138     * @param primitive The affected primitive
     139     * @param code The test error reference code
     140     */
     141    public TestError(Test tester, Severity severity, String message, String description, String descriptionEn,
    94142            int code, OsmPrimitive primitive) {
    95         this(tester, severity, message, description, description_en, code, Collections.singletonList(primitive));
     143        this(tester, severity, message, description, descriptionEn, code, Collections.singletonList(primitive));
    96144    }
    97145
  • trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

    r8404 r8435  
    3939import org.openstreetmap.josm.data.osm.OsmUtils;
    4040import org.openstreetmap.josm.data.osm.Tag;
     41import org.openstreetmap.josm.data.validation.FixableTestError;
    4142import org.openstreetmap.josm.data.validation.Severity;
    42 import org.openstreetmap.josm.data.validation.Test;
     43import org.openstreetmap.josm.data.validation.Test.TagTest;
    4344import org.openstreetmap.josm.data.validation.TestError;
    4445import org.openstreetmap.josm.data.validation.util.Entities;
     
    5657import org.openstreetmap.josm.tools.GBC;
    5758import org.openstreetmap.josm.tools.MultiMap;
     59import org.openstreetmap.josm.tools.Utils;
    5860
    5961/**
     
    6163 *
    6264 * @author frsantos
     65 * @since 3669
    6366 */
    64 public class TagChecker extends Test.TagTest {
    65 
    66     /** The default data file of tagchecker rules */
    67     //public static final String DATA_FILE = "resource://data/validator/tagchecker.cfg";
     67public class TagChecker extends TagTest {
     68
    6869    /** The config file of ignored tags */
    6970    public static final String IGNORE_FILE = "resource://data/validator/ignoretags.cfg";
     
    125126    protected static final int LOW_CHAR_VALUE    = 1210;
    126127    protected static final int LOW_CHAR_KEY      = 1211;
     128    protected static final int MISSPELLED_VALUE  = 1212;
    127129    /** 1250 and up is used by tagcheck */
    128130
     
    324326            for (CheckerData d : checkerData) {
    325327                if (d.match(p, keys)) {
    326                     errors.add( new TestError(this, d.getSeverity(), tr("Suspicious tag/value combinations"),
    327                             d.getDescription(), d.getDescriptionOrig(), d.getCode(), p) );
     328                    errors.add(new TestError(this, d.getSeverity(), tr("Suspicious tag/value combinations"),
     329                            d.getDescription(), d.getDescriptionOrig(), d.getCode(), p));
    328330                    withErrors.put(p, "TC");
    329331                }
     
    336338            String value = prop.getValue();
    337339            if (checkValues && (containsLow(value)) && !withErrors.contains(p, "ICV")) {
    338                 errors.add( new TestError(this, Severity.WARNING, tr("Tag value contains character with code less than 0x20"),
    339                         tr(s, key), MessageFormat.format(s, key), LOW_CHAR_VALUE, p) );
     340                errors.add(new TestError(this, Severity.WARNING, tr("Tag value contains character with code less than 0x20"),
     341                        tr(s, key), MessageFormat.format(s, key), LOW_CHAR_VALUE, p));
    340342                withErrors.put(p, "ICV");
    341343            }
    342344            if (checkKeys && (containsLow(key)) && !withErrors.contains(p, "ICK")) {
    343                 errors.add( new TestError(this, Severity.WARNING, tr("Tag key contains character with code less than 0x20"),
    344                         tr(s, key), MessageFormat.format(s, key), LOW_CHAR_KEY, p) );
     345                errors.add(new TestError(this, Severity.WARNING, tr("Tag key contains character with code less than 0x20"),
     346                        tr(s, key), MessageFormat.format(s, key), LOW_CHAR_KEY, p));
    345347                withErrors.put(p, "ICK");
    346348            }
    347349            if (checkValues && (value!=null && value.length() > 255) && !withErrors.contains(p, "LV")) {
    348                 errors.add( new TestError(this, Severity.ERROR, tr("Tag value longer than allowed"),
    349                         tr(s, key), MessageFormat.format(s, key), LONG_VALUE, p) );
     350                errors.add(new TestError(this, Severity.ERROR, tr("Tag value longer than allowed"),
     351                        tr(s, key), MessageFormat.format(s, key), LONG_VALUE, p));
    350352                withErrors.put(p, "LV");
    351353            }
    352354            if (checkKeys && (key!=null && key.length() > 255) && !withErrors.contains(p, "LK")) {
    353                 errors.add( new TestError(this, Severity.ERROR, tr("Tag key longer than allowed"),
    354                         tr(s, key), MessageFormat.format(s, key), LONG_KEY, p) );
     355                errors.add(new TestError(this, Severity.ERROR, tr("Tag key longer than allowed"),
     356                        tr(s, key), MessageFormat.format(s, key), LONG_KEY, p));
    355357                withErrors.put(p, "LK");
    356358            }
    357359            if (checkValues && (value==null || value.trim().isEmpty()) && !withErrors.contains(p, "EV")) {
    358                 errors.add( new TestError(this, Severity.WARNING, tr("Tags with empty values"),
    359                         tr(s, key), MessageFormat.format(s, key), EMPTY_VALUES, p) );
     360                errors.add(new TestError(this, Severity.WARNING, tr("Tags with empty values"),
     361                        tr(s, key), MessageFormat.format(s, key), EMPTY_VALUES, p));
    360362                withErrors.put(p, "EV");
    361363            }
    362364            if (checkKeys && spellCheckKeyData.containsKey(key) && !withErrors.contains(p, "IPK")) {
    363                 errors.add( new TestError(this, Severity.WARNING, tr("Invalid property key"),
    364                         tr(s, key), MessageFormat.format(s, key), INVALID_KEY, p) );
     365                errors.add(new TestError(this, Severity.WARNING, tr("Invalid property key"),
     366                        tr(s, key), MessageFormat.format(s, key), INVALID_KEY, p));
    365367                withErrors.put(p, "IPK");
    366368            }
    367369            if (checkKeys && key != null && key.indexOf(' ') >= 0 && !withErrors.contains(p, "IPK")) {
    368                 errors.add( new TestError(this, Severity.WARNING, tr("Invalid white space in property key"),
    369                         tr(s, key), MessageFormat.format(s, key), INVALID_KEY_SPACE, p) );
     370                errors.add(new TestError(this, Severity.WARNING, tr("Invalid white space in property key"),
     371                        tr(s, key), MessageFormat.format(s, key), INVALID_KEY_SPACE, p));
    370372                withErrors.put(p, "IPK");
    371373            }
    372374            if (checkValues && value != null && (value.startsWith(" ") || value.endsWith(" ")) && !withErrors.contains(p, "SPACE")) {
    373                 errors.add( new TestError(this, Severity.WARNING, tr("Property values start or end with white space"),
    374                         tr(s, key), MessageFormat.format(s, key), INVALID_SPACE, p) );
     375                errors.add(new TestError(this, Severity.WARNING, tr("Property values start or end with white space"),
     376                        tr(s, key), MessageFormat.format(s, key), INVALID_SPACE, p));
    375377                withErrors.put(p, "SPACE");
    376378            }
    377379            if (checkValues && value != null && !value.equals(entities.unescape(value)) && !withErrors.contains(p, "HTML")) {
    378                 errors.add( new TestError(this, Severity.OTHER, tr("Property values contain HTML entity"),
    379                         tr(s, key), MessageFormat.format(s, key), INVALID_HTML, p) );
     380                errors.add(new TestError(this, Severity.OTHER, tr("Property values contain HTML entity"),
     381                        tr(s, key), MessageFormat.format(s, key), INVALID_HTML, p));
    380382                withErrors.put(p, "HTML");
    381383            }
     
    413415                    if (!keyInPresets) {
    414416                        String i = marktr("Key ''{0}'' not in presets.");
    415                         errors.add( new TestError(this, Severity.OTHER, tr("Presets do not contain property key"),
    416                                 tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p) );
     417                        errors.add(new TestError(this, Severity.OTHER, tr("Presets do not contain property key"),
     418                                tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p));
    417419                        withErrors.put(p, "UPK");
    418420                    } else if (!tagInPresets) {
    419                         String i = marktr("Value ''{0}'' for key ''{1}'' not in presets.");
    420                         errors.add( new TestError(this, Severity.OTHER, tr("Presets do not contain property value"),
    421                                 tr(i, prop.getValue(), key), MessageFormat.format(i, prop.getValue(), key), INVALID_VALUE, p) );
    422                         withErrors.put(p, "UPV");
     421                        // try to fix common typos and check again if value is still unknown
     422                        String fixedValue = prettifyValue(prop.getValue());
     423                        if (values != null && values.contains(fixedValue)) {
     424                            // misspelled preset value
     425                            String i = marktr("Value ''{0}'' for key ''{1}'' looks like ''{2}}.");
     426                            errors.add(new FixableTestError(this, Severity.WARNING, tr("Misspelled property value"),
     427                                    tr(i, prop.getValue(), key, fixedValue), MessageFormat.format(i, prop.getValue(), fixedValue),
     428                                    MISSPELLED_VALUE, p, new ChangePropertyCommand(p, key, fixedValue)));
     429                            withErrors.put(p, "WPV");
     430                        } else {
     431                            // unknown preset value
     432                            String i = marktr("Value ''{0}'' for key ''{1}'' not in presets.");
     433                            errors.add(new TestError(this, Severity.OTHER, tr("Presets do not contain property value"),
     434                                    tr(i, prop.getValue(), key), MessageFormat.format(i, prop.getValue(), key), INVALID_VALUE, p));
     435                            withErrors.put(p, "UPV");
     436                        }
    423437                    }
    424438                }
     
    435449            }
    436450        }
     451    }
     452
     453    private static String prettifyValue(String value) {
     454        // convert to lower case, replace ' ' or '-' with '_'
     455        value = value.toLowerCase(Locale.ENGLISH).replace('-', '_').replace(' ', '_');
     456        // remove trailing or leading special chars
     457        return Utils.strip(value, "-_;:,");
    437458    }
    438459
     
    554575        List<Command> commands = new ArrayList<>(50);
    555576
    556         Collection<? extends OsmPrimitive> primitives = testError.getPrimitives();
    557         for (OsmPrimitive p : primitives) {
    558             Map<String, String> tags = p.getKeys();
    559             if (tags == null || tags.isEmpty()) {
    560                 continue;
    561             }
    562 
    563             for (Entry<String, String> prop: tags.entrySet()) {
    564                 String key = prop.getKey();
    565                 String value = prop.getValue();
    566                 if (value == null || value.trim().isEmpty()) {
    567                     commands.add(new ChangePropertyCommand(p, key, null));
    568                 } else if (value.startsWith(" ") || value.endsWith(" ")) {
    569                     commands.add(new ChangePropertyCommand(p, key, Tag.removeWhiteSpaces(value)));
    570                 } else if (key.startsWith(" ") || key.endsWith(" ")) {
    571                     commands.add(new ChangePropertyKeyCommand(p, key, Tag.removeWhiteSpaces(key)));
    572                 } else {
    573                     String evalue = entities.unescape(value);
    574                     if (!evalue.equals(value)) {
    575                         commands.add(new ChangePropertyCommand(p, key, evalue));
     577        if (testError instanceof FixableTestError) {
     578            commands.add(testError.getFix());
     579        } else {
     580            Collection<? extends OsmPrimitive> primitives = testError.getPrimitives();
     581            for (OsmPrimitive p : primitives) {
     582                Map<String, String> tags = p.getKeys();
     583                if (tags == null || tags.isEmpty()) {
     584                    continue;
     585                }
     586
     587                for (Entry<String, String> prop: tags.entrySet()) {
     588                    String key = prop.getKey();
     589                    String value = prop.getValue();
     590                    if (value == null || value.trim().isEmpty()) {
     591                        commands.add(new ChangePropertyCommand(p, key, null));
     592                    } else if (value.startsWith(" ") || value.endsWith(" ")) {
     593                        commands.add(new ChangePropertyCommand(p, key, Tag.removeWhiteSpaces(value)));
     594                    } else if (key.startsWith(" ") || key.endsWith(" ")) {
     595                        commands.add(new ChangePropertyKeyCommand(p, key, Tag.removeWhiteSpaces(key)));
    576596                    } else {
    577                         String replacementKey = spellCheckKeyData.get(key);
    578                         if (replacementKey != null) {
    579                             commands.add(new ChangePropertyKeyCommand(p, key, replacementKey));
     597                        String evalue = entities.unescape(value);
     598                        if (!evalue.equals(value)) {
     599                            commands.add(new ChangePropertyCommand(p, key, evalue));
     600                        } else {
     601                            String replacementKey = spellCheckKeyData.get(key);
     602                            if (replacementKey != null) {
     603                                commands.add(new ChangePropertyKeyCommand(p, key, replacementKey));
     604                            }
    580605                        }
    581606                    }
     
    596621        if (testError.getTester() instanceof TagChecker) {
    597622            int code = testError.getCode();
    598             return code == INVALID_KEY || code == EMPTY_VALUES || code == INVALID_SPACE || code == INVALID_KEY_SPACE || code == INVALID_HTML;
     623            return code == INVALID_KEY || code == EMPTY_VALUES || code == INVALID_SPACE ||
     624                   code == INVALID_KEY_SPACE || code == INVALID_HTML || code == MISSPELLED_VALUE;
    599625        }
    600626
  • trunk/src/org/openstreetmap/josm/tools/Utils.java

    r8429 r8435  
    4040import java.util.Collection;
    4141import java.util.Collections;
     42import java.util.HashSet;
    4243import java.util.Iterator;
    4344import java.util.List;
    4445import java.util.Locale;
     46import java.util.Set;
    4547import java.util.concurrent.ExecutorService;
    4648import java.util.concurrent.Executors;
     
    899901     * @since 5772
    900902     */
    901     public static String strip(String str) {
     903    public static String strip(final String str) {
     904        return strip(str, null);
     905    }
     906
     907    /**
     908     * An alternative to {@link String#trim()} to effectively remove all leading and trailing white characters, including Unicode ones.
     909     * @param str The string to strip
     910     * @param skipChars additional characters to skip
     911     * @return <code>str</code>, without leading and trailing characters, according to
     912     *         {@link Character#isWhitespace(char)}, {@link Character#isSpaceChar(char)} and skipChars.
     913     * @since 8435
     914     */
     915    public static String strip(final String str, final String skipChars) {
    902916        if (str == null || str.isEmpty()) {
    903917            return str;
    904918        }
    905         int start = 0, end = str.length();
    906         boolean leadingWhite = true;
    907         while (leadingWhite && start < end) {
     919        // create set with chars to skip
     920        Set<Character> skipSet = new HashSet<>();
     921        // '\u200B' (ZERO WIDTH SPACE character) needs to be handled manually because of change in Unicode 6.0 (Java 7, see #8918)
     922        skipSet.add('\u200B');
     923        // same for '\uFEFF' (ZERO WIDTH NO-BREAK SPACE)
     924        skipSet.add('\uFEFF');
     925        if (skipChars != null) {
     926            for (char c : skipChars.toCharArray()) {
     927                skipSet.add(c);
     928            }
     929        }
     930        int start = 0;
     931        int end = str.length();
     932        boolean leadingSkipChar = true;
     933        while (leadingSkipChar && start < end) {
    908934            char c = str.charAt(start);
    909             // '\u200B' (ZERO WIDTH SPACE character) needs to be handled manually because of change in Unicode 6.0 (Java 7, see #8918)
    910             // same for '\uFEFF' (ZERO WIDTH NO-BREAK SPACE)
    911             leadingWhite = (Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\u200B' || c == '\uFEFF');
    912             if (leadingWhite) {
     935            leadingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || skipSet.contains(c);
     936            if (leadingSkipChar) {
    913937                start++;
    914938            }
    915939        }
    916         boolean trailingWhite = true;
    917         while (trailingWhite && end > start+1) {
     940        boolean trailingSkipChar = true;
     941        while (trailingSkipChar && end > start+1) {
    918942            char c = str.charAt(end-1);
    919             trailingWhite = (Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\u200B' || c == '\uFEFF');
    920             if (trailingWhite) {
     943            trailingSkipChar = Character.isWhitespace(c) || Character.isSpaceChar(c) || skipSet.contains(c);
     944            if (trailingSkipChar) {
    921945                end--;
    922946            }
Note: See TracChangeset for help on using the changeset viewer.