diff options
author | Chris Loer <chris.loer@gmail.com> | 2018-06-29 15:56:37 -0700 |
---|---|---|
committer | Chris Loer <chris.loer@mapbox.com> | 2018-07-03 10:03:05 -0700 |
commit | 9ff5d34ef2ed2a236cc495f0ad84919cedce9abc (patch) | |
tree | a8c0fca2f710bce564b2ef9c8f7f68291b9926ff | |
parent | b9d3ecc990ccac102bcfde0e848a4f31b739ad54 (diff) | |
download | qtlocation-mapboxgl-9ff5d34ef2ed2a236cc495f0ad84919cedce9abc.tar.gz |
[core] Introduce "collator" expressions
Cross platform parsing and evaluation code.
-rw-r--r-- | cmake/core-files.cmake | 3 | ||||
-rw-r--r-- | include/mbgl/style/expression/collator.hpp | 29 | ||||
-rw-r--r-- | include/mbgl/style/expression/collator_expression.hpp | 44 | ||||
-rw-r--r-- | include/mbgl/style/expression/equals.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/style/expression/type.hpp | 8 | ||||
-rw-r--r-- | include/mbgl/style/expression/value.hpp | 2 | ||||
-rw-r--r-- | platform/node/src/node_expression.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/style/expression/collator_expression.cpp | 120 | ||||
-rw-r--r-- | src/mbgl/style/expression/compound_expression.cpp | 33 | ||||
-rw-r--r-- | src/mbgl/style/expression/dsl.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/style/expression/equals.cpp | 33 | ||||
-rw-r--r-- | src/mbgl/style/expression/is_constant.cpp | 9 | ||||
-rw-r--r-- | src/mbgl/style/expression/parsing_context.cpp | 1 | ||||
-rw-r--r-- | src/mbgl/style/expression/value.cpp | 13 | ||||
-rw-r--r-- | test/style/expression/expression.test.cpp | 2 |
15 files changed, 297 insertions, 16 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 462ead3b1f..66f569abc9 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -447,6 +447,8 @@ set(MBGL_CORE_FILES include/mbgl/style/expression/check_subtype.hpp include/mbgl/style/expression/coalesce.hpp include/mbgl/style/expression/coercion.hpp + include/mbgl/style/expression/collator.hpp + include/mbgl/style/expression/collator_expression.hpp include/mbgl/style/expression/compound_expression.hpp include/mbgl/style/expression/dsl.hpp include/mbgl/style/expression/equals.hpp @@ -473,6 +475,7 @@ set(MBGL_CORE_FILES src/mbgl/style/expression/check_subtype.cpp src/mbgl/style/expression/coalesce.cpp src/mbgl/style/expression/coercion.cpp + src/mbgl/style/expression/collator_expression.cpp src/mbgl/style/expression/compound_expression.cpp src/mbgl/style/expression/dsl.cpp src/mbgl/style/expression/equals.cpp diff --git a/include/mbgl/style/expression/collator.hpp b/include/mbgl/style/expression/collator.hpp new file mode 100644 index 0000000000..2a79e55556 --- /dev/null +++ b/include/mbgl/style/expression/collator.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include <mbgl/util/feature.hpp> +#include <mbgl/util/optional.hpp> + +#include <string> +#include <memory> + +namespace mbgl { +namespace style { +namespace expression { + +class Collator { +public: + Collator(bool caseSensitive, bool diacriticSensitive, optional<std::string> locale = {}); + + bool operator==(const Collator& other) const; + + int compare(const std::string& lhs, const std::string& rhs) const; + + std::string resolvedLocale() const; +private: + class Impl; + std::shared_ptr<Impl> impl; +}; + +} // namespace expression +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/expression/collator_expression.hpp b/include/mbgl/style/expression/collator_expression.hpp new file mode 100644 index 0000000000..2551cd19c8 --- /dev/null +++ b/include/mbgl/style/expression/collator_expression.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include <mbgl/style/expression/expression.hpp> +#include <mbgl/style/expression/parsing_context.hpp> +#include <mbgl/style/conversion.hpp> + +#include <memory> + +namespace mbgl { +namespace style { +namespace expression { + +class CollatorExpression : public Expression { +public: + CollatorExpression(std::unique_ptr<Expression> caseSensitive, + std::unique_ptr<Expression> diacriticSensitive, + optional<std::unique_ptr<Expression>> locale); + + EvaluationResult evaluate(const EvaluationContext&) const override; + static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&); + + void eachChild(const std::function<void(const Expression&)>&) const override; + + bool operator==(const Expression& e) const override; + + std::vector<optional<Value>> possibleOutputs() const override { + // Technically the set of possible outputs is the combinatoric set of Collators produced + // by all possibleOutputs of locale/caseSensitive/diacriticSensitive + // But for the primary use of Collators in comparison operators, we ignore the Collator's + // possibleOutputs anyway, so we can get away with leaving this undefined for now. + return { nullopt }; + } + + mbgl::Value serialize() const override; + std::string getOperator() const override { return "collator"; } +private: + std::unique_ptr<Expression> caseSensitive; + std::unique_ptr<Expression> diacriticSensitive; + optional<std::unique_ptr<Expression>> locale; +}; + +} // namespace expression +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/expression/equals.hpp b/include/mbgl/style/expression/equals.hpp index 54df890a68..1e8bf7acef 100644 --- a/include/mbgl/style/expression/equals.hpp +++ b/include/mbgl/style/expression/equals.hpp @@ -1,5 +1,6 @@ #pragma once +#include <mbgl/style/expression/collator_expression.hpp> #include <mbgl/style/expression/expression.hpp> #include <mbgl/style/expression/parsing_context.hpp> #include <mbgl/style/conversion.hpp> @@ -12,7 +13,7 @@ namespace expression { class Equals : public Expression { public: - Equals(std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs, bool negate); + Equals(std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs, optional<std::unique_ptr<Expression>> collator, bool negate); static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&); @@ -25,6 +26,7 @@ public: private: std::unique_ptr<Expression> lhs; std::unique_ptr<Expression> rhs; + optional<std::unique_ptr<Expression>> collator; bool negate; }; diff --git a/include/mbgl/style/expression/type.hpp b/include/mbgl/style/expression/type.hpp index 513c4bdc17..316496839b 100644 --- a/include/mbgl/style/expression/type.hpp +++ b/include/mbgl/style/expression/type.hpp @@ -60,6 +60,12 @@ struct ValueType { std::string getName() const { return "value"; } bool operator==(const ValueType&) const { return true; } }; + +struct CollatorType { + constexpr CollatorType() {}; // NOLINT + std::string getName() const { return "collator"; } + bool operator==(const CollatorType&) const { return true; } +}; constexpr NullType Null; constexpr NumberType Number; @@ -68,6 +74,7 @@ constexpr BooleanType Boolean; constexpr ColorType Color; constexpr ValueType Value; constexpr ObjectType Object; +constexpr CollatorType Collator; constexpr ErrorType Error; struct Array; @@ -81,6 +88,7 @@ using Type = variant< ObjectType, ValueType, mapbox::util::recursive_wrapper<Array>, + CollatorType, ErrorType>; struct Array { diff --git a/include/mbgl/style/expression/value.hpp b/include/mbgl/style/expression/value.hpp index 7839ff2ca7..fc38c36ff0 100644 --- a/include/mbgl/style/expression/value.hpp +++ b/include/mbgl/style/expression/value.hpp @@ -1,5 +1,6 @@ #pragma once +#include <mbgl/style/expression/collator.hpp> #include <mbgl/style/expression/type.hpp> #include <mbgl/style/position.hpp> #include <mbgl/style/types.hpp> @@ -23,6 +24,7 @@ using ValueBase = variant< double, std::string, Color, + Collator, mapbox::util::recursive_wrapper<std::vector<Value>>, mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>; struct Value : ValueBase { diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp index 9faa41d8b8..c0b512a899 100644 --- a/platform/node/src/node_expression.cpp +++ b/platform/node/src/node_expression.cpp @@ -144,6 +144,14 @@ struct ToValue { return scope.Escape(result); } + v8::Local<v8::Value> operator()(const Collator&) { + // Collators are excluded from constant folding and there's no Literal parser + // for them so there shouldn't be any way to serialize this value. + assert(false); + Nan::EscapableHandleScope scope; + return scope.Escape(Nan::Null()); + } + v8::Local<v8::Value> operator()(const mbgl::Color& color) { return operator()(std::vector<Value> { static_cast<double>(color.r), diff --git a/src/mbgl/style/expression/collator_expression.cpp b/src/mbgl/style/expression/collator_expression.cpp new file mode 100644 index 0000000000..f5e4e3fdff --- /dev/null +++ b/src/mbgl/style/expression/collator_expression.cpp @@ -0,0 +1,120 @@ +#include <mbgl/style/expression/collator.hpp> +#include <mbgl/style/expression/collator_expression.hpp> +#include <mbgl/style/expression/literal.hpp> +#include <mbgl/util/string.hpp> + +namespace mbgl { +namespace style { +namespace expression { + +CollatorExpression::CollatorExpression(std::unique_ptr<Expression> caseSensitive_, + std::unique_ptr<Expression> diacriticSensitive_, + optional<std::unique_ptr<Expression>> locale_) + : Expression(type::Collator) + , caseSensitive(std::move(caseSensitive_)) + , diacriticSensitive(std::move(diacriticSensitive_)) + , locale(std::move(locale_)) +{} + +using namespace mbgl::style::conversion; + +ParseResult CollatorExpression::parse(const Convertible& value, ParsingContext& ctx) { + if (arrayLength(value) != 2) { + ctx.error("Expected one argument."); + return ParseResult(); + } + + auto options = arrayMember(value, 1); + if (!isObject(options)) { + ctx.error("Collator options argument must be an object."); + return ParseResult(); + } + + const optional<Convertible> caseSensitiveOption = objectMember(options, "case-sensitive"); + ParseResult caseSensitive; + if (caseSensitiveOption) { + caseSensitive = ctx.parse(*caseSensitiveOption, 1, {type::Boolean}); + } else { + caseSensitive = { std::make_unique<Literal>(false) }; + } + if (!caseSensitive) { + return ParseResult(); + } + + const optional<Convertible> diacriticSensitiveOption = objectMember(options, "diacritic-sensitive"); + ParseResult diacriticSensitive; + if (diacriticSensitiveOption) { + diacriticSensitive = ctx.parse(*diacriticSensitiveOption, 1, {type::Boolean}); + } else { + diacriticSensitive = { std::make_unique<Literal>(false) }; + } + if (!diacriticSensitive) { + return ParseResult(); + } + + const optional<Convertible> localeOption = objectMember(options, "locale"); + ParseResult locale; + if (localeOption) { + locale = ctx.parse(*localeOption, 1, {type::String}); + if (!locale) { + return ParseResult(); + } + } + + return ParseResult(std::make_unique<CollatorExpression>(std::move(*caseSensitive), std::move(*diacriticSensitive), std::move(locale))); +} + +void CollatorExpression::eachChild(const std::function<void(const Expression&)>& fn) const { + fn(*caseSensitive); + fn(*diacriticSensitive); + if (locale) { + fn(**locale); + } +} + +bool CollatorExpression::operator==(const Expression& e) const { + if (auto rhs = dynamic_cast<const CollatorExpression*>(&e)) { + if ((locale && (!rhs->locale || **locale != **(rhs->locale))) || + (!locale && rhs->locale)) { + return false; + } + return *caseSensitive == *(rhs->caseSensitive) && + *diacriticSensitive == *(rhs->diacriticSensitive); + } + return false; +} + +mbgl::Value CollatorExpression::serialize() const { + std::unordered_map<std::string, mbgl::Value> options; + options["case-sensitive"] = caseSensitive->serialize(); + options["diacritic-sensitive"] = diacriticSensitive->serialize(); + if (locale) { + options["locale"] = (*locale)->serialize(); + } + return std::vector<mbgl::Value>{{ std::string("collator"), options }}; +} + +EvaluationResult CollatorExpression::evaluate(const EvaluationContext& params) const { + auto caseSensitiveResult = caseSensitive->evaluate(params); + if (!caseSensitiveResult) { + return caseSensitiveResult.error(); + } + auto diacriticSensitiveResult = diacriticSensitive->evaluate(params); + if (!diacriticSensitiveResult) { + return diacriticSensitiveResult.error(); + } + + if (locale) { + auto localeResult = (*locale)->evaluate(params); + if (!localeResult) { + return localeResult.error(); + } + return Collator(caseSensitiveResult->get<bool>(), diacriticSensitiveResult->get<bool>(), localeResult->get<std::string>()); + } else { + return Collator(caseSensitiveResult->get<bool>(), diacriticSensitiveResult->get<bool>()); + } +} + +} // namespace expression +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp index c37f02612b..46b0c7fe18 100644 --- a/src/mbgl/style/expression/compound_expression.cpp +++ b/src/mbgl/style/expression/compound_expression.cpp @@ -1,3 +1,5 @@ +#include <boost/algorithm/string/join.hpp> +#include <mbgl/style/expression/collator.hpp> #include <mbgl/style/expression/compound_expression.hpp> #include <mbgl/style/expression/check_subtype.hpp> #include <mbgl/style/expression/util.hpp> @@ -481,12 +483,16 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali define(">", [](double lhs, double rhs) -> Result<bool> { return lhs > rhs; }); define(">", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs > rhs; }); + define(">", [](const std::string& lhs, const std::string& rhs, const Collator& c) -> Result<bool> { return c.compare(lhs, rhs) > 0; }); define(">=", [](double lhs, double rhs) -> Result<bool> { return lhs >= rhs; }); define(">=",[](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs >= rhs; }); + define(">=", [](const std::string& lhs, const std::string& rhs, const Collator& c) -> Result<bool> { return c.compare(lhs, rhs) >= 0; }); define("<", [](double lhs, double rhs) -> Result<bool> { return lhs < rhs; }); define("<", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs < rhs; }); + define("<", [](const std::string& lhs, const std::string& rhs, const Collator& c) -> Result<bool> { return c.compare(lhs, rhs) < 0; }); define("<=", [](double lhs, double rhs) -> Result<bool> { return lhs <= rhs; }); define("<=", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs <= rhs; }); + define("<=", [](const std::string& lhs, const std::string& rhs, const Collator& c) -> Result<bool> { return c.compare(lhs, rhs) <= 0; }); define("!", [](bool e) -> Result<bool> { return !e; }); @@ -507,6 +513,10 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali } return s; }); + define("resolved-locale", [](const Collator& collator) -> Result<std::string> { + return collator.resolvedLocale(); + }); + define("error", [](const std::string& input) -> Result<type::ErrorType> { return EvaluationError { input }; }); @@ -686,26 +696,35 @@ static ParseResult createCompoundExpression(const Definition& definition, if (definition.size() == 1) { ctx.appendErrors(std::move(signatureContext)); } else { - std::string signatures; + std::vector<std::string> availableOverloads; // Only used if there are no overloads with matching number of args + std::vector<std::string> overloads; for (const auto& signature : definition) { - signatures += (signatures.size() > 0 ? " | " : ""); signature->params.match( [&](const VarargsType& varargs) { - signatures += "(" + toString(varargs.type) + ")"; + std::string overload = "(" + toString(varargs.type) + ")"; + overloads.push_back(overload); }, [&](const std::vector<type::Type>& params) { - signatures += "("; + std::string overload = "("; bool first = true; for (const type::Type& param : params) { - if (!first) signatures += ", "; - signatures += toString(param); + if (!first) overload += ", "; + overload += toString(param); first = false; } - signatures += ")"; + overload += ")"; + if (params.size() == args.size()) { + overloads.push_back(overload); + } else { + availableOverloads.push_back(overload); + } } ); } + std::string signatures = overloads.empty() ? + boost::algorithm::join(availableOverloads, " | ") : + boost::algorithm::join(overloads, " | "); std::string actualTypes; for (const auto& arg : args) { if (actualTypes.size() > 0) { diff --git a/src/mbgl/style/expression/dsl.cpp b/src/mbgl/style/expression/dsl.cpp index 15822ccf66..2298bdf8d3 100644 --- a/src/mbgl/style/expression/dsl.cpp +++ b/src/mbgl/style/expression/dsl.cpp @@ -86,12 +86,12 @@ std::unique_ptr<Expression> zoom() { std::unique_ptr<Expression> eq(std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs) { - return std::make_unique<Equals>(std::move(lhs), std::move(rhs), false); + return std::make_unique<Equals>(std::move(lhs), std::move(rhs), nullopt, false); } std::unique_ptr<Expression> ne(std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs) { - return std::make_unique<Equals>(std::move(lhs), std::move(rhs), true); + return std::make_unique<Equals>(std::move(lhs), std::move(rhs), nullopt, true); } std::unique_ptr<Expression> gt(std::unique_ptr<Expression> lhs, diff --git a/src/mbgl/style/expression/equals.cpp b/src/mbgl/style/expression/equals.cpp index f2f59e31ef..245899f975 100644 --- a/src/mbgl/style/expression/equals.cpp +++ b/src/mbgl/style/expression/equals.cpp @@ -1,3 +1,4 @@ +#include <mbgl/style/expression/collator.hpp> #include <mbgl/style/expression/equals.hpp> namespace mbgl { @@ -11,10 +12,11 @@ static bool isComparableType(const type::Type& type) { type == type::Null; } -Equals::Equals(std::unique_ptr<Expression> lhs_, std::unique_ptr<Expression> rhs_, bool negate_) +Equals::Equals(std::unique_ptr<Expression> lhs_, std::unique_ptr<Expression> rhs_, optional<std::unique_ptr<Expression>> collator_, bool negate_) : Expression(type::Boolean), lhs(std::move(lhs_)), rhs(std::move(rhs_)), + collator(std::move(collator_)), negate(negate_) { assert(isComparableType(lhs->getType()) || isComparableType(rhs->getType())); assert(lhs->getType() == rhs->getType() || lhs->getType() == type::Value || rhs->getType() == type::Value); @@ -27,7 +29,15 @@ EvaluationResult Equals::evaluate(const EvaluationContext& params) const { EvaluationResult rhsResult = rhs->evaluate(params); if (!rhsResult) return lhsResult; - bool result = *lhsResult == *rhsResult; + bool result; + + if (collator) { + auto collatorResult = (*collator)->evaluate(params); + const Collator& c = collatorResult->get<Collator>(); + result = c.compare(lhsResult->get<std::string>(), rhsResult->get<std::string>()) == 0; + } else { + result = *lhsResult == *rhsResult; + } if (negate) { result = !result; } @@ -37,6 +47,9 @@ EvaluationResult Equals::evaluate(const EvaluationContext& params) const { void Equals::eachChild(const std::function<void(const Expression&)>& visit) const { visit(*lhs); visit(*rhs); + if (collator) { + visit(**collator); + } } bool Equals::operator==(const Expression& e) const { @@ -54,8 +67,8 @@ using namespace mbgl::style::conversion; ParseResult Equals::parse(const Convertible& value, ParsingContext& ctx) { std::size_t length = arrayLength(value); - if (length != 3) { - ctx.error("Expected two arguments."); + if (length != 3 && length != 4) { + ctx.error("Expected two or three arguments."); return ParseResult(); } @@ -80,8 +93,18 @@ ParseResult Equals::parse(const Convertible& value, ParsingContext& ctx) { ctx.error("Cannot compare " + toString(lhsType) + " and " + toString(rhsType) + "."); return ParseResult(); } + + ParseResult collatorParseResult; + if (length == 4) { + if (lhsType != type::String && rhsType != type::String) { + ctx.error("Cannot use collator to compare non-string types."); + return ParseResult(); + } + collatorParseResult = ctx.parse(arrayMember(value, 3), 3, {type::Collator}); + if (!collatorParseResult) return ParseResult(); + } - return ParseResult(std::make_unique<Equals>(std::move(*lhs), std::move(*rhs), negate)); + return ParseResult(std::make_unique<Equals>(std::move(*lhs), std::move(*rhs), std::move(collatorParseResult), negate)); } } // namespace expression diff --git a/src/mbgl/style/expression/is_constant.cpp b/src/mbgl/style/expression/is_constant.cpp index 577ecf8cb6..b877ed550a 100644 --- a/src/mbgl/style/expression/is_constant.cpp +++ b/src/mbgl/style/expression/is_constant.cpp @@ -1,4 +1,6 @@ #include <mbgl/style/expression/is_constant.hpp> +#include <mbgl/style/expression/collator_expression.hpp> + namespace mbgl { namespace style { @@ -25,6 +27,13 @@ bool isFeatureConstant(const Expression& expression) { return false; } } + + if (dynamic_cast<const CollatorExpression*>(&expression)) { + // Although the results of a Collator expression with fixed arguments + // generally shouldn't change between executions, we can't serialize them + // as constant expressions because results change based on environment. + return false; + } bool featureConstant = true; expression.eachChild([&](const Expression& e) { diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp index 72585c35df..fe3102f158 100644 --- a/src/mbgl/style/expression/parsing_context.cpp +++ b/src/mbgl/style/expression/parsing_context.cpp @@ -102,6 +102,7 @@ const ExpressionRegistry& getExpressionRegistry() { {"boolean", Assertion::parse}, {"case", Case::parse}, {"coalesce", Coalesce::parse}, + {"collator", CollatorExpression::parse}, {"interpolate", parseInterpolate}, {"length", Length::parse}, {"let", Let::parse}, diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp index 7c329e8f1f..b1b05ea617 100644 --- a/src/mbgl/style/expression/value.cpp +++ b/src/mbgl/style/expression/value.cpp @@ -12,6 +12,7 @@ type::Type typeOf(const Value& value) { [&](double) -> type::Type { return type::Number; }, [&](const std::string&) -> type::Type { return type::String; }, [&](const Color&) -> type::Type { return type::Color; }, + [&](const Collator&) -> type::Type { return type::Collator; }, [&](const NullValue&) -> type::Type { return type::Null; }, [&](const std::unordered_map<std::string, Value>&) -> type::Type { return type::Object; }, [&](const std::vector<Value>& arr) -> type::Type { @@ -43,6 +44,11 @@ void writeJSON(rapidjson::Writer<rapidjson::StringBuffer>& writer, const Value& }, [&] (const std::string& s) { writer.String(s); }, [&] (const Color& c) { writer.String(c.stringify()); }, + [&] (const Collator&) { + // Collators are excluded from constant folding and there's no Literal parser + // for them so there shouldn't be any way to serialize this value. + assert(false); + }, [&] (const std::vector<Value>& arr) { writer.StartArray(); for(const auto& item : arr) { @@ -115,6 +121,12 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) array[3], }; }, + [&](const Collator&)->mbgl::Value { + // fromExpressionValue can't be used for Collator values, + // because they have no meaningful representation as an mbgl::Value + assert(false); + return mbgl::Value(); + }, [&](const std::vector<Value>& values)->mbgl::Value { std::vector<mbgl::Value> converted; converted.reserve(values.size()); @@ -261,6 +273,7 @@ template <> type::Type valueTypeToExpressionType<bool>() { return type::Boolean; template <> type::Type valueTypeToExpressionType<double>() { return type::Number; } template <> type::Type valueTypeToExpressionType<std::string>() { return type::String; } template <> type::Type valueTypeToExpressionType<Color>() { return type::Color; } +template <> type::Type valueTypeToExpressionType<Collator>() { return type::Collator; } template <> type::Type valueTypeToExpressionType<std::unordered_map<std::string, Value>>() { return type::Object; } template <> type::Type valueTypeToExpressionType<std::vector<Value>>() { return type::Array(type::Value); } diff --git a/test/style/expression/expression.test.cpp b/test/style/expression/expression.test.cpp index 709624a50f..0b46facf42 100644 --- a/test/style/expression/expression.test.cpp +++ b/test/style/expression/expression.test.cpp @@ -29,7 +29,7 @@ TEST(Expression, IsExpression) { for(auto& entry : allExpressions.GetObject()) { const std::string name { entry.name.GetString(), entry.name.GetStringLength() }; - if (name == "collator" || name == "line-progress" || name == "resolved-locale" || name == "feature-state") { + if (name == "line-progress" || name == "feature-state") { // Not yet implemented continue; } |