Skip to content

Commit

Permalink
Disallow interface ivars and repeated use of weak.
Browse files Browse the repository at this point in the history
Refs #111
  • Loading branch information
Kentzo committed Apr 7, 2020
1 parent 2f7fa58 commit d60f4c1
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 65 deletions.
13 changes: 7 additions & 6 deletions Library/SRKeyCodeTransformer.m
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,9 @@ - (NSUInteger)hash
Cache of the key code translation with respect to input source identifier.
*/
@interface _SRKeyCodeTranslator : NSObject
{
NSCache<_SRKeyCodeTranslatorCacheKey *, NSString *> *_translationCache;
_SRKeyCodeTransformerCacheInputSourceCreate _inputSourceCreator;
id _inputSource;
}

@property (class, readonly) _SRKeyCodeTranslator *shared;
@property (readonly) _SRKeyCodeTransformerCacheInputSourceCreate inputSourceCreator;
@property (readonly) id inputSource;
/*!
@param aCreator Lazily instantiates an instance of input source.
Expand All @@ -106,6 +103,10 @@ - (nullable NSString *)translateKeyCode:(SRKeyCode)aKeyCode


@implementation _SRKeyCodeTranslator
{
NSCache<_SRKeyCodeTranslatorCacheKey *, NSString *> *_translationCache;
id _inputSource;
}

+ (_SRKeyCodeTranslator *)shared
{
Expand Down Expand Up @@ -282,7 +283,7 @@ - (NSNumber *)keyCodeForTranslation:(NSString *)aTranslation
{
NSAssert([aTranslation.lowercaseString isEqualToString:aTranslation], @"aTranslation must be a lowercase string");

TISInputSourceRef inputSource = _inputSourceCreator();
TISInputSourceRef inputSource = self.inputSourceCreator();

if (!inputSource)
{
Expand Down
5 changes: 2 additions & 3 deletions Library/SRRecorderControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(RecorderControl)
IB_DESIGNABLE
@interface SRRecorderControl : NSControl <NSAccessibilityButton, NSEditor, NSViewToolTipOwner> /* <NSNibLoading, NSKeyValueBindingCreation> */
{
BOOL _isCompatibilityModeEnabled;
}

/*!
Called by a designated initializer to set up internal state.
Expand Down Expand Up @@ -299,6 +296,8 @@ IB_DESIGNABLE
enter compatibility mode where objectValue and NSValueBinding accessors will
accept and return instances of NSDictionary.
To check whether the control has compatibility mode enabled use KVC with the "isCompatibilityModeEnabled" key.
@seealso SRShortcutKey
*/
@property (nullable, copy) SRShortcut *objectValue;
Expand Down
4 changes: 3 additions & 1 deletion Library/SRRecorderControl.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ typedef NS_ENUM(NSUInteger, _SRRecorderControlButtonTag)

@implementation SRRecorderControl
{
BOOL _isCompatibilityModeEnabled;

SRRecorderControlStyle *_style;
NSInvocation *_notifyStyle;

Expand Down Expand Up @@ -1140,7 +1142,7 @@ - (void)setAttributedStringValue:(NSAttributedString *)newAttributedStringValue
- (NSString *)stringValue
{
if (!_objectValue)
return @"";
return SRLoc(@"");

__auto_type layoutDirection = self.stringValueRespectsUserInterfaceLayoutDirection ? self.userInterfaceLayoutDirection : NSUserInterfaceLayoutDirectionLeftToRight;
NSString *flags = [SRSymbolicModifierFlagsTransformer.sharedTransformer transformedValue:@(_objectValue.modifierFlags)
Expand Down
57 changes: 30 additions & 27 deletions Library/SRRecorderControlStyle.m
Original file line number Diff line number Diff line change
Expand Up @@ -984,13 +984,14 @@ + (SRRecorderControlStyleResourceLoader *)resourceLoader

- (void)addConstraints
{
[self.recorderControl addLayoutGuide:self.alignmentGuide];
[self.recorderControl addLayoutGuide:self.backgroundDrawingGuide];
[self.recorderControl addLayoutGuide:self.labelDrawingGuide];
[self.recorderControl addLayoutGuide:self.cancelButtonDrawingGuide];
[self.recorderControl addLayoutGuide:self.clearButtonDrawingGuide];
[self.recorderControl addLayoutGuide:self.cancelButtonLayoutGuide];
[self.recorderControl addLayoutGuide:self.clearButtonLayoutGuide];
__auto_type strongRecorderControl = self.recorderControl;
[strongRecorderControl addLayoutGuide:self.alignmentGuide];
[strongRecorderControl addLayoutGuide:self.backgroundDrawingGuide];
[strongRecorderControl addLayoutGuide:self.labelDrawingGuide];
[strongRecorderControl addLayoutGuide:self.cancelButtonDrawingGuide];
[strongRecorderControl addLayoutGuide:self.clearButtonDrawingGuide];
[strongRecorderControl addLayoutGuide:self.cancelButtonLayoutGuide];
[strongRecorderControl addLayoutGuide:self.clearButtonLayoutGuide];

__auto_type SetConstraint = ^(NSLayoutConstraint * __strong *var, NSLayoutConstraint *value) {
*var = value;
Expand Down Expand Up @@ -1055,16 +1056,16 @@ - (void)addConstraints

_alwaysConstraints = @[
MakeEqConstraint(self.alignmentGuide.topAnchor,
self.recorderControl.topAnchor,
strongRecorderControl.topAnchor,
@"SR_alignmentGuide_topToView"),
MakeEqConstraint(self.alignmentGuide.leftAnchor,
self.recorderControl.leftAnchor,
strongRecorderControl.leftAnchor,
@"SR_alignmentGuide_leftToView"),
MakeEqConstraint(self.alignmentGuide.rightAnchor,
self.recorderControl.rightAnchor,
strongRecorderControl.rightAnchor,
@"SR_alignmentGuide_rightToView"),
MakeConstraint(self.alignmentGuide.bottomAnchor,
self.recorderControl.bottomAnchor,
strongRecorderControl.bottomAnchor,
0.0,
NSLayoutPriorityDefaultHigh,
NSLayoutRelationEqual,
Expand Down Expand Up @@ -1202,7 +1203,7 @@ - (void)addConstraints
@"SR_clearButtonLayoutGuide_trailingToAlignment"),
];

self.recorderControl.needsUpdateConstraints = YES;
strongRecorderControl.needsUpdateConstraints = YES;
}

#pragma mark SRRecorderControlStyling
Expand Down Expand Up @@ -1271,29 +1272,30 @@ - (void)prepareForRecorderControl:(SRRecorderControl *)aControl
_recorderControl = aControl;
[self didChangeValueForKey:@"recorderControl"];

if (!_recorderControl)
if (!aControl)
return;

[self addConstraints];
[self recorderControlAppearanceDidChange:nil];

_recorderControl.needsDisplay = YES;
aControl.needsDisplay = YES;
}

- (void)prepareForRemoval
{
NSAssert(_recorderControl != nil, @"Style was not applied properly.");
__auto_type strongRecorderControl = _recorderControl;
NSAssert(strongRecorderControl != nil, @"Style was not applied properly.");

[_recorderControl removeLayoutGuide:_alignmentGuide];
[_recorderControl removeLayoutGuide:_backgroundDrawingGuide];
[_recorderControl removeLayoutGuide:_labelDrawingGuide];
[_recorderControl removeLayoutGuide:_cancelButtonDrawingGuide];
[_recorderControl removeLayoutGuide:_clearButtonDrawingGuide];
[_recorderControl removeLayoutGuide:_cancelButtonLayoutGuide];
[_recorderControl removeLayoutGuide:_clearButtonLayoutGuide];
[strongRecorderControl removeLayoutGuide:_alignmentGuide];
[strongRecorderControl removeLayoutGuide:_backgroundDrawingGuide];
[strongRecorderControl removeLayoutGuide:_labelDrawingGuide];
[strongRecorderControl removeLayoutGuide:_cancelButtonDrawingGuide];
[strongRecorderControl removeLayoutGuide:_clearButtonDrawingGuide];
[strongRecorderControl removeLayoutGuide:_cancelButtonLayoutGuide];
[strongRecorderControl removeLayoutGuide:_clearButtonLayoutGuide];

[self willChangeValueForKey:@"recorderControl"];
_recorderControl = nil;
strongRecorderControl = nil;
[self didChangeValueForKey:@"recorderControl"];
}

Expand Down Expand Up @@ -1357,7 +1359,8 @@ - (void)recorderControlAppearanceDidChange:(nullable id)aReason
[self.recorderControl setNeedsDisplayInRect:frame];
};

NSRect controlBounds = self.recorderControl.bounds;
__auto_type strongRecorderControl = self.recorderControl;
NSRect controlBounds = strongRecorderControl.bounds;

UpdateImage(@"bezel-normal-left", @selector(bezelNormalLeft), controlBounds);
UpdateImage(@"bezel-normal-center", @selector(bezelNormalCenter), controlBounds);
Expand Down Expand Up @@ -1433,9 +1436,9 @@ - (void)recorderControlAppearanceDidChange:(nullable id)aReason

_intrinsicContentSize = NSMakeSize(_alignmentSuggestedWidthConstraint.constant, _alignmentHeightConstraint.constant);

[self.recorderControl noteFocusRingMaskChanged];
[self.recorderControl invalidateIntrinsicContentSize];
self.recorderControl.needsDisplay = YES;
[strongRecorderControl noteFocusRingMaskChanged];
[strongRecorderControl invalidateIntrinsicContentSize];
strongRecorderControl.needsDisplay = YES;
}

_currentLookupPrefixes = newLookupPrefixes;
Expand Down
18 changes: 12 additions & 6 deletions Library/SRShortcutAction.m
Original file line number Diff line number Diff line change
Expand Up @@ -186,23 +186,27 @@ - (void)setActionHandler:(SRShortcutActionHandler)newActionHandler

- (id)target
{
id strongTarget = _target;

@synchronized (self)
{
return _target != nil ? _target : NSApplication.sharedApplication;
return strongTarget != nil ? strongTarget : NSApplication.sharedApplication;
}
}

- (void)setTarget:(id)newTarget
{
id strongTarget = _target;

@synchronized (self)
{
if (newTarget == _target)
if (newTarget == strongTarget)
return;

[self willChangeValueForKey:@"target"];
_target = newTarget;
strongTarget = newTarget;

if (_target && _actionHandler)
if (strongTarget && _actionHandler)
{
[self willChangeValueForKey:@"actionHandler"];
_actionHandler = nil;
Expand Down Expand Up @@ -304,8 +308,10 @@ - (BOOL)performActionOnTarget:(id)aTarget

- (void)_invalidateObserving
{
if (_observedObject)
[_observedObject removeObserver:self forKeyPath:_observedKeyPath context:_SRShortcutActionContext];
id strongObservedObject = _observedObject;

if (strongObservedObject)
[strongObservedObject removeObserver:self forKeyPath:_observedKeyPath context:_SRShortcutActionContext];

_observedObject = nil;
_observedKeyPath = nil;
Expand Down
12 changes: 7 additions & 5 deletions Library/SRShortcutController.m
Original file line number Diff line number Diff line change
Expand Up @@ -245,18 +245,20 @@ - (void)updateComputedKeyPaths

- (void)_updateRecorderControlValueBinding
{
if (!_recorderControl)
__auto_type strongRecorderControl = _recorderControl;

if (!strongRecorderControl)
return;

NSDictionary *contentBindingInfo = [self infoForBinding:NSContentObjectBinding];
if (!contentBindingInfo)
return;

NSDictionary *bindingOptions = [contentBindingInfo[NSOptionsKey] dictionaryWithValuesForKeys:@[NSValueTransformerBindingOption, NSValueTransformerNameBindingOption]];
[_recorderControl bind:NSValueBinding
toObject:contentBindingInfo[NSObservedObjectKey]
withKeyPath:contentBindingInfo[NSObservedKeyPathKey]
options:bindingOptions];
[strongRecorderControl bind:NSValueBinding
toObject:contentBindingInfo[NSObservedObjectKey]
withKeyPath:contentBindingInfo[NSObservedKeyPathKey]
options:bindingOptions];
}


Expand Down
47 changes: 30 additions & 17 deletions Library/SRShortcutValidator.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,20 @@ - (BOOL)validateShortcut:(SRShortcut *)aShortcut error:(NSError * __autoreleasin
{
__block BOOL result = NO;
os_activity_initiate("-[SRShortcutValidator validateShortcut:error:]", OS_ACTIVITY_FLAG_DEFAULT, ^{
__auto_type strongDelegate = self.delegate;

if (![self validateShortcutAgainstDelegate:aShortcut error:outError])
{
result = NO;
}
else if ((![self.delegate respondsToSelector:@selector(shortcutValidatorShouldCheckSystemShortcuts:)] ||
[self.delegate shortcutValidatorShouldCheckSystemShortcuts:self]) &&
else if ((![strongDelegate respondsToSelector:@selector(shortcutValidatorShouldCheckSystemShortcuts:)] ||
[strongDelegate shortcutValidatorShouldCheckSystemShortcuts:self]) &&
![self validateShortcutAgainstSystemShortcuts:aShortcut error:outError])
{
result = NO;
}
else if ((![self.delegate respondsToSelector:@selector(shortcutValidatorShouldCheckMenu:)] ||
[self.delegate shortcutValidatorShouldCheckMenu:self]) &&
else if ((![strongDelegate respondsToSelector:@selector(shortcutValidatorShouldCheckMenu:)] ||
[strongDelegate shortcutValidatorShouldCheckMenu:self]) &&
NSApp.mainMenu &&
![self validateShortcut:aShortcut againstMenu:NSApp.mainMenu error:outError])
{
Expand All @@ -75,13 +77,21 @@ - (BOOL)validateShortcutAgainstDelegate:(SRShortcut *)aShortcut error:(NSError *
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
__auto_type DelegateIsShortcutValid = ^(NSString * __autoreleasing * aReason) {
if ([self.delegate respondsToSelector:@selector(shortcutValidator:isShortcutValid:reason:)])
return [self.delegate shortcutValidator:self isShortcutValid:aShortcut reason:aReason];
else if ([self.delegate respondsToSelector:@selector(shortcutValidator:isKeyCode:andFlagsTaken:reason:)])
return (BOOL)![self.delegate shortcutValidator:self
isKeyCode:aShortcut.keyCode
andFlagsTaken:aShortcut.modifierFlags
reason:aReason];
__auto_type strongDelegate = self.delegate;

if ([strongDelegate respondsToSelector:@selector(shortcutValidator:isShortcutValid:reason:)])
{
return [strongDelegate shortcutValidator:self
isShortcutValid:aShortcut
reason:aReason];
}
else if ([strongDelegate respondsToSelector:@selector(shortcutValidator:isKeyCode:andFlagsTaken:reason:)])
{
return (BOOL)![strongDelegate shortcutValidator:self
isKeyCode:aShortcut.keyCode
andFlagsTaken:aShortcut.modifierFlags
reason:aReason];
}
else
return YES;
};
Expand All @@ -94,9 +104,10 @@ - (BOOL)validateShortcutAgainstDelegate:(SRShortcut *)aShortcut error:(NSError *
if (outError)
{
BOOL isASCIIOnly = YES;
__auto_type strongDelegate = self.delegate;

if ([self.delegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
isASCIIOnly = [self.delegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];
if ([strongDelegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
isASCIIOnly = [strongDelegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];

NSString *shortcut = [aShortcut readableStringRepresentation:isASCIIOnly];
NSString *failureReason = [NSString stringWithFormat:SRLoc(@"The \"%@\" shortcut can't be used!"), shortcut];
Expand Down Expand Up @@ -155,9 +166,10 @@ - (BOOL)validateShortcutAgainstSystemShortcuts:(SRShortcut *)aShortcut error:(NS
if (outError)
{
BOOL isASCIIOnly = YES;
__auto_type strongDelegate = self.delegate;

if ([self.delegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
isASCIIOnly = [self.delegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];
if ([strongDelegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
isASCIIOnly = [strongDelegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];

NSString *shortcut = [aShortcut readableStringRepresentation:isASCIIOnly];
NSString *failureReason = [NSString stringWithFormat:
Expand Down Expand Up @@ -210,9 +222,10 @@ - (BOOL)validateShortcut:(SRShortcut *)aShortcut againstMenu:(NSMenu *)aMenu err
if (outError)
{
BOOL isASCIIOnly = YES;
__auto_type strongDelegate = self.delegate;

if ([self.delegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
isASCIIOnly = [self.delegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];
if ([strongDelegate respondsToSelector:@selector(shortcutValidatorShouldUseASCIIStringForKeyCodes:)])
isASCIIOnly = [strongDelegate shortcutValidatorShouldUseASCIIStringForKeyCodes:self];

NSString *shortcut = [aShortcut readableStringRepresentation:isASCIIOnly];
NSString *failureReason = [NSString stringWithFormat:SRLoc(@"The \"%@\" shortcut can't be used!"), shortcut];
Expand Down
6 changes: 6 additions & 0 deletions ShortcutRecorder.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,9 @@
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_INTERFACE_IVARS = YES_ERROR;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES_AGGRESSIVE;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
Expand All @@ -986,6 +988,7 @@
MACOSX_DEPLOYMENT_TARGET = 10.11;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "-fstack-protector";
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = macosx;
SKIP_INSTALL = YES;
WARNING_CFLAGS = "-Wall";
Expand Down Expand Up @@ -1014,7 +1017,9 @@
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_INTERFACE_IVARS = YES_ERROR;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES_AGGRESSIVE;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
Expand All @@ -1035,6 +1040,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
OTHER_CFLAGS = "-fstack-protector";
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_COMPILATION_MODE = wholemodule;
Expand Down

0 comments on commit d60f4c1

Please sign in to comment.