-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Auto-coerce top-level results and concat arguments to strings #7280
Conversation
fcced57
to
1b5e28c
Compare
1b5e28c
to
4256281
Compare
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.
Awesome, excited for this change – just had one piece of feedback about the expression migration script.
return get; | ||
// By default, expressions for string-valued properties get coerced. To preserve | ||
// legacy function semantics, insert an explicit assertion instead. | ||
return propertySpec.type === 'string' ? ['string', get] : get; |
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.
Should the to-string
expression be dropped here: https://github.com/mapbox/mapbox-gl-js/pull/7280/files#diff-4b96c63e8fcfc96468a92c7a73e53b5eR229
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.
// For string-valued properties, coerce to string at the top level rather than asserting. | ||
const parsed = parser.parse(expression, undefined, undefined, undefined, | ||
propertySpec.type === 'string' ? {typeAnnotation: 'coerce'} : undefined); | ||
|
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.
🎉
No longer need to-string when using concat. However, it is still needed if the token string consists of a single token.
0a5cacd
to
1ff116c
Compare
The recently added
|
const types = { | ||
color: ColorType, | ||
string: StringType, | ||
number: NumberType, | ||
enum: StringType, | ||
boolean: BooleanType | ||
boolean: BooleanType, | ||
formatted: FormattedType |
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 with this change, every place in the code that checks text instanceof Formatted
has a dead branch. I can go clean those up in a later PR. There may also be some performance impact here because of the extra bookkeeping the "formatted" path uses, although I'd guess it's pretty minimal.
This avoids a troublesome circular import.
9680322
to
11b6a19
Compare
I went ahead and made the changes to strip out the
The reason was that the coalesce introduced a
I'm not sure of the right answer here -- it seems like allowing I tried going back to the approach of using @mollymerp since I've started modifying this PR, can I ask you to step in as reviewer? I'm going to try to add some test cases for the different "type annotation" cases. |
…tion time. - Add coercion after call to 'getValueAndResolveTokens`, since the non-expression pathway here skips the coercion logic in parsing_context - Remove 'string | Formatted' typing and 'text instanceof Formatted' checks - Add Coercion support for 'Formatted', along with dedicated serialization - Use Coercion when parsing expected.kind === 'formatted' instead of directly creating a FormatExpression. This is necessary to accommodate expressions such as 'coalesce' that introduce a typeAnnotation.
f5cd8c3
to
b0dffd2
Compare
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.
This looks good overall (to me, someone with limited expression parsing knowledge – thank you for the additional context in chat @ChrisLoer !)
"compiled": { | ||
"result": "error", | ||
"errors": [ | ||
{"key": "", "error": "Expected formatted but found number instead."} |
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.
This seems like a rather unhelpful error message, considering that most "text-field"
values won't be actually using the "format"
expression. Should we special case this type checking error for formatted
or punt on this for a later error message improvement project?
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 defer? The way I kind of think about it is: it's confusing because people expect to be able to return a 'string', and have it implicitly-coerce to 'formatted' without them having to even know 'formatted' exists. So you'd kind of like it to say something like Expected formatted or string but found number instead.
-- but that's still actually confusing because (1) things other than 'formatted' or 'string' can still successfully coerce to 'formatted', (2) even 'number' can coerce to 'formatted' - the problem is that the assertion disables the implicit coercion.
if (expr === null || typeof expr === 'string' || typeof expr === 'boolean' || typeof expr === 'number') { | ||
expr = ['literal', expr]; | ||
} | ||
|
||
function annotate(parsed, type, typeAnnotation: 'assert' | 'coerce' | 'omit') { |
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 find typeAnnotation
to be a very confusing name for this modifier (typeModifier
🤔 ) but we don't have to deal with that in this PR 😶
Fixes #6190, implementing auto-coercion for
"concat"
and string-valued properties. The latter change affects the behavior of coalesce as well, for instance"text-field": ["coalesce", ["get", "a"], ["get", "b"]]
will now never produce a type error.Launch Checklist