blob: bc814ad99447fcdb8811a43a6a827e8537b10d36 [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'
zhanyong.wan19eb9e92009-11-24 20:23:18 +0000343 r'.*error: no matching function for call to \'implicit_cast\('
344 r'long int&\)')
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
zhanyong.wan19eb9e92009-11-24 20:23:18 +0000347NULL into the right type. Use ReturnNull() instead.
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000348Note: 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
zhanyong.wan099e3b92009-12-09 17:58:37 +0000369 gcc_4_3_1_regex = (
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')
zhanyong.wanb8243162009-06-04 05:48:20 +0000375 diagnosis = _TTB_DIAGNOSIS % {'type': 'Foo'}
zhanyong.wan099e3b92009-12-09 17:58:37 +0000376 return (list(_GenericDiagnoser('TTB', 'Type in Template Base',
377 gcc_4_3_1_regex, diagnosis, msg)) +
378 list(_GenericDiagnoser('TTB', 'Type in Template Base',
379 gcc_4_4_0_regex, diagnosis, msg)))
zhanyong.wanb8243162009-06-04 05:48:20 +0000380
381
382def _TypeInTemplatedBaseDiagnoser2(msg):
383 """Diagnoses the TTB disease, given the error messages by gcc.
384
385 This version works when the type is used as the mock function's sole
386 parameter type.
387 """
388
zhanyong.wan099e3b92009-12-09 17:58:37 +0000389 regex = (_FILE_LINE_RE +
zhanyong.wanb8243162009-06-04 05:48:20 +0000390 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
391 r'.*error: template argument 1 is invalid\n')
392 return _GenericDiagnoser('TTB', 'Type in Template Base',
393 regex, _TTB_DIAGNOSIS, msg)
394
395
396def _TypeInTemplatedBaseDiagnoser3(msg):
397 """Diagnoses the TTB disease, given the error messages by gcc.
398
399 This version works when the type is used as a parameter of a mock
400 function that has multiple parameters.
401 """
402
403 regex = (r'error: expected `;\' before \'::\' token\n'
404 + _FILE_LINE_RE +
405 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
406 r'.*error: template argument 1 is invalid\n'
407 r'.*error: \'.+\' was not declared in this scope')
408 return _GenericDiagnoser('TTB', 'Type in Template Base',
409 regex, _TTB_DIAGNOSIS, msg)
410
411
zhanyong.wan16cf4732009-05-14 20:55:30 +0000412def _WrongMockMethodMacroDiagnoser(msg):
413 """Diagnoses the WMM disease, given the error messages by gcc."""
414
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000415 regex = (_FILE_LINE_RE +
zhanyong.wan16cf4732009-05-14 20:55:30 +0000416 r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
417 r'.*\n'
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000418 r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
419 diagnosis = """
zhanyong.wan16cf4732009-05-14 20:55:30 +0000420You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
421%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
422MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
zhanyong.wanb8243162009-06-04 05:48:20 +0000423 return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
zhanyong.wan16cf4732009-05-14 20:55:30 +0000424 regex, diagnosis, msg)
425
426
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000427def _WrongParenPositionDiagnoser(msg):
428 """Diagnoses the WPP disease, given the error messages by gcc."""
429
430 regex = (_FILE_LINE_RE +
431 r'error:.*testing::internal::MockSpec<.* has no member named \''
432 r'(?P<method>\w+)\'')
433 diagnosis = """
434The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
435".%(method)s". For example, you should write:
436 EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
437instead of:
438 EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
zhanyong.wanb8243162009-06-04 05:48:20 +0000439 return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000440 regex, diagnosis, msg)
441
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000442
shiqiane35fdd92008-12-10 05:08:54 +0000443_DIAGNOSERS = [
444 _IncompleteByReferenceArgumentDiagnoser,
445 _MockObjectPointerDiagnoser,
446 _NeedToReturnNothingDiagnoser,
447 _NeedToReturnReferenceDiagnoser,
448 _NeedToReturnSomethingDiagnoser,
zhanyong.wan5b95fa72009-01-27 22:28:45 +0000449 _NeedToUseReturnNullDiagnoser,
shiqiane35fdd92008-12-10 05:08:54 +0000450 _NeedToUseSymbolDiagnoser,
451 _OverloadedFunctionActionDiagnoser,
452 _OverloadedFunctionMatcherDiagnoser,
453 _OverloadedMethodActionDiagnoser1,
454 _OverloadedMethodActionDiagnoser2,
zhanyong.wanb8243162009-06-04 05:48:20 +0000455 _TypeInTemplatedBaseDiagnoser1,
456 _TypeInTemplatedBaseDiagnoser2,
457 _TypeInTemplatedBaseDiagnoser3,
zhanyong.wan16cf4732009-05-14 20:55:30 +0000458 _WrongMockMethodMacroDiagnoser,
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000459 _WrongParenPositionDiagnoser,
shiqiane35fdd92008-12-10 05:08:54 +0000460 ]
461
462
463def Diagnose(msg):
464 """Generates all possible diagnoses given the gcc error message."""
465
zhanyong.wan099e3b92009-12-09 17:58:37 +0000466 diagnoses = []
shiqiane35fdd92008-12-10 05:08:54 +0000467 for diagnoser in _DIAGNOSERS:
zhanyong.wan099e3b92009-12-09 17:58:37 +0000468 for diag in diagnoser(msg):
469 diagnosis = '[%s - %s]\n%s' % diag
470 if not diagnosis in diagnoses:
471 diagnoses.append(diagnosis)
472 return diagnoses
shiqiane35fdd92008-12-10 05:08:54 +0000473
474
475def main():
476 print ('Google Mock Doctor v%s - '
477 'diagnoses problems in code using Google Mock.' % _VERSION)
478
479 if sys.stdin.isatty():
480 print ('Please copy and paste the compiler errors here. Press c-D when '
481 'you are done:')
482 else:
483 print 'Waiting for compiler errors on stdin . . .'
484
485 msg = sys.stdin.read().strip()
zhanyong.wan099e3b92009-12-09 17:58:37 +0000486 diagnoses = Diagnose(msg)
shiqiane35fdd92008-12-10 05:08:54 +0000487 count = len(diagnoses)
488 if not count:
489 print '\nGcc complained:'
490 print '8<------------------------------------------------------------'
491 print msg
492 print '------------------------------------------------------------>8'
493 print """
494Uh-oh, I'm not smart enough to figure out what the problem is. :-(
495However...
496If you send your source code and gcc's error messages to
497googlemock@googlegroups.com, you can be helped and I can get smarter --
498win-win for us!"""
499 else:
500 print '------------------------------------------------------------'
501 print 'Your code appears to have the following',
502 if count > 1:
503 print '%s diseases:' % (count,)
504 else:
505 print 'disease:'
506 i = 0
507 for d in diagnoses:
508 i += 1
509 if count > 1:
510 print '\n#%s:' % (i,)
511 print d
512 print """
513How did I do? If you think I'm wrong or unhelpful, please send your
514source code and gcc's error messages to googlemock@googlegroups.com. Then
515you can be helped and I can get smarter -- I promise I won't be upset!"""
516
517
518if __name__ == '__main__':
519 main()