Xcode autocompletion does not work correctly for block typedefs containing nullability specifiers

Originator:steipete
Number:rdar://20839310 Date Originated:06-May-2015 02:01 PM
Status:Open Resolved:
Product:iOS SDK Product Version:6.3
Classification:UI/Usability Reproducible:Always
 
Summary:

When a method prototype contains a block parameter whose type is provided as a typedef, Xcode Objective-C autocompletion does not work correctly and prevents from directly (and thus conveniently!) implementing the block.

Steps to Reproduce:

Create a source file with the following contents:

NS_ASSUME_NONNULL_BEGIN
typedef void (^SomeBlockSignature)(NSString * __nullable param);

@interface SomeClass ()

- (void)someMethodWithABlock:(SomeBlockSignature)block;

@end
NS_ASSUME_NONNULL_END

@implementation SomeClass

- (void)someMethodWithABlock:(SomeBlockSignature)block
{
	// Implementation is irrelevant here
}

@end

Then begin implementing another method which calls -someMethodWithABlock, by typing ‘[self someMethod’  and pressing Enter twice. Xcode fills the remaining of the prototype and attempts to fill in the block signature. You get the following annoying result, though:

@implementation SomeClass

// … see above

- (void)otherMethod
{
	[self someMethodWithABlock:(SomeBlockSignature __nonnull()block
}

@end

instead of the result

@implementation SomeClass

// … see above

- (void)otherMethod
{
	[self someMethodWithABlock:^(NSString * __nullable) {
		<#code#>
	}
}

@end

you would get if no block signature typedef was used, i.e. if the block signature was directly inlined in the method prototype itself:

NS_ASSUME_NONNULL_BEGIN
@interface SomeClass ()

- (void)someMethodWithABlock:(void (^)(NSString * __nullable param))block;

@end
NS_ASSUME_NONNULL_END

Note that the ‘param’ parameter incorrectly disappears from the autocompleted result in this case, though. If the NONNULL region is removed:

@interface SomeClass ()

- (void)someMethodWithABlock:(void (^)(NSString *param))block;

@end

autocompletion namely provides the usual convenient result:

@implementation SomeClass

// … see above

- (void)otherMethod
{
	[self someMethodWithABlock:^(NSString *param) {
		<#code#>
	}
}

which can immediately be used for implementation.

@end

Expected Results:

Autocompletion correctly fills in the block signature, with immediately available parameters:

@implementation SomeClass

// … see above

- (void)otherMethod
{
	[self someMethodWithABlock:^(NSString * __nullable param) {
		<#code#>
	}
}

@end

Actual Results:

The autocompletion result is useless:

@implementation SomeClass

// … see above

- (void)otherMethod
{
	[self someMethodWithABlock:(SomeBlockSignature __nonnull()block
}

@end

Configuration:

Xcode 6.3

Notes: This is a duplicate of rdar://20723086

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!