PageRenderTime 80ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 1ms

/core/externals/update-engine/externals/google-toolbox-for-mac/XcodePlugin/GTMXcodeGCovItem.m

http://macfuse.googlecode.com/
Objective C | 498 lines | 408 code | 63 blank | 27 comment | 44 complexity | a6f19091bccb2e603ab3adaed0be51ee MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-2.0
  1. //
  2. // GTMXcodeGCovItem.m
  3. //
  4. // Copyright 2007-2009 Google Inc.
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7. // use this file except in compliance with the License. You may obtain a copy
  8. // of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  14. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  15. // License for the specific language governing permissions and limitations under
  16. // the License.
  17. //
  18. #import "GTMXcodeMenuItem.h"
  19. #import "GTMXcodePlugin.h"
  20. #import "PBXAppDelegate.h"
  21. #import "PBXExtendedApplication.h"
  22. #import "PBXProject.h"
  23. #import "PBXTarget.h"
  24. #import "GTMMethodCheck.h"
  25. #import "NSTask+Script.h"
  26. #import "GTMDefines.h"
  27. // Indices for our various menu items
  28. enum {
  29. kGTMXcodeGCovSeparatorItemIndex = 19,
  30. kGTMXcodeGCovEnableCoverageItemIndex,
  31. kGTMXcodeGCovCheckCoverageMenuItemIndex,
  32. kGTMXcodeGCovCleanCoverageMenuItemIndex,
  33. kGTMXcodeGCovCleanCoverageAndBuildMenuItemIndex,
  34. };
  35. // The different methods of open coverage provided.
  36. typedef enum {
  37. kGTMXcodeGCovOpenFile,
  38. kGTMXcodeGCovOpenTarget,
  39. kGTMXcodeGCovOpenBuildFolder,
  40. } GTMXcodeGCovOpenMode;
  41. typedef enum {
  42. kGTMXcodeGCovCleanDataTarget,
  43. kGTMXcodeGCovCleanDataBuildFolder,
  44. } GTMXcodeGCovCleanMode;
  45. // Some paths that we resolve
  46. NSString *const kObjectsDirPath
  47. = @"$(OBJECT_FILE_DIR)-$(BUILD_VARIANTS)";
  48. NSString *const kObjectsDirNoArchPath
  49. = @"$(OBJECT_FILE_DIR)-$(BUILD_VARIANTS)";
  50. NSString *const kBuildRootDirPath = @"$(BUILD_ROOT)";
  51. // the title for our menu items w/ submenus
  52. NSString *kShowCodeCoverageForMenuTitle = @"Show Code Coverage For";
  53. NSString *kCleanCodeCoverageDataForMenuTitle = @"Clean Code Coverage Data For";
  54. // Separator above the GCov menu items
  55. @interface GTMXcodeGCovSeparatorItem : GTMXcodeMenuItem
  56. @end
  57. // Enable Code Coverage menu item
  58. @interface GTMXcodeGCovEnableItem : GTMXcodeMenuItem
  59. @end
  60. // Check coverage for menu
  61. @interface GTMXcodeGCovCoverageMenuItem : GTMXcodeMenuItem {
  62. NSString *title_;
  63. int index_;
  64. }
  65. - (id)initWithTitle:(NSString *)title index:(int)index;
  66. @end
  67. // Check coverage for option
  68. @interface GTMXcodeGCovCheckCoverageItem : GTMXcodeMenuItem {
  69. NSString *title_;
  70. GTMXcodeGCovOpenMode mode_;
  71. int index_;
  72. }
  73. - (id)initWithTitle:(NSString *)title
  74. mode:(GTMXcodeGCovOpenMode)mode
  75. index:(int)index;
  76. @end
  77. // Clean coverage data item
  78. @interface GTMXcodeGCovCleanItem : GTMXcodeMenuItem {
  79. NSString *title_;
  80. GTMXcodeGCovCleanMode mode_;
  81. int index_;
  82. }
  83. - (id)initWithTitle:(NSString *)title
  84. mode:(GTMXcodeGCovCleanMode)mode
  85. index:(int)index;
  86. @end
  87. @interface GTMXcodeGCovCleanAndBuildItem : GTMXcodeMenuItem
  88. @end
  89. // Category for checking if gcov is enabled on current target
  90. @interface PBXExtendedApplication (GTMXcodeGCovMenuItemAdditions)
  91. - (BOOL)gtm_gcovEnabledForActiveTarget;
  92. @end
  93. @interface NSString (GTMXcodeGCovItem)
  94. - (BOOL)gtm_isCOrObjCFile;
  95. @end
  96. @implementation GTMXcodeGCovSeparatorItem
  97. + (void)load {
  98. [GTMXcodePlugin registerMenuItem:[[[self alloc] init] autorelease]];
  99. }
  100. - (NSString*)title {
  101. return @"-";
  102. }
  103. - (NSMenu*)insertionMenu {
  104. return [[NSApp delegate] buildMenu];
  105. }
  106. - (int)insertionIndex {
  107. return kGTMXcodeGCovSeparatorItemIndex;
  108. }
  109. @end
  110. @implementation GTMXcodeGCovCoverageMenuItem
  111. + (void)load {
  112. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  113. GTMXcodeGCovCoverageMenuItem *item
  114. = [[[self alloc] initWithTitle:kShowCodeCoverageForMenuTitle
  115. index:kGTMXcodeGCovCheckCoverageMenuItemIndex]
  116. autorelease];
  117. [GTMXcodePlugin registerMenuItem:item];
  118. item = [[[self alloc] initWithTitle:kCleanCodeCoverageDataForMenuTitle
  119. index:kGTMXcodeGCovCleanCoverageMenuItemIndex]
  120. autorelease];
  121. [GTMXcodePlugin registerMenuItem:item];
  122. [pool release];
  123. }
  124. - (id)initWithTitle:(NSString *)title index:(int)idx {
  125. if ((self = [super init])) {
  126. title_ = title;
  127. index_ = idx;
  128. }
  129. return self;
  130. }
  131. - (NSString*)title {
  132. return title_;
  133. }
  134. - (NSMenu*)insertionMenu {
  135. return [[NSApp delegate] buildMenu];
  136. }
  137. - (int)insertionIndex {
  138. return index_;
  139. }
  140. - (void)wasInserted:(NSMenuItem*)item {
  141. NSMenu *menu = [[[NSMenu alloc] initWithTitle:title_] autorelease];
  142. [item setSubmenu:menu];
  143. }
  144. @end
  145. @implementation GTMXcodeGCovCheckCoverageItem
  146. GTM_METHOD_CHECK(NSTask, gtm_runScript:withArguments:);
  147. + (void)load {
  148. struct OpenItemDesc {
  149. NSString *title;
  150. GTMXcodeGCovOpenMode mode;
  151. int index;
  152. };
  153. struct OpenItemDesc items [] = {
  154. { @"Selected file", kGTMXcodeGCovOpenFile, 0 },
  155. { @"Current target", kGTMXcodeGCovOpenTarget, 1 },
  156. { @"Current project", kGTMXcodeGCovOpenBuildFolder, 2 },
  157. };
  158. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  159. for(size_t i = 0; i < sizeof(items) / sizeof(struct OpenItemDesc); ++i) {
  160. GTMXcodeGCovCheckCoverageItem *item
  161. = [[[self alloc] initWithTitle:items[i].title
  162. mode:items[i].mode
  163. index:items[i].index] autorelease];
  164. [GTMXcodePlugin registerMenuItem:item];
  165. }
  166. [pool release];
  167. }
  168. - (id)initWithTitle:(NSString *)title
  169. mode:(GTMXcodeGCovOpenMode)mode
  170. index:(int)idx {
  171. if ((self = [super init])) {
  172. title_ = title;
  173. mode_ = mode;
  174. index_ = idx;
  175. }
  176. return self;
  177. }
  178. - (NSMenu*)insertionMenu {
  179. NSMenu *menu = [[NSApp delegate] buildMenu];
  180. NSInteger menuIndex
  181. = [menu indexOfItemWithTitle:kShowCodeCoverageForMenuTitle];
  182. NSMenuItem *menuItem = [menu itemAtIndex:menuIndex];
  183. return [menuItem submenu];
  184. }
  185. - (NSString*)title {
  186. return title_;
  187. }
  188. - (void)action:(id)sender {
  189. NSString *pathToOpen = nil;
  190. PBXProject *project = [NSApp currentProject];
  191. PBXTarget *target = [project activeTarget];
  192. NSString *buildConfig = [project activeBuildConfigurationName];
  193. if (mode_ == kGTMXcodeGCovOpenFile) {
  194. NSArray *selectedPaths = [self selectedPaths];
  195. NSString *selectedPath = nil;
  196. if ([selectedPaths count] == 1) {
  197. NSString *path = [selectedPaths objectAtIndex:0];
  198. if ([path gtm_isCOrObjCFile]) {
  199. selectedPath = path;
  200. }
  201. if (selectedPath) {
  202. NSString *srcFileName = [selectedPath lastPathComponent];
  203. NSUInteger fileLength = [srcFileName length];
  204. NSUInteger extensionLength = [[srcFileName pathExtension] length];
  205. NSString *subStr
  206. = [srcFileName substringToIndex:(fileLength - extensionLength)];
  207. NSString *gcdaFileName = [NSString stringWithFormat:@"%@gcda", subStr];
  208. NSString *objectsDir = [self pathByExpandingString:kObjectsDirPath
  209. forBuildConfiguration:buildConfig
  210. ofTarget:target];
  211. NSString *activeArchitecture = [project activeArchitecture];
  212. NSString *archPath
  213. = [objectsDir stringByAppendingPathComponent:activeArchitecture];
  214. NSString *gcdaPath
  215. = [archPath stringByAppendingPathComponent:gcdaFileName];
  216. pathToOpen = gcdaPath;
  217. }
  218. }
  219. } else if (mode_ == kGTMXcodeGCovOpenTarget) {
  220. NSString *objectsDirNoArch
  221. = [self pathByExpandingString:kObjectsDirNoArchPath
  222. forBuildConfiguration:buildConfig
  223. ofTarget:target];
  224. pathToOpen = objectsDirNoArch;
  225. } else if (mode_ == kGTMXcodeGCovOpenBuildFolder) {
  226. NSString *buildRootDir = [self pathByExpandingString:kBuildRootDirPath
  227. forBuildConfiguration:buildConfig
  228. ofTarget:target];
  229. pathToOpen = buildRootDir;
  230. }
  231. if (pathToOpen) {
  232. [NSTask gtm_runScript:@"opencoverage" withArguments:pathToOpen, nil];
  233. }
  234. }
  235. - (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
  236. BOOL isGood = NO;
  237. switch (mode_) {
  238. case kGTMXcodeGCovOpenFile:
  239. if ([NSApp gtm_gcovEnabledForActiveTarget]) {
  240. NSArray *selectedPaths = [self selectedPaths];
  241. if ([selectedPaths count] == 1) {
  242. NSString *path = [selectedPaths objectAtIndex:0];
  243. if ([path gtm_isCOrObjCFile]) {
  244. isGood = YES;
  245. }
  246. }
  247. }
  248. break;
  249. case kGTMXcodeGCovOpenTarget:
  250. isGood = [NSApp gtm_gcovEnabledForActiveTarget];
  251. break;
  252. case kGTMXcodeGCovOpenBuildFolder:
  253. isGood = ([NSApp currentProject] != nil);
  254. break;
  255. }
  256. return isGood;
  257. }
  258. - (int)depth {
  259. return 2;
  260. }
  261. - (int)insertionIndex {
  262. return index_;
  263. }
  264. - (BOOL)allowGDTMenuIcon {
  265. return NO;
  266. }
  267. @end
  268. @implementation GTMXcodeGCovEnableItem
  269. GTM_METHOD_CHECK(NSTask, gtm_runScript:withArguments:);
  270. + (void)load {
  271. [GTMXcodePlugin registerMenuItem:[[[self alloc] init] autorelease]];
  272. }
  273. - (NSMenu*)insertionMenu {
  274. return [[NSApp delegate] buildMenu];
  275. }
  276. - (NSString*)title {
  277. return @"";
  278. }
  279. - (void)action:(id)sender {
  280. NSString *enabled = [NSApp gtm_gcovEnabledForActiveTarget] ? @"NO" : @"YES";
  281. [NSTask gtm_runScript:@"EnableGCov" withArguments:enabled, nil];
  282. }
  283. - (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
  284. BOOL isGood = NO;
  285. NSString *title = @"Turn Code Coverage On";
  286. PBXProject *project = [NSApp currentProject];
  287. if (project) {
  288. isGood = YES;
  289. if ([NSApp gtm_gcovEnabledForActiveTarget]) {
  290. title = @"Turn Code Coverage Off";
  291. }
  292. }
  293. [menuItem setTitle:title];
  294. return isGood;
  295. }
  296. - (int)insertionIndex {
  297. return kGTMXcodeGCovEnableCoverageItemIndex;
  298. }
  299. @end
  300. @implementation GTMXcodeGCovCleanItem
  301. GTM_METHOD_CHECK(NSTask, gtm_runScript:withArguments:);
  302. + (void)load {
  303. struct CleanItemDesc {
  304. NSString *title;
  305. GTMXcodeGCovCleanMode mode;
  306. int index;
  307. };
  308. struct CleanItemDesc items [] = {
  309. { @"Current target", kGTMXcodeGCovCleanDataTarget, 0 },
  310. { @"Current project", kGTMXcodeGCovCleanDataBuildFolder, 1 },
  311. };
  312. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  313. for(size_t i = 0; i < sizeof(items) / sizeof(struct CleanItemDesc); ++i) {
  314. GTMXcodeGCovCleanItem *item = [[[self alloc] initWithTitle:items[i].title
  315. mode:items[i].mode
  316. index:items[i].index]
  317. autorelease];
  318. [GTMXcodePlugin registerMenuItem:item];
  319. }
  320. [pool release];
  321. }
  322. - (id)initWithTitle:(NSString *)title
  323. mode:(GTMXcodeGCovCleanMode)mode
  324. index:(int)idx {
  325. if ((self = [super init])) {
  326. title_ = title;
  327. mode_ = mode;
  328. index_ = idx;
  329. }
  330. return self;
  331. }
  332. - (NSMenu*)insertionMenu {
  333. NSMenu *menu = [[NSApp delegate] buildMenu];
  334. NSInteger menuIndex
  335. = [menu indexOfItemWithTitle:kCleanCodeCoverageDataForMenuTitle];
  336. NSMenuItem *menuItem = [menu itemAtIndex:menuIndex];
  337. return [menuItem submenu];
  338. }
  339. - (NSString*)title {
  340. return title_;
  341. }
  342. - (void)action:(id)sender {
  343. NSString *pathToClean = nil;
  344. PBXProject *project = [NSApp currentProject];
  345. PBXTarget *target = [project activeTarget];
  346. NSString *buildConfig = [project activeBuildConfigurationName];
  347. if (mode_ == kGTMXcodeGCovCleanDataTarget) {
  348. NSString *objectsDirNoArch
  349. = [self pathByExpandingString:kObjectsDirNoArchPath
  350. forBuildConfiguration:buildConfig
  351. ofTarget:target];
  352. pathToClean = objectsDirNoArch;
  353. } else if (mode_ == kGTMXcodeGCovCleanDataBuildFolder) {
  354. NSString *buildRootDir = [self pathByExpandingString:kBuildRootDirPath
  355. forBuildConfiguration:buildConfig
  356. ofTarget:target];
  357. pathToClean = buildRootDir;
  358. }
  359. if (pathToClean) {
  360. [NSTask gtm_runScript:@"ResetGCov" withArguments:pathToClean, nil];
  361. }
  362. }
  363. - (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
  364. BOOL isGood = NO;
  365. switch (mode_) {
  366. case kGTMXcodeGCovCleanDataTarget:
  367. isGood = [NSApp gtm_gcovEnabledForActiveTarget];
  368. break;
  369. case kGTMXcodeGCovCleanDataBuildFolder:
  370. isGood = ([NSApp currentProject] != nil);
  371. break;
  372. }
  373. return isGood;
  374. }
  375. - (int)depth {
  376. return 2;
  377. }
  378. - (int)insertionIndex {
  379. return index_;
  380. }
  381. - (BOOL)allowGDTMenuIcon {
  382. return NO;
  383. }
  384. @end
  385. @implementation GTMXcodeGCovCleanAndBuildItem
  386. + (void)load {
  387. [GTMXcodePlugin registerMenuItem:[[[self alloc] init] autorelease]];
  388. }
  389. - (NSString*)title {
  390. return @"Clean Project Coverage and Build";
  391. }
  392. - (NSMenu*)insertionMenu {
  393. return [[NSApp delegate] buildMenu];
  394. }
  395. - (int)insertionIndex {
  396. return kGTMXcodeGCovCleanCoverageAndBuildMenuItemIndex;
  397. }
  398. - (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
  399. return [NSApp gtm_gcovEnabledForActiveTarget];
  400. }
  401. - (void)action:(id)sender {
  402. NSString *pathToClean = nil;
  403. PBXProject *project = [NSApp currentProject];
  404. PBXTarget *target = [project activeTarget];
  405. NSString *buildConfig = [project activeBuildConfigurationName];
  406. NSString *buildRootDir = [self pathByExpandingString:kBuildRootDirPath
  407. forBuildConfiguration:buildConfig
  408. ofTarget:target];
  409. pathToClean = buildRootDir;
  410. if (pathToClean) {
  411. [NSTask gtm_runScript:@"CleanCovAndBuild" withArguments:pathToClean, nil];
  412. }
  413. }
  414. @end
  415. @implementation PBXExtendedApplication (GTMXcodeGCovMenuItemAdditions)
  416. - (BOOL)gtm_gcovEnabledForActiveTarget {
  417. BOOL answer = NO;
  418. PBXProject *project = [NSApp currentProject];
  419. PBXTarget *target = [project activeTarget];
  420. NSString *buildConfig = [project activeBuildConfigurationName];
  421. if (project && target && buildConfig) {
  422. NSString *setting = [target stringByExpandingString:@"$(OTHER_LDFLAGS)"
  423. forBuildConfigurationNamed:buildConfig];
  424. answer = [setting rangeOfString:@"-lgcov"].length != 0;
  425. }
  426. return answer;
  427. }
  428. @end
  429. @implementation NSString (GTMXcodeGCovItem)
  430. - (BOOL)gtm_isCOrObjCFile {
  431. return [self hasSuffix:@".c"] || [self hasSuffix:@".cpp"]
  432. || [self hasSuffix:@".cc"] || [self hasSuffix:@".cp"]
  433. || [self hasSuffix:@".m"] || [self hasSuffix:@".mm"];
  434. }
  435. @end