diff --git a/InjectionIII.xcodeproj/project.pbxproj b/InjectionIII.xcodeproj/project.pbxproj index 987a20eb..1a773178 100644 --- a/InjectionIII.xcodeproj/project.pbxproj +++ b/InjectionIII.xcodeproj/project.pbxproj @@ -166,6 +166,7 @@ BBE490DA1FB2C643003D41BB /* InjectionError.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = InjectionError.tif; sourceTree = ""; }; BBEB704A1FD28C6F00127711 /* XcodeHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XcodeHash.h; sourceTree = ""; }; BBEB704B1FD28C6F00127711 /* XcodeHash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XcodeHash.m; sourceTree = ""; }; + BDB6A7CE21824C800001CF95 /* UserDefaults.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserDefaults.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -350,6 +351,7 @@ BBCA02581FB112F500E45F0F /* App.icns */, BBCA02091FB0F10400E45F0F /* main.m */, BBCA020B1FB0F10400E45F0F /* InjectionIII.entitlements */, + BDB6A7CE21824C800001CF95 /* UserDefaults.h */, ); path = InjectionIII; sourceTree = ""; diff --git a/InjectionIII/AppDelegate.mm b/InjectionIII/AppDelegate.mm index efb19d2e..b4351577 100644 --- a/InjectionIII/AppDelegate.mm +++ b/InjectionIII/AppDelegate.mm @@ -18,6 +18,7 @@ //#import "DDHotKeyCenter.h" #import "InjectionIII-Swift.h" +#import "UserDefaults.h" #ifdef XPROBE_PORT #import "../XprobePlugin/Classes/XprobePluginMenuController.h" @@ -32,7 +33,7 @@ @interface AppDelegate () @implementation AppDelegate { IBOutlet NSMenu *statusMenu; - IBOutlet NSMenuItem *startItem, *xprobeItem, *windowItem; + IBOutlet NSMenuItem *startItem, *xprobeItem, *enabledTDDItem, *windowItem; IBOutlet NSStatusItem *statusItem; } @@ -49,6 +50,10 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { statusItem.enabled = TRUE; statusItem.title = @""; + enabledTDDItem.state = ([[NSUserDefaults standardUserDefaults] boolForKey:UserDefaultsTDDEnabled]) + ? NSControlStateValueOn + : NSControlStateValueOff; + [self setMenuIcon:@"InjectionIdle"]; #if 0 [[DDHotKeyCenter sharedHotKeyCenter] registerHotKeyWithKeyCode:kVK_ANSI_Equal @@ -61,6 +66,15 @@ - (IBAction)openProject:sender { [self application:NSApp openFile:nil]; } +- (IBAction)toggleTDD:(NSMenuItem *)sender { + [self toggleState:sender]; + + BOOL newSetting = sender.state == NSControlStateValueOn; + + [[NSUserDefaults standardUserDefaults] setBool:newSetting forKey:UserDefaultsTDDEnabled]; + NSLog(@"sender: %ld", (long)[sender state]); +} + - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { NSOpenPanel *open = [NSOpenPanel new]; open.prompt = NSLocalizedString(@"Select Project Directory", @"Project Directory"); diff --git a/InjectionIII/Base.lproj/MainMenu.xib b/InjectionIII/Base.lproj/MainMenu.xib index 393d9701..80fab245 100644 --- a/InjectionIII/Base.lproj/MainMenu.xib +++ b/InjectionIII/Base.lproj/MainMenu.xib @@ -16,6 +16,7 @@ + @@ -619,13 +620,13 @@ - + - - + + @@ -651,7 +652,7 @@ - + @@ -690,6 +691,12 @@ + + + + + + diff --git a/InjectionIII/FileWatcher.m b/InjectionIII/FileWatcher.m index eceeb031..72821371 100644 --- a/InjectionIII/FileWatcher.m +++ b/InjectionIII/FileWatcher.m @@ -60,13 +60,16 @@ - (void)filesChanged:(NSArray *)changes; NSFileManager *fileManager = [NSFileManager defaultManager]; NSMutableSet *changed = [NSMutableSet new]; - for (NSString *path in changes) + for (NSString *path in changes) { if ([path rangeOfString:INJECTABLE_PATTERN options:NSRegularExpressionSearch].location != NSNotFound && [path rangeOfString:@"DerivedData/|InjectionProject/|main.mm?$" options:NSRegularExpressionSearch].location == NSNotFound && - [fileManager fileExistsAtPath:path]) + [fileManager fileExistsAtPath:path]) { + [changed addObject:path]; + } + } //NSLog( @"filesChanged: %@", changed ); if (changed.count) diff --git a/InjectionIII/Info.plist b/InjectionIII/Info.plist index dae596e5..4653afd6 100644 --- a/InjectionIII/Info.plist +++ b/InjectionIII/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2 CFBundleVersion - 1199 + 1287 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/InjectionIII/InjectionServer.mm b/InjectionIII/InjectionServer.mm index f320af16..c120db56 100644 --- a/InjectionIII/InjectionServer.mm +++ b/InjectionIII/InjectionServer.mm @@ -14,6 +14,7 @@ #import "Xcode.h" #import "XcodeHash.h" +#import "UserDefaults.h" #import "InjectionIII-Swift.h" @@ -155,7 +156,16 @@ - (void)runInBackground { injector = ^(NSArray *changed) { NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate]; - for (NSString *swiftSource in changed) + NSMutableArray *changedFiles = [NSMutableArray arrayWithArray:changed]; + + if ([[NSUserDefaults standardUserDefaults] boolForKey:UserDefaultsTDDEnabled]) { + NSArray *matchedTests = [InjectionServer searchForTestWithFiles:changed + projectRoot:projectFile.stringByDeletingLastPathComponent + fileManager:[NSFileManager defaultManager]]; + [changedFiles addObjectsFromArray:matchedTests]; + } + + for (NSString *swiftSource in changedFiles) if (now > lastInjected[swiftSource].doubleValue + MIN_INJECTION_INTERVAL && now > pause) { lastInjected[swiftSource] = [NSNumber numberWithDouble:now]; inject(swiftSource); @@ -197,6 +207,49 @@ - (void)setProject:(NSString *)project { plugin:injector]; } ++ (NSArray *)searchForTestWithFiles:(NSArray *)injectedFiles projectRoot:(NSString *)projectRoot fileManager:(NSFileManager *)fileManager; +{ + NSMutableArray *matchedTests = [NSMutableArray array]; + for (NSString *injectedFile in injectedFiles) { + NSString *injectedFileName = [[injectedFile lastPathComponent] stringByDeletingPathExtension]; + NSURL *projectUrl = [NSURL URLWithString:projectRoot]; + NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtURL:projectUrl + includingPropertiesForKeys:@[NSURLNameKey, NSURLIsDirectoryKey] + options:NSDirectoryEnumerationSkipsHiddenFiles + errorHandler:^BOOL(NSURL *url, NSError *error) + { + if (error) { + NSLog(@"[Error] %@ (%@)", error, url); + return NO; + } + + return YES; + }]; + + + for (NSURL *fileURL in enumerator) { + NSString *filename; + NSNumber *isDirectory; + + [fileURL getResourceValue:&filename forKey:NSURLNameKey error:nil]; + [fileURL getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil]; + + if ([filename hasPrefix:@"_"] && [isDirectory boolValue]) { + [enumerator skipDescendants]; + continue; + } + + if (![isDirectory boolValue] && + ![[filename lastPathComponent] isEqualToString:[injectedFile lastPathComponent]] && + [[filename lowercaseString] containsString:[injectedFileName lowercaseString]]) { + [matchedTests addObject:fileURL.path]; + } + } + } + + return matchedTests; +} + - (void)dealloc { NSLog(@"- [%@ dealloc]", self); } diff --git a/InjectionIII/UserDefaults.h b/InjectionIII/UserDefaults.h new file mode 100644 index 00000000..fcbc3da7 --- /dev/null +++ b/InjectionIII/UserDefaults.h @@ -0,0 +1,11 @@ +// +// UserDefaults.h +// InjectionIII +// +// Created by Christoffer Winterkvist on 10/25/18. +// Copyright © 2018 John Holdsworth. All rights reserved. +// + +#import "AppDelegate.h" + +NSString *const UserDefaultsTDDEnabled = @"Enabled TDD";