Skip to content

Commit

Permalink
fix(iOS): assign -> copy for numeric types (#61)
Browse files Browse the repository at this point in the history
Resolves an issue in iOS clients for required numeric values where the incorrect value was supplied to `analytics-ios`.
  • Loading branch information
colinking authored Jun 4, 2019
1 parent e224c9b commit 7a2ec99
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ NS_ASSUME_NONNULL_BEGIN
/// Currency code associated with the transaction
@property (nonatomic, nullable, copy) NSString *currency;
/// Total discount associated with the transaction
@property (nonatomic, nullable, assign) NSNumber *discount;
@property (nonatomic, nullable, copy) NSNumber *discount;
/// Order/transaction ID
@property (nonatomic, copy) NSString *orderID;
/// Products in the order
@property (nonatomic, nullable, copy) NSArray<SEGProduct *> *products;
/// Revenue associated with the transaction (excluding shipping and tax)
@property (nonatomic, nullable, assign) NSNumber *revenue;
@property (nonatomic, nullable, copy) NSNumber *revenue;
/// Shipping cost associated with the transaction
@property (nonatomic, nullable, assign) NSNumber *shipping;
@property (nonatomic, nullable, copy) NSNumber *shipping;
/// Total tax associated with the transaction
@property (nonatomic, nullable, assign) NSNumber *tax;
@property (nonatomic, nullable, copy) NSNumber *tax;
/// Revenue with discounts and coupons added in. Note that our Google Analytics Ecommerce
/// destination accepts total or revenue, but not both. For better flexibility and total
/// control over tracking, we let you decide how to calculate how coupons and discounts are
/// applied
@property (nonatomic, nullable, assign) NSNumber *total;
@property (nonatomic, nullable, copy) NSNumber *total;
@end

typedef void (^ SEGOrderCompletedBuilderBlock)(SEGOrderCompletedBuilder *);
Expand All @@ -55,22 +55,22 @@ typedef void (^ SEGOrderCompletedBuilderBlock)(SEGOrderCompletedBuilder *);
/// Currency code associated with the transaction
@property (nonatomic, nullable, copy) NSString *currency;
/// Total discount associated with the transaction
@property (nonatomic, nullable, assign) NSNumber *discount;
@property (nonatomic, nullable, copy) NSNumber *discount;
/// Order/transaction ID
@property (nonatomic, copy) NSString *orderID;
/// Products in the order
@property (nonatomic, nullable, copy) NSArray<SEGProduct *> *products;
/// Revenue associated with the transaction (excluding shipping and tax)
@property (nonatomic, nullable, assign) NSNumber *revenue;
@property (nonatomic, nullable, copy) NSNumber *revenue;
/// Shipping cost associated with the transaction
@property (nonatomic, nullable, assign) NSNumber *shipping;
@property (nonatomic, nullable, copy) NSNumber *shipping;
/// Total tax associated with the transaction
@property (nonatomic, nullable, assign) NSNumber *tax;
@property (nonatomic, nullable, copy) NSNumber *tax;
/// Revenue with discounts and coupons added in. Note that our Google Analytics Ecommerce
/// destination accepts total or revenue, but not both. For better flexibility and total
/// control over tracking, we let you decide how to calculate how coupons and discounts are
/// applied
@property (nonatomic, nullable, assign) NSNumber *total;
@property (nonatomic, nullable, copy) NSNumber *total;
@end

@interface SEGProduct : NSObject
Expand All @@ -85,13 +85,13 @@ typedef void (^ SEGOrderCompletedBuilderBlock)(SEGOrderCompletedBuilder *);
/// Name of the product being viewed
@property (nonatomic, nullable, copy) NSString *name;
/// Position in the product list (ex. 3)
@property (nonatomic, nullable, assign) NSNumber *position;
@property (nonatomic, nullable, copy) NSNumber *position;
/// Price of the product being viewed
@property (nonatomic, nullable, assign) NSNumber *price;
@property (nonatomic, nullable, copy) NSNumber *price;
/// Database id of the product being viewed
@property (nonatomic, nullable, copy) NSString *productID;
/// Quantity of a product
@property (nonatomic, nullable, assign) NSNumber *quantity;
@property (nonatomic, nullable, copy) NSNumber *quantity;
/// Sku of the product being viewed
@property (nonatomic, nullable, copy) NSString *sku;
/// URL of the product page
Expand All @@ -114,13 +114,13 @@ typedef void (^ SEGProductBuilderBlock)(SEGProductBuilder *);
/// Name of the product being viewed
@property (nonatomic, nullable, copy) NSString *name;
/// Position in the product list (ex. 3)
@property (nonatomic, nullable, assign) NSNumber *position;
@property (nonatomic, nullable, copy) NSNumber *position;
/// Price of the product being viewed
@property (nonatomic, nullable, assign) NSNumber *price;
@property (nonatomic, nullable, copy) NSNumber *price;
/// Database id of the product being viewed
@property (nonatomic, nullable, copy) NSString *productID;
/// Quantity of a product
@property (nonatomic, nullable, assign) NSNumber *quantity;
@property (nonatomic, nullable, copy) NSNumber *quantity;
/// Sku of the product being viewed
@property (nonatomic, nullable, copy) NSString *sku;
/// URL of the product page
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
"scripts": {
"start": "node ./dist/src/index.js",
"test": "jest",
"update-snapshots": "jest -u",
"watch": "tsc -w",
"build": "rm -rf dist && tsc",
"prepare": "yarn run build",
Expand Down
31 changes: 29 additions & 2 deletions src/commands/gen-ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import {
Name,
Sourcelike,
Type,
ObjectType
ObjectType,
matchType
} from 'quicktype-core'
import { stringEscape } from 'quicktype-core/dist/support/Strings'
import { OptionValues, StringOption } from 'quicktype-core/dist/RendererOptions'
import { objcOptions } from 'quicktype-core/dist/language/Objective-C'
import { objcOptions, MemoryAttribute } from 'quicktype-core/dist/language/Objective-C'

import {
getTypedTrackHandler,
Expand Down Expand Up @@ -564,9 +565,35 @@ class AnalyticsObjectiveCWrapperRenderer extends ObjectiveCRenderer {
})
}

/**
* Always used the boxed types, because of a potential upstream bu with nullable values
* in QuickType. We need to use a boxed type if we make attach the `nullable` property modifier.
*/
protected objcType(t: Type, _: boolean): [Sourcelike, string] {
return super.objcType(t, true)
}

/**
* Override memoryAttribute in order to replace assign with copy for numeric types.
*
* Defer to QuickType for all other types.
*/
protected memoryAttribute(t: Type, isNullable: boolean): MemoryAttribute {
return matchType<MemoryAttribute>(
t,
anyType => super.memoryAttribute(t, isNullable),
nullType => super.memoryAttribute(t, isNullable),
boolType => super.memoryAttribute(t, isNullable),
integerType => (isNullable ? 'strong' : 'copy'),
doubleType => (isNullable ? 'strong' : 'copy'),
stringType => super.memoryAttribute(t, isNullable),
arrayType => super.memoryAttribute(t, isNullable),
classType => super.memoryAttribute(t, isNullable),
mapType => super.memoryAttribute(t, isNullable),
enumType => super.memoryAttribute(t, isNullable),
unionType => super.memoryAttribute(t, isNullable)
)
}
}

export async function genObjC(events: TrackedEvent[], { trackingPlan, classPrefix }: Params) {
Expand Down
32 changes: 16 additions & 16 deletions tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ typedef void (^ SEGThe42_TerribleEventName3BuilderBlock)(SEGThe42_TerribleEventN
/// Optional boolean property
@property (nonatomic, nullable, assign) NSNumber *isOptionalBoolean;
/// Optional integer property
@property (nonatomic, nullable, assign) NSNumber *optionalInt;
@property (nonatomic, nullable, copy) NSString *optionalNullableString;
@property (nonatomic, nullable, copy) NSNumber *optionalInt;
@property (nonatomic, nullable, copy) NSString *optionalNullableString;
/// Optional number property
@property (nonatomic, nullable, assign) NSNumber *optionalNumber;
@property (nonatomic, nullable, copy) id optionalNumberOrString;
@property (nonatomic, nullable, copy) NSNumber *optionalNumber;
@property (nonatomic, nullable, copy) id optionalNumberOrString;
/// Optional object property
@property (nonatomic, nullable, strong) SEGOptionalObject *optionalObject;
/// Optional object (empty) property
Expand All @@ -75,11 +75,11 @@ typedef void (^ SEGThe42_TerribleEventName3BuilderBlock)(SEGThe42_TerribleEventN
/// Required boolean property
@property (nonatomic, assign) NSNumber *isRequiredBoolean;
/// Required integer property
@property (nonatomic, assign) NSNumber *requiredInt;
@property (nonatomic, copy) NSString *requiredNullableString;
@property (nonatomic, copy) NSNumber *requiredInt;
@property (nonatomic, copy) NSString *requiredNullableString;
/// Required number property
@property (nonatomic, assign) NSNumber *requiredNumber;
@property (nonatomic, copy) id requiredNumberOrString;
@property (nonatomic, copy) NSNumber *requiredNumber;
@property (nonatomic, copy) id requiredNumberOrString;
/// Required object property
@property (nonatomic, strong) SEGRequiredObject *requiredObject;
/// Required object (empty) property
Expand All @@ -102,11 +102,11 @@ typedef void (^ SEGExampleEventBuilderBlock)(SEGExampleEventBuilder *);
/// Optional boolean property
@property (nonatomic, nullable, assign) NSNumber *isOptionalBoolean;
/// Optional integer property
@property (nonatomic, nullable, assign) NSNumber *optionalInt;
@property (nonatomic, nullable, copy) NSString *optionalNullableString;
@property (nonatomic, nullable, copy) NSNumber *optionalInt;
@property (nonatomic, nullable, copy) NSString *optionalNullableString;
/// Optional number property
@property (nonatomic, nullable, assign) NSNumber *optionalNumber;
@property (nonatomic, nullable, copy) id optionalNumberOrString;
@property (nonatomic, nullable, copy) NSNumber *optionalNumber;
@property (nonatomic, nullable, copy) id optionalNumberOrString;
/// Optional object property
@property (nonatomic, nullable, strong) SEGOptionalObject *optionalObject;
/// Optional object (empty) property
Expand All @@ -124,11 +124,11 @@ typedef void (^ SEGExampleEventBuilderBlock)(SEGExampleEventBuilder *);
/// Required boolean property
@property (nonatomic, assign) NSNumber *isRequiredBoolean;
/// Required integer property
@property (nonatomic, assign) NSNumber *requiredInt;
@property (nonatomic, copy) NSString *requiredNullableString;
@property (nonatomic, copy) NSNumber *requiredInt;
@property (nonatomic, copy) NSString *requiredNullableString;
/// Required number property
@property (nonatomic, assign) NSNumber *requiredNumber;
@property (nonatomic, copy) id requiredNumberOrString;
@property (nonatomic, copy) NSNumber *requiredNumber;
@property (nonatomic, copy) id requiredNumberOrString;
/// Required object property
@property (nonatomic, strong) SEGRequiredObject *requiredObject;
/// Required object (empty) property
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4056,9 +4056,9 @@ js-tokens@^3.0.2:
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=

js-yaml@^3.12.0, js-yaml@^3.7.0, js-yaml@^3.9.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
Expand Down

0 comments on commit 7a2ec99

Please sign in to comment.