Changeset 18757 in josm for trunk/src/org


Ignore:
Timestamp:
2023-06-14T18:01:00+02:00 (18 months ago)
Author:
taylor.smock
Message:

Fix #17669, #22096: Allow placeholders in more locations in MapCSS

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

Legend:

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

    r18365 r18757  
    232232                final Selector selector = check.whichSelectorMatchesEnvironment(env);
    233233                if (selector != null) {
    234                     check.rule.declaration.execute(env);
     234                    final Environment envWithSelector = env.withSelector(selector);
     235                    check.rule.declaration.execute(envWithSelector);
    235236                    if (!ignoreError && !check.errors.isEmpty()) {
    236                         r.addAll(check.getErrorsForPrimitive(p, selector, env, new MapCSSTagCheckerAndRule(check.rule)));
     237                        r.addAll(check.getErrorsForPrimitive(p, selector, envWithSelector, new MapCSSTagCheckerAndRule(check.rule)));
    237238                    }
    238239                }
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerAsserts.java

    r18365 r18757  
    7575                Command fix = check.fixPrimitive(p);
    7676                if (fix != null && fix.executeCommand() && !MapCSSTagChecker.getErrorsForPrimitive(p, true, checksToRun).isEmpty()) {
    77                     assertionConsumer.accept(MessageFormat.format("Autofix does not work for test ''{0}'' (i.e., {1})",
    78                             check.getMessage(p), check.rule.selectors));
     77                    assertionConsumer.accept(MessageFormat.format("Autofix does not work for test ''{0}'' (i.e., {1}). Failing test: {2}",
     78                            check.getMessage(p), check.rule.selectors, i.getKey()));
    7979                }
    8080            }
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerFixCommand.java

    r17620 r18757  
    4949        final String s;
    5050        if (obj instanceof Expression) {
    51             s = (String) ((Expression) obj).evaluate(new Environment(p));
     51            s = (String) ((Expression) obj).evaluate(new Environment(p).withSelector(matchingSelector));
    5252        } else if (obj instanceof String) {
    5353            s = (String) obj;
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerRule.java

    r18365 r18757  
    1818import java.util.function.Consumer;
    1919import java.util.function.Predicate;
    20 import java.util.regex.Matcher;
    21 import java.util.regex.Pattern;
    2220import java.util.stream.Collectors;
    2321
     
    2725import org.openstreetmap.josm.data.osm.IPrimitive;
    2826import org.openstreetmap.josm.data.osm.OsmPrimitive;
    29 import org.openstreetmap.josm.data.osm.Tag;
    3027import org.openstreetmap.josm.data.osm.Way;
    3128import org.openstreetmap.josm.data.osm.WaySegment;
     
    3532import org.openstreetmap.josm.gui.mappaint.Environment;
    3633import org.openstreetmap.josm.gui.mappaint.Keyword;
     34import org.openstreetmap.josm.gui.mappaint.MultiCascade;
    3735import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
    38 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.TagCondition;
    3936import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
    4037import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
    4138import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule;
    4239import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
     40import org.openstreetmap.josm.gui.mappaint.mapcss.PlaceholderExpression;
    4341import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
    4442import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser;
     
    215213
    216214    Selector whichSelectorMatchesPrimitive(OsmPrimitive primitive) {
    217         return whichSelectorMatchesEnvironment(new Environment(primitive));
     215        return whichSelectorMatchesEnvironment(new Environment(primitive, new MultiCascade(), Environment.DEFAULT_LAYER, null));
    218216    }
    219217
     
    226224
    227225    /**
    228      * Determines the {@code index}-th key/value/tag (depending on {@code type}) of the
    229      * {@link org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector}.
    230      *
    231      * @param matchingSelector matching selector
    232      * @param index            index
    233      * @param type             selector type ("key", "value" or "tag")
    234      * @param p                OSM primitive
    235      * @return argument value, can be {@code null}
    236      */
    237     static String determineArgument(Selector.GeneralSelector matchingSelector, int index, String type, OsmPrimitive p) {
    238         try {
    239             final Condition c = matchingSelector.getConditions().get(index);
    240             final Tag tag = c instanceof TagCondition
    241                     ? ((TagCondition) c).asTag(p)
    242                     : null;
    243             if (tag == null) {
    244                 return null;
    245             } else if ("key".equals(type)) {
    246                 return tag.getKey();
    247             } else if ("value".equals(type)) {
    248                 return tag.getValue();
    249             } else if ("tag".equals(type)) {
    250                 return tag.toString();
    251             }
    252         } catch (IndexOutOfBoundsException ignore) {
    253             Logging.debug(ignore);
    254         }
    255         return null;
    256     }
    257 
    258     /**
    259226     * Replaces occurrences of <code>{i.key}</code>, <code>{i.value}</code>, <code>{i.tag}</code> in {@code s} by the corresponding
    260227     * key/value/tag of the {@code index}-th {@link Condition} of {@code matchingSelector}.
     
    266233     */
    267234    static String insertArguments(Selector matchingSelector, String s, OsmPrimitive p) {
    268         if (s != null && matchingSelector instanceof Selector.ChildOrParentSelector) {
    269             return insertArguments(((Selector.ChildOrParentSelector) matchingSelector).right, s, p);
    270         } else if (s == null || !(matchingSelector instanceof Selector.GeneralSelector)) {
    271             return s;
    272         }
    273         final Matcher m = Pattern.compile("\\{(\\d+)\\.(key|value|tag)\\}").matcher(s);
    274         final StringBuffer sb = new StringBuffer();
    275         while (m.find()) {
    276             final String argument = determineArgument((Selector.GeneralSelector) matchingSelector,
    277                     Integer.parseInt(m.group(1)), m.group(2), p);
    278             try {
    279                 // Perform replacement with null-safe + regex-safe handling
    280                 m.appendReplacement(sb, String.valueOf(argument).replace("^(", "").replace(")$", ""));
    281             } catch (IndexOutOfBoundsException | IllegalArgumentException e) {
    282                 Logging.log(Logging.LEVEL_ERROR, tr("Unable to replace argument {0} in {1}: {2}", argument, sb, e.getMessage()), e);
    283             }
    284         }
    285         m.appendTail(sb);
    286         return sb.toString();
     235        return PlaceholderExpression.insertArguments(matchingSelector, s, p);
    287236    }
    288237
     
    329278            return String.valueOf(
    330279                    val instanceof Expression
    331                             ? ((Expression) val).evaluate(new Environment(p))
     280                            ? ((Expression) val).evaluate(new Environment(p).withSelector(p == null ? null : whichSelectorMatchesPrimitive(p)))
    332281                            : val
    333282            );
  • trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java

    r18275 r18757  
    1313import org.openstreetmap.josm.data.osm.WaySegment;
    1414import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
     15import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
    1516import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.LinkSelector;
    1617import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    4243    private Context context = Context.PRIMITIVE;
    4344
     45    /** The selector that is currently being evaluated */
     46    private final Selector selector;
     47
    4448    /**
    4549     * The name of the default layer. It is used if no layer is specified in the MapCSS rule
     
    98102    public Environment() {
    99103        // environment can be initialized later through with* methods
     104        this.selector = null;
    100105    }
    101106
     
    107112     */
    108113    public Environment(IPrimitive osm) {
    109         this.osm = osm;
     114        this(osm, null, null, null);
    110115    }
    111116
     
    123128        this.layer = layer;
    124129        this.source = source;
     130        this.selector = null;
    125131    }
    126132
     
    132138     */
    133139    public Environment(Environment other) {
     140        this(other, other.selector);
     141    }
     142
     143    /**
     144     * Creates a clone of the environment {@code other}.
     145     *
     146     * @param other the other environment. Must not be null.
     147     * @param selector the selector for this environment. May be null.
     148     * @throws IllegalArgumentException if {@code param} is {@code null}
     149     */
     150    private Environment(Environment other, Selector selector) {
    134151        CheckParameterUtil.ensureParameterNotNull(other);
    135152        this.osm = other.osm;
     
    147164        this.mpAreaCache = other.mpAreaCache;
    148165        this.toMatchForSurrounding = other.toMatchForSurrounding;
     166        this.selector = selector;
    149167    }
    150168
     
    264282
    265283    /**
     284     * Creates a clone of this environment, with the selector set
     285     * @param selector The selector to use
     286     * @return A clone of this environment, with the specified selector
     287     * @since xxx
     288     */
     289    public Environment withSelector(Selector selector) {
     290        return new Environment(this, selector);
     291    }
     292
     293    /**
    266294     * Determines if the context of this environment is {@link Context#LINK}.
    267295     * @return {@code true} if the context of this environment is {@code Context#LINK}, {@code false} otherwise
     
    302330            return ((Relation) osm).getMember(index).getRole();
    303331        return null;
     332    }
     333
     334    /**
     335     * Get the selector for this environment
     336     * @return The selector. May be {@code null}.
     337     * @since xxx
     338     */
     339    public Selector selector() {
     340        return this.selector;
    304341    }
    305342
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj

    r18712 r18757  
    3232import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule;
    3333import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
     34import org.openstreetmap.josm.gui.mappaint.mapcss.PlaceholderExpression;
    3435import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
    3536import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.ChildOrParentSelector;
     
    10531054            if (lit == null)
    10541055                return NullExpression.INSTANCE;
     1056            else if (lit instanceof String && PlaceholderExpression.PATTERN_PLACEHOLDER.matcher((String) lit).find()) {
     1057                return new PlaceholderExpression((String) lit);
     1058            }
    10551059            return new LiteralExpression(lit);
    10561060        }
Note: See TracChangeset for help on using the changeset viewer.