Skip to content

Commit

Permalink
Improve SMLSyntaxError with image caching and a new factory method.
Browse files Browse the repository at this point in the history
  • Loading branch information
shysaur committed May 12, 2015
1 parent 7887bfe commit 8518dcb
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 118 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -22,3 +22,4 @@ profile

## Generated Documentation
AppleDoc
Doxygen
4 changes: 3 additions & 1 deletion Applications/MGSFragariaView/AppDelegate.m
Expand Up @@ -204,8 +204,10 @@ - (NSArray *)makeSyntaxErrors
error4.character = 12;
error4.length = 7;
error4.hidden = NO;

SMLSyntaxError *error5 = [SMLSyntaxError errorWithDescription:@"Yet another error" ofLevel:-912454 atLine:5];

return @[error1, error2, error3, error4];
return @[error1, error2, error3, error4, error5];
}


Expand Down
13 changes: 5 additions & 8 deletions MGSFragaria Tests/SMLSyntaxErrorTests.m
Expand Up @@ -42,12 +42,9 @@ - (void)setUp {
@"hidden" : @(YES),
@"warningLevel" : @(601.223) // panic
}],
[SMLSyntaxError errorWithDictionary:@{
@"errorDescription" : @"Sample error 3.",
@"line" : @(37),
@"hidden" : @(NO),
@"warningLevel" : @(kMGSErrorCategoryDocument)
}],
[SMLSyntaxError errorWithDescription:@"Sample error 3."
ofLevel:kMGSErrorCategoryDocument
atLine:37],
[SMLSyntaxError errorWithDictionary:@{
@"errorDescription" : @"Sample error 4.",
@"line" : @(37),
Expand Down Expand Up @@ -79,7 +76,7 @@ - (void)tearDown {

/*
* - test_defaultImagesForWarningLevel
* Here wer want to ensure that if an image isn't specified, the correct
* Here we want to ensure that if an image isn't specified, the correct
* default image is supplied based on the warningLevel property.
*/
- (void)test_defaultImageForWarningLevel
Expand All @@ -94,7 +91,7 @@ - (void)test_defaultImageForWarningLevel
expect = [[NSBundle bundleForClass:[SMLSyntaxError class]] imageForResource:@"messagesPanic"];
XCTAssert([[result TIFFRepresentation] isEqualToData:[expect TIFFRepresentation]]);

// Tests the default case where the value is 0.
// Tests the default value
test = self.syntaxErrors[5];
result = [SMLSyntaxError defaultImageForWarningLevel:test.warningLevel];
expect = [[NSBundle bundleForClass:[SMLSyntaxError class]] imageForResource:@"messagesWarning"];
Expand Down
124 changes: 67 additions & 57 deletions SMLSyntaxError.h
Expand Up @@ -9,23 +9,25 @@

#import <Foundation/Foundation.h>

/**
* MGSErrorType describes the warningLevel for an error, ranging from least severe to most severe.
* This can be used to automatically provide an appropriate image for error displays. The constants
* below can serve as as a convenience for setting warningLevel, and as long as the warningLevel is
* within the ranges described below the default warningImage can be used. This allows you to implement
* varying warningLevels within a "category."
*
**/

extern float const kMGSErrorCategoryAccess; ///< warningLevel > 0.0, <= 100.0
extern float const kMGSErrorCategoryConfig; ///< warningLevel > 100.0, <= 200.0
extern float const kMGSErrorCategoryDocument; ///< warningLevel > 200.0, <= 300.0
extern float const kMGSErrorCategoryInfo; ///< warningLevel > 300.0, <= 400.0
extern float const kMGSErrorCategoryWarning; ///< warningLevel > 400.0, <= 500.0
extern float const kMGSErrorCategoryError; ///< warningLevel > 500.0, <= 600.0
extern float const kMGSErrorCategoryPanic; ///< warningLevel > 600.0
extern float const kMGSErrorCategoryDefault; ///< warningLevel = kMGSErrorCategoryWarning
/** @defgroup warninglevels SMLSyntaxError Warning Levels
* These are Fragaria's default warning levels. Warning levels are used to
* decide which error badge will be shown on a line if more than one error
* is located on that line. Also, when the warningLevel property is set, the
* SMLSyntaxError's default image will also be set to one of various predefined
* images; each of these images correspond to one of the following
* constants. */

/** @{ */
extern float const kMGSErrorCategoryAccess; ///< warningLevel < 100.0
extern float const kMGSErrorCategoryConfig; ///< 100.0 <= warningLevel < 200.0
extern float const kMGSErrorCategoryDocument; ///< 200.0 <= warningLevel < 300.0
extern float const kMGSErrorCategoryInfo; ///< 300.0 <= warningLevel < 400.0
extern float const kMGSErrorCategoryWarning; ///< 400.0 <= warningLevel < 500.0
extern float const kMGSErrorCategoryError; ///< 500.0 <= warningLevel < 600.0
extern float const kMGSErrorCategoryPanic; ///< 600.0 <= warningLevel
extern float const kMGSErrorCategoryDefault; ///< kMGSErrorCategoryWarning
/** @} */


/**
Expand All @@ -43,64 +45,72 @@ extern float const kMGSErrorCategoryDefault; ///< warningLevel = kMGSErrorCateg
@interface SMLSyntaxError : NSObject


/// @name Class Methods
#pragma mark - Retrieving Default Images
/// @name Retrieving Default Images


/**
* This class method will return an image that represents the property `warningLevel`.
* The default images are stored in and loaded from the framework bundle automatically.
* @param level indicates the level (severity) of this error.
**/
/** The image which will be set on a SMLSyntaxError instance when the given
* warningLevel is set.
* @discussion The default images are stored in and loaded from the
* framework bundle automatically.
* @param level indicates the level (severity) of this error. */
+ (NSImage *)defaultImageForWarningLevel:(float)level;


/**
* This class method is a convenience for creating new SMLSyntaxError instances.
* @param dictionary indicates a dictionary where each key is the property name.
**/
+ (instancetype)errorWithDictionary:(NSDictionary *)dictionary;
#pragma mark - Creating Instances
/// @name Creating Instances


/// @name Instance Methods

/** Returns an SMLSyntaxError with its properties set as indicated by the
* given dictionary.
* @param dictionary A dictionary where each key is the property name. */
+ (instancetype)errorWithDictionary:(NSDictionary *)dictionary;

/**
* This initializer receives a dictionary of keys and values, where the dictionary
* keys correspond to property names of this class.
* @param dictionary indicates the dictionary from which to initialize this class.
**/
/** Return an SMLSyntaxError with the specified properties.
* @discussion The created error's character and length properties will be set
* to 1 and 0 respectively, and the error will not be hidden.
* @param desc The description of the error.
* @param level The error's warning level.
* @param line The line where the error appears. */
+ (instancetype)errorWithDescription:(NSString *)desc ofLevel:(float)level
atLine:(NSUInteger)line;

/** Returns an SMLSyntaxError initialized as specified by the given dictionary.
* @param dictionary A dictionary where each key is a property name. */
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;


/// @name Properties
#pragma mark - Getting and Setting Error Properties
/// @name Getting and Setting Error Properties


/** The line at which this error occurs.
* @discussion the line number is always one-based. Although Fragaria can display
* line numbers starting with any value, but errors are always on lines 1...n. */
@property (nonatomic,assign) NSUInteger line;
* @discussion The line number is always one-based.*/
@property NSUInteger line;
/** The one-based character position at which this error begins. */
@property (nonatomic,assign) NSUInteger character;
@property NSUInteger character;
/** The length of this error, in characters. */
@property (nonatomic,assign) NSUInteger length;
@property NSUInteger length;
/** A description for this error. */
@property (nonatomic,copy) NSString* errorDescription;
@property NSString *errorDescription;
/** Indicates whether or not this error is hidden from display. */
@property (nonatomic,assign) BOOL hidden;

/** The color to use to highlight lines that have syntax errors. */
@property (nonatomic,copy) NSColor *errorLineHighlightColor;
/** The warning level or severity of this syntax error. */
@property (nonatomic,assign) float warningLevel;

/**
* Specifies an image that should be associated with this syntax error.
* @discussion By default this property will return one of the built-in
* images that represent the warningLevel. However you can assign your
* own image to this property regardless of warningLevel. This property
* cannot be nil. Attempts to set it to nil will revert it to the
* built-in default.
**/
@property (nonatomic,strong) NSImage *warningImage;
@property BOOL hidden;

/** The color to use to highlight the line where this error is placed.
* @discussion This property can be overridden by other errors on the same
* line with equal or higher warningLevel. */
@property NSColor *errorLineHighlightColor;
/** The warning level or severity of this error.
* @discussion This property will also change warningImage if warningImage
* has never been set manually. */
@property (nonatomic) float warningLevel;

/** An image that should be associated with this syntax error.
* @discussion If you never set this property, it will be automatically set
* to a default image every time warningLevel is set. As soon
* as you set an image to this property manually, this behavior
* will stop. */
@property (nonatomic) NSImage *warningImage;


@end
110 changes: 58 additions & 52 deletions SMLSyntaxError.m
Expand Up @@ -9,58 +9,51 @@
#import "SMLSyntaxError.h"


float const kMGSErrorCategoryAccess = 100;
float const kMGSErrorCategoryConfig = 200;
float const kMGSErrorCategoryDocument = 300;
float const kMGSErrorCategoryInfo = 400;
float const kMGSErrorCategoryWarning = 500;
float const kMGSErrorCategoryError = 600;
float const kMGSErrorCategoryPanic = FLT_MAX;
float const kMGSErrorCategoryDefault = 500;


@implementation SMLSyntaxError


// manual
@synthesize warningImage = _warningImage;
float const kMGSErrorCategoryAccess = 50.0;
float const kMGSErrorCategoryConfig = 150.0;
float const kMGSErrorCategoryDocument = 250.0;
float const kMGSErrorCategoryInfo = 350.0;
float const kMGSErrorCategoryWarning = 450.0;
float const kMGSErrorCategoryError = 550.0;
float const kMGSErrorCategoryPanic = 650.0;
float const kMGSErrorCategoryDefault = 450.0;


@implementation SMLSyntaxError {
BOOL manualImage;
}


#pragma mark - Class Methods


+ (NSImage *)defaultImageForWarningLevel:(float)level
{
static NSArray *imageNames;
static NSMutableDictionary *imageCache;
static dispatch_once_t onceToken;
NSString *imageName;
NSInteger imageIdx;
NSNumber *imageNum;
NSImage *res;

dispatch_once(&onceToken, ^{
imageCache = [[NSMutableDictionary alloc] init];
imageNames = @[@"messagesAccess", @"messagesConfig",
@"messagesDocument", @"messagesInfo", @"messagesWarning",
@"messagesError", @"messagesPanic"];
});

imageIdx = MIN(MAX(0, (NSInteger)(level/100.0)), 6);
imageNum = @(imageIdx);

if (!(res = [imageCache objectForKey:imageNum])) {
imageName = [imageNames objectAtIndex:imageIdx];
res = [[NSBundle bundleForClass:[self class]] imageForResource:imageName];
[imageCache setObject:res forKey:imageNum];
}

switch ((int)ceil(level/100.0))
{
case 1:
imageName = @"messagesAccess";
break;
case 2:
imageName = @"messagesConfig";
break;
case 3:
imageName = @"messagesDocument";
break;
case 4:
imageName = @"messagesInfo";
break;
case 0:
case 5:
imageName = @"messagesWarning";
break;
case 6:
imageName = @"messagesError";
break;
default:
imageName = @"messagesPanic";
break;
}

NSImage *warningImage = [[NSBundle bundleForClass:[self class]] imageForResource:imageName];
return warningImage;
return res;
}


Expand All @@ -70,6 +63,19 @@ + (instancetype) errorWithDictionary:(NSDictionary *)dictionary
}


+ (instancetype)errorWithDescription:(NSString *)desc ofLevel:(float)level
atLine:(NSUInteger)line
{
SMLSyntaxError *res;

res = [[SMLSyntaxError alloc] init];
res.errorDescription = desc;
res.line = line;
res.warningLevel = level;
return res;
}


#pragma mark - Instance Methods


Expand All @@ -86,6 +92,7 @@ - (instancetype)init
{
self = [super init];

manualImage = NO;
self.line = 1;
self.character = 1;
self.warningLevel = kMGSErrorCategoryWarning;
Expand All @@ -105,19 +112,18 @@ - (NSString*)description
#pragma mark - Property Accessors


- (void)setWarningImage:(NSImage *)warningImage
- (void)setWarningLevel:(float)warningLevel
{
_warningImage = warningImage;
_warningLevel = warningLevel;
if (!manualImage)
_warningImage = [[self class] defaultImageForWarningLevel:warningLevel];
}

- (NSImage *)warningImage
{
if (!_warningImage)
{
_warningImage = [[self class] defaultImageForWarningLevel:self.warningLevel];
}

return _warningImage;
- (void)setWarningImage:(NSImage *)warningImage
{
_warningImage = warningImage;
manualImage = YES;
}


Expand Down

0 comments on commit 8518dcb

Please sign in to comment.