blob: 05e42585493118c5f55fc7704c1687250e4f025f [file] [log] [blame]
shiqiane35fdd92008-12-10 05:08:54 +00001#!/usr/bin/python2.4
2#
3# Copyright 2008, Google Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are
8# met:
9#
10# * Redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer.
12# * Redistributions in binary form must reproduce the above
13# copyright notice, this list of conditions and the following disclaimer
14# in the documentation and/or other materials provided with the
15# distribution.
16# * Neither the name of Google Inc. nor the names of its
17# contributors may be used to endorse or promote products derived from
18# this software without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32"""Converts gcc errors in code using Google Mock to plain English."""
33
34__author__ = 'wan@google.com (Zhanyong Wan)'
35
36import re
37import sys
38
zhanyong.wanb8243162009-06-04 05:48:20 +000039_VERSION = '1.0.3'
shiqiane35fdd92008-12-10 05:08:54 +000040
41_COMMON_GMOCK_SYMBOLS = [
42 # Matchers
43 '_',
44 'A',
45 'AddressSatisfies',
46 'AllOf',
47 'An',
48 'AnyOf',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000049 'ContainerEq',
50 'Contains',
shiqiane35fdd92008-12-10 05:08:54 +000051 'ContainsRegex',
52 'DoubleEq',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000053 'ElementsAre',
54 'ElementsAreArray',
shiqiane35fdd92008-12-10 05:08:54 +000055 'EndsWith',
56 'Eq',
57 'Field',
58 'FloatEq',
59 'Ge',
60 'Gt',
61 'HasSubstr',
zhanyong.wan5b95fa72009-01-27 22:28:45 +000062 'IsInitializedProto',
shiqiane35fdd92008-12-10 05:08:54 +000063 'Le',
64 'Lt',
65 'MatcherCast',
zhanyong.wanb8243162009-06-04 05:48:20 +000066 'Matches',
shiqiane35fdd92008-12-10 05:08:54 +000067 'MatchesRegex',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000068 'NanSensitiveDoubleEq',
69 'NanSensitiveFloatEq',
shiqiane35fdd92008-12-10 05:08:54 +000070 'Ne',
71 'Not',
72 'NotNull',
73 'Pointee',
zhanyong.wan5b95fa72009-01-27 22:28:45 +000074 'PointeeIsInitializedProto',
shiqiane35fdd92008-12-10 05:08:54 +000075 'Property',
76 'Ref',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000077 'ResultOf',
78 'SafeMatcherCast',
shiqiane35fdd92008-12-10 05:08:54 +000079 'StartsWith',
80 'StrCaseEq',
81 'StrCaseNe',
82 'StrEq',
83 'StrNe',
84 'Truly',
85 'TypedEq',
zhanyong.wanb8243162009-06-04 05:48:20 +000086 'Value',
shiqiane35fdd92008-12-10 05:08:54 +000087
88 # Actions
zhanyong.wan9413f2f2009-05-29 19:50:06 +000089 'Assign',
shiqiane35fdd92008-12-10 05:08:54 +000090 'ByRef',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000091 'DeleteArg',
shiqiane35fdd92008-12-10 05:08:54 +000092 'DoAll',
93 'DoDefault',
94 'IgnoreResult',
95 'Invoke',
96 'InvokeArgument',
97 'InvokeWithoutArgs',
98 'Return',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000099 'ReturnNew',
shiqiane35fdd92008-12-10 05:08:54 +0000100 'ReturnNull',
101 'ReturnRef',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000102 'SaveArg',
103 'SetArgReferee',
shiqiane35fdd92008-12-10 05:08:54 +0000104 'SetArgumentPointee',
105 'SetArrayArgument',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000106 'SetErrnoAndReturn',
107 'Throw',
108 'WithArg',
shiqiane35fdd92008-12-10 05:08:54 +0000109 'WithArgs',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000110 'WithoutArgs',
shiqiane35fdd92008-12-10 05:08:54 +0000111
112 # Cardinalities
113 'AnyNumber',
114 'AtLeast',
115 'AtMost',
116 'Between',
117 'Exactly',
118
119 # Sequences
120 'InSequence',
121 'Sequence',
122
123 # Misc
124 'DefaultValue',
125 'Mock',
126 ]
127
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000128# Regex for matching source file path and line number in gcc's errors.
129_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):\s+'
130
shiqiane35fdd92008-12-10 05:08:54 +0000131
132def _FindAllMatches(regex, s):
133 """Generates all matches of regex in string s."""
134
135 r = re.compile(regex)
136 return r.finditer(s)
137
138
139def _GenericDiagnoser(short_name, long_name, regex, diagnosis, msg):
140 """Diagnoses the given disease by pattern matching.
141
142 Args:
143 short_name: Short name of the disease.
144 long_name: Long name of the disease.
145 regex: Regex for matching the symptoms.
146 diagnosis: Pattern for formatting the diagnosis.
147 msg: Gcc's error messages.
148 Yields:
149 Tuples of the form
150 (short name of disease, long name of disease, diagnosis).
151 """
152
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000153 diagnosis = '%(file)s:%(line)s:' + diagnosis
shiqiane35fdd92008-12-10 05:08:54 +0000154 for m in _FindAllMatches(regex, msg):
155 yield (short_name, long_name, diagnosis % m.groupdict())
156
157
158def _NeedToReturnReferenceDiagnoser(msg):
159 """Diagnoses the NRR disease, given the error messages by gcc."""
160
161 regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000162 + _FILE_LINE_RE + r'instantiated from here\n'
shiqiane35fdd92008-12-10 05:08:54 +0000163 r'.*gmock-actions\.h.*error: creating array with negative size')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000164 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000165You are using an Return() action in a function that returns a reference.
166Please use ReturnRef() instead."""
167 return _GenericDiagnoser('NRR', 'Need to Return Reference',
168 regex, diagnosis, msg)
169
170
171def _NeedToReturnSomethingDiagnoser(msg):
172 """Diagnoses the NRS disease, given the error messages by gcc."""
173
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000174 regex = (_FILE_LINE_RE +
zhanyong.wan16cf4732009-05-14 20:55:30 +0000175 r'(instantiated from here\n.'
zhanyong.wanb8243162009-06-04 05:48:20 +0000176 r'*gmock.*actions\.h.*error: void value not ignored)'
zhanyong.wan16cf4732009-05-14 20:55:30 +0000177 r'|(error: control reaches end of non-void function)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000178 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000179You are using an action that returns void, but it needs to return
zhanyong.wan16cf4732009-05-14 20:55:30 +0000180*something*. Please tell it *what* to return. Perhaps you can use
181the pattern DoAll(some_action, Return(some_value))?"""
shiqiane35fdd92008-12-10 05:08:54 +0000182 return _GenericDiagnoser('NRS', 'Need to Return Something',
183 regex, diagnosis, msg)
184
185
186def _NeedToReturnNothingDiagnoser(msg):
187 """Diagnoses the NRN disease, given the error messages by gcc."""
188
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000189 regex = (_FILE_LINE_RE + r'instantiated from here\n'
shiqiane35fdd92008-12-10 05:08:54 +0000190 r'.*gmock-actions\.h.*error: return-statement with a value, '
191 r'in function returning \'void\'')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000192 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000193You are using an action that returns *something*, but it needs to return
194void. Please use a void-returning action instead.
195
196All actions but the last in DoAll(...) must return void. Perhaps you need
197to re-arrange the order of actions in a DoAll(), if you are using one?"""
198 return _GenericDiagnoser('NRN', 'Need to Return Nothing',
199 regex, diagnosis, msg)
200
201
202def _IncompleteByReferenceArgumentDiagnoser(msg):
203 """Diagnoses the IBRA disease, given the error messages by gcc."""
204
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000205 regex = (_FILE_LINE_RE + r'instantiated from here\n'
shiqiane35fdd92008-12-10 05:08:54 +0000206 r'.*gmock-printers\.h.*error: invalid application of '
207 r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000208 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000209In order to mock this function, Google Mock needs to see the definition
210of type "%(type)s" - declaration alone is not enough. Either #include
211the header that defines it, or change the argument to be passed
212by pointer."""
213 return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
214 regex, diagnosis, msg)
215
216
217def _OverloadedFunctionMatcherDiagnoser(msg):
218 """Diagnoses the OFM disease, given the error messages by gcc."""
219
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000220 regex = (_FILE_LINE_RE + r'error: no matching function for '
shiqiane35fdd92008-12-10 05:08:54 +0000221 r'call to \'Truly\(<unresolved overloaded function type>\)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000222 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000223The argument you gave to Truly() is an overloaded function. Please tell
224gcc which overloaded version you want to use.
225
226For example, if you want to use the version whose signature is
227 bool Foo(int n);
228you should write
229 Truly(static_cast<bool (*)(int n)>(Foo))"""
230 return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
231 regex, diagnosis, msg)
232
233
234def _OverloadedFunctionActionDiagnoser(msg):
235 """Diagnoses the OFA disease, given the error messages by gcc."""
236
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000237 regex = (_FILE_LINE_RE + r'error: no matching function for call to \'Invoke\('
shiqiane35fdd92008-12-10 05:08:54 +0000238 r'<unresolved overloaded function type>')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000239 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000240You are passing an overloaded function to Invoke(). Please tell gcc
241which overloaded version you want to use.
242
243For example, if you want to use the version whose signature is
244 bool MyFunction(int n, double x);
245you should write something like
246 Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
247 return _GenericDiagnoser('OFA', 'Overloaded Function Action',
248 regex, diagnosis, msg)
249
250
251def _OverloadedMethodActionDiagnoser1(msg):
252 """Diagnoses the OMA disease, given the error messages by gcc."""
253
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000254 regex = (_FILE_LINE_RE + r'error: '
shiqiane35fdd92008-12-10 05:08:54 +0000255 r'.*no matching function for call to \'Invoke\(.*, '
256 r'unresolved overloaded function type>')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000257 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000258The second argument you gave to Invoke() is an overloaded method. Please
259tell gcc which overloaded version you want to use.
260
261For example, if you want to use the version whose signature is
262 class Foo {
263 ...
264 bool Bar(int n, double x);
265 };
266you should write something like
267 Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
268 return _GenericDiagnoser('OMA', 'Overloaded Method Action',
269 regex, diagnosis, msg)
270
271
272def _MockObjectPointerDiagnoser(msg):
273 """Diagnoses the MOP disease, given the error messages by gcc."""
274
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000275 regex = (_FILE_LINE_RE + r'error: request for member '
shiqiane35fdd92008-12-10 05:08:54 +0000276 r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
277 r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000278 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000279The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
280not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
281'%(mock_object)s' as your first argument.
282
283For example, given the mock class:
284
285 class %(class_name)s : public ... {
286 ...
287 MOCK_METHOD0(%(method)s, ...);
288 };
289
290and the following mock instance:
291
292 %(class_name)s* mock_ptr = ...
293
294you should use the EXPECT_CALL like this:
295
296 EXPECT_CALL(*mock_ptr, %(method)s(...));"""
297 return _GenericDiagnoser('MOP', 'Mock Object Pointer',
298 regex, diagnosis, msg)
299
300
301def _OverloadedMethodActionDiagnoser2(msg):
302 """Diagnoses the OMA disease, given the error messages by gcc."""
303
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000304 regex = (_FILE_LINE_RE + r'error: no matching function for '
shiqiane35fdd92008-12-10 05:08:54 +0000305 r'call to \'Invoke\(.+, <unresolved overloaded function type>\)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000306 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000307The second argument you gave to Invoke() is an overloaded method. Please
308tell gcc which overloaded version you want to use.
309
310For example, if you want to use the version whose signature is
311 class Foo {
312 ...
313 bool Bar(int n, double x);
314 };
315you should write something like
316 Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
317 return _GenericDiagnoser('OMA', 'Overloaded Method Action',
318 regex, diagnosis, msg)
319
320
321def _NeedToUseSymbolDiagnoser(msg):
322 """Diagnoses the NUS disease, given the error messages by gcc."""
323
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000324 regex = (_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
shiqiane35fdd92008-12-10 05:08:54 +0000325 r'(was not declared in this scope|has not been declared)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000326 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000327'%(symbol)s' is defined by Google Mock in the testing namespace.
328Did you forget to write
329 using testing::%(symbol)s;
330?"""
331 for m in _FindAllMatches(regex, msg):
332 symbol = m.groupdict()['symbol']
333 if symbol in _COMMON_GMOCK_SYMBOLS:
334 yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
335
336
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000337def _NeedToUseReturnNullDiagnoser(msg):
338 """Diagnoses the NRNULL disease, given the error messages by gcc."""
339
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000340 regex = (_FILE_LINE_RE + r'instantiated from here\n'
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000341 r'.*gmock-actions\.h.*error: invalid conversion from '
342 r'\'long int\' to \'(?P<type>.+\*)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000343 diagnosis = """
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000344You are probably calling Return(NULL) and the compiler isn't sure how to turn
345NULL into a %(type)s*. Use ReturnNull() instead.
346Note: the line number may be off; please fix all instances of Return(NULL)."""
347 return _GenericDiagnoser('NRNULL', 'Need to use ReturnNull',
348 regex, diagnosis, msg)
349
350
zhanyong.wanb8243162009-06-04 05:48:20 +0000351_TTB_DIAGNOSIS = """
352In a mock class template, types or typedefs defined in the base class
353template are *not* automatically visible. This is how C++ works. Before
354you can use a type or typedef named %(type)s defined in base class Base<T>, you
355need to make it visible. One way to do it is:
356
357 typedef typename Base<T>::%(type)s %(type)s;"""
358
359
360def _TypeInTemplatedBaseDiagnoser1(msg):
361 """Diagnoses the TTB disease, given the error messages by gcc.
362
363 This version works when the type is used as the mock function's return
364 type.
365 """
366
367 regex = (r'In member function \'int .*\n' + _FILE_LINE_RE +
368 r'error: a function call cannot appear in a constant-expression')
369 diagnosis = _TTB_DIAGNOSIS % {'type': 'Foo'}
370 return _GenericDiagnoser('TTB', 'Type in Template Base',
371 regex, diagnosis, msg)
372
373
374def _TypeInTemplatedBaseDiagnoser2(msg):
375 """Diagnoses the TTB disease, given the error messages by gcc.
376
377 This version works when the type is used as the mock function's sole
378 parameter type.
379 """
380
381 regex = (r'In member function \'int .*\n'
382 + _FILE_LINE_RE +
383 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
384 r'.*error: template argument 1 is invalid\n')
385 return _GenericDiagnoser('TTB', 'Type in Template Base',
386 regex, _TTB_DIAGNOSIS, msg)
387
388
389def _TypeInTemplatedBaseDiagnoser3(msg):
390 """Diagnoses the TTB disease, given the error messages by gcc.
391
392 This version works when the type is used as a parameter of a mock
393 function that has multiple parameters.
394 """
395
396 regex = (r'error: expected `;\' before \'::\' token\n'
397 + _FILE_LINE_RE +
398 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
399 r'.*error: template argument 1 is invalid\n'
400 r'.*error: \'.+\' was not declared in this scope')
401 return _GenericDiagnoser('TTB', 'Type in Template Base',
402 regex, _TTB_DIAGNOSIS, msg)
403
404
zhanyong.wan16cf4732009-05-14 20:55:30 +0000405def _WrongMockMethodMacroDiagnoser(msg):
406 """Diagnoses the WMM disease, given the error messages by gcc."""
407
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000408 regex = (_FILE_LINE_RE +
zhanyong.wan16cf4732009-05-14 20:55:30 +0000409 r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
410 r'.*\n'
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000411 r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
412 diagnosis = """
zhanyong.wan16cf4732009-05-14 20:55:30 +0000413You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
414%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
415MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
zhanyong.wanb8243162009-06-04 05:48:20 +0000416 return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
zhanyong.wan16cf4732009-05-14 20:55:30 +0000417 regex, diagnosis, msg)
418
419
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000420def _WrongParenPositionDiagnoser(msg):
421 """Diagnoses the WPP disease, given the error messages by gcc."""
422
423 regex = (_FILE_LINE_RE +
424 r'error:.*testing::internal::MockSpec<.* has no member named \''
425 r'(?P<method>\w+)\'')
426 diagnosis = """
427The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
428".%(method)s". For example, you should write:
429 EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
430instead of:
431 EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
zhanyong.wanb8243162009-06-04 05:48:20 +0000432 return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000433 regex, diagnosis, msg)
434
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000435
shiqiane35fdd92008-12-10 05:08:54 +0000436_DIAGNOSERS = [
437 _IncompleteByReferenceArgumentDiagnoser,
438 _MockObjectPointerDiagnoser,
439 _NeedToReturnNothingDiagnoser,
440 _NeedToReturnReferenceDiagnoser,
441 _NeedToReturnSomethingDiagnoser,
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000442 _NeedToUseReturnNullDiagnoser,
shiqiane35fdd92008-12-10 05:08:54 +0000443 _NeedToUseSymbolDiagnoser,
444 _OverloadedFunctionActionDiagnoser,
445 _OverloadedFunctionMatcherDiagnoser,
446 _OverloadedMethodActionDiagnoser1,
447 _OverloadedMethodActionDiagnoser2,
zhanyong.wanb8243162009-06-04 05:48:20 +0000448 _TypeInTemplatedBaseDiagnoser1,
449 _TypeInTemplatedBaseDiagnoser2,
450 _TypeInTemplatedBaseDiagnoser3,
zhanyong.wan16cf4732009-05-14 20:55:30 +0000451 _WrongMockMethodMacroDiagnoser,
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000452 _WrongParenPositionDiagnoser,
shiqiane35fdd92008-12-10 05:08:54 +0000453 ]
454
455
456def Diagnose(msg):
457 """Generates all possible diagnoses given the gcc error message."""
458
459 for diagnoser in _DIAGNOSERS:
460 for diagnosis in diagnoser(msg):
461 yield '[%s - %s]\n%s' % diagnosis
462
463
464def main():
465 print ('Google Mock Doctor v%s - '
466 'diagnoses problems in code using Google Mock.' % _VERSION)
467
468 if sys.stdin.isatty():
469 print ('Please copy and paste the compiler errors here. Press c-D when '
470 'you are done:')
471 else:
472 print 'Waiting for compiler errors on stdin . . .'
473
474 msg = sys.stdin.read().strip()
475 diagnoses = list(Diagnose(msg))
476 count = len(diagnoses)
477 if not count:
478 print '\nGcc complained:'
479 print '8<------------------------------------------------------------'
480 print msg
481 print '------------------------------------------------------------>8'
482 print """
483Uh-oh, I'm not smart enough to figure out what the problem is. :-(
484However...
485If you send your source code and gcc's error messages to
486googlemock@googlegroups.com, you can be helped and I can get smarter --
487win-win for us!"""
488 else:
489 print '------------------------------------------------------------'
490 print 'Your code appears to have the following',
491 if count > 1:
492 print '%s diseases:' % (count,)
493 else:
494 print 'disease:'
495 i = 0
496 for d in diagnoses:
497 i += 1
498 if count > 1:
499 print '\n#%s:' % (i,)
500 print d
501 print """
502How did I do? If you think I'm wrong or unhelpful, please send your
503source code and gcc's error messages to googlemock@googlegroups.com. Then
504you can be helped and I can get smarter -- I promise I won't be upset!"""
505
506
507if __name__ == '__main__':
508 main()