OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2008, Google Inc. | 3 # Copyright 2008, Google Inc. |
4 # All rights reserved. | 4 # All rights reserved. |
5 # | 5 # |
6 # Redistribution and use in source and binary forms, with or without | 6 # Redistribution and use in source and binary forms, with or without |
7 # modification, are permitted provided that the following conditions are | 7 # modification, are permitted provided that the following conditions are |
8 # met: | 8 # met: |
9 # | 9 # |
10 # * Redistributions of source code must retain the above copyright | 10 # * Redistributions of source code must retain the above copyright |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 *something*. Please tell it *what* to return. Perhaps you can use | 179 *something*. Please tell it *what* to return. Perhaps you can use |
180 the pattern DoAll(some_action, Return(some_value))?""" | 180 the pattern DoAll(some_action, Return(some_value))?""" |
181 return _GenericDiagnoser('NRS', 'Need to Return Something', | 181 return _GenericDiagnoser('NRS', 'Need to Return Something', |
182 regex, diagnosis, msg) | 182 regex, diagnosis, msg) |
183 | 183 |
184 | 184 |
185 def _NeedToReturnNothingDiagnoser(msg): | 185 def _NeedToReturnNothingDiagnoser(msg): |
186 """Diagnoses the NRN disease, given the error messages by gcc.""" | 186 """Diagnoses the NRN disease, given the error messages by gcc.""" |
187 | 187 |
188 regex = (_FILE_LINE_RE + r'instantiated from here\n' | 188 regex = (_FILE_LINE_RE + r'instantiated from here\n' |
189 r'.*gmock-actions\.h.*error: return-statement with a value, ' | 189 r'.*gmock-actions\.h.*error: instantiation of ' |
190 r'in function returning \'void\'') | 190 r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' ' |
| 191 r'as type \'void\'') |
191 diagnosis = """ | 192 diagnosis = """ |
192 You are using an action that returns *something*, but it needs to return | 193 You are using an action that returns *something*, but it needs to return |
193 void. Please use a void-returning action instead. | 194 void. Please use a void-returning action instead. |
194 | 195 |
195 All actions but the last in DoAll(...) must return void. Perhaps you need | 196 All actions but the last in DoAll(...) must return void. Perhaps you need |
196 to re-arrange the order of actions in a DoAll(), if you are using one?""" | 197 to re-arrange the order of actions in a DoAll(), if you are using one?""" |
197 return _GenericDiagnoser('NRN', 'Need to Return Nothing', | 198 return _GenericDiagnoser('NRN', 'Need to Return Nothing', |
198 regex, diagnosis, msg) | 199 regex, diagnosis, msg) |
199 | 200 |
200 | 201 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 ?""" | 330 ?""" |
330 for m in _FindAllMatches(regex, msg): | 331 for m in _FindAllMatches(regex, msg): |
331 symbol = m.groupdict()['symbol'] | 332 symbol = m.groupdict()['symbol'] |
332 if symbol in _COMMON_GMOCK_SYMBOLS: | 333 if symbol in _COMMON_GMOCK_SYMBOLS: |
333 yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict()) | 334 yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict()) |
334 | 335 |
335 | 336 |
336 def _NeedToUseReturnNullDiagnoser(msg): | 337 def _NeedToUseReturnNullDiagnoser(msg): |
337 """Diagnoses the NRNULL disease, given the error messages by gcc.""" | 338 """Diagnoses the NRNULL disease, given the error messages by gcc.""" |
338 | 339 |
339 regex = (_FILE_LINE_RE + r'instantiated from here\n' | 340 regex = ('instantiated from \'testing::internal::ReturnAction<R>' |
340 r'.*gmock-actions\.h.*error: invalid conversion from ' | 341 '::operator testing::Action<Func>\(\) const.*\n' + |
341 r'\'long int\' to \'(?P<type>.+\*)') | 342 _FILE_LINE_RE + r'instantiated from here\n' |
| 343 r'.*error: no matching function for call to \'implicit_cast\(' |
| 344 r'long int&\)') |
342 diagnosis = """ | 345 diagnosis = """ |
343 You are probably calling Return(NULL) and the compiler isn't sure how to turn | 346 You are probably calling Return(NULL) and the compiler isn't sure how to turn |
344 NULL into a %(type)s*. Use ReturnNull() instead. | 347 NULL into the right type. Use ReturnNull() instead. |
345 Note: the line number may be off; please fix all instances of Return(NULL).""" | 348 Note: the line number may be off; please fix all instances of Return(NULL).""" |
346 return _GenericDiagnoser('NRNULL', 'Need to use ReturnNull', | 349 return _GenericDiagnoser('NRNULL', 'Need to use ReturnNull', |
347 regex, diagnosis, msg) | 350 regex, diagnosis, msg) |
348 | 351 |
349 | 352 |
350 _TTB_DIAGNOSIS = """ | 353 _TTB_DIAGNOSIS = """ |
351 In a mock class template, types or typedefs defined in the base class | 354 In a mock class template, types or typedefs defined in the base class |
352 template are *not* automatically visible. This is how C++ works. Before | 355 template are *not* automatically visible. This is how C++ works. Before |
353 you can use a type or typedef named %(type)s defined in base class Base<T>, you | 356 you can use a type or typedef named %(type)s defined in base class Base<T>, you |
354 need to make it visible. One way to do it is: | 357 need to make it visible. One way to do it is: |
355 | 358 |
356 typedef typename Base<T>::%(type)s %(type)s;""" | 359 typedef typename Base<T>::%(type)s %(type)s;""" |
357 | 360 |
358 | 361 |
359 def _TypeInTemplatedBaseDiagnoser1(msg): | 362 def _TypeInTemplatedBaseDiagnoser1(msg): |
360 """Diagnoses the TTB disease, given the error messages by gcc. | 363 """Diagnoses the TTB disease, given the error messages by gcc. |
361 | 364 |
362 This version works when the type is used as the mock function's return | 365 This version works when the type is used as the mock function's return |
363 type. | 366 type. |
364 """ | 367 """ |
365 | 368 |
366 regex = (r'In member function \'int .*\n' + _FILE_LINE_RE + | 369 gcc_4_3_1_regex = ( |
367 r'error: a function call cannot appear in a constant-expression') | 370 r'In member function \'int .*\n' + _FILE_LINE_RE + |
| 371 r'error: a function call cannot appear in a constant-expression') |
| 372 gcc_4_4_0_regex = ( |
| 373 r'error: a function call cannot appear in a constant-expression' |
| 374 + _FILE_LINE_RE + r'error: template argument 1 is invalid\n') |
368 diagnosis = _TTB_DIAGNOSIS % {'type': 'Foo'} | 375 diagnosis = _TTB_DIAGNOSIS % {'type': 'Foo'} |
369 return _GenericDiagnoser('TTB', 'Type in Template Base', | 376 return (list(_GenericDiagnoser('TTB', 'Type in Template Base', |
370 regex, diagnosis, msg) | 377 gcc_4_3_1_regex, diagnosis, msg)) + |
| 378 list(_GenericDiagnoser('TTB', 'Type in Template Base', |
| 379 gcc_4_4_0_regex, diagnosis, msg))) |
371 | 380 |
372 | 381 |
373 def _TypeInTemplatedBaseDiagnoser2(msg): | 382 def _TypeInTemplatedBaseDiagnoser2(msg): |
374 """Diagnoses the TTB disease, given the error messages by gcc. | 383 """Diagnoses the TTB disease, given the error messages by gcc. |
375 | 384 |
376 This version works when the type is used as the mock function's sole | 385 This version works when the type is used as the mock function's sole |
377 parameter type. | 386 parameter type. |
378 """ | 387 """ |
379 | 388 |
380 regex = (r'In member function \'int .*\n' | 389 regex = (_FILE_LINE_RE + |
381 + _FILE_LINE_RE + | |
382 r'error: \'(?P<type>.+)\' was not declared in this scope\n' | 390 r'error: \'(?P<type>.+)\' was not declared in this scope\n' |
383 r'.*error: template argument 1 is invalid\n') | 391 r'.*error: template argument 1 is invalid\n') |
384 return _GenericDiagnoser('TTB', 'Type in Template Base', | 392 return _GenericDiagnoser('TTB', 'Type in Template Base', |
385 regex, _TTB_DIAGNOSIS, msg) | 393 regex, _TTB_DIAGNOSIS, msg) |
386 | 394 |
387 | 395 |
388 def _TypeInTemplatedBaseDiagnoser3(msg): | 396 def _TypeInTemplatedBaseDiagnoser3(msg): |
389 """Diagnoses the TTB disease, given the error messages by gcc. | 397 """Diagnoses the TTB disease, given the error messages by gcc. |
390 | 398 |
391 This version works when the type is used as a parameter of a mock | 399 This version works when the type is used as a parameter of a mock |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 _TypeInTemplatedBaseDiagnoser2, | 456 _TypeInTemplatedBaseDiagnoser2, |
449 _TypeInTemplatedBaseDiagnoser3, | 457 _TypeInTemplatedBaseDiagnoser3, |
450 _WrongMockMethodMacroDiagnoser, | 458 _WrongMockMethodMacroDiagnoser, |
451 _WrongParenPositionDiagnoser, | 459 _WrongParenPositionDiagnoser, |
452 ] | 460 ] |
453 | 461 |
454 | 462 |
455 def Diagnose(msg): | 463 def Diagnose(msg): |
456 """Generates all possible diagnoses given the gcc error message.""" | 464 """Generates all possible diagnoses given the gcc error message.""" |
457 | 465 |
| 466 diagnoses = [] |
458 for diagnoser in _DIAGNOSERS: | 467 for diagnoser in _DIAGNOSERS: |
459 for diagnosis in diagnoser(msg): | 468 for diag in diagnoser(msg): |
460 yield '[%s - %s]\n%s' % diagnosis | 469 diagnosis = '[%s - %s]\n%s' % diag |
| 470 if not diagnosis in diagnoses: |
| 471 diagnoses.append(diagnosis) |
| 472 return diagnoses |
461 | 473 |
462 | 474 |
463 def main(): | 475 def main(): |
464 print ('Google Mock Doctor v%s - ' | 476 print ('Google Mock Doctor v%s - ' |
465 'diagnoses problems in code using Google Mock.' % _VERSION) | 477 'diagnoses problems in code using Google Mock.' % _VERSION) |
466 | 478 |
467 if sys.stdin.isatty(): | 479 if sys.stdin.isatty(): |
468 print ('Please copy and paste the compiler errors here. Press c-D when ' | 480 print ('Please copy and paste the compiler errors here. Press c-D when ' |
469 'you are done:') | 481 'you are done:') |
470 else: | 482 else: |
471 print 'Waiting for compiler errors on stdin . . .' | 483 print 'Waiting for compiler errors on stdin . . .' |
472 | 484 |
473 msg = sys.stdin.read().strip() | 485 msg = sys.stdin.read().strip() |
474 diagnoses = list(Diagnose(msg)) | 486 diagnoses = Diagnose(msg) |
475 count = len(diagnoses) | 487 count = len(diagnoses) |
476 if not count: | 488 if not count: |
477 print '\nGcc complained:' | 489 print '\nGcc complained:' |
478 print '8<------------------------------------------------------------' | 490 print '8<------------------------------------------------------------' |
479 print msg | 491 print msg |
480 print '------------------------------------------------------------>8' | 492 print '------------------------------------------------------------>8' |
481 print """ | 493 print """ |
482 Uh-oh, I'm not smart enough to figure out what the problem is. :-( | 494 Uh-oh, I'm not smart enough to figure out what the problem is. :-( |
483 However... | 495 However... |
484 If you send your source code and gcc's error messages to | 496 If you send your source code and gcc's error messages to |
(...skipping 13 matching lines...) Expand all Loading... |
498 print '\n#%s:' % (i,) | 510 print '\n#%s:' % (i,) |
499 print d | 511 print d |
500 print """ | 512 print """ |
501 How did I do? If you think I'm wrong or unhelpful, please send your | 513 How did I do? If you think I'm wrong or unhelpful, please send your |
502 source code and gcc's error messages to googlemock@googlegroups.com. Then | 514 source code and gcc's error messages to googlemock@googlegroups.com. Then |
503 you can be helped and I can get smarter -- I promise I won't be upset!""" | 515 you can be helped and I can get smarter -- I promise I won't be upset!""" |
504 | 516 |
505 | 517 |
506 if __name__ == '__main__': | 518 if __name__ == '__main__': |
507 main() | 519 main() |
OLD | NEW |