blob: d21b9ee744b528eb573033a1a0f264d56abfdfe4 [file] [log] [blame]
zhanyong.wana89034c2009-09-22 16:18:42 +00001#!/usr/bin/env python
shiqiane35fdd92008-12-10 05:08:54 +00002#
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',
74 'Property',
75 'Ref',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000076 'ResultOf',
77 'SafeMatcherCast',
shiqiane35fdd92008-12-10 05:08:54 +000078 'StartsWith',
79 'StrCaseEq',
80 'StrCaseNe',
81 'StrEq',
82 'StrNe',
83 'Truly',
84 'TypedEq',
zhanyong.wanb8243162009-06-04 05:48:20 +000085 'Value',
shiqiane35fdd92008-12-10 05:08:54 +000086
87 # Actions
zhanyong.wan9413f2f2009-05-29 19:50:06 +000088 'Assign',
shiqiane35fdd92008-12-10 05:08:54 +000089 'ByRef',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000090 'DeleteArg',
shiqiane35fdd92008-12-10 05:08:54 +000091 'DoAll',
92 'DoDefault',
93 'IgnoreResult',
94 'Invoke',
95 'InvokeArgument',
96 'InvokeWithoutArgs',
97 'Return',
zhanyong.wan9413f2f2009-05-29 19:50:06 +000098 'ReturnNew',
shiqiane35fdd92008-12-10 05:08:54 +000099 'ReturnNull',
100 'ReturnRef',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000101 'SaveArg',
102 'SetArgReferee',
shiqiane35fdd92008-12-10 05:08:54 +0000103 'SetArgumentPointee',
104 'SetArrayArgument',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000105 'SetErrnoAndReturn',
106 'Throw',
107 'WithArg',
shiqiane35fdd92008-12-10 05:08:54 +0000108 'WithArgs',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000109 'WithoutArgs',
shiqiane35fdd92008-12-10 05:08:54 +0000110
111 # Cardinalities
112 'AnyNumber',
113 'AtLeast',
114 'AtMost',
115 'Between',
116 'Exactly',
117
118 # Sequences
119 'InSequence',
120 'Sequence',
121
122 # Misc
123 'DefaultValue',
124 'Mock',
125 ]
126
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000127# Regex for matching source file path and line number in gcc's errors.
128_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):\s+'
129
shiqiane35fdd92008-12-10 05:08:54 +0000130
131def _FindAllMatches(regex, s):
132 """Generates all matches of regex in string s."""
133
134 r = re.compile(regex)
135 return r.finditer(s)
136
137
138def _GenericDiagnoser(short_name, long_name, regex, diagnosis, msg):
139 """Diagnoses the given disease by pattern matching.
140
141 Args:
142 short_name: Short name of the disease.
143 long_name: Long name of the disease.
144 regex: Regex for matching the symptoms.
145 diagnosis: Pattern for formatting the diagnosis.
146 msg: Gcc's error messages.
147 Yields:
148 Tuples of the form
149 (short name of disease, long name of disease, diagnosis).
150 """
151
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000152 diagnosis = '%(file)s:%(line)s:' + diagnosis
shiqiane35fdd92008-12-10 05:08:54 +0000153 for m in _FindAllMatches(regex, msg):
154 yield (short_name, long_name, diagnosis % m.groupdict())
155
156
157def _NeedToReturnReferenceDiagnoser(msg):
158 """Diagnoses the NRR disease, given the error messages by gcc."""
159
160 regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000161 + _FILE_LINE_RE + r'instantiated from here\n'
shiqiane35fdd92008-12-10 05:08:54 +0000162 r'.*gmock-actions\.h.*error: creating array with negative size')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000163 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000164You are using an Return() action in a function that returns a reference.
165Please use ReturnRef() instead."""
166 return _GenericDiagnoser('NRR', 'Need to Return Reference',
167 regex, diagnosis, msg)
168
169
170def _NeedToReturnSomethingDiagnoser(msg):
171 """Diagnoses the NRS disease, given the error messages by gcc."""
172
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000173 regex = (_FILE_LINE_RE +
zhanyong.wan16cf4732009-05-14 20:55:30 +0000174 r'(instantiated from here\n.'
zhanyong.wanb8243162009-06-04 05:48:20 +0000175 r'*gmock.*actions\.h.*error: void value not ignored)'
zhanyong.wan16cf4732009-05-14 20:55:30 +0000176 r'|(error: control reaches end of non-void function)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000177 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000178You are using an action that returns void, but it needs to return
zhanyong.wan16cf4732009-05-14 20:55:30 +0000179*something*. Please tell it *what* to return. Perhaps you can use
180the pattern DoAll(some_action, Return(some_value))?"""
shiqiane35fdd92008-12-10 05:08:54 +0000181 return _GenericDiagnoser('NRS', 'Need to Return Something',
182 regex, diagnosis, msg)
183
184
185def _NeedToReturnNothingDiagnoser(msg):
186 """Diagnoses the NRN disease, given the error messages by gcc."""
187
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000188 regex = (_FILE_LINE_RE + r'instantiated from here\n'
vladloseva63be0b2009-11-18 00:42:27 +0000189 r'.*gmock-actions\.h.*error: instantiation of '
190 r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' '
191 r'as type \'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
vladloseva63be0b2009-11-18 00:42:27 +0000340 regex = ('instantiated from \'testing::internal::ReturnAction<R>'
341 '::operator testing::Action<Func>\(\) const.*\n' +
342 _FILE_LINE_RE + r'instantiated from here\n'
343 r'.*gmock-port\.h.*error: invalid conversion from '
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000344 r'\'long int\' to \'(?P<type>.+\*)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000345 diagnosis = """
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000346You are probably calling Return(NULL) and the compiler isn't sure how to turn
347NULL into a %(type)s*. Use ReturnNull() instead.
348Note: the line number may be off; please fix all instances of Return(NULL)."""
349 return _GenericDiagnoser('NRNULL', 'Need to use ReturnNull',
350 regex, diagnosis, msg)
351
352
zhanyong.wanb8243162009-06-04 05:48:20 +0000353_TTB_DIAGNOSIS = """
354In a mock class template, types or typedefs defined in the base class
355template are *not* automatically visible. This is how C++ works. Before
356you can use a type or typedef named %(type)s defined in base class Base<T>, you
357need to make it visible. One way to do it is:
358
359 typedef typename Base<T>::%(type)s %(type)s;"""
360
361
362def _TypeInTemplatedBaseDiagnoser1(msg):
363 """Diagnoses the TTB disease, given the error messages by gcc.
364
365 This version works when the type is used as the mock function's return
366 type.
367 """
368
369 regex = (r'In member function \'int .*\n' + _FILE_LINE_RE +
370 r'error: a function call cannot appear in a constant-expression')
371 diagnosis = _TTB_DIAGNOSIS % {'type': 'Foo'}
372 return _GenericDiagnoser('TTB', 'Type in Template Base',
373 regex, diagnosis, msg)
374
375
376def _TypeInTemplatedBaseDiagnoser2(msg):
377 """Diagnoses the TTB disease, given the error messages by gcc.
378
379 This version works when the type is used as the mock function's sole
380 parameter type.
381 """
382
383 regex = (r'In member function \'int .*\n'
384 + _FILE_LINE_RE +
385 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
386 r'.*error: template argument 1 is invalid\n')
387 return _GenericDiagnoser('TTB', 'Type in Template Base',
388 regex, _TTB_DIAGNOSIS, msg)
389
390
391def _TypeInTemplatedBaseDiagnoser3(msg):
392 """Diagnoses the TTB disease, given the error messages by gcc.
393
394 This version works when the type is used as a parameter of a mock
395 function that has multiple parameters.
396 """
397
398 regex = (r'error: expected `;\' before \'::\' token\n'
399 + _FILE_LINE_RE +
400 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
401 r'.*error: template argument 1 is invalid\n'
402 r'.*error: \'.+\' was not declared in this scope')
403 return _GenericDiagnoser('TTB', 'Type in Template Base',
404 regex, _TTB_DIAGNOSIS, msg)
405
406
zhanyong.wan16cf4732009-05-14 20:55:30 +0000407def _WrongMockMethodMacroDiagnoser(msg):
408 """Diagnoses the WMM disease, given the error messages by gcc."""
409
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000410 regex = (_FILE_LINE_RE +
zhanyong.wan16cf4732009-05-14 20:55:30 +0000411 r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
412 r'.*\n'
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000413 r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
414 diagnosis = """
zhanyong.wan16cf4732009-05-14 20:55:30 +0000415You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
416%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
417MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
zhanyong.wanb8243162009-06-04 05:48:20 +0000418 return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
zhanyong.wan16cf4732009-05-14 20:55:30 +0000419 regex, diagnosis, msg)
420
421
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000422def _WrongParenPositionDiagnoser(msg):
423 """Diagnoses the WPP disease, given the error messages by gcc."""
424
425 regex = (_FILE_LINE_RE +
426 r'error:.*testing::internal::MockSpec<.* has no member named \''
427 r'(?P<method>\w+)\'')
428 diagnosis = """
429The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
430".%(method)s". For example, you should write:
431 EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
432instead of:
433 EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
zhanyong.wanb8243162009-06-04 05:48:20 +0000434 return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000435 regex, diagnosis, msg)
436
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000437
shiqiane35fdd92008-12-10 05:08:54 +0000438_DIAGNOSERS = [
439 _IncompleteByReferenceArgumentDiagnoser,
440 _MockObjectPointerDiagnoser,
441 _NeedToReturnNothingDiagnoser,
442 _NeedToReturnReferenceDiagnoser,
443 _NeedToReturnSomethingDiagnoser,
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000444 _NeedToUseReturnNullDiagnoser,
shiqiane35fdd92008-12-10 05:08:54 +0000445 _NeedToUseSymbolDiagnoser,
446 _OverloadedFunctionActionDiagnoser,
447 _OverloadedFunctionMatcherDiagnoser,
448 _OverloadedMethodActionDiagnoser1,
449 _OverloadedMethodActionDiagnoser2,
zhanyong.wanb8243162009-06-04 05:48:20 +0000450 _TypeInTemplatedBaseDiagnoser1,
451 _TypeInTemplatedBaseDiagnoser2,
452 _TypeInTemplatedBaseDiagnoser3,
zhanyong.wan16cf4732009-05-14 20:55:30 +0000453 _WrongMockMethodMacroDiagnoser,
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000454 _WrongParenPositionDiagnoser,
shiqiane35fdd92008-12-10 05:08:54 +0000455 ]
456
457
458def Diagnose(msg):
459 """Generates all possible diagnoses given the gcc error message."""
460
461 for diagnoser in _DIAGNOSERS:
462 for diagnosis in diagnoser(msg):
463 yield '[%s - %s]\n%s' % diagnosis
464
465
466def main():
467 print ('Google Mock Doctor v%s - '
468 'diagnoses problems in code using Google Mock.' % _VERSION)
469
470 if sys.stdin.isatty():
471 print ('Please copy and paste the compiler errors here. Press c-D when '
472 'you are done:')
473 else:
474 print 'Waiting for compiler errors on stdin . . .'
475
476 msg = sys.stdin.read().strip()
477 diagnoses = list(Diagnose(msg))
478 count = len(diagnoses)
479 if not count:
480 print '\nGcc complained:'
481 print '8<------------------------------------------------------------'
482 print msg
483 print '------------------------------------------------------------>8'
484 print """
485Uh-oh, I'm not smart enough to figure out what the problem is. :-(
486However...
487If you send your source code and gcc's error messages to
488googlemock@googlegroups.com, you can be helped and I can get smarter --
489win-win for us!"""
490 else:
491 print '------------------------------------------------------------'
492 print 'Your code appears to have the following',
493 if count > 1:
494 print '%s diseases:' % (count,)
495 else:
496 print 'disease:'
497 i = 0
498 for d in diagnoses:
499 i += 1
500 if count > 1:
501 print '\n#%s:' % (i,)
502 print d
503 print """
504How did I do? If you think I'm wrong or unhelpful, please send your
505source code and gcc's error messages to googlemock@googlegroups.com. Then
506you can be helped and I can get smarter -- I promise I won't be upset!"""
507
508
509if __name__ == '__main__':
510 main()