Skip to content

Commit

Permalink
[Fix] Add missing selectors for NSExpression.
Browse files Browse the repository at this point in the history
Added the missing static factory methods and the missing property. In
order to give a clean API a new flag was added to the NSExpression class
to track if the Block property does return a block or a null ptr. The
idea is to avoid user from seeing an obj-c exception.

This commit fixes bug #35012:

https://bugzilla.xamarin.com/show_bug.cgi?id=35012

The evaluation of the NSExpression and the defition of the
NSExpressionHandler have also been fixed since both should be using
NSObjects.
  • Loading branch information
mandel-macaque committed May 19, 2016
1 parent 323c7f4 commit 5508aa3
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 29 deletions.
168 changes: 168 additions & 0 deletions src/Foundation/NSExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// TODO: The NSExpression class is a cluster class in cococa. This means that now all the properties are supported by all the types of NSExpressions.
// At the point of this written all the properties have been tested with all types EXCEPT NSExpressionType.Subquery and NSExpressionType.Conditional because writting
// tests for those was not possible. The properties for these two types have been deduced from the other types yet bugs are possible and an objc excection will be thrown.
using System;
using System.Runtime.InteropServices;
using XamCore.ObjCRuntime;

namespace XamCore.Foundation {

public partial class NSExpression {

[Export ("arguments")]
public virtual NSExpression[] Arguments {
get {
var type = ExpressionType;
if (type != NSExpressionType.Function && type != NSExpressionType.Block && type != NSExpressionType.KeyPath)
throw new InvalidOperationException (
$"NSExpressions of type {type} do not support the Arguments property. Expressions that support the property "
+ "are of type Function, Block and KeyPath");
return _Arguments;
}
}


[Export ("collection")]
public virtual NSObject Collection {
get {
var type = ExpressionType;
if (type != NSExpressionType.NSAggregate)
throw new InvalidOperationException (
$"NSExpressions of type {type} do not support the Collection property. Expressions that support the property "
+ "are of type NSAggregate");
return _Collection;
}
}

[Export ("predicate")]
public virtual NSPredicate Predicate {
get {
var type = ExpressionType;
if (type != NSExpressionType.Conditional && type != NSExpressionType.Subquery)
throw new InvalidOperationException (
$"NSExpressions of type {type} do not support the Predicate property. Expressions that support the property "
+ "are of type Conditional and Subquery");
return _Predicate;
}
}

[Export ("expressionBlock")]
public virtual NSExpressionCallbackHandler Block {
get {
if (ExpressionType != NSExpressionType.Block)
throw new InvalidOperationException (
$"NSExpressions of type {ExpressionType} do not support the Block property. Expressions that support the property "
+ "are created via the FromFunction (NSExpressionHandler target, NSExpression[] parameters) method.");
return _Block;
}
}

[Export ("constantValue")]
public virtual NSObject ConstantValue {
get {
if (ExpressionType != NSExpressionType.ConstantValue)
throw new InvalidOperationException (
$"NSExpressions of type {ExpressionType} do not support the ConstantValue property. Expressions that support the property "
+ "are created via the FromConstant methods.");
return _ConstantValue;
}
}

[Export ("keyPath")]
public virtual string KeyPath {
get {
if (ExpressionType != NSExpressionType.KeyPath)
throw new InvalidOperationException (
$"NSExpressions of type {ExpressionType} do not support the KeyPath property. Expressions that support the property "
+ "are created via the FromKeyPath method.");
return _KeyPath;
}
}

[Export ("leftExpression")]
public virtual NSExpression LeftExpression {
get {
var type = ExpressionType;
if (type != NSExpressionType.Conditional && type != NSExpressionType.IntersectSet && type != NSExpressionType.MinusSet
&& type != NSExpressionType.Subquery && type != NSExpressionType.UnionSet)
throw new InvalidOperationException (
$"NSExpressions of type {type} do not support the LeftExpression property. Expressions that support the property "
+ "are of type Conditional, IntersectSet, MinusSet, Subquery or UnionSet");
return _LeftExpression;
}
}

[Mac(10,11),iOS(9,0)]
[Export ("trueExpression")]
public virtual NSExpression TrueExpression {
get {
var type = ExpressionType;
if (type != NSExpressionType.Conditional && type != NSExpressionType.Subquery)
throw new InvalidOperationException (
$"NSExpressions of type {type} do not support the TrueExpression property. Expressions that support the property "
+ "are of type Conditional and Subquery");
return _TrueExpression;
}
}

[Mac(10,11),iOS(9,0)]
[Export ("falseExpression")]
public virtual NSExpression FalseExpression {
get {
var type = ExpressionType;
if (type != NSExpressionType.Conditional && type != NSExpressionType.Subquery)
throw new InvalidOperationException (
$"NSExpressions of type {type} do not support the FalseExpression property. Expressions that support the property "
+ "are of type Conditional and Subquery");
return _FalseExpression;
}
}

[Export ("rightExpression")]
public virtual NSExpression RightExpression {
get {
var type = ExpressionType;
if (type != NSExpressionType.Conditional && type != NSExpressionType.IntersectSet && type != NSExpressionType.MinusSet
&& type != NSExpressionType.Subquery && type != NSExpressionType.UnionSet)
throw new InvalidOperationException (
$"NSExpressions of type {type} do not support the RightExpression property. Expressions that support the property "
+ "are of type Conditional, IntersectSet, MinusSet, Subquery or UnionSet");
return _RightExpression;
}
}

[Export ("function")]
public virtual string Function {
get {
if (ExpressionType != NSExpressionType.Function)
throw new InvalidOperationException (
$"NSExpressions of type {ExpressionType} do not support the Function property. Expressions that support the property "
+ "are created via the FromFunction (FromFunction (string name, NSExpression[] parameters) or FromFormat methods.");
return _Function;
}
}

[Export ("variable")]
public virtual string Variable {
get {
if (ExpressionType != NSExpressionType.Variable)
throw new InvalidOperationException (
$"NSExpressions of type {ExpressionType} do not support the Function property. Expressions that support the property "
+ "are created via the FromVariable method.");
return _Variable;
}
}

[Export ("operand")]
public virtual NSExpression Operand {
get {
var type = ExpressionType;
if (type != NSExpressionType.KeyPath && type != NSExpressionType.Function)
throw new InvalidOperationException (
$"NSExpressions of type {type} do not support the Arguments property. Expressions that support the property "
+ "are of type Function, Block and KeyPath");
return _Operand;
}
}
}
}
85 changes: 56 additions & 29 deletions src/foundation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3152,8 +3152,11 @@ public interface NSException : NSCoding, NSCopying {
string[] CallStackSymbols { get; }
}

#if !XAMCORE_4_0
[Obsolete("NSExpressionHandler is deprecated, please use FromFormat (string, NSObject[]) instead.")]
public delegate void NSExpressionHandler (NSObject evaluatedObject, NSExpression [] expressions, NSMutableDictionary context);

#endif
public delegate NSObject NSExpressionCallbackHandler (NSObject evaluatedObject, NSExpression [] expressions, NSMutableDictionary context);
[BaseType (typeof (NSObject))]
// Objective-C exception thrown. Name: NSInvalidArgumentException Reason: *** -predicateFormat cannot be sent to an abstract object of class NSExpression: Create a concrete instance!
[DisableDefaultCtor]
Expand All @@ -3173,9 +3176,18 @@ public interface NSExpression : NSSecureCoding, NSCopying {
[Static, Export ("expressionForFunction:arguments:")]
NSExpression FromFunction (string name, NSExpression[] parameters);

[Static, Export ("expressionWithFormat:argumentArray:")]
[Static, Export ("expressionWithFormat:")]
NSExpression FromFormat (string expressionFormat);

#if !XAMCORE_4_0
[Obsolete("FromFormat (string, NSExpression[]) is deprecated, please use FromFormat (string, NSObject[]) instead.")]
[Sealed, Static, Export ("expressionWithFormat:argumentArray:")]
NSExpression FromFormat (string format, NSExpression [] parameters);

#endif

[Static, Export ("expressionWithFormat:argumentArray:")]
NSExpression FromFormat (string format, NSObject [] parameters);

//+ (NSExpression *)expressionForAggregate:(NSArray *)subexpressions;
[Static, Export ("expressionForAggregate:")]
NSExpression FromAggregate (NSExpression [] subexpressions);
Expand All @@ -3196,8 +3208,14 @@ public interface NSExpression : NSSecureCoding, NSCopying {
[Static, Export ("expressionForFunction:selectorName:arguments:")]
NSExpression FromFunction (NSExpression target, string name, NSExpression[] parameters);

[Static, Export ("expressionForBlock:arguments:")]
#if !XAMCORE_4_0
[Obsolete("FromFunction (NSExpressionHandler, NSExpression[]) is deprecated, please use FromFunction (NSExpressionCallbackHandler, NSExpression[]) instead.")]
[Sealed, Static, Export ("expressionForBlock:arguments:")]
NSExpression FromFunction (NSExpressionHandler target, NSExpression[] parameters);
#endif

[Static, Export ("expressionForBlock:arguments:")]
NSExpression FromFunction (NSExpressionCallbackHandler target, NSExpression[] parameters);

[Since (7,0), Mavericks]
[Static]
Expand All @@ -3220,46 +3238,55 @@ public interface NSExpression : NSSecureCoding, NSCopying {
[Export ("expressionType")]
NSExpressionType ExpressionType { get; }

[Export ("constantValue")]
NSObject ConstantValue { get; }
[Sealed, Internal, Export ("expressionBlock")]
NSExpressionCallbackHandler _Block { get; }

[Export ("keyPath")]
string KeyPath { get; }
[Sealed, Internal, Export ("constantValue")]
NSObject _ConstantValue { get; }

[Export ("function")]
string Function { get; }
[Sealed, Internal, Export ("keyPath")]
string _KeyPath { get; }

[Export ("variable")]
string Variable { get; }
[Sealed, Internal, Export ("function")]
string _Function { get; }

[Export ("operand")]
NSExpression Operand { get; }
[Sealed, Internal, Export ("variable")]
string _Variable { get; }

[Export ("arguments")]
NSExpression[] Arguments { get; }
[Sealed, Internal, Export ("operand")]
NSExpression _Operand { get; }

[Export ("collection")]
NSObject Collection { get; }
[Sealed, Internal, Export ("arguments")]
NSExpression[] _Arguments { get; }

[Export ("predicate")]
NSPredicate Predicate { get; }
[Sealed, Internal, Export ("collection")]
NSObject _Collection { get; }

[Export ("leftExpression")]
NSExpression LeftExpression { get; }
[Sealed, Internal, Export ("predicate")]
NSPredicate _Predicate { get; }

[Export ("rightExpression")]
NSExpression RightExpression { get; }
[Sealed, Internal, Export ("leftExpression")]
NSExpression _LeftExpression { get; }

[Sealed, Internal, Export ("rightExpression")]
NSExpression _RightExpression { get; }

[Mac(10,11),iOS(9,0)]
[Export ("trueExpression")]
NSExpression TrueExpression { get; }
[Sealed, Internal, Export ("trueExpression")]
NSExpression _TrueExpression { get; }

[Mac(10,11),iOS(9,0)]
[Export ("falseExpression")]
NSExpression FalseExpression { get; }
[Sealed, Internal, Export ("falseExpression")]
NSExpression _FalseExpression { get; }

#if !XAMCORE_4_0
[Obsolete("ValueWithObject is deprecated, please use EvaluateWith instead.")]
[Sealed, Export ("expressionValueWithObject:context:")]
NSExpression ExpressionValueWithObject (NSObject object1, NSMutableDictionary context);
#endif

[Export ("expressionValueWithObject:context:")]
NSExpression ExpressionValueWithObject (NSObject object1, NSMutableDictionary context);
NSObject EvaluateWith ([NullAllowed] NSObject obj, [NullAllowed] NSMutableDictionary context);
}

[iOS (8,0)][Mac (10,10, onlyOn64 : true)] // Not defined in 32-bit
Expand Down
1 change: 1 addition & 0 deletions src/frameworks.sources
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ FOUNDATION_SOURCES = \
Foundation/NSDirectoryEnumerator.cs \
Foundation/NSDistributedNotificationCenter.cs \
Foundation/NSErrorException.cs \
Foundation/NSExpression.cs \
Foundation/NSExtension.cs \
Foundation/NSFastEnumerationState.cs \
Foundation/NSFastEnumerator.cs \
Expand Down

0 comments on commit 5508aa3

Please sign in to comment.