summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2018-03-16 10:17:32 -0700
committerFabian Guerra <fabian.guerra@mapbox.com>2018-03-28 19:31:53 -0400
commit09810d53bf224e68ba4cbe95cf633f4ad6c29592 (patch)
tree65a49b209125084d5db41be263179e5d739eb0d7
parent2aaa038ef182cbba3095fa7636c15ab376f87b84 (diff)
downloadqtlocation-mapboxgl-09810d53bf224e68ba4cbe95cf633f4ad6c29592.tar.gz
[ios, macos] Introduced more ergonomic expression concatenation syntax
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm43
-rw-r--r--platform/darwin/test/MGLExpressionTests.mm5
2 files changed, 44 insertions, 4 deletions
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index a193b85caa..cb9f5813f3 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -11,8 +11,47 @@
#import "NSPredicate+MGLAdditions.h"
#import "NSValue+MGLStyleAttributeAdditions.h"
+#import <objc/runtime.h>
+
#import <mbgl/style/expression/expression.hpp>
+/**
+ Joins the given components into a single string by concatenating each component
+ in order.
+ */
+NSString *MGLJoinComponents(Class self, SEL _cmd, NSArray<NSString *> *components) {
+ return [components componentsJoinedByString:@""];
+}
+
+/**
+ Adds to NSExpression’s built-in repertoire of functions.
+ */
+void MGLEndowExpressionsWithCustomFunctions() {
+ // NSExpression’s built-in functions are backed by class methods on a
+ // private class, so use a function expression to get at the class.
+ // http://funwithobjc.tumblr.com/post/2922267976/using-custom-functions-with-nsexpression
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"sum({})"];
+ NSString *className = NSStringFromClass([functionExpression.operand.constantValue class]);
+
+ // Effectively categorize the class with some extra class methods.
+ Class NSPredicateUtilities = objc_getMetaClass(className.UTF8String);
+#pragma clang push
+#pragma clang diagnostic ignored "-Wundeclared-selector"
+ class_addMethod(NSPredicateUtilities, @selector(mgl_join:), (IMP)MGLJoinComponents, "@@:@");
+#pragma clang pop
+}
+
+@interface MGLExpressionEndowmentLoader: NSObject
+@end
+
+@implementation MGLExpressionEndowmentLoader
+
++ (void)load {
+ MGLEndowExpressionsWithCustomFunctions();
+}
+
+@end
+
@implementation NSExpression (MGLPrivateAdditions)
- (std::vector<mbgl::Value>)mgl_aggregateMBGLValue {
@@ -415,9 +454,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
return [NSExpression expressionForConstantValue:@(M_PI)];
} else if ([op isEqualToString:@"concat"]) {
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
- NSExpression *operand = subexpressions.firstObject;
- subexpressions = [subexpressions subarrayWithRange:NSMakeRange(1, subexpressions.count - 1)];
- return [NSExpression expressionForFunction:operand selectorName:@"stringByAppendingString:" arguments:subexpressions];
+ return [NSExpression expressionForFunction:@"mgl_join" arguments:subexpressions];
} else if ([op isEqualToString:@"at"]) {
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
NSExpression *index = subexpressions.firstObject;
diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm
index d189b41cd7..a78126ef95 100644
--- a/platform/darwin/test/MGLExpressionTests.mm
+++ b/platform/darwin/test/MGLExpressionTests.mm
@@ -510,10 +510,13 @@ using namespace std::string_literals;
NSArray *arguments = @[MGLConstantExpression(@"MacDonald")];
{
NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION('Old', 'stringByAppendingString:', 'MacDonald')"];
+ NSExpression *customExpression = [NSExpression expressionWithFormat:@"mgl_join({'Old', 'McDonald'})"];
NSArray *jsonExpression = @[@"concat", @"Old", @"MacDonald"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(customExpression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @"OldMacDonald");
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([customExpression expressionValueWithObject:nil context:nil], @"OldMacDonald");
+ XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], customExpression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"uppercase:" arguments:arguments];