Update remodel iglistdiffable plugin to the latest

Summary:
Remodel changed quite a bit, this updates the plugin to work correctly with the latest state.
It also includes other recent Remodel changes like e.g. autoformatting of the codebase.

Resolves #1353

Reviewed By: natestedman

Differential Revision: D16794236

fbshipit-source-id: f543d0e3e5656f540accd5e359bbaf0acc8071fc
This commit is contained in:
Markus Emrich 2019-08-14 12:20:36 -07:00 committed by Facebook Github Bot
parent cb344f9814
commit 3deecff55a
4 changed files with 381 additions and 447 deletions

View file

@ -4,22 +4,22 @@ Feature: Outputting Value Objects implementing IGListDiffable
@announce
Scenario: Generating a value object, which correctly implements IGListDiffable using the specified diffIdentifier
Given a file named "project/values/Test.value" with:
Given a file named "project/values/IGListDiffableTest.value" with:
"""
Test includes(IGListDiffable) {
IGListDiffableTest includes(IGListDiffable) {
CGRect someRect
%diffIdentifier
NSString *stringOne
%diffIdentifier NSString *stringOne
}
"""
When I run `../../bin/generate project`
Then the file "project/values/Test.h" should contain:
Then the file "project/values/IGListDiffableTest.h" should contain:
"""
#import <Foundation/Foundation.h>
#import <CoreGraphics/CGGeometry.h>
#import <IGListKit/IGListDiffable.h>
@interface Test : NSObject <IGListDiffable, NSCopying>
@interface IGListDiffableTest : NSObject <IGListDiffable, NSCopying>
@property (nonatomic, readonly) CGRect someRect;
@property (nonatomic, readonly, copy) NSString *stringOne;
@ -33,89 +33,37 @@ Feature: Outputting Value Objects implementing IGListDiffable
@end
"""
And the file "project/values/Test.m" should contain:
And the file "project/values/IGListDiffableTest.m" should contain:
"""
@implementation Test
- (instancetype)initWithSomeRect:(CGRect)someRect stringOne:(NSString *)stringOne
{
if ((self = [super init])) {
_someRect = someRect;
_stringOne = [stringOne copy];
}
return self;
}
- (id)copyWithZone:(nullable NSZone *)zone
{
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"%@ - \n\t someRect: %@; \n\t stringOne: %@; \n", [super description], NSStringFromCGRect(_someRect), _stringOne];
}
- (id<NSObject>)diffIdentifier
{
return _stringOne;
}
- (NSUInteger)hash
{
NSUInteger subhashes[] = {HashCGFloat(_someRect.origin.x), HashCGFloat(_someRect.origin.y), HashCGFloat(_someRect.size.width), HashCGFloat(_someRect.size.height), [_stringOne hash]};
NSUInteger result = subhashes[0];
for (int ii = 1; ii < 5; ++ii) {
unsigned long long base = (((unsigned long long)result) << 32 | subhashes[ii]);
base = (~base) + (base << 18);
base ^= (base >> 31);
base *= 21;
base ^= (base >> 11);
base += (base << 6);
base ^= (base >> 22);
result = base;
}
return result;
}
- (BOOL)isEqual:(Test *)object
{
if (self == object) {
return YES;
} else if (object == nil || ![object isKindOfClass:[self class]]) {
return NO;
}
return
CGRectEqualToRect(_someRect, object->_someRect) &&
(_stringOne == object->_stringOne ? YES : [_stringOne isEqual:object->_stringOne]);
}
"""
And the file "project/values/IGListDiffableTest.m" should contain:
"""
- (BOOL)isEqualToDiffableObject:(nullable id)object
{
return [self isEqual:object];
}
@end
"""
Scenario: Generating a value object, which correctly implements IGListDiffable using a CGRect property
Given a file named "project/values/Test.value" with:
Given a file named "project/values/IGListDiffableTest2.value" with:
"""
Test includes(IGListDiffable) {
%diffIdentifier
CGRect someRect
IGListDiffableTest2 includes(IGListDiffable) {
%diffIdentifier CGRect someRect
}
"""
When I run `../../bin/generate project`
Then the file "project/values/Test.h" should contain:
Then the file "project/values/IGListDiffableTest2.h" should contain:
"""
#import <Foundation/Foundation.h>
#import <CoreGraphics/CGGeometry.h>
#import <IGListKit/IGListDiffable.h>
@interface Test : NSObject <IGListDiffable, NSCopying>
@interface IGListDiffableTest2 : NSObject <IGListDiffable, NSCopying>
@property (nonatomic, readonly) CGRect someRect;
@ -126,106 +74,60 @@ Feature: Outputting Value Objects implementing IGListDiffable
- (instancetype)initWithSomeRect:(CGRect)someRect NS_DESIGNATED_INITIALIZER;
@end
"""
And the file "project/values/Test.m" should contain:
And the file "project/values/IGListDiffableTest2.m" should contain:
"""
@implementation Test
- (instancetype)initWithSomeRect:(CGRect)someRect
{
if ((self = [super init])) {
_someRect = someRect;
}
return self;
}
- (id)copyWithZone:(nullable NSZone *)zone
{
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"%@ - \n\t someRect: %@; \n", [super description], NSStringFromCGRect(_someRect)];
}
- (id<NSObject>)diffIdentifier
{
return [NSValue valueWithCGRect:_someRect];
}
- (NSUInteger)hash
{
NSUInteger subhashes[] = {HashCGFloat(_someRect.origin.x), HashCGFloat(_someRect.origin.y), HashCGFloat(_someRect.size.width), HashCGFloat(_someRect.size.height)};
NSUInteger result = subhashes[0];
for (int ii = 1; ii < 4; ++ii) {
unsigned long long base = (((unsigned long long)result) << 32 | subhashes[ii]);
base = (~base) + (base << 18);
base ^= (base >> 31);
base *= 21;
base ^= (base >> 11);
base += (base << 6);
base ^= (base >> 22);
result = base;
}
return result;
}
- (BOOL)isEqual:(Test *)object
{
if (self == object) {
return YES;
} else if (object == nil || ![object isKindOfClass:[self class]]) {
return NO;
}
return
CGRectEqualToRect(_someRect, object->_someRect);
}
"""
And the file "project/values/IGListDiffableTest2.m" should contain:
"""
- (BOOL)isEqualToDiffableObject:(nullable id)object
{
return [self isEqual:object];
}
@end
"""
Scenario: Generating a value object, which correctly implements IGListDiffable using an NSInteger property
Given a file named "project/values/Test.value" with:
Given a file named "project/values/IGListDiffableTest3.value" with:
"""
Test includes(IGListDiffable) {
%diffIdentifier
NSInteger count
IGListDiffableTest3 includes(IGListDiffable) {
%diffIdentifier NSInteger count
}
"""
When I run `../../bin/generate project`
Then the file "project/values/Test.m" should contain:
Then the file "project/values/IGListDiffableTest3.m" should contain:
"""
- (id<NSObject>)diffIdentifier
{
return @(_count);
}
"""
And the file "project/values/IGListDiffableTest3.m" should contain:
"""
- (BOOL)isEqualToDiffableObject:(nullable id)object
{
return [self isEqual:object];
}
"""
Scenario: Generating a value object, which correctly implements IGListDiffable defaulting to self as diffIdentifier
Given a file named "project/values/Test.value" with:
Given a file named "project/values/IGListDiffableTest4.value" with:
"""
Test includes(IGListDiffable) {
IGListDiffableTest4 includes(IGListDiffable) {
CGRect someRect
}
"""
When I run `../../bin/generate project`
Then the file "project/values/Test.h" should contain:
Then the file "project/values/IGListDiffableTest4.h" should contain:
"""
#import <Foundation/Foundation.h>
#import <CoreGraphics/CGGeometry.h>
#import <IGListKit/IGListDiffable.h>
@interface Test : NSObject <IGListDiffable, NSCopying>
@interface IGListDiffableTest4 : NSObject <IGListDiffable, NSCopying>
@property (nonatomic, readonly) CGRect someRect;
@ -238,67 +140,17 @@ Feature: Outputting Value Objects implementing IGListDiffable
@end
"""
And the file "project/values/Test.m" should contain:
And the file "project/values/IGListDiffableTest4.m" should contain:
"""
@implementation Test
- (instancetype)initWithSomeRect:(CGRect)someRect
{
if ((self = [super init])) {
_someRect = someRect;
}
return self;
}
- (id)copyWithZone:(nullable NSZone *)zone
{
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"%@ - \n\t someRect: %@; \n", [super description], NSStringFromCGRect(_someRect)];
}
- (id<NSObject>)diffIdentifier
{
return self;
}
- (NSUInteger)hash
{
NSUInteger subhashes[] = {HashCGFloat(_someRect.origin.x), HashCGFloat(_someRect.origin.y), HashCGFloat(_someRect.size.width), HashCGFloat(_someRect.size.height)};
NSUInteger result = subhashes[0];
for (int ii = 1; ii < 4; ++ii) {
unsigned long long base = (((unsigned long long)result) << 32 | subhashes[ii]);
base = (~base) + (base << 18);
base ^= (base >> 31);
base *= 21;
base ^= (base >> 11);
base += (base << 6);
base ^= (base >> 22);
result = base;
}
return result;
}
- (BOOL)isEqual:(Test *)object
{
if (self == object) {
return YES;
} else if (object == nil || ![object isKindOfClass:[self class]]) {
return NO;
}
return
CGRectEqualToRect(_someRect, object->_someRect);
}
"""
And the file "project/values/IGListDiffableTest4.m" should contain:
"""
- (BOOL)isEqualToDiffableObject:(nullable id)object
{
return [self isEqual:object];
}
@end
"""

View file

@ -8,22 +8,22 @@
///<reference path='../../type-defs/jasmine.d.ts'/>
///<reference path='../../type-defs/jasmine-test-additions.d.ts'/>
import IGListDiffable = require('../../plugins/iglistdiffable');
import Error = require('../../error');
import Maybe = require('../../maybe');
import ObjC = require('../../objc');
import ObjectSpec = require('../../object-spec');
import ObjectGeneration = require('../../object-generation');
import * as IGListDiffable from '../../plugins/iglistdiffable';
import * as Error from '../../error';
import * as Maybe from '../../maybe';
import * as ObjC from '../../objc';
import * as ObjectSpec from '../../object-spec';
import * as ObjectGeneration from '../../object-generation';
const ObjectSpecPlugin = IGListDiffable.createPlugin();
function igListDiffableIsEqualMethod():ObjC.Method {
function igListDiffableIsEqualMethod(): ObjC.Method {
return {
preprocessors:[],
belongsToProtocol:Maybe.Just('IGListDiffable'),
preprocessors: [],
belongsToProtocol: Maybe.Just('IGListDiffable'),
code: ['return [self isEqual:object];'],
comments:[],
compilerAttributes:[],
comments: [],
compilerAttributes: [],
keywords: [
{
name: 'isEqualToDiffableObject',
@ -32,234 +32,250 @@ function igListDiffableIsEqualMethod():ObjC.Method {
modifiers: [ObjC.KeywordArgumentModifier.Nullable()],
type: {
name: 'id',
reference: 'id'
}
})
}
reference: 'id',
},
}),
},
],
returnType: { type:Maybe.Just({
name: 'BOOL',
reference: 'BOOL'
}), modifiers: [] }
}
returnType: {
type: Maybe.Just({
name: 'BOOL',
reference: 'BOOL',
}),
modifiers: [],
},
};
}
function igListDiffableDiffIdentifierMethodWithCode(code:string):ObjC.Method {
function igListDiffableDiffIdentifierMethodWithCode(code: string): ObjC.Method {
return {
preprocessors:[],
belongsToProtocol:Maybe.Just<string>('IGListDiffable'),
preprocessors: [],
belongsToProtocol: Maybe.Just<string>('IGListDiffable'),
code: [code],
comments:[],
compilerAttributes:[],
comments: [],
compilerAttributes: [],
keywords: [
{
name: 'diffIdentifier',
argument: Maybe.Nothing<ObjC.KeywordArgument>()
}
argument: Maybe.Nothing<ObjC.KeywordArgument>(),
},
],
returnType: { type:Maybe.Just({
name: 'NSObject',
reference: 'id<NSObject>'
}), modifiers: [] }
}
returnType: {
type: Maybe.Just({
name: 'NSObject',
reference: 'id<NSObject>',
}),
modifiers: [],
},
};
}
describe('ObjectSpecPlugins.IGListDiffable', function() {
describe('Value Object', function() {
describe('#instanceMethods', function() {
it('returns two instance methods and uses self as diffIdentifier with no input attributes', function() {
const objectType:ObjectSpec.Type = {
annotations: {},
attributes: [],
comments: [],
excludes: [],
includes: [],
libraryName: Maybe.Nothing<string>(),
typeLookups:[],
typeName: 'Foo'
};
const objectType: ObjectSpec.Type = {
annotations: {},
attributes: [],
comments: [],
excludes: [],
includes: [],
libraryName: Maybe.Nothing<string>(),
typeLookups: [],
typeName: 'Foo',
};
const instanceMethods:ObjC.Method[] = ObjectSpecPlugin.instanceMethods(objectType);
const instanceMethods: ObjC.Method[] = ObjectSpecPlugin.instanceMethods(
objectType,
);
const expectedInstanceMethods:ObjC.Method[] = [
const expectedInstanceMethods: ObjC.Method[] = [
igListDiffableIsEqualMethod(),
igListDiffableDiffIdentifierMethodWithCode('return self;')
igListDiffableDiffIdentifierMethodWithCode('return self;'),
];
expect(instanceMethods).toEqualJSON(expectedInstanceMethods);
});
it('returns NSObjects directly as diffIdentifier', function() {
const objectType:ObjectSpec.Type = {
const objectType: ObjectSpec.Type = {
annotations: {},
attributes: [
{
annotations: {
diffIdentifier: []
diffIdentifier: [],
},
comments: [],
name: 'name',
nullability:ObjC.Nullability.Inherited(),
nullability: ObjC.Nullability.Inherited(),
type: {
fileTypeIsDefinedIn:Maybe.Nothing<string>(),
libraryTypeIsDefinedIn:Maybe.Nothing<string>(),
fileTypeIsDefinedIn: Maybe.Nothing<string>(),
libraryTypeIsDefinedIn: Maybe.Nothing<string>(),
name: 'NSString',
reference: 'NSString *',
underlyingType:Maybe.Just<string>('NSObject'),
conformingProtocol: Maybe.Nothing<string>()
}
}
underlyingType: Maybe.Just<string>('NSObject'),
conformingProtocol: Maybe.Nothing<string>(),
},
},
],
comments: [],
excludes: [],
includes: [],
libraryName: Maybe.Nothing<string>(),
typeLookups:[],
typeName: 'Foo'
typeLookups: [],
typeName: 'Foo',
};
const instanceMethods:ObjC.Method[] = ObjectSpecPlugin.instanceMethods(objectType);
const instanceMethods: ObjC.Method[] = ObjectSpecPlugin.instanceMethods(
objectType,
);
const expectedInstanceMethods:ObjC.Method[] = [
const expectedInstanceMethods: ObjC.Method[] = [
igListDiffableIsEqualMethod(),
igListDiffableDiffIdentifierMethodWithCode('return _name;')
igListDiffableDiffIdentifierMethodWithCode('return _name;'),
];
expect(instanceMethods).toEqualJSON(expectedInstanceMethods);
});
it('returns NSInteger as formatString as diffIdentifier', function() {
const objectType:ObjectSpec.Type = {
const objectType: ObjectSpec.Type = {
annotations: {},
attributes: [
{
annotations: {
diffIdentifier: []
diffIdentifier: [],
},
comments: [],
name: 'age',
nullability:ObjC.Nullability.Inherited(),
nullability: ObjC.Nullability.Inherited(),
type: {
fileTypeIsDefinedIn:Maybe.Nothing<string>(),
libraryTypeIsDefinedIn:Maybe.Nothing<string>(),
fileTypeIsDefinedIn: Maybe.Nothing<string>(),
libraryTypeIsDefinedIn: Maybe.Nothing<string>(),
name: 'NSInteger',
reference: 'NSInteger',
underlyingType:Maybe.Nothing<string>(),
conformingProtocol: Maybe.Nothing<string>()
}
}
underlyingType: Maybe.Nothing<string>(),
conformingProtocol: Maybe.Nothing<string>(),
},
},
],
comments: [],
excludes: [],
includes: [],
libraryName: Maybe.Nothing<string>(),
typeLookups:[],
typeName: 'Foo'
typeLookups: [],
typeName: 'Foo',
};
const instanceMethods:ObjC.Method[] = ObjectSpecPlugin.instanceMethods(objectType);
const instanceMethods: ObjC.Method[] = ObjectSpecPlugin.instanceMethods(
objectType,
);
const expectedInstanceMethods:ObjC.Method[] = [
const expectedInstanceMethods: ObjC.Method[] = [
igListDiffableIsEqualMethod(),
igListDiffableDiffIdentifierMethodWithCode('return @(_age);')
igListDiffableDiffIdentifierMethodWithCode('return @(_age);'),
];
expect(instanceMethods).toEqualJSON(expectedInstanceMethods);
});
it('returns CGRect as string as diffIdentifier', function() {
const objectType:ObjectSpec.Type = {
const objectType: ObjectSpec.Type = {
annotations: {},
attributes: [
{
annotations: {
diffIdentifier: []
diffIdentifier: [],
},
comments: [],
name: 'rect',
nullability:ObjC.Nullability.Inherited(),
nullability: ObjC.Nullability.Inherited(),
type: {
fileTypeIsDefinedIn:Maybe.Nothing<string>(),
libraryTypeIsDefinedIn:Maybe.Nothing<string>(),
fileTypeIsDefinedIn: Maybe.Nothing<string>(),
libraryTypeIsDefinedIn: Maybe.Nothing<string>(),
name: 'CGRect',
reference: 'CGRect',
underlyingType:Maybe.Nothing<string>(),
conformingProtocol: Maybe.Nothing<string>()
}
}
underlyingType: Maybe.Nothing<string>(),
conformingProtocol: Maybe.Nothing<string>(),
},
},
],
comments: [],
excludes: [],
includes: [],
libraryName: Maybe.Nothing<string>(),
typeLookups:[],
typeName: 'Foo'
typeLookups: [],
typeName: 'Foo',
};
const instanceMethods:ObjC.Method[] = ObjectSpecPlugin.instanceMethods(objectType);
const instanceMethods: ObjC.Method[] = ObjectSpecPlugin.instanceMethods(
objectType,
);
const expectedInstanceMethods:ObjC.Method[] = [
const expectedInstanceMethods: ObjC.Method[] = [
igListDiffableIsEqualMethod(),
igListDiffableDiffIdentifierMethodWithCode('return [NSValue valueWithCGRect:_rect];')
igListDiffableDiffIdentifierMethodWithCode(
'return [NSValue valueWithCGRect:_rect];',
),
];
expect(instanceMethods).toEqualJSON(expectedInstanceMethods);
});
it('returns property marked with %diffIdentifier as diffIdentifier', function() {
const objectType:ObjectSpec.Type = {
const objectType: ObjectSpec.Type = {
annotations: {},
attributes: [
{
annotations: {},
comments: [],
name: 'name',
nullability:ObjC.Nullability.Inherited(),
nullability: ObjC.Nullability.Inherited(),
type: {
fileTypeIsDefinedIn:Maybe.Nothing<string>(),
libraryTypeIsDefinedIn:Maybe.Nothing<string>(),
fileTypeIsDefinedIn: Maybe.Nothing<string>(),
libraryTypeIsDefinedIn: Maybe.Nothing<string>(),
name: 'NSString',
reference: 'NSString *',
underlyingType:Maybe.Just<string>('NSObject'),
conformingProtocol: Maybe.Nothing<string>()
}
underlyingType: Maybe.Just<string>('NSObject'),
conformingProtocol: Maybe.Nothing<string>(),
},
},
{
annotations: {
diffIdentifier: []
diffIdentifier: [],
},
comments: [],
name: 'age',
nullability:ObjC.Nullability.Inherited(),
nullability: ObjC.Nullability.Inherited(),
type: {
fileTypeIsDefinedIn:Maybe.Nothing<string>(),
libraryTypeIsDefinedIn:Maybe.Nothing<string>(),
fileTypeIsDefinedIn: Maybe.Nothing<string>(),
libraryTypeIsDefinedIn: Maybe.Nothing<string>(),
name: 'NSInteger',
reference: 'NSInteger',
underlyingType:Maybe.Nothing<string>(),
conformingProtocol: Maybe.Nothing<string>()
}
}
underlyingType: Maybe.Nothing<string>(),
conformingProtocol: Maybe.Nothing<string>(),
},
},
],
comments: [],
excludes: [],
includes: [],
libraryName: Maybe.Nothing<string>(),
typeLookups:[],
typeName: 'Foo'
typeLookups: [],
typeName: 'Foo',
};
const instanceMethods:ObjC.Method[] = ObjectSpecPlugin.instanceMethods(objectType);
const instanceMethods: ObjC.Method[] = ObjectSpecPlugin.instanceMethods(
objectType,
);
const expectedInstanceMethods:ObjC.Method[] = [
const expectedInstanceMethods: ObjC.Method[] = [
igListDiffableIsEqualMethod(),
igListDiffableDiffIdentifierMethodWithCode('return @(_age);')
igListDiffableDiffIdentifierMethodWithCode('return @(_age);'),
];
expect(instanceMethods).toEqualJSON(expectedInstanceMethods);
});
});
});
});

View file

@ -5,19 +5,19 @@
* LICENSE file in the root directory of this source tree.
*/
import Maybe = require('../maybe');
import ObjC = require('../objc');
import ObjCTypeUtils = require('../objc-type-utils');
import ObjectSpec = require('../object-spec');
import ObjectSpecCodeUtils = require('../object-spec-code-utils');
import * as Maybe from '../maybe';
import * as ObjC from '../objc';
import * as ObjCTypeUtils from '../objc-type-utils';
import * as ObjectSpec from '../object-spec';
import * as ObjectSpecCodeUtils from '../object-spec-code-utils';
function isEqualToDiffableObjectMethod():ObjC.Method {
function isEqualToDiffableObjectMethod(): ObjC.Method {
return {
preprocessors:[],
belongsToProtocol:Maybe.Just<string>('IGListDiffable'),
preprocessors: [],
belongsToProtocol: Maybe.Just<string>('IGListDiffable'),
code: ['return [self isEqual:object];'],
comments:[],
compilerAttributes:[],
comments: [],
compilerAttributes: [],
keywords: [
{
name: 'isEqualToDiffableObject',
@ -26,110 +26,142 @@ function isEqualToDiffableObjectMethod():ObjC.Method {
modifiers: [ObjC.KeywordArgumentModifier.Nullable()],
type: {
name: 'id',
reference: 'id'
}
})
}
reference: 'id',
},
}),
},
],
returnType: { type: Maybe.Just({
name: 'BOOL',
reference: 'BOOL'
}), modifiers: [] }
}
returnType: {
type: Maybe.Just({
name: 'BOOL',
reference: 'BOOL',
}),
modifiers: [],
},
};
}
function functionReturnValueForIvarWithFunctionName(iVarString:string, functionToCall:string):string {
function functionReturnValueForIvarWithFunctionName(
iVarString: string,
functionToCall: string,
): string {
return functionToCall + '(' + iVarString + ')';
}
function formattedStringValueForIvarWithFormatSpecifier(iVarString:string, stringFormatSpecifier:string, optionalCast:string=null):string {
var castString:string = (optionalCast === null ? "" : "(" + optionalCast + ")");
return "[NSString stringWithFormat:@\"" + stringFormatSpecifier + "\", " + castString + iVarString + "]";
function formattedStringValueForIvarWithFormatSpecifier(
iVarString: string,
stringFormatSpecifier: string,
optionalCast: string = null,
): string {
var castString: string =
optionalCast === null ? '' : '(' + optionalCast + ')';
return (
'[NSString stringWithFormat:@"' +
stringFormatSpecifier +
'", ' +
castString +
iVarString +
']'
);
}
function nullableObjectValueWithFallback(objectValue:string, optionalFallback:string=null) {
return (optionalFallback === null) ? objectValue : `${objectValue} ?: ${optionalFallback}`;
function nullableObjectValueWithFallback(
objectValue: string,
optionalFallback: string = null,
) {
return optionalFallback === null
? objectValue
: `${objectValue} ?: ${optionalFallback}`;
}
function wrappedInNSValueForTypeName(iVarString:string, typeName:string) {
function wrappedInNSValueForTypeName(iVarString: string, typeName: string) {
return `[NSValue valueWith${typeName}:${iVarString}]`;
}
function objectValueForAttribute(attribute:ObjectSpec.Attribute, optionalFallback:string=null):string {
const iVarString:string = ObjectSpecCodeUtils.ivarForAttribute(attribute);
const type:ObjC.Type = ObjectSpecCodeUtils.computeTypeOfAttribute(attribute);
function objectValueForAttribute(
attribute: ObjectSpec.Attribute,
optionalFallback: string = null,
): string {
const iVarString: string = ObjectSpecCodeUtils.ivarForAttribute(attribute);
const type: ObjC.Type = ObjectSpecCodeUtils.computeTypeOfAttribute(attribute);
return ObjCTypeUtils.matchType({
id: function() {
return formattedStringValueForIvarWithFormatSpecifier(iVarString, "%@");
return ObjCTypeUtils.matchType(
{
id: function() {
return formattedStringValueForIvarWithFormatSpecifier(iVarString, '%@');
},
NSObject: function() {
return nullableObjectValueWithFallback(iVarString, optionalFallback);
},
BOOL: function() {
return `@(${iVarString})`;
},
NSInteger: function() {
return `@(${iVarString})`;
},
NSUInteger: function() {
return `@(${iVarString})`;
},
double: function() {
return `@(${iVarString})`;
},
float: function() {
return `@(${iVarString})`;
},
CGFloat: function() {
return `@(${iVarString})`;
},
NSTimeInterval: function() {
return `@(${iVarString})`;
},
uintptr_t: function() {
return `@(${iVarString})`;
},
uint32_t: function() {
return `@(${iVarString})`;
},
uint64_t: function() {
return `@(${iVarString})`;
},
int32_t: function() {
return `@(${iVarString})`;
},
int64_t: function() {
return `@(${iVarString})`;
},
SEL: function() {
return functionReturnValueForIvarWithFunctionName(
iVarString,
'NSStringFromSelector',
);
},
NSRange: function() {
return wrappedInNSValueForTypeName(iVarString, 'Range');
},
CGRect: function() {
return wrappedInNSValueForTypeName(iVarString, type.name);
},
CGPoint: function() {
return wrappedInNSValueForTypeName(iVarString, type.name);
},
CGSize: function() {
return wrappedInNSValueForTypeName(iVarString, type.name);
},
UIEdgeInsets: function() {
return wrappedInNSValueForTypeName(iVarString, type.name);
},
Class: function() {
return formattedStringValueForIvarWithFormatSpecifier(iVarString, '%@');
},
dispatch_block_t: function() {
return formattedStringValueForIvarWithFormatSpecifier(iVarString, '%@');
},
unmatchedType: function() {
return nullableObjectValueWithFallback('self', optionalFallback);
},
},
NSObject: function() {
return nullableObjectValueWithFallback(iVarString, optionalFallback);
},
BOOL: function() {
return `@(${iVarString})`;
},
NSInteger: function() {
return `@(${iVarString})`;
},
NSUInteger: function() {
return `@(${iVarString})`;
},
double: function() {
return `@(${iVarString})`;
},
float: function() {
return `@(${iVarString})`;
},
CGFloat: function() {
return `@(${iVarString})`;
},
NSTimeInterval: function() {
return `@(${iVarString})`;
},
uintptr_t: function() {
return `@(${iVarString})`;
},
uint32_t: function() {
return `@(${iVarString})`;
},
uint64_t: function() {
return `@(${iVarString})`;
},
int32_t: function() {
return `@(${iVarString})`;
},
int64_t: function() {
return `@(${iVarString})`;
},
SEL: function() {
return functionReturnValueForIvarWithFunctionName(iVarString, "NSStringFromSelector");
},
NSRange: function() {
return wrappedInNSValueForTypeName(iVarString, 'Range');
},
CGRect: function() {
return wrappedInNSValueForTypeName(iVarString, type.name);
},
CGPoint: function() {
return wrappedInNSValueForTypeName(iVarString, type.name);
},
CGSize: function() {
return wrappedInNSValueForTypeName(iVarString, type.name);
},
UIEdgeInsets: function() {
return wrappedInNSValueForTypeName(iVarString, type.name);
},
Class: function() {
return formattedStringValueForIvarWithFormatSpecifier(iVarString, "%@");
},
dispatch_block_t: function() {
return formattedStringValueForIvarWithFormatSpecifier(iVarString, "%@");
},
unmatchedType: function() {
return nullableObjectValueWithFallback('self', optionalFallback);
}
}, type);
type,
);
}
export {isEqualToDiffableObjectMethod, objectValueForAttribute};

View file

@ -5,113 +5,147 @@
* LICENSE file in the root directory of this source tree.
*/
import Code = require('../code');
import Error = require('../error');
import FileWriter = require('../file-writer');
import FunctionUtils = require('../function-utils');
import IGListDiffableUtils = require ('./iglistdiffable-utils');
import Maybe = require('../maybe');
import ObjC = require('../objc');
import ObjectSpec = require('../object-spec');
import ObjectSpecUtils = require('../object-spec-utils');
import * as Code from '../code';
import * as Error from '../error';
import * as FileWriter from '../file-writer';
import * as IGListDiffableUtils from './iglistdiffable-utils';
import * as Maybe from '../maybe';
import * as ObjC from '../objc';
import * as ObjectSpec from '../object-spec';
function diffIdentiferAttributeFilter(attribute:ObjectSpec.Attribute, index, array):boolean {
return (attribute.annotations["diffIdentifier"] != null);
function diffIdentiferAttributeFilter(
attribute: ObjectSpec.Attribute,
index,
array,
): boolean {
return attribute.annotations['diffIdentifier'] != null;
}
function diffIdentifierMethodImplementation(objectType:ObjectSpec.Type):string[] {
const diffIdentifierAttributes:ObjectSpec.Attribute[] = objectType.attributes.filter(diffIdentiferAttributeFilter);
function diffIdentifierMethodImplementation(
objectType: ObjectSpec.Type,
): string[] {
const diffIdentifierAttributes: ObjectSpec.Attribute[] = objectType.attributes.filter(
diffIdentiferAttributeFilter,
);
if (diffIdentifierAttributes.length > 0) {
// use first marked attribute as identifier, if available
return ['return ' + IGListDiffableUtils.objectValueForAttribute(diffIdentifierAttributes[0]) + ';']
return [
'return ' +
IGListDiffableUtils.objectValueForAttribute(
diffIdentifierAttributes[0],
) +
';',
];
} else {
// fallback/default to self
return ['return self;'];
}
}
function diffIdentifierMethod(objectType:ObjectSpec.Type):ObjC.Method {
function diffIdentifierMethod(objectType: ObjectSpec.Type): ObjC.Method {
return {
preprocessors:[],
belongsToProtocol:Maybe.Just<string>('IGListDiffable'),
preprocessors: [],
belongsToProtocol: Maybe.Just<string>('IGListDiffable'),
code: diffIdentifierMethodImplementation(objectType),
comments:[],
compilerAttributes:[],
comments: [],
compilerAttributes: [],
keywords: [
{
name: 'diffIdentifier',
argument: Maybe.Nothing<ObjC.KeywordArgument>()
}
argument: Maybe.Nothing<ObjC.KeywordArgument>(),
},
],
returnType: { type: Maybe.Just({
name: 'NSObject',
reference: 'id<NSObject>'
}), modifiers: [] }
}
returnType: {
type: Maybe.Just({
name: 'NSObject',
reference: 'id<NSObject>',
}),
modifiers: [],
},
};
}
export function createPlugin():ObjectSpec.Plugin {
export function createPlugin(): ObjectSpec.Plugin {
return {
additionalFiles: function(objectType:ObjectSpec.Type):Code.File[] {
additionalFiles: function(objectType: ObjectSpec.Type): Code.File[] {
return [];
},
additionalTypes: function(objectType:ObjectSpec.Type):ObjectSpec.Type[] {
transformBaseFile: function(
objectType: ObjectSpec.Type,
baseFile: Code.File,
): Code.File {
return baseFile;
},
additionalTypes: function(objectType: ObjectSpec.Type): ObjectSpec.Type[] {
return [];
},
attributes: function(objectType:ObjectSpec.Type):ObjectSpec.Attribute[] {
attributes: function(objectType: ObjectSpec.Type): ObjectSpec.Attribute[] {
return [];
},
classMethods: function(objectType:ObjectSpec.Type):ObjC.Method[] {
classMethods: function(objectType: ObjectSpec.Type): ObjC.Method[] {
return [];
},
fileTransformation: function(request:FileWriter.Request):FileWriter.Request {
transformFileRequest: function(
request: FileWriter.Request,
): FileWriter.Request {
return request;
},
fileType: function(objectType:ObjectSpec.Type):Maybe.Maybe<Code.FileType> {
fileType: function(
objectType: ObjectSpec.Type,
): Maybe.Maybe<Code.FileType> {
return Maybe.Nothing<Code.FileType>();
},
forwardDeclarations: function(objectType:ObjectSpec.Type):ObjC.ForwardDeclaration[] {
forwardDeclarations: function(
objectType: ObjectSpec.Type,
): ObjC.ForwardDeclaration[] {
return [];
},
functions: function(objectType:ObjectSpec.Type):ObjC.Function[] {
functions: function(objectType: ObjectSpec.Type): ObjC.Function[] {
return [];
},
headerComments: function(objectType:ObjectSpec.Type):ObjC.Comment[] {
headerComments: function(objectType: ObjectSpec.Type): ObjC.Comment[] {
return [];
},
implementedProtocols: function(objectType:ObjectSpec.Type):ObjC.Protocol[] {
implementedProtocols: function(
objectType: ObjectSpec.Type,
): ObjC.Protocol[] {
return [{name: 'IGListDiffable'}];
},
imports: function(objectType: ObjectSpec.Type): ObjC.Import[] {
return [
{ name: 'IGListDiffable' },
{
file: 'IGListDiffable.h',
isPublic: true,
requiresCPlusPlus: false,
library: Maybe.Just('IGListKit'),
},
];
},
imports: function(objectType:ObjectSpec.Type):ObjC.Import[] {
return [
{file:'IGListDiffable.h', isPublic:true, library:Maybe.Just('IGListKit')},
];
},
instanceMethods: function(objectType:ObjectSpec.Type):ObjC.Method[] {
instanceMethods: function(objectType: ObjectSpec.Type): ObjC.Method[] {
return [
IGListDiffableUtils.isEqualToDiffableObjectMethod(),
diffIdentifierMethod(objectType)
diffIdentifierMethod(objectType),
];
},
macros: function(valueType:ObjectSpec.Type):ObjC.Macro[] {
macros: function(valueType: ObjectSpec.Type): ObjC.Macro[] {
return [];
},
properties: function(objectType:ObjectSpec.Type):ObjC.Property[] {
properties: function(objectType: ObjectSpec.Type): ObjC.Property[] {
return [];
},
requiredIncludesToRun:['IGListDiffable'],
staticConstants: function(objectType:ObjectSpec.Type):ObjC.Constant[] {
requiredIncludesToRun: ['IGListDiffable'],
staticConstants: function(objectType: ObjectSpec.Type): ObjC.Constant[] {
return [];
},
validationErrors: function(objectType:ObjectSpec.Type):Error.Error[] {
validationErrors: function(objectType: ObjectSpec.Type): Error.Error[] {
return [];
},
nullability: function(objectType:ObjectSpec.Type):Maybe.Maybe<ObjC.ClassNullability> {
nullability: function(
objectType: ObjectSpec.Type,
): Maybe.Maybe<ObjC.ClassNullability> {
return Maybe.Nothing<ObjC.ClassNullability>();
},
subclassingRestricted: function(objectType:ObjectSpec.Type):boolean {
subclassingRestricted: function(objectType: ObjectSpec.Type): boolean {
return false;
},
};