diff options
author | Anand Thakker <anandthakker@users.noreply.github.com> | 2018-04-09 17:59:18 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-09 17:59:18 -0400 |
commit | 8d26f7409106c94f37689d206f9a68aac57572a4 (patch) | |
tree | fa1dea3966bc88b76c4877663160b354ac5a01ab /src | |
parent | c1dabbde8d58143b1f7f64eddeb75c06ab417d32 (diff) | |
download | qtlocation-mapboxgl-8d26f7409106c94f37689d206f9a68aac57572a4.tar.gz |
Fix style parsing bug for constant expressions (#11606)
* Fix style parsing bug for constant expressions
Closes #10849
* Ignore tests for unported GL JS change
Refs https://github.com/mapbox/mapbox-gl-js/pull/6429
* Fuller fix
* Update mapbox-gl-js
Diffstat (limited to 'src')
-rw-r--r-- | src/mbgl/style/expression/parsing_context.cpp | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp index 364c3f740a..713c0b5d27 100644 --- a/src/mbgl/style/expression/parsing_context.cpp +++ b/src/mbgl/style/expression/parsing_context.cpp @@ -32,23 +32,36 @@ namespace style { namespace expression { bool isConstant(const Expression& expression) { - if (dynamic_cast<const Var*>(&expression)) { - return false; + if (auto varExpression = dynamic_cast<const Var*>(&expression)) { + return isConstant(*varExpression->getBoundExpression()); } - + if (auto compound = dynamic_cast<const CompoundExpressionBase*>(&expression)) { if (compound->getName() == "error") { return false; } } + + bool isTypeAnnotation = dynamic_cast<const Coercion*>(&expression) || + dynamic_cast<const Assertion*>(&expression) || + dynamic_cast<const ArrayAssertion*>(&expression); - bool literalArgs = true; + bool childrenConstant = true; expression.eachChild([&](const Expression& child) { - if (!dynamic_cast<const Literal*>(&child)) { - literalArgs = false; + // We can _almost_ assume that if `expressions` children are constant, + // they would already have been evaluated to Literal values when they + // were parsed. Type annotations are the exception, because they might + // have been inferred and added after a child was parsed. + + // So we recurse into isConstant() for the children of type annotations, + // but otherwise simply check whether they are Literals. + if (isTypeAnnotation) { + childrenConstant = childrenConstant && isConstant(child); + } else { + childrenConstant = childrenConstant && dynamic_cast<const Literal*>(&child); } }); - if (!literalArgs) { + if (!childrenConstant) { return false; } @@ -141,13 +154,13 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption return parsed; } - if (expected) { - auto array = [&](std::unique_ptr<Expression> expression) { - std::vector<std::unique_ptr<Expression>> args; - args.push_back(std::move(expression)); - return args; - }; + auto array = [&](std::unique_ptr<Expression> expression) { + std::vector<std::unique_ptr<Expression>> args; + args.push_back(std::move(expression)); + return args; + }; + if (expected) { const type::Type actual = (*parsed)->getType(); if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean || *expected == type::Object) && actual == type::Value) { if (typeAnnotationOption == includeTypeAnnotations) { @@ -169,7 +182,7 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption } } - // If an expression's arguments are all literals, we can evaluate + // If an expression's arguments are all constant, we can evaluate // it immediately and replace it with a literal value in the // parsed result. if (!dynamic_cast<Literal *>(parsed->get()) && isConstant(**parsed)) { |