File indexing completed on 2025-08-06 08:19:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 """Converts compiler's errors in code using Google Mock to plain English."""
0033
0034 __author__ = 'wan@google.com (Zhanyong Wan)'
0035
0036 import re
0037 import sys
0038
0039 _VERSION = '1.0.3'
0040
0041 _EMAIL = 'googlemock@googlegroups.com'
0042
0043 _COMMON_GMOCK_SYMBOLS = [
0044
0045 '_',
0046 'A',
0047 'AddressSatisfies',
0048 'AllOf',
0049 'An',
0050 'AnyOf',
0051 'ContainerEq',
0052 'Contains',
0053 'ContainsRegex',
0054 'DoubleEq',
0055 'ElementsAre',
0056 'ElementsAreArray',
0057 'EndsWith',
0058 'Eq',
0059 'Field',
0060 'FloatEq',
0061 'Ge',
0062 'Gt',
0063 'HasSubstr',
0064 'IsInitializedProto',
0065 'Le',
0066 'Lt',
0067 'MatcherCast',
0068 'Matches',
0069 'MatchesRegex',
0070 'NanSensitiveDoubleEq',
0071 'NanSensitiveFloatEq',
0072 'Ne',
0073 'Not',
0074 'NotNull',
0075 'Pointee',
0076 'Property',
0077 'Ref',
0078 'ResultOf',
0079 'SafeMatcherCast',
0080 'StartsWith',
0081 'StrCaseEq',
0082 'StrCaseNe',
0083 'StrEq',
0084 'StrNe',
0085 'Truly',
0086 'TypedEq',
0087 'Value',
0088
0089
0090 'Assign',
0091 'ByRef',
0092 'DeleteArg',
0093 'DoAll',
0094 'DoDefault',
0095 'IgnoreResult',
0096 'Invoke',
0097 'InvokeArgument',
0098 'InvokeWithoutArgs',
0099 'Return',
0100 'ReturnNew',
0101 'ReturnNull',
0102 'ReturnRef',
0103 'SaveArg',
0104 'SetArgReferee',
0105 'SetArgPointee',
0106 'SetArgumentPointee',
0107 'SetArrayArgument',
0108 'SetErrnoAndReturn',
0109 'Throw',
0110 'WithArg',
0111 'WithArgs',
0112 'WithoutArgs',
0113
0114
0115 'AnyNumber',
0116 'AtLeast',
0117 'AtMost',
0118 'Between',
0119 'Exactly',
0120
0121
0122 'InSequence',
0123 'Sequence',
0124
0125
0126 'DefaultValue',
0127 'Mock',
0128 ]
0129
0130
0131 _GCC_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(\d+:)?\s+'
0132 _CLANG_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(?P<column>\d+):\s+'
0133 _CLANG_NON_GMOCK_FILE_LINE_RE = (
0134 r'(?P<file>.*[/\\^](?!gmock-)[^/\\]+):(?P<line>\d+):(?P<column>\d+):\s+')
0135
0136
0137 def _FindAllMatches(regex, s):
0138 """Generates all matches of regex in string s."""
0139
0140 r = re.compile(regex)
0141 return r.finditer(s)
0142
0143
0144 def _GenericDiagnoser(short_name, long_name, diagnoses, msg):
0145 """Diagnoses the given disease by pattern matching.
0146
0147 Can provide different diagnoses for different patterns.
0148
0149 Args:
0150 short_name: Short name of the disease.
0151 long_name: Long name of the disease.
0152 diagnoses: A list of pairs (regex, pattern for formatting the diagnosis
0153 for matching regex).
0154 msg: Compiler's error messages.
0155 Yields:
0156 Tuples of the form
0157 (short name of disease, long name of disease, diagnosis).
0158 """
0159 for regex, diagnosis in diagnoses:
0160 if re.search(regex, msg):
0161 diagnosis = '%(file)s:%(line)s:' + diagnosis
0162 for m in _FindAllMatches(regex, msg):
0163 yield (short_name, long_name, diagnosis % m.groupdict())
0164
0165
0166 def _NeedToReturnReferenceDiagnoser(msg):
0167 """Diagnoses the NRR disease, given the error messages by the compiler."""
0168
0169 gcc_regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
0170 + _GCC_FILE_LINE_RE + r'instantiated from here\n'
0171 r'.*gmock-actions\.h.*error: creating array with negative size')
0172 clang_regex = (r'error:.*array.*negative.*\r?\n'
0173 r'(.*\n)*?' +
0174 _CLANG_NON_GMOCK_FILE_LINE_RE +
0175 r'note: in instantiation of function template specialization '
0176 r'\'testing::internal::ReturnAction<(?P<type>.*)>'
0177 r'::operator Action<.*>\' requested here')
0178 clang11_re = (r'use_ReturnRef_instead_of_Return_to_return_a_reference.*'
0179 r'(.*\n)*?' + _CLANG_NON_GMOCK_FILE_LINE_RE)
0180
0181 diagnosis = """
0182 You are using a Return() action in a function that returns a reference to
0183 %(type)s. Please use ReturnRef() instead."""
0184 return _GenericDiagnoser('NRR', 'Need to Return Reference',
0185 [(clang_regex, diagnosis),
0186 (clang11_re, diagnosis % {'type': 'a type'}),
0187 (gcc_regex, diagnosis % {'type': 'a type'})],
0188 msg)
0189
0190
0191 def _NeedToReturnSomethingDiagnoser(msg):
0192 """Diagnoses the NRS disease, given the error messages by the compiler."""
0193
0194 gcc_regex = (_GCC_FILE_LINE_RE + r'(instantiated from here\n.'
0195 r'*gmock.*actions\.h.*error: void value not ignored)'
0196 r'|(error: control reaches end of non-void function)')
0197 clang_regex1 = (_CLANG_FILE_LINE_RE +
0198 r'error: cannot initialize return object '
0199 r'of type \'Result\' \(aka \'(?P<return_type>.*)\'\) '
0200 r'with an rvalue of type \'void\'')
0201 clang_regex2 = (_CLANG_FILE_LINE_RE +
0202 r'error: cannot initialize return object '
0203 r'of type \'(?P<return_type>.*)\' '
0204 r'with an rvalue of type \'void\'')
0205 diagnosis = """
0206 You are using an action that returns void, but it needs to return
0207 %(return_type)s. Please tell it *what* to return. Perhaps you can use
0208 the pattern DoAll(some_action, Return(some_value))?"""
0209 return _GenericDiagnoser(
0210 'NRS',
0211 'Need to Return Something',
0212 [(gcc_regex, diagnosis % {'return_type': '*something*'}),
0213 (clang_regex1, diagnosis),
0214 (clang_regex2, diagnosis)],
0215 msg)
0216
0217
0218 def _NeedToReturnNothingDiagnoser(msg):
0219 """Diagnoses the NRN disease, given the error messages by the compiler."""
0220
0221 gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
0222 r'.*gmock-actions\.h.*error: instantiation of '
0223 r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' '
0224 r'as type \'void\'')
0225 clang_regex1 = (r'error: field has incomplete type '
0226 r'\'Result\' \(aka \'void\'\)(\r)?\n'
0227 r'(.*\n)*?' +
0228 _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
0229 r'of function template specialization '
0230 r'\'testing::internal::ReturnAction<(?P<return_type>.*)>'
0231 r'::operator Action<void \(.*\)>\' requested here')
0232 clang_regex2 = (r'error: field has incomplete type '
0233 r'\'Result\' \(aka \'void\'\)(\r)?\n'
0234 r'(.*\n)*?' +
0235 _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
0236 r'of function template specialization '
0237 r'\'testing::internal::DoBothAction<.*>'
0238 r'::operator Action<(?P<return_type>.*) \(.*\)>\' '
0239 r'requested here')
0240 diagnosis = """
0241 You are using an action that returns %(return_type)s, but it needs to return
0242 void. Please use a void-returning action instead.
0243
0244 All actions but the last in DoAll(...) must return void. Perhaps you need
0245 to re-arrange the order of actions in a DoAll(), if you are using one?"""
0246 return _GenericDiagnoser(
0247 'NRN',
0248 'Need to Return Nothing',
0249 [(gcc_regex, diagnosis % {'return_type': '*something*'}),
0250 (clang_regex1, diagnosis),
0251 (clang_regex2, diagnosis)],
0252 msg)
0253
0254
0255 def _IncompleteByReferenceArgumentDiagnoser(msg):
0256 """Diagnoses the IBRA disease, given the error messages by the compiler."""
0257
0258 gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
0259 r'.*gtest-printers\.h.*error: invalid application of '
0260 r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
0261
0262 clang_regex = (r'.*gtest-printers\.h.*error: invalid application of '
0263 r'\'sizeof\' to an incomplete type '
0264 r'\'(?P<type>.*)( const)?\'\r?\n'
0265 r'(.*\n)*?' +
0266 _CLANG_NON_GMOCK_FILE_LINE_RE +
0267 r'note: in instantiation of member function '
0268 r'\'testing::internal2::TypeWithoutFormatter<.*>::'
0269 r'PrintValue\' requested here')
0270 diagnosis = """
0271 In order to mock this function, Google Mock needs to see the definition
0272 of type "%(type)s" - declaration alone is not enough. Either #include
0273 the header that defines it, or change the argument to be passed
0274 by pointer."""
0275
0276 return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
0277 [(gcc_regex, diagnosis),
0278 (clang_regex, diagnosis)],
0279 msg)
0280
0281
0282 def _OverloadedFunctionMatcherDiagnoser(msg):
0283 """Diagnoses the OFM disease, given the error messages by the compiler."""
0284
0285 gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
0286 r'call to \'Truly\(<unresolved overloaded function type>\)')
0287 clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function for '
0288 r'call to \'Truly')
0289 diagnosis = """
0290 The argument you gave to Truly() is an overloaded function. Please tell
0291 your compiler which overloaded version you want to use.
0292
0293 For example, if you want to use the version whose signature is
0294 bool Foo(int n);
0295 you should write
0296 Truly(static_cast<bool (*)(int n)>(Foo))"""
0297 return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
0298 [(gcc_regex, diagnosis),
0299 (clang_regex, diagnosis)],
0300 msg)
0301
0302
0303 def _OverloadedFunctionActionDiagnoser(msg):
0304 """Diagnoses the OFA disease, given the error messages by the compiler."""
0305
0306 gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for call to '
0307 r'\'Invoke\(<unresolved overloaded function type>')
0308 clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching '
0309 r'function for call to \'Invoke\'\r?\n'
0310 r'(.*\n)*?'
0311 r'.*\bgmock-generated-actions\.h:\d+:\d+:\s+'
0312 r'note: candidate template ignored:\s+'
0313 r'couldn\'t infer template argument \'FunctionImpl\'')
0314 diagnosis = """
0315 Function you are passing to Invoke is overloaded. Please tell your compiler
0316 which overloaded version you want to use.
0317
0318 For example, if you want to use the version whose signature is
0319 bool MyFunction(int n, double x);
0320 you should write something like
0321 Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
0322 return _GenericDiagnoser('OFA', 'Overloaded Function Action',
0323 [(gcc_regex, diagnosis),
0324 (clang_regex, diagnosis)],
0325 msg)
0326
0327
0328 def _OverloadedMethodActionDiagnoser(msg):
0329 """Diagnoses the OMA disease, given the error messages by the compiler."""
0330
0331 gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
0332 r'call to \'Invoke\(.+, <unresolved overloaded function '
0333 r'type>\)')
0334 clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function '
0335 r'for call to \'Invoke\'\r?\n'
0336 r'(.*\n)*?'
0337 r'.*\bgmock-generated-actions\.h:\d+:\d+: '
0338 r'note: candidate function template not viable: '
0339 r'requires .*, but 2 (arguments )?were provided')
0340 diagnosis = """
0341 The second argument you gave to Invoke() is an overloaded method. Please
0342 tell your compiler which overloaded version you want to use.
0343
0344 For example, if you want to use the version whose signature is
0345 class Foo {
0346 ...
0347 bool Bar(int n, double x);
0348 };
0349 you should write something like
0350 Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
0351 return _GenericDiagnoser('OMA', 'Overloaded Method Action',
0352 [(gcc_regex, diagnosis),
0353 (clang_regex, diagnosis)],
0354 msg)
0355
0356
0357 def _MockObjectPointerDiagnoser(msg):
0358 """Diagnoses the MOP disease, given the error messages by the compiler."""
0359
0360 gcc_regex = (_GCC_FILE_LINE_RE + r'error: request for member '
0361 r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
0362 r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
0363 clang_regex = (_CLANG_FILE_LINE_RE + r'error: member reference type '
0364 r'\'(?P<class_name>.*?) *\' is a pointer; '
0365 r'(did you mean|maybe you meant) to use \'->\'\?')
0366 diagnosis = """
0367 The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
0368 not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
0369 '%(mock_object)s' as your first argument.
0370
0371 For example, given the mock class:
0372
0373 class %(class_name)s : public ... {
0374 ...
0375 MOCK_METHOD0(%(method)s, ...);
0376 };
0377
0378 and the following mock instance:
0379
0380 %(class_name)s* mock_ptr = ...
0381
0382 you should use the EXPECT_CALL like this:
0383
0384 EXPECT_CALL(*mock_ptr, %(method)s(...));"""
0385
0386 return _GenericDiagnoser(
0387 'MOP',
0388 'Mock Object Pointer',
0389 [(gcc_regex, diagnosis),
0390 (clang_regex, diagnosis % {'mock_object': 'mock_object',
0391 'method': 'method',
0392 'class_name': '%(class_name)s'})],
0393 msg)
0394
0395
0396 def _NeedToUseSymbolDiagnoser(msg):
0397 """Diagnoses the NUS disease, given the error messages by the compiler."""
0398
0399 gcc_regex = (_GCC_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
0400 r'(was not declared in this scope|has not been declared)')
0401 clang_regex = (_CLANG_FILE_LINE_RE +
0402 r'error: (use of undeclared identifier|unknown type name|'
0403 r'no template named) \'(?P<symbol>[^\']+)\'')
0404 diagnosis = """
0405 '%(symbol)s' is defined by Google Mock in the testing namespace.
0406 Did you forget to write
0407 using testing::%(symbol)s;
0408 ?"""
0409 for m in (list(_FindAllMatches(gcc_regex, msg)) +
0410 list(_FindAllMatches(clang_regex, msg))):
0411 symbol = m.groupdict()['symbol']
0412 if symbol in _COMMON_GMOCK_SYMBOLS:
0413 yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
0414
0415
0416 def _NeedToUseReturnNullDiagnoser(msg):
0417 """Diagnoses the NRNULL disease, given the error messages by the compiler."""
0418
0419 gcc_regex = ('instantiated from \'testing::internal::ReturnAction<R>'
0420 '::operator testing::Action<Func>\(\) const.*\n' +
0421 _GCC_FILE_LINE_RE + r'instantiated from here\n'
0422 r'.*error: no matching function for call to \'ImplicitCast_\('
0423 r'(:?long )?int&\)')
0424 clang_regex = (r'\bgmock-actions.h:.* error: no matching function for '
0425 r'call to \'ImplicitCast_\'\r?\n'
0426 r'(.*\n)*?' +
0427 _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
0428 r'of function template specialization '
0429 r'\'testing::internal::ReturnAction<(int|long)>::operator '
0430 r'Action<(?P<type>.*)\(\)>\' requested here')
0431 diagnosis = """
0432 You are probably calling Return(NULL) and the compiler isn't sure how to turn
0433 NULL into %(type)s. Use ReturnNull() instead.
0434 Note: the line number may be off; please fix all instances of Return(NULL)."""
0435 return _GenericDiagnoser(
0436 'NRNULL', 'Need to use ReturnNull',
0437 [(clang_regex, diagnosis),
0438 (gcc_regex, diagnosis % {'type': 'the right type'})],
0439 msg)
0440
0441
0442 def _TypeInTemplatedBaseDiagnoser(msg):
0443 """Diagnoses the TTB disease, given the error messages by the compiler."""
0444
0445
0446
0447 gcc_4_3_1_regex_type_in_retval = (
0448 r'In member function \'int .*\n' + _GCC_FILE_LINE_RE +
0449 r'error: a function call cannot appear in a constant-expression')
0450 gcc_4_4_0_regex_type_in_retval = (
0451 r'error: a function call cannot appear in a constant-expression'
0452 + _GCC_FILE_LINE_RE + r'error: template argument 1 is invalid\n')
0453
0454
0455 gcc_regex_type_of_sole_param = (
0456 _GCC_FILE_LINE_RE +
0457 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
0458 r'.*error: template argument 1 is invalid\n')
0459
0460
0461 gcc_regex_type_of_a_param = (
0462 r'error: expected `;\' before \'::\' token\n'
0463 + _GCC_FILE_LINE_RE +
0464 r'error: \'(?P<type>.+)\' was not declared in this scope\n'
0465 r'.*error: template argument 1 is invalid\n'
0466 r'.*error: \'.+\' was not declared in this scope')
0467 clang_regex_type_of_retval_or_sole_param = (
0468 _CLANG_FILE_LINE_RE +
0469 r'error: use of undeclared identifier \'(?P<type>.*)\'\n'
0470 r'(.*\n)*?'
0471 r'(?P=file):(?P=line):\d+: error: '
0472 r'non-friend class member \'Result\' cannot have a qualified name'
0473 )
0474 clang_regex_type_of_a_param = (
0475 _CLANG_FILE_LINE_RE +
0476 r'error: C\+\+ requires a type specifier for all declarations\n'
0477 r'(.*\n)*?'
0478 r'(?P=file):(?P=line):(?P=column): error: '
0479 r'C\+\+ requires a type specifier for all declarations'
0480 )
0481 clang_regex_unknown_type = (
0482 _CLANG_FILE_LINE_RE +
0483 r'error: unknown type name \'(?P<type>[^\']+)\''
0484 )
0485
0486 diagnosis = """
0487 In a mock class template, types or typedefs defined in the base class
0488 template are *not* automatically visible. This is how C++ works. Before
0489 you can use a type or typedef named %(type)s defined in base class Base<T>, you
0490 need to make it visible. One way to do it is:
0491
0492 typedef typename Base<T>::%(type)s %(type)s;"""
0493
0494 for diag in _GenericDiagnoser(
0495 'TTB', 'Type in Template Base',
0496 [(gcc_4_3_1_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
0497 (gcc_4_4_0_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
0498 (gcc_regex_type_of_sole_param, diagnosis),
0499 (gcc_regex_type_of_a_param, diagnosis),
0500 (clang_regex_type_of_retval_or_sole_param, diagnosis),
0501 (clang_regex_type_of_a_param, diagnosis % {'type': 'Foo'})],
0502 msg):
0503 yield diag
0504
0505 for m in _FindAllMatches(clang_regex_unknown_type, msg):
0506 type_ = m.groupdict()['type']
0507 if type_ not in _COMMON_GMOCK_SYMBOLS:
0508 yield ('TTB', 'Type in Template Base', diagnosis % m.groupdict())
0509
0510
0511 def _WrongMockMethodMacroDiagnoser(msg):
0512 """Diagnoses the WMM disease, given the error messages by the compiler."""
0513
0514 gcc_regex = (_GCC_FILE_LINE_RE +
0515 r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
0516 r'.*\n'
0517 r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
0518 clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
0519 r'error:.*array.*negative.*r?\n'
0520 r'(.*\n)*?'
0521 r'(?P=file):(?P=line):(?P=column): error: too few arguments '
0522 r'to function call, expected (?P<args>\d+), '
0523 r'have (?P<wrong_args>\d+)')
0524 clang11_re = (_CLANG_NON_GMOCK_FILE_LINE_RE +
0525 r'.*this_method_does_not_take_'
0526 r'(?P<wrong_args>\d+)_argument.*')
0527 diagnosis = """
0528 You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
0529 %(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
0530 MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
0531 return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
0532 [(gcc_regex, diagnosis),
0533 (clang11_re, diagnosis % {'wrong_args': 'm',
0534 'args': 'n'}),
0535 (clang_regex, diagnosis)],
0536 msg)
0537
0538
0539 def _WrongParenPositionDiagnoser(msg):
0540 """Diagnoses the WPP disease, given the error messages by the compiler."""
0541
0542 gcc_regex = (_GCC_FILE_LINE_RE +
0543 r'error:.*testing::internal::MockSpec<.* has no member named \''
0544 r'(?P<method>\w+)\'')
0545 clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
0546 r'error: no member named \'(?P<method>\w+)\' in '
0547 r'\'testing::internal::MockSpec<.*>\'')
0548 diagnosis = """
0549 The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
0550 ".%(method)s". For example, you should write:
0551 EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
0552 instead of:
0553 EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
0554 return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
0555 [(gcc_regex, diagnosis),
0556 (clang_regex, diagnosis)],
0557 msg)
0558
0559
0560 _DIAGNOSERS = [
0561 _IncompleteByReferenceArgumentDiagnoser,
0562 _MockObjectPointerDiagnoser,
0563 _NeedToReturnNothingDiagnoser,
0564 _NeedToReturnReferenceDiagnoser,
0565 _NeedToReturnSomethingDiagnoser,
0566 _NeedToUseReturnNullDiagnoser,
0567 _NeedToUseSymbolDiagnoser,
0568 _OverloadedFunctionActionDiagnoser,
0569 _OverloadedFunctionMatcherDiagnoser,
0570 _OverloadedMethodActionDiagnoser,
0571 _TypeInTemplatedBaseDiagnoser,
0572 _WrongMockMethodMacroDiagnoser,
0573 _WrongParenPositionDiagnoser,
0574 ]
0575
0576
0577 def Diagnose(msg):
0578 """Generates all possible diagnoses given the compiler error message."""
0579
0580 msg = re.sub(r'\x1b\[[^m]*m', '', msg)
0581
0582
0583 msg = re.sub(r'(\xe2\x80\x98|\xe2\x80\x99)', "'", msg)
0584
0585 diagnoses = []
0586 for diagnoser in _DIAGNOSERS:
0587 for diag in diagnoser(msg):
0588 diagnosis = '[%s - %s]\n%s' % diag
0589 if not diagnosis in diagnoses:
0590 diagnoses.append(diagnosis)
0591 return diagnoses
0592
0593
0594 def main():
0595 print ('Google Mock Doctor v%s - '
0596 'diagnoses problems in code using Google Mock.' % _VERSION)
0597
0598 if sys.stdin.isatty():
0599 print ('Please copy and paste the compiler errors here. Press c-D when '
0600 'you are done:')
0601 else:
0602 print ('Waiting for compiler errors on stdin . . .')
0603
0604 msg = sys.stdin.read().strip()
0605 diagnoses = Diagnose(msg)
0606 count = len(diagnoses)
0607 if not count:
0608 print ("""
0609 Your compiler complained:
0610 8<------------------------------------------------------------
0611 %s
0612 ------------------------------------------------------------>8
0613
0614 Uh-oh, I'm not smart enough to figure out what the problem is. :-(
0615 However...
0616 If you send your source code and the compiler's error messages to
0617 %s, you can be helped and I can get smarter --
0618 win-win for us!""" % (msg, _EMAIL))
0619 else:
0620 print ('------------------------------------------------------------')
0621 print ('Your code appears to have the following',)
0622 if count > 1:
0623 print ('%s diseases:' % (count,))
0624 else:
0625 print ('disease:')
0626 i = 0
0627 for d in diagnoses:
0628 i += 1
0629 if count > 1:
0630 print ('\n#%s:' % (i,))
0631 print (d)
0632 print ("""
0633 How did I do? If you think I'm wrong or unhelpful, please send your
0634 source code and the compiler's error messages to %s.
0635 Then you can be helped and I can get smarter -- I promise I won't be upset!""" %
0636 _EMAIL)
0637
0638
0639 if __name__ == '__main__':
0640 main()