OpenCores
URL https://opencores.org/ocsvn/s80186/s80186/trunk

Subversion Repositories s80186

[/] [s80186/] [trunk/] [vendor/] [googletest/] [googlemock/] [scripts/] [gmock_doctor.py] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
#!/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()

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.