]> git.proxmox.com Git - ceph.git/blob - ceph/src/rapidjson/thirdparty/gtest/googlemock/scripts/gmock_doctor.py
buildsys: change download over to reef release
[ceph.git] / ceph / src / rapidjson / thirdparty / gtest / googlemock / scripts / gmock_doctor.py
1 #!/usr/bin/env python
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 compiler's errors in code using Google Mock to plain English."""
33
34 __author__ = 'wan@google.com (Zhanyong Wan)'
35
36 import re
37 import sys
38
39 _VERSION = '1.0.3'
40
41 _EMAIL = 'googlemock@googlegroups.com'
42
43 _COMMON_GMOCK_SYMBOLS = [
44 # Matchers
45 '_',
46 'A',
47 'AddressSatisfies',
48 'AllOf',
49 'An',
50 'AnyOf',
51 'ContainerEq',
52 'Contains',
53 'ContainsRegex',
54 'DoubleEq',
55 'ElementsAre',
56 'ElementsAreArray',
57 'EndsWith',
58 'Eq',
59 'Field',
60 'FloatEq',
61 'Ge',
62 'Gt',
63 'HasSubstr',
64 'IsInitializedProto',
65 'Le',
66 'Lt',
67 'MatcherCast',
68 'Matches',
69 'MatchesRegex',
70 'NanSensitiveDoubleEq',
71 'NanSensitiveFloatEq',
72 'Ne',
73 'Not',
74 'NotNull',
75 'Pointee',
76 'Property',
77 'Ref',
78 'ResultOf',
79 'SafeMatcherCast',
80 'StartsWith',
81 'StrCaseEq',
82 'StrCaseNe',
83 'StrEq',
84 'StrNe',
85 'Truly',
86 'TypedEq',
87 'Value',
88
89 # Actions
90 'Assign',
91 'ByRef',
92 'DeleteArg',
93 'DoAll',
94 'DoDefault',
95 'IgnoreResult',
96 'Invoke',
97 'InvokeArgument',
98 'InvokeWithoutArgs',
99 'Return',
100 'ReturnNew',
101 'ReturnNull',
102 'ReturnRef',
103 'SaveArg',
104 'SetArgReferee',
105 'SetArgPointee',
106 'SetArgumentPointee',
107 'SetArrayArgument',
108 'SetErrnoAndReturn',
109 'Throw',
110 'WithArg',
111 'WithArgs',
112 'WithoutArgs',
113
114 # Cardinalities
115 'AnyNumber',
116 'AtLeast',
117 'AtMost',
118 'Between',
119 'Exactly',
120
121 # Sequences
122 'InSequence',
123 'Sequence',
124
125 # Misc
126 'DefaultValue',
127 'Mock',
128 ]
129
130 # Regex for matching source file path and line number in the compiler's errors.
131 _GCC_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(\d+:)?\s+'
132 _CLANG_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(?P<column>\d+):\s+'
133 _CLANG_NON_GMOCK_FILE_LINE_RE = (
134 r'(?P<file>.*[/\\^](?!gmock-)[^/\\]+):(?P<line>\d+):(?P<column>\d+):\s+')
135
136
137 def _FindAllMatches(regex, s):
138 """Generates all matches of regex in string s."""
139
140 r = re.compile(regex)
141 return r.finditer(s)
142
143
144 def _GenericDiagnoser(short_name, long_name, diagnoses, msg):
145 """Diagnoses the given disease by pattern matching.
146
147 Can provide different diagnoses for different patterns.
148
149 Args:
150 short_name: Short name of the disease.
151 long_name: Long name of the disease.
152 diagnoses: A list of pairs (regex, pattern for formatting the diagnosis
153 for matching regex).
154 msg: Compiler's error messages.
155 Yields:
156 Tuples of the form
157 (short name of disease, long name of disease, diagnosis).
158 """
159 for regex, diagnosis in diagnoses:
160 if re.search(regex, msg):
161 diagnosis = '%(file)s:%(line)s:' + diagnosis
162 for m in _FindAllMatches(regex, msg):
163 yield (short_name, long_name, diagnosis % m.groupdict())
164
165
166 def _NeedToReturnReferenceDiagnoser(msg):
167 """Diagnoses the NRR disease, given the error messages by the compiler."""
168
169 gcc_regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
170 + _GCC_FILE_LINE_RE + r'instantiated from here\n'
171 r'.*gmock-actions\.h.*error: creating array with negative size')
172 clang_regex = (r'error:.*array.*negative.*\r?\n'
173 r'(.*\n)*?' +
174 _CLANG_NON_GMOCK_FILE_LINE_RE +
175 r'note: in instantiation of function template specialization '
176 r'\'testing::internal::ReturnAction<(?P<type>.*)>'
177 r'::operator Action<.*>\' requested here')
178 clang11_re = (r'use_ReturnRef_instead_of_Return_to_return_a_reference.*'
179 r'(.*\n)*?' + _CLANG_NON_GMOCK_FILE_LINE_RE)
180
181 diagnosis = """
182 You are using a Return() action in a function that returns a reference to
183 %(type)s. Please use ReturnRef() instead."""
184 return _GenericDiagnoser('NRR', 'Need to Return Reference',
185 [(clang_regex, diagnosis),
186 (clang11_re, diagnosis % {'type': 'a type'}),
187 (gcc_regex, diagnosis % {'type': 'a type'})],
188 msg)
189
190
191 def _NeedToReturnSomethingDiagnoser(msg):
192 """Diagnoses the NRS disease, given the error messages by the compiler."""
193
194 gcc_regex = (_GCC_FILE_LINE_RE + r'(instantiated from here\n.'
195 r'*gmock.*actions\.h.*error: void value not ignored)'
196 r'|(error: control reaches end of non-void function)')
197 clang_regex1 = (_CLANG_FILE_LINE_RE +
198 r'error: cannot initialize return object '
199 r'of type \'Result\' \(aka \'(?P<return_type>.*)\'\) '
200 r'with an rvalue of type \'void\'')
201 clang_regex2 = (_CLANG_FILE_LINE_RE +
202 r'error: cannot initialize return object '
203 r'of type \'(?P<return_type>.*)\' '
204 r'with an rvalue of type \'void\'')
205 diagnosis = """
206 You are using an action that returns void, but it needs to return
207 %(return_type)s. Please tell it *what* to return. Perhaps you can use
208 the pattern DoAll(some_action, Return(some_value))?"""
209 return _GenericDiagnoser(
210 'NRS',
211 'Need to Return Something',
212 [(gcc_regex, diagnosis % {'return_type': '*something*'}),
213 (clang_regex1, diagnosis),
214 (clang_regex2, diagnosis)],
215 msg)
216
217
218 def _NeedToReturnNothingDiagnoser(msg):
219 """Diagnoses the NRN disease, given the error messages by the compiler."""
220
221 gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
222 r'.*gmock-actions\.h.*error: instantiation of '
223 r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' '
224 r'as type \'void\'')
225 clang_regex1 = (r'error: field has incomplete type '
226 r'\'Result\' \(aka \'void\'\)(\r)?\n'
227 r'(.*\n)*?' +
228 _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
229 r'of function template specialization '
230 r'\'testing::internal::ReturnAction<(?P<return_type>.*)>'
231 r'::operator Action<void \(.*\)>\' requested here')
232 clang_regex2 = (r'error: field has incomplete type '
233 r'\'Result\' \(aka \'void\'\)(\r)?\n'
234 r'(.*\n)*?' +
235 _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
236 r'of function template specialization '
237 r'\'testing::internal::DoBothAction<.*>'
238 r'::operator Action<(?P<return_type>.*) \(.*\)>\' '
239 r'requested here')
240 diagnosis = """
241 You are using an action that returns %(return_type)s, but it needs to return
242 void. Please use a void-returning action instead.
243
244 All actions but the last in DoAll(...) must return void. Perhaps you need
245 to re-arrange the order of actions in a DoAll(), if you are using one?"""
246 return _GenericDiagnoser(
247 'NRN',
248 'Need to Return Nothing',
249 [(gcc_regex, diagnosis % {'return_type': '*something*'}),
250 (clang_regex1, diagnosis),
251 (clang_regex2, diagnosis)],
252 msg)
253
254
255 def _IncompleteByReferenceArgumentDiagnoser(msg):
256 """Diagnoses the IBRA disease, given the error messages by the compiler."""
257
258 gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
259 r'.*gtest-printers\.h.*error: invalid application of '
260 r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
261
262 clang_regex = (r'.*gtest-printers\.h.*error: invalid application of '
263 r'\'sizeof\' to an incomplete type '
264 r'\'(?P<type>.*)( const)?\'\r?\n'
265 r'(.*\n)*?' +
266 _CLANG_NON_GMOCK_FILE_LINE_RE +
267 r'note: in instantiation of member function '
268 r'\'testing::internal2::TypeWithoutFormatter<.*>::'
269 r'PrintValue\' requested here')
270 diagnosis = """
271 In order to mock this function, Google Mock needs to see the definition
272 of type "%(type)s" - declaration alone is not enough. Either #include
273 the header that defines it, or change the argument to be passed
274 by pointer."""
275
276 return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
277 [(gcc_regex, diagnosis),
278 (clang_regex, diagnosis)],
279 msg)
280
281
282 def _OverloadedFunctionMatcherDiagnoser(msg):
283 """Diagnoses the OFM disease, given the error messages by the compiler."""
284
285 gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
286 r'call to \'Truly\(<unresolved overloaded function type>\)')
287 clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function for '
288 r'call to \'Truly')
289 diagnosis = """
290 The argument you gave to Truly() is an overloaded function. Please tell
291 your compiler which overloaded version you want to use.
292
293 For example, if you want to use the version whose signature is
294 bool Foo(int n);
295 you should write
296 Truly(static_cast<bool (*)(int n)>(Foo))"""
297 return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
298 [(gcc_regex, diagnosis),
299 (clang_regex, diagnosis)],
300 msg)
301
302
303 def _OverloadedFunctionActionDiagnoser(msg):
304 """Diagnoses the OFA disease, given the error messages by the compiler."""
305
306 gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for call to '
307 r'\'Invoke\(<unresolved overloaded function type>')
308 clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching '
309 r'function for call to \'Invoke\'\r?\n'
310 r'(.*\n)*?'
311 r'.*\bgmock-generated-actions\.h:\d+:\d+:\s+'
312 r'note: candidate template ignored:\s+'
313 r'couldn\'t infer template argument \'FunctionImpl\'')
314 diagnosis = """
315 Function you are passing to Invoke is overloaded. Please tell your compiler
316 which overloaded version you want to use.
317
318 For example, if you want to use the version whose signature is
319 bool MyFunction(int n, double x);
320 you should write something like
321 Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
322 return _GenericDiagnoser('OFA', 'Overloaded Function Action',
323 [(gcc_regex, diagnosis),
324 (clang_regex, diagnosis)],
325 msg)
326
327
328 def _OverloadedMethodActionDiagnoser(msg):
329 """Diagnoses the OMA disease, given the error messages by the compiler."""
330
331 gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
332 r'call to \'Invoke\(.+, <unresolved overloaded function '
333 r'type>\)')
334 clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function '
335 r'for call to \'Invoke\'\r?\n'
336 r'(.*\n)*?'
337 r'.*\bgmock-generated-actions\.h:\d+:\d+: '
338 r'note: candidate function template not viable: '
339 r'requires .*, but 2 (arguments )?were provided')
340 diagnosis = """
341 The second argument you gave to Invoke() is an overloaded method. Please
342 tell your compiler which overloaded version you want to use.
343
344 For example, if you want to use the version whose signature is
345 class Foo {
346 ...
347 bool Bar(int n, double x);
348 };
349 you should write something like
350 Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
351 return _GenericDiagnoser('OMA', 'Overloaded Method Action',
352 [(gcc_regex, diagnosis),
353 (clang_regex, diagnosis)],
354 msg)
355
356
357 def _MockObjectPointerDiagnoser(msg):
358 """Diagnoses the MOP disease, given the error messages by the compiler."""
359
360 gcc_regex = (_GCC_FILE_LINE_RE + r'error: request for member '
361 r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
362 r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
363 clang_regex = (_CLANG_FILE_LINE_RE + r'error: member reference type '
364 r'\'(?P<class_name>.*?) *\' is a pointer; '
365 r'(did you mean|maybe you meant) to use \'->\'\?')
366 diagnosis = """
367 The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
368 not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
369 '%(mock_object)s' as your first argument.
370
371 For example, given the mock class:
372
373 class %(class_name)s : public ... {
374 ...
375 MOCK_METHOD0(%(method)s, ...);
376 };
377
378 and the following mock instance:
379
380 %(class_name)s* mock_ptr = ...
381
382 you should use the EXPECT_CALL like this:
383
384 EXPECT_CALL(*mock_ptr, %(method)s(...));"""
385
386 return _GenericDiagnoser(
387 'MOP',
388 'Mock Object Pointer',
389 [(gcc_regex, diagnosis),
390 (clang_regex, diagnosis % {'mock_object': 'mock_object',
391 'method': 'method',
392 'class_name': '%(class_name)s'})],
393 msg)
394
395
396 def _NeedToUseSymbolDiagnoser(msg):
397 """Diagnoses the NUS disease, given the error messages by the compiler."""
398
399 gcc_regex = (_GCC_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
400 r'(was not declared in this scope|has not been declared)')
401 clang_regex = (_CLANG_FILE_LINE_RE +
402 r'error: (use of undeclared identifier|unknown type name|'
403 r'no template named) \'(?P<symbol>[^\']+)\'')
404 diagnosis = """
405 '%(symbol)s' is defined by Google Mock in the testing namespace.
406 Did you forget to write
407 using testing::%(symbol)s;
408 ?"""
409 for m in (list(_FindAllMatches(gcc_regex, msg)) +
410 list(_FindAllMatches(clang_regex, msg))):
411 symbol = m.groupdict()['symbol']
412 if symbol in _COMMON_GMOCK_SYMBOLS:
413 yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
414
415
416 def _NeedToUseReturnNullDiagnoser(msg):
417 """Diagnoses the NRNULL disease, given the error messages by the compiler."""
418
419 gcc_regex = ('instantiated from \'testing::internal::ReturnAction<R>'
420 '::operator testing::Action<Func>\(\) const.*\n' +
421 _GCC_FILE_LINE_RE + r'instantiated from here\n'
422 r'.*error: no matching function for call to \'ImplicitCast_\('
423 r'(:?long )?int&\)')
424 clang_regex = (r'\bgmock-actions.h:.* error: no matching function for '
425 r'call to \'ImplicitCast_\'\r?\n'
426 r'(.*\n)*?' +
427 _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
428 r'of function template specialization '
429 r'\'testing::internal::ReturnAction<(int|long)>::operator '
430 r'Action<(?P<type>.*)\(\)>\' requested here')
431 diagnosis = """
432 You are probably calling Return(NULL) and the compiler isn't sure how to turn
433 NULL into %(type)s. Use ReturnNull() instead.
434 Note: the line number may be off; please fix all instances of Return(NULL)."""
435 return _GenericDiagnoser(
436 'NRNULL', 'Need to use ReturnNull',
437 [(clang_regex, diagnosis),
438 (gcc_regex, diagnosis % {'type': 'the right type'})],
439 msg)
440
441
442 def _TypeInTemplatedBaseDiagnoser(msg):
443 """Diagnoses the TTB disease, given the error messages by the compiler."""
444
445 # This version works when the type is used as the mock function's return
446 # type.
447 gcc_4_3_1_regex_type_in_retval = (
448 r'In member function \'int .*\n' + _GCC_FILE_LINE_RE +
449 r'error: a function call cannot appear in a constant-expression')
450 gcc_4_4_0_regex_type_in_retval = (
451 r'error: a function call cannot appear in a constant-expression'
452 + _GCC_FILE_LINE_RE + r'error: template argument 1 is invalid\n')
453 # This version works when the type is used as the mock function's sole
454 # parameter type.
455 gcc_regex_type_of_sole_param = (
456 _GCC_FILE_LINE_RE +
457 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
458 r'.*error: template argument 1 is invalid\n')
459 # This version works when the type is used as a parameter of a mock
460 # function that has multiple parameters.
461 gcc_regex_type_of_a_param = (
462 r'error: expected `;\' before \'::\' token\n'
463 + _GCC_FILE_LINE_RE +
464 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
465 r'.*error: template argument 1 is invalid\n'
466 r'.*error: \'.+\' was not declared in this scope')
467 clang_regex_type_of_retval_or_sole_param = (
468 _CLANG_FILE_LINE_RE +
469 r'error: use of undeclared identifier \'(?P<type>.*)\'\n'
470 r'(.*\n)*?'
471 r'(?P=file):(?P=line):\d+: error: '
472 r'non-friend class member \'Result\' cannot have a qualified name'
473 )
474 clang_regex_type_of_a_param = (
475 _CLANG_FILE_LINE_RE +
476 r'error: C\+\+ requires a type specifier for all declarations\n'
477 r'(.*\n)*?'
478 r'(?P=file):(?P=line):(?P=column): error: '
479 r'C\+\+ requires a type specifier for all declarations'
480 )
481 clang_regex_unknown_type = (
482 _CLANG_FILE_LINE_RE +
483 r'error: unknown type name \'(?P<type>[^\']+)\''
484 )
485
486 diagnosis = """
487 In a mock class template, types or typedefs defined in the base class
488 template are *not* automatically visible. This is how C++ works. Before
489 you can use a type or typedef named %(type)s defined in base class Base<T>, you
490 need to make it visible. One way to do it is:
491
492 typedef typename Base<T>::%(type)s %(type)s;"""
493
494 for diag in _GenericDiagnoser(
495 'TTB', 'Type in Template Base',
496 [(gcc_4_3_1_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
497 (gcc_4_4_0_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
498 (gcc_regex_type_of_sole_param, diagnosis),
499 (gcc_regex_type_of_a_param, diagnosis),
500 (clang_regex_type_of_retval_or_sole_param, diagnosis),
501 (clang_regex_type_of_a_param, diagnosis % {'type': 'Foo'})],
502 msg):
503 yield diag
504 # Avoid overlap with the NUS pattern.
505 for m in _FindAllMatches(clang_regex_unknown_type, msg):
506 type_ = m.groupdict()['type']
507 if type_ not in _COMMON_GMOCK_SYMBOLS:
508 yield ('TTB', 'Type in Template Base', diagnosis % m.groupdict())
509
510
511 def _WrongMockMethodMacroDiagnoser(msg):
512 """Diagnoses the WMM disease, given the error messages by the compiler."""
513
514 gcc_regex = (_GCC_FILE_LINE_RE +
515 r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
516 r'.*\n'
517 r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
518 clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
519 r'error:.*array.*negative.*r?\n'
520 r'(.*\n)*?'
521 r'(?P=file):(?P=line):(?P=column): error: too few arguments '
522 r'to function call, expected (?P<args>\d+), '
523 r'have (?P<wrong_args>\d+)')
524 clang11_re = (_CLANG_NON_GMOCK_FILE_LINE_RE +
525 r'.*this_method_does_not_take_'
526 r'(?P<wrong_args>\d+)_argument.*')
527 diagnosis = """
528 You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
529 %(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
530 MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
531 return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
532 [(gcc_regex, diagnosis),
533 (clang11_re, diagnosis % {'wrong_args': 'm',
534 'args': 'n'}),
535 (clang_regex, diagnosis)],
536 msg)
537
538
539 def _WrongParenPositionDiagnoser(msg):
540 """Diagnoses the WPP disease, given the error messages by the compiler."""
541
542 gcc_regex = (_GCC_FILE_LINE_RE +
543 r'error:.*testing::internal::MockSpec<.* has no member named \''
544 r'(?P<method>\w+)\'')
545 clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
546 r'error: no member named \'(?P<method>\w+)\' in '
547 r'\'testing::internal::MockSpec<.*>\'')
548 diagnosis = """
549 The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
550 ".%(method)s". For example, you should write:
551 EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
552 instead of:
553 EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
554 return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
555 [(gcc_regex, diagnosis),
556 (clang_regex, diagnosis)],
557 msg)
558
559
560 _DIAGNOSERS = [
561 _IncompleteByReferenceArgumentDiagnoser,
562 _MockObjectPointerDiagnoser,
563 _NeedToReturnNothingDiagnoser,
564 _NeedToReturnReferenceDiagnoser,
565 _NeedToReturnSomethingDiagnoser,
566 _NeedToUseReturnNullDiagnoser,
567 _NeedToUseSymbolDiagnoser,
568 _OverloadedFunctionActionDiagnoser,
569 _OverloadedFunctionMatcherDiagnoser,
570 _OverloadedMethodActionDiagnoser,
571 _TypeInTemplatedBaseDiagnoser,
572 _WrongMockMethodMacroDiagnoser,
573 _WrongParenPositionDiagnoser,
574 ]
575
576
577 def Diagnose(msg):
578 """Generates all possible diagnoses given the compiler error message."""
579
580 msg = re.sub(r'\x1b\[[^m]*m', '', msg) # Strips all color formatting.
581 # Assuming the string is using the UTF-8 encoding, replaces the left and
582 # the right single quote characters with apostrophes.
583 msg = re.sub(r'(\xe2\x80\x98|\xe2\x80\x99)', "'", msg)
584
585 diagnoses = []
586 for diagnoser in _DIAGNOSERS:
587 for diag in diagnoser(msg):
588 diagnosis = '[%s - %s]\n%s' % diag
589 if not diagnosis in diagnoses:
590 diagnoses.append(diagnosis)
591 return diagnoses
592
593
594 def main():
595 print ('Google Mock Doctor v%s - '
596 'diagnoses problems in code using Google Mock.' % _VERSION)
597
598 if sys.stdin.isatty():
599 print ('Please copy and paste the compiler errors here. Press c-D when '
600 'you are done:')
601 else:
602 print ('Waiting for compiler errors on stdin . . .')
603
604 msg = sys.stdin.read().strip()
605 diagnoses = Diagnose(msg)
606 count = len(diagnoses)
607 if not count:
608 print ("""
609 Your compiler complained:
610 8<------------------------------------------------------------
611 %s
612 ------------------------------------------------------------>8
613
614 Uh-oh, I'm not smart enough to figure out what the problem is. :-(
615 However...
616 If you send your source code and the compiler's error messages to
617 %s, you can be helped and I can get smarter --
618 win-win for us!""" % (msg, _EMAIL))
619 else:
620 print ('------------------------------------------------------------')
621 print ('Your code appears to have the following',)
622 if count > 1:
623 print ('%s diseases:' % (count,))
624 else:
625 print ('disease:')
626 i = 0
627 for d in diagnoses:
628 i += 1
629 if count > 1:
630 print ('\n#%s:' % (i,))
631 print (d)
632 print ("""
633 How did I do? If you think I'm wrong or unhelpful, please send your
634 source code and the compiler's error messages to %s.
635 Then you can be helped and I can get smarter -- I promise I won't be upset!""" %
636 _EMAIL)
637
638
639 if __name__ == '__main__':
640 main()