blob: 40512fcd851e908263c8f9729f54b9c4fc5369e8 [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'
shiqiane35fdd92008-12-10 05:08:54 +0000189 r'.*gmock-actions\.h.*error: return-statement with a value, '
190 r'in function returning \'void\'')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000191 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000192You are using an action that returns *something*, but it needs to return
193void. Please use a void-returning action instead.
194
195All actions but the last in DoAll(...) must return void. Perhaps you need
196to re-arrange the order of actions in a DoAll(), if you are using one?"""
197 return _GenericDiagnoser('NRN', 'Need to Return Nothing',
198 regex, diagnosis, msg)
199
200
201def _IncompleteByReferenceArgumentDiagnoser(msg):
202 """Diagnoses the IBRA disease, given the error messages by gcc."""
203
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000204 regex = (_FILE_LINE_RE + r'instantiated from here\n'
shiqiane35fdd92008-12-10 05:08:54 +0000205 r'.*gmock-printers\.h.*error: invalid application of '
206 r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000207 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000208In order to mock this function, Google Mock needs to see the definition
209of type "%(type)s" - declaration alone is not enough. Either #include
210the header that defines it, or change the argument to be passed
211by pointer."""
212 return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
213 regex, diagnosis, msg)
214
215
216def _OverloadedFunctionMatcherDiagnoser(msg):
217 """Diagnoses the OFM disease, given the error messages by gcc."""
218
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000219 regex = (_FILE_LINE_RE + r'error: no matching function for '
shiqiane35fdd92008-12-10 05:08:54 +0000220 r'call to \'Truly\(<unresolved overloaded function type>\)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000221 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000222The argument you gave to Truly() is an overloaded function. Please tell
223gcc which overloaded version you want to use.
224
225For example, if you want to use the version whose signature is
226 bool Foo(int n);
227you should write
228 Truly(static_cast<bool (*)(int n)>(Foo))"""
229 return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
230 regex, diagnosis, msg)
231
232
233def _OverloadedFunctionActionDiagnoser(msg):
234 """Diagnoses the OFA disease, given the error messages by gcc."""
235
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000236 regex = (_FILE_LINE_RE + r'error: no matching function for call to \'Invoke\('
shiqiane35fdd92008-12-10 05:08:54 +0000237 r'<unresolved overloaded function type>')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000238 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000239You are passing an overloaded function to Invoke(). Please tell gcc
240which overloaded version you want to use.
241
242For example, if you want to use the version whose signature is
243 bool MyFunction(int n, double x);
244you should write something like
245 Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
246 return _GenericDiagnoser('OFA', 'Overloaded Function Action',
247 regex, diagnosis, msg)
248
249
250def _OverloadedMethodActionDiagnoser1(msg):
251 """Diagnoses the OMA disease, given the error messages by gcc."""
252
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000253 regex = (_FILE_LINE_RE + r'error: '
shiqiane35fdd92008-12-10 05:08:54 +0000254 r'.*no matching function for call to \'Invoke\(.*, '
255 r'unresolved overloaded function type>')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000256 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000257The second argument you gave to Invoke() is an overloaded method. Please
258tell gcc which overloaded version you want to use.
259
260For example, if you want to use the version whose signature is
261 class Foo {
262 ...
263 bool Bar(int n, double x);
264 };
265you should write something like
266 Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
267 return _GenericDiagnoser('OMA', 'Overloaded Method Action',
268 regex, diagnosis, msg)
269
270
271def _MockObjectPointerDiagnoser(msg):
272 """Diagnoses the MOP disease, given the error messages by gcc."""
273
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000274 regex = (_FILE_LINE_RE + r'error: request for member '
shiqiane35fdd92008-12-10 05:08:54 +0000275 r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
276 r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000277 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000278The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
279not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
280'%(mock_object)s' as your first argument.
281
282For example, given the mock class:
283
284 class %(class_name)s : public ... {
285 ...
286 MOCK_METHOD0(%(method)s, ...);
287 };
288
289and the following mock instance:
290
291 %(class_name)s* mock_ptr = ...
292
293you should use the EXPECT_CALL like this:
294
295 EXPECT_CALL(*mock_ptr, %(method)s(...));"""
296 return _GenericDiagnoser('MOP', 'Mock Object Pointer',
297 regex, diagnosis, msg)
298
299
300def _OverloadedMethodActionDiagnoser2(msg):
301 """Diagnoses the OMA disease, given the error messages by gcc."""
302
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000303 regex = (_FILE_LINE_RE + r'error: no matching function for '
shiqiane35fdd92008-12-10 05:08:54 +0000304 r'call to \'Invoke\(.+, <unresolved overloaded function type>\)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000305 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000306The second argument you gave to Invoke() is an overloaded method. Please
307tell gcc which overloaded version you want to use.
308
309For example, if you want to use the version whose signature is
310 class Foo {
311 ...
312 bool Bar(int n, double x);
313 };
314you should write something like
315 Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
316 return _GenericDiagnoser('OMA', 'Overloaded Method Action',
317 regex, diagnosis, msg)
318
319
320def _NeedToUseSymbolDiagnoser(msg):
321 """Diagnoses the NUS disease, given the error messages by gcc."""
322
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000323 regex = (_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
shiqiane35fdd92008-12-10 05:08:54 +0000324 r'(was not declared in this scope|has not been declared)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000325 diagnosis = """
shiqiane35fdd92008-12-10 05:08:54 +0000326'%(symbol)s' is defined by Google Mock in the testing namespace.
327Did you forget to write
328 using testing::%(symbol)s;
329?"""
330 for m in _FindAllMatches(regex, msg):
331 symbol = m.groupdict()['symbol']
332 if symbol in _COMMON_GMOCK_SYMBOLS:
333 yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
334
335
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000336def _NeedToUseReturnNullDiagnoser(msg):
337 """Diagnoses the NRNULL disease, given the error messages by gcc."""
338
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000339 regex = (_FILE_LINE_RE + r'instantiated from here\n'
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000340 r'.*gmock-actions\.h.*error: invalid conversion from '
341 r'\'long int\' to \'(?P<type>.+\*)')
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000342 diagnosis = """
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000343You are probably calling Return(NULL) and the compiler isn't sure how to turn
344NULL into a %(type)s*. Use ReturnNull() instead.
345Note: the line number may be off; please fix all instances of Return(NULL)."""
346 return _GenericDiagnoser('NRNULL', 'Need to use ReturnNull',
347 regex, diagnosis, msg)
348
349
zhanyong.wanb8243162009-06-04 05:48:20 +0000350_TTB_DIAGNOSIS = """
351In a mock class template, types or typedefs defined in the base class
352template are *not* automatically visible. This is how C++ works. Before
353you can use a type or typedef named %(type)s defined in base class Base<T>, you
354need to make it visible. One way to do it is:
355
356 typedef typename Base<T>::%(type)s %(type)s;"""
357
358
359def _TypeInTemplatedBaseDiagnoser1(msg):
360 """Diagnoses the TTB disease, given the error messages by gcc.
361
362 This version works when the type is used as the mock function's return
363 type.
364 """
365
366 regex = (r'In member function \'int .*\n' + _FILE_LINE_RE +
367 r'error: a function call cannot appear in a constant-expression')
368 diagnosis = _TTB_DIAGNOSIS % {'type': 'Foo'}
369 return _GenericDiagnoser('TTB', 'Type in Template Base',
370 regex, diagnosis, msg)
371
372
373def _TypeInTemplatedBaseDiagnoser2(msg):
374 """Diagnoses the TTB disease, given the error messages by gcc.
375
376 This version works when the type is used as the mock function's sole
377 parameter type.
378 """
379
380 regex = (r'In member function \'int .*\n'
381 + _FILE_LINE_RE +
382 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
383 r'.*error: template argument 1 is invalid\n')
384 return _GenericDiagnoser('TTB', 'Type in Template Base',
385 regex, _TTB_DIAGNOSIS, msg)
386
387
388def _TypeInTemplatedBaseDiagnoser3(msg):
389 """Diagnoses the TTB disease, given the error messages by gcc.
390
391 This version works when the type is used as a parameter of a mock
392 function that has multiple parameters.
393 """
394
395 regex = (r'error: expected `;\' before \'::\' token\n'
396 + _FILE_LINE_RE +
397 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
398 r'.*error: template argument 1 is invalid\n'
399 r'.*error: \'.+\' was not declared in this scope')
400 return _GenericDiagnoser('TTB', 'Type in Template Base',
401 regex, _TTB_DIAGNOSIS, msg)
402
403
zhanyong.wan16cf4732009-05-14 20:55:30 +0000404def _WrongMockMethodMacroDiagnoser(msg):
405 """Diagnoses the WMM disease, given the error messages by gcc."""
406
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000407 regex = (_FILE_LINE_RE +
zhanyong.wan16cf4732009-05-14 20:55:30 +0000408 r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
409 r'.*\n'
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000410 r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
411 diagnosis = """
zhanyong.wan16cf4732009-05-14 20:55:30 +0000412You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
413%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
414MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
zhanyong.wanb8243162009-06-04 05:48:20 +0000415 return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
zhanyong.wan16cf4732009-05-14 20:55:30 +0000416 regex, diagnosis, msg)
417
418
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000419def _WrongParenPositionDiagnoser(msg):
420 """Diagnoses the WPP disease, given the error messages by gcc."""
421
422 regex = (_FILE_LINE_RE +
423 r'error:.*testing::internal::MockSpec<.* has no member named \''
424 r'(?P<method>\w+)\'')
425 diagnosis = """
426The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
427".%(method)s". For example, you should write:
428 EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
429instead of:
430 EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
zhanyong.wanb8243162009-06-04 05:48:20 +0000431 return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000432 regex, diagnosis, msg)
433
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000434
shiqiane35fdd92008-12-10 05:08:54 +0000435_DIAGNOSERS = [
436 _IncompleteByReferenceArgumentDiagnoser,
437 _MockObjectPointerDiagnoser,
438 _NeedToReturnNothingDiagnoser,
439 _NeedToReturnReferenceDiagnoser,
440 _NeedToReturnSomethingDiagnoser,
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000441 _NeedToUseReturnNullDiagnoser,
shiqiane35fdd92008-12-10 05:08:54 +0000442 _NeedToUseSymbolDiagnoser,
443 _OverloadedFunctionActionDiagnoser,
444 _OverloadedFunctionMatcherDiagnoser,
445 _OverloadedMethodActionDiagnoser1,
446 _OverloadedMethodActionDiagnoser2,
zhanyong.wanb8243162009-06-04 05:48:20 +0000447 _TypeInTemplatedBaseDiagnoser1,
448 _TypeInTemplatedBaseDiagnoser2,
449 _TypeInTemplatedBaseDiagnoser3,
zhanyong.wan16cf4732009-05-14 20:55:30 +0000450 _WrongMockMethodMacroDiagnoser,
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000451 _WrongParenPositionDiagnoser,
shiqiane35fdd92008-12-10 05:08:54 +0000452 ]
453
454
455def Diagnose(msg):
456 """Generates all possible diagnoses given the gcc error message."""
457
458 for diagnoser in _DIAGNOSERS:
459 for diagnosis in diagnoser(msg):
460 yield '[%s - %s]\n%s' % diagnosis
461
462
463def main():
464 print ('Google Mock Doctor v%s - '
465 'diagnoses problems in code using Google Mock.' % _VERSION)
466
467 if sys.stdin.isatty():
468 print ('Please copy and paste the compiler errors here. Press c-D when '
469 'you are done:')
470 else:
471 print 'Waiting for compiler errors on stdin . . .'
472
473 msg = sys.stdin.read().strip()
474 diagnoses = list(Diagnose(msg))
475 count = len(diagnoses)
476 if not count:
477 print '\nGcc complained:'
478 print '8<------------------------------------------------------------'
479 print msg
480 print '------------------------------------------------------------>8'
481 print """
482Uh-oh, I'm not smart enough to figure out what the problem is. :-(
483However...
484If you send your source code and gcc's error messages to
485googlemock@googlegroups.com, you can be helped and I can get smarter --
486win-win for us!"""
487 else:
488 print '------------------------------------------------------------'
489 print 'Your code appears to have the following',
490 if count > 1:
491 print '%s diseases:' % (count,)
492 else:
493 print 'disease:'
494 i = 0
495 for d in diagnoses:
496 i += 1
497 if count > 1:
498 print '\n#%s:' % (i,)
499 print d
500 print """
501How did I do? If you think I'm wrong or unhelpful, please send your
502source code and gcc's error messages to googlemock@googlegroups.com. Then
503you can be helped and I can get smarter -- I promise I won't be upset!"""
504
505
506if __name__ == '__main__':
507 main()