-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Convert between predicate options and collator expressions #12329
Conversation
src/mbgl/style/conversion/filter.cpp
Outdated
@@ -55,7 +55,8 @@ bool isExpression(const Convertible& filter) { | |||
return false; | |||
|
|||
} else if (*op == "==" || *op == "!=" || *op == ">" || *op == ">=" || *op == "<" || *op == "<=") { | |||
return arrayLength(filter) == 3 && (isArray(arrayMember(filter, 1)) || isArray(arrayMember(filter, 2))); | |||
auto length = arrayLength(filter); | |||
return (length == 3 || length == 4) && (isArray(arrayMember(filter, 1)) || isArray(arrayMember(filter, 2))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently this code was ported from GL JS code that will also need to be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed as mapbox/mapbox-gl-js#6920
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe slightly better would be:
length != 3 || (isArray(arrayMember(filter, 1)) || isArray(arrayMember(filter, 2)))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reasoning being that the default should be "this is an expression", and we should scope the fallback to legacy filters as tightly as possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reasoning being that the default should be "this is an expression", and we should scope the fallback to legacy filters as tightly as possible?
Yeah, pretty much: sending as many inputs as possible through the expression parsing pipeline, since that will be more and more likely what users will be trying to write, and so expression-related validation messages are more likely to be useful
@"case-sensitive": @(!(self.options & NSCaseInsensitivePredicateOption)), | ||
@"diacritic-sensitive": @(!(self.options & NSDiacriticInsensitivePredicateOption)), | ||
}; | ||
return [comparisonArray arrayByAddingObject:@[@"collator", collatorObject]]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this means 'Québec' =[] 'Quebec'
will use a collator (and thus the current locale) vs. 'Québec' = 'Quebec'
doing non-locale-aware comparison?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as an option is specified in brackets, it’ll use a collator. To match Core Data behavior, I suppose we could default the locale
to en-posix
when c
or d
is specified unless l
is also specified.
A literal =[]
is invalid syntax; there has to be an option. NSPredicate will raise an exception immediately on initialization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the current behavior sounds right. 👍
@@ -12,6 +12,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT | |||
|
|||
* Added an `MGLRasterStyleLayer.rasterResamplingMode` property for configuring how raster style layers are overscaled. ([#12176](https://github.com/mapbox/mapbox-gl-native/pull/12176)) | |||
* `-[MGLStyle localizeLabelsIntoLocale:]` and `-[NSExpression mgl_expressionLocalizedIntoLocale:]` can automatically localize labels into Japanese or Korean based on the system’s language settings. ([#12286](https://github.com/mapbox/mapbox-gl-native/pull/12286)) | |||
* The `c` and `d` options are supported within comparison predicates for case and diacritic insensitivity, respectively. ([#12329](https://github.com/mapbox/mapbox-gl-native/pull/12329)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 Now that I see this, I wonder if it makes sense to treat the core feature ("support styles using the collator
expression") as a separate changelog entry from the platform-specific wrapper...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s a good point; we normally mention the JSON equivalent when that’s also new.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the changelog entry.
`NSCaseInsensitivePredicateOption` | `'QUEBEC' =[c] 'Quebec'` | ||
`NSDiacriticInsensitivePredicateOption` | `'Québec' =[d] 'Quebec'` | ||
|
||
Other comparison predicate options are unsupported, namely `l` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make sure I'm understanding: if you wanted to explicitly do locale-sensitive comparison with something other than the current locale, you'd have to manually craft your expression, because NSPredicate only supports a binary "locale-sensitive"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That’s correct. The syntax would look something like this:
NSPredicate(format: "MGL_FUNCTION('==', 'QUEBEC', 'Québec', MGL_FUNCTION('collator', %@))", ["case-sensitive": false, "locale": "fr-CA"])
There’s a couple things we could adjust at the SDK level, like allowing locale
to be set to an NSLocale instead of a raw locale identifier. But my understanding is that we normally want developers to keep using the default collator for better performance, so maybe it doesn’t help much to simplify the locale-specific collator syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made some last-minute changes so that this predicate would work:
- The collator options object is no longer wrapped in a
literal
expression when converting from NSExpression to JSON. - The
MGL_FUNCTION()
syntax is used instead of the==[…]
syntax when alocale
is specified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼
if ([op isEqualToString:@">="]) { | ||
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]); | ||
return [NSPredicate predicateWithFormat:@"%@ >= %@" argumentArray:subexpressions]; | ||
return [NSComparisonPredicate predicateWithLeftExpression:subexpressions[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
421db04
to
e992355
Compare
When detecting an expression used as a filter, relax the check for expressions to allow comparison expressions to contain a fourth member for the collator.
e992355
to
aaac2a5
Compare
The
[c]
and[d]
options are now supported within comparison predicates for case and diacritic insensitivity, respectively. Along the way, the mbgl code that detects expressions in filters had to be updated to allow a collator as the third argument to a comparison expression.Fixes #12269. Working towards #11786.
/cc @ChrisLoer @fabian-guerra @anandthakker