Detect and report basic self-conflicting filters.

This does not yet report anything for more complex cases. We were also testing for
tolerance of self-conflicting filters, which this breaks, in
partial_overrides. This patch may want to wait for warning reporting
since it may break stylesheets in the wild.
This commit is contained in:
Tom MacWright 2013-01-03 15:06:07 -05:00
parent 6f687ff9e3
commit 29b641c72d
9 changed files with 68 additions and 32 deletions

View File

@ -530,7 +530,13 @@ carto.Parser = function Parser(env) {
zooms.push(z); zooms.push(z);
conditions++; conditions++;
} else if (f) { } else if (f) {
filters.add(f); var err = filters.add(f);
if (err) {
throw makeError({
message: err,
index: i - 1
});
}
conditions++; conditions++;
} else if (attachment) { } else if (attachment) {
throw makeError({ throw makeError({

View File

@ -155,9 +155,37 @@ tree.Filterset.prototype.addable = function(filter) {
} }
}; };
// Does the new filter constitute a conflict?
tree.Filterset.prototype.conflict = function(filter) {
var key = filter.key.toString(),
value = filter.val.toString();
if (!isNaN(parseFloat(value))) value = parseFloat(value);
// if (a=b) && (a=c)
// if (a=b) && (a!=b)
// or (a!=b) && (a=b)
if ((filter.op === '=' && key + '=' in this.filters &&
value != this.filters[key + '='].val.toString()) ||
(filter.op === '!=' && key + '=' in this.filters &&
value == this.filters[key + '='].val.toString()) ||
(filter.op === '=' && key + '!=' in this.filters &&
value == this.filters[key + '!='].val.toString())) {
return filter.toString() + ' added to ' + this.toString() + ' produces an invalid filter';
}
return false;
};
// Only call this function for filters that have been cleared by .addable(). // Only call this function for filters that have been cleared by .addable().
tree.Filterset.prototype.add = function(filter) { tree.Filterset.prototype.add = function(filter, env) {
var key = filter.key.toString(), id, op = filter.op, numval; var key = filter.key.toString(),
id,
op = filter.op,
conflict = this.conflict(filter),
numval;
if (conflict) return conflict;
if (op === '=') { if (op === '=') {
for (var i in this.filters) { for (var i in this.filters) {

View File

@ -0,0 +1,15 @@
{
"srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over",
"Stylesheet": [
"contradiction.mss"
],
"Layer": [{
"name": "world",
"srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over",
"Datasource": {
"file": "http://tilemill-data.s3.amazonaws.com/district.geojson",
"type": "ogr",
"layer": "OGRGeoJSON"
}
}]
}

View File

@ -0,0 +1,3 @@
#world[FeatureCla!=""][FeatureCla=""] {
polygon-fill: #fff;
}

View File

@ -0,0 +1 @@
contradiction.mss:1:37 [[FeatureCla]=] added to [FeatureCla]!= produces an invalid filter

View File

@ -0,0 +1,3 @@
#world[FeatureCla=""][FeatureCla!=""] {
polygon-fill: #fff;
}

View File

@ -0,0 +1 @@
contradiction_2.mss:1:37 [[FeatureCla]!=] added to [FeatureCla]= produces an invalid filter

View File

@ -18,10 +18,6 @@
line-color: #f00; line-color: #f00;
} }
#world.m_5[NAME="United States"][NAME="Canada"] {
line-color: #f00;
}
#world.m_6[NAME!="Canada"][zoom > 5] { #world.m_6[NAME!="Canada"][zoom > 5] {
line-opacity: .7; line-opacity: .7;
} }

View File

@ -80,22 +80,6 @@
<Filter>([NAME] != 'Canada')</Filter> <Filter>([NAME] != 'Canada')</Filter>
<LineSymbolizer stroke-width="5" /> <LineSymbolizer stroke-width="5" />
</Rule> </Rule>
<Rule>
<MaxScaleDenominator>1500000</MaxScaleDenominator>
<Filter>([NAME] = 'Canada')</Filter>
<LineSymbolizer stroke="#ff0000" stroke-opacity="0.4" stroke-width="3" />
</Rule>
<Rule>
<MaxScaleDenominator>100000000</MaxScaleDenominator>
<MinScaleDenominator>1500000</MinScaleDenominator>
<Filter>([NAME] = 'Canada')</Filter>
<LineSymbolizer stroke="#ff0000" stroke-opacity="0.2" stroke-width="3" />
</Rule>
<Rule>
<MinScaleDenominator>100000000</MinScaleDenominator>
<Filter>([NAME] = 'Canada')</Filter>
<LineSymbolizer stroke="#ff0000" stroke-width="3" />
</Rule>
<Rule> <Rule>
<MaxScaleDenominator>1500000</MaxScaleDenominator> <MaxScaleDenominator>1500000</MaxScaleDenominator>
<LineSymbolizer stroke-opacity="0.4" stroke-width="3" /> <LineSymbolizer stroke-opacity="0.4" stroke-width="3" />
@ -110,13 +94,12 @@
<LineSymbolizer stroke-width="3" /> <LineSymbolizer stroke-width="3" />
</Rule> </Rule>
</Style> </Style>
<Layer <Layer name="world"
name="world"
srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"> srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
<StyleName>world</StyleName> <StyleName>world</StyleName>
<Datasource> <Datasource>
<Parameter name="file">[absolute path]</Parameter> <Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
<Parameter name="type">shape</Parameter> <Parameter name="type"><![CDATA[shape]]></Parameter>
</Datasource> </Datasource>
</Layer> </Layer>