gmock_doctor.py revision 13481
113481Sgiacomo.travaglini@arm.com#!/usr/bin/env python 213481Sgiacomo.travaglini@arm.com# 313481Sgiacomo.travaglini@arm.com# Copyright 2008, Google Inc. 413481Sgiacomo.travaglini@arm.com# All rights reserved. 513481Sgiacomo.travaglini@arm.com# 613481Sgiacomo.travaglini@arm.com# Redistribution and use in source and binary forms, with or without 713481Sgiacomo.travaglini@arm.com# modification, are permitted provided that the following conditions are 813481Sgiacomo.travaglini@arm.com# met: 913481Sgiacomo.travaglini@arm.com# 1013481Sgiacomo.travaglini@arm.com# * Redistributions of source code must retain the above copyright 1113481Sgiacomo.travaglini@arm.com# notice, this list of conditions and the following disclaimer. 1213481Sgiacomo.travaglini@arm.com# * Redistributions in binary form must reproduce the above 1313481Sgiacomo.travaglini@arm.com# copyright notice, this list of conditions and the following disclaimer 1413481Sgiacomo.travaglini@arm.com# in the documentation and/or other materials provided with the 1513481Sgiacomo.travaglini@arm.com# distribution. 1613481Sgiacomo.travaglini@arm.com# * Neither the name of Google Inc. nor the names of its 1713481Sgiacomo.travaglini@arm.com# contributors may be used to endorse or promote products derived from 1813481Sgiacomo.travaglini@arm.com# this software without specific prior written permission. 1913481Sgiacomo.travaglini@arm.com# 2013481Sgiacomo.travaglini@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2113481Sgiacomo.travaglini@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2213481Sgiacomo.travaglini@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2313481Sgiacomo.travaglini@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2413481Sgiacomo.travaglini@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2513481Sgiacomo.travaglini@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2613481Sgiacomo.travaglini@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2713481Sgiacomo.travaglini@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2813481Sgiacomo.travaglini@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2913481Sgiacomo.travaglini@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3013481Sgiacomo.travaglini@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3113481Sgiacomo.travaglini@arm.com 3213481Sgiacomo.travaglini@arm.com"""Converts compiler's errors in code using Google Mock to plain English.""" 3313481Sgiacomo.travaglini@arm.com 3413481Sgiacomo.travaglini@arm.com__author__ = 'wan@google.com (Zhanyong Wan)' 3513481Sgiacomo.travaglini@arm.com 3613481Sgiacomo.travaglini@arm.comimport re 3713481Sgiacomo.travaglini@arm.comimport sys 3813481Sgiacomo.travaglini@arm.com 3913481Sgiacomo.travaglini@arm.com_VERSION = '1.0.3' 4013481Sgiacomo.travaglini@arm.com 4113481Sgiacomo.travaglini@arm.com_EMAIL = 'googlemock@googlegroups.com' 4213481Sgiacomo.travaglini@arm.com 4313481Sgiacomo.travaglini@arm.com_COMMON_GMOCK_SYMBOLS = [ 4413481Sgiacomo.travaglini@arm.com # Matchers 4513481Sgiacomo.travaglini@arm.com '_', 4613481Sgiacomo.travaglini@arm.com 'A', 4713481Sgiacomo.travaglini@arm.com 'AddressSatisfies', 4813481Sgiacomo.travaglini@arm.com 'AllOf', 4913481Sgiacomo.travaglini@arm.com 'An', 5013481Sgiacomo.travaglini@arm.com 'AnyOf', 5113481Sgiacomo.travaglini@arm.com 'ContainerEq', 5213481Sgiacomo.travaglini@arm.com 'Contains', 5313481Sgiacomo.travaglini@arm.com 'ContainsRegex', 5413481Sgiacomo.travaglini@arm.com 'DoubleEq', 5513481Sgiacomo.travaglini@arm.com 'ElementsAre', 5613481Sgiacomo.travaglini@arm.com 'ElementsAreArray', 5713481Sgiacomo.travaglini@arm.com 'EndsWith', 5813481Sgiacomo.travaglini@arm.com 'Eq', 5913481Sgiacomo.travaglini@arm.com 'Field', 6013481Sgiacomo.travaglini@arm.com 'FloatEq', 6113481Sgiacomo.travaglini@arm.com 'Ge', 6213481Sgiacomo.travaglini@arm.com 'Gt', 6313481Sgiacomo.travaglini@arm.com 'HasSubstr', 6413481Sgiacomo.travaglini@arm.com 'IsInitializedProto', 6513481Sgiacomo.travaglini@arm.com 'Le', 6613481Sgiacomo.travaglini@arm.com 'Lt', 6713481Sgiacomo.travaglini@arm.com 'MatcherCast', 6813481Sgiacomo.travaglini@arm.com 'Matches', 6913481Sgiacomo.travaglini@arm.com 'MatchesRegex', 7013481Sgiacomo.travaglini@arm.com 'NanSensitiveDoubleEq', 7113481Sgiacomo.travaglini@arm.com 'NanSensitiveFloatEq', 7213481Sgiacomo.travaglini@arm.com 'Ne', 7313481Sgiacomo.travaglini@arm.com 'Not', 7413481Sgiacomo.travaglini@arm.com 'NotNull', 7513481Sgiacomo.travaglini@arm.com 'Pointee', 7613481Sgiacomo.travaglini@arm.com 'Property', 7713481Sgiacomo.travaglini@arm.com 'Ref', 7813481Sgiacomo.travaglini@arm.com 'ResultOf', 7913481Sgiacomo.travaglini@arm.com 'SafeMatcherCast', 8013481Sgiacomo.travaglini@arm.com 'StartsWith', 8113481Sgiacomo.travaglini@arm.com 'StrCaseEq', 8213481Sgiacomo.travaglini@arm.com 'StrCaseNe', 8313481Sgiacomo.travaglini@arm.com 'StrEq', 8413481Sgiacomo.travaglini@arm.com 'StrNe', 8513481Sgiacomo.travaglini@arm.com 'Truly', 8613481Sgiacomo.travaglini@arm.com 'TypedEq', 8713481Sgiacomo.travaglini@arm.com 'Value', 8813481Sgiacomo.travaglini@arm.com 8913481Sgiacomo.travaglini@arm.com # Actions 9013481Sgiacomo.travaglini@arm.com 'Assign', 9113481Sgiacomo.travaglini@arm.com 'ByRef', 9213481Sgiacomo.travaglini@arm.com 'DeleteArg', 9313481Sgiacomo.travaglini@arm.com 'DoAll', 9413481Sgiacomo.travaglini@arm.com 'DoDefault', 9513481Sgiacomo.travaglini@arm.com 'IgnoreResult', 9613481Sgiacomo.travaglini@arm.com 'Invoke', 9713481Sgiacomo.travaglini@arm.com 'InvokeArgument', 9813481Sgiacomo.travaglini@arm.com 'InvokeWithoutArgs', 9913481Sgiacomo.travaglini@arm.com 'Return', 10013481Sgiacomo.travaglini@arm.com 'ReturnNew', 10113481Sgiacomo.travaglini@arm.com 'ReturnNull', 10213481Sgiacomo.travaglini@arm.com 'ReturnRef', 10313481Sgiacomo.travaglini@arm.com 'SaveArg', 10413481Sgiacomo.travaglini@arm.com 'SetArgReferee', 10513481Sgiacomo.travaglini@arm.com 'SetArgPointee', 10613481Sgiacomo.travaglini@arm.com 'SetArgumentPointee', 10713481Sgiacomo.travaglini@arm.com 'SetArrayArgument', 10813481Sgiacomo.travaglini@arm.com 'SetErrnoAndReturn', 10913481Sgiacomo.travaglini@arm.com 'Throw', 11013481Sgiacomo.travaglini@arm.com 'WithArg', 11113481Sgiacomo.travaglini@arm.com 'WithArgs', 11213481Sgiacomo.travaglini@arm.com 'WithoutArgs', 11313481Sgiacomo.travaglini@arm.com 11413481Sgiacomo.travaglini@arm.com # Cardinalities 11513481Sgiacomo.travaglini@arm.com 'AnyNumber', 11613481Sgiacomo.travaglini@arm.com 'AtLeast', 11713481Sgiacomo.travaglini@arm.com 'AtMost', 11813481Sgiacomo.travaglini@arm.com 'Between', 11913481Sgiacomo.travaglini@arm.com 'Exactly', 12013481Sgiacomo.travaglini@arm.com 12113481Sgiacomo.travaglini@arm.com # Sequences 12213481Sgiacomo.travaglini@arm.com 'InSequence', 12313481Sgiacomo.travaglini@arm.com 'Sequence', 12413481Sgiacomo.travaglini@arm.com 12513481Sgiacomo.travaglini@arm.com # Misc 12613481Sgiacomo.travaglini@arm.com 'DefaultValue', 12713481Sgiacomo.travaglini@arm.com 'Mock', 12813481Sgiacomo.travaglini@arm.com ] 12913481Sgiacomo.travaglini@arm.com 13013481Sgiacomo.travaglini@arm.com# Regex for matching source file path and line number in the compiler's errors. 13113481Sgiacomo.travaglini@arm.com_GCC_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(\d+:)?\s+' 13213481Sgiacomo.travaglini@arm.com_CLANG_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(?P<column>\d+):\s+' 13313481Sgiacomo.travaglini@arm.com_CLANG_NON_GMOCK_FILE_LINE_RE = ( 13413481Sgiacomo.travaglini@arm.com r'(?P<file>.*[/\\^](?!gmock-)[^/\\]+):(?P<line>\d+):(?P<column>\d+):\s+') 13513481Sgiacomo.travaglini@arm.com 13613481Sgiacomo.travaglini@arm.com 13713481Sgiacomo.travaglini@arm.comdef _FindAllMatches(regex, s): 13813481Sgiacomo.travaglini@arm.com """Generates all matches of regex in string s.""" 13913481Sgiacomo.travaglini@arm.com 14013481Sgiacomo.travaglini@arm.com r = re.compile(regex) 14113481Sgiacomo.travaglini@arm.com return r.finditer(s) 14213481Sgiacomo.travaglini@arm.com 14313481Sgiacomo.travaglini@arm.com 14413481Sgiacomo.travaglini@arm.comdef _GenericDiagnoser(short_name, long_name, diagnoses, msg): 14513481Sgiacomo.travaglini@arm.com """Diagnoses the given disease by pattern matching. 14613481Sgiacomo.travaglini@arm.com 14713481Sgiacomo.travaglini@arm.com Can provide different diagnoses for different patterns. 14813481Sgiacomo.travaglini@arm.com 14913481Sgiacomo.travaglini@arm.com Args: 15013481Sgiacomo.travaglini@arm.com short_name: Short name of the disease. 15113481Sgiacomo.travaglini@arm.com long_name: Long name of the disease. 15213481Sgiacomo.travaglini@arm.com diagnoses: A list of pairs (regex, pattern for formatting the diagnosis 15313481Sgiacomo.travaglini@arm.com for matching regex). 15413481Sgiacomo.travaglini@arm.com msg: Compiler's error messages. 15513481Sgiacomo.travaglini@arm.com Yields: 15613481Sgiacomo.travaglini@arm.com Tuples of the form 15713481Sgiacomo.travaglini@arm.com (short name of disease, long name of disease, diagnosis). 15813481Sgiacomo.travaglini@arm.com """ 15913481Sgiacomo.travaglini@arm.com for regex, diagnosis in diagnoses: 16013481Sgiacomo.travaglini@arm.com if re.search(regex, msg): 16113481Sgiacomo.travaglini@arm.com diagnosis = '%(file)s:%(line)s:' + diagnosis 16213481Sgiacomo.travaglini@arm.com for m in _FindAllMatches(regex, msg): 16313481Sgiacomo.travaglini@arm.com yield (short_name, long_name, diagnosis % m.groupdict()) 16413481Sgiacomo.travaglini@arm.com 16513481Sgiacomo.travaglini@arm.com 16613481Sgiacomo.travaglini@arm.comdef _NeedToReturnReferenceDiagnoser(msg): 16713481Sgiacomo.travaglini@arm.com """Diagnoses the NRR disease, given the error messages by the compiler.""" 16813481Sgiacomo.travaglini@arm.com 16913481Sgiacomo.travaglini@arm.com gcc_regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n' 17013481Sgiacomo.travaglini@arm.com + _GCC_FILE_LINE_RE + r'instantiated from here\n' 17113481Sgiacomo.travaglini@arm.com r'.*gmock-actions\.h.*error: creating array with negative size') 17213481Sgiacomo.travaglini@arm.com clang_regex = (r'error:.*array.*negative.*\r?\n' 17313481Sgiacomo.travaglini@arm.com r'(.*\n)*?' + 17413481Sgiacomo.travaglini@arm.com _CLANG_NON_GMOCK_FILE_LINE_RE + 17513481Sgiacomo.travaglini@arm.com r'note: in instantiation of function template specialization ' 17613481Sgiacomo.travaglini@arm.com r'\'testing::internal::ReturnAction<(?P<type>.*)>' 17713481Sgiacomo.travaglini@arm.com r'::operator Action<.*>\' requested here') 17813481Sgiacomo.travaglini@arm.com clang11_re = (r'use_ReturnRef_instead_of_Return_to_return_a_reference.*' 17913481Sgiacomo.travaglini@arm.com r'(.*\n)*?' + _CLANG_NON_GMOCK_FILE_LINE_RE) 18013481Sgiacomo.travaglini@arm.com 18113481Sgiacomo.travaglini@arm.com diagnosis = """ 18213481Sgiacomo.travaglini@arm.comYou are using a Return() action in a function that returns a reference to 18313481Sgiacomo.travaglini@arm.com%(type)s. Please use ReturnRef() instead.""" 18413481Sgiacomo.travaglini@arm.com return _GenericDiagnoser('NRR', 'Need to Return Reference', 18513481Sgiacomo.travaglini@arm.com [(clang_regex, diagnosis), 18613481Sgiacomo.travaglini@arm.com (clang11_re, diagnosis % {'type': 'a type'}), 18713481Sgiacomo.travaglini@arm.com (gcc_regex, diagnosis % {'type': 'a type'})], 18813481Sgiacomo.travaglini@arm.com msg) 18913481Sgiacomo.travaglini@arm.com 19013481Sgiacomo.travaglini@arm.com 19113481Sgiacomo.travaglini@arm.comdef _NeedToReturnSomethingDiagnoser(msg): 19213481Sgiacomo.travaglini@arm.com """Diagnoses the NRS disease, given the error messages by the compiler.""" 19313481Sgiacomo.travaglini@arm.com 19413481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + r'(instantiated from here\n.' 19513481Sgiacomo.travaglini@arm.com r'*gmock.*actions\.h.*error: void value not ignored)' 19613481Sgiacomo.travaglini@arm.com r'|(error: control reaches end of non-void function)') 19713481Sgiacomo.travaglini@arm.com clang_regex1 = (_CLANG_FILE_LINE_RE + 19813481Sgiacomo.travaglini@arm.com r'error: cannot initialize return object ' 19913481Sgiacomo.travaglini@arm.com r'of type \'Result\' \(aka \'(?P<return_type>.*)\'\) ' 20013481Sgiacomo.travaglini@arm.com r'with an rvalue of type \'void\'') 20113481Sgiacomo.travaglini@arm.com clang_regex2 = (_CLANG_FILE_LINE_RE + 20213481Sgiacomo.travaglini@arm.com r'error: cannot initialize return object ' 20313481Sgiacomo.travaglini@arm.com r'of type \'(?P<return_type>.*)\' ' 20413481Sgiacomo.travaglini@arm.com r'with an rvalue of type \'void\'') 20513481Sgiacomo.travaglini@arm.com diagnosis = """ 20613481Sgiacomo.travaglini@arm.comYou are using an action that returns void, but it needs to return 20713481Sgiacomo.travaglini@arm.com%(return_type)s. Please tell it *what* to return. Perhaps you can use 20813481Sgiacomo.travaglini@arm.comthe pattern DoAll(some_action, Return(some_value))?""" 20913481Sgiacomo.travaglini@arm.com return _GenericDiagnoser( 21013481Sgiacomo.travaglini@arm.com 'NRS', 21113481Sgiacomo.travaglini@arm.com 'Need to Return Something', 21213481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis % {'return_type': '*something*'}), 21313481Sgiacomo.travaglini@arm.com (clang_regex1, diagnosis), 21413481Sgiacomo.travaglini@arm.com (clang_regex2, diagnosis)], 21513481Sgiacomo.travaglini@arm.com msg) 21613481Sgiacomo.travaglini@arm.com 21713481Sgiacomo.travaglini@arm.com 21813481Sgiacomo.travaglini@arm.comdef _NeedToReturnNothingDiagnoser(msg): 21913481Sgiacomo.travaglini@arm.com """Diagnoses the NRN disease, given the error messages by the compiler.""" 22013481Sgiacomo.travaglini@arm.com 22113481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n' 22213481Sgiacomo.travaglini@arm.com r'.*gmock-actions\.h.*error: instantiation of ' 22313481Sgiacomo.travaglini@arm.com r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' ' 22413481Sgiacomo.travaglini@arm.com r'as type \'void\'') 22513481Sgiacomo.travaglini@arm.com clang_regex1 = (r'error: field has incomplete type ' 22613481Sgiacomo.travaglini@arm.com r'\'Result\' \(aka \'void\'\)(\r)?\n' 22713481Sgiacomo.travaglini@arm.com r'(.*\n)*?' + 22813481Sgiacomo.travaglini@arm.com _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation ' 22913481Sgiacomo.travaglini@arm.com r'of function template specialization ' 23013481Sgiacomo.travaglini@arm.com r'\'testing::internal::ReturnAction<(?P<return_type>.*)>' 23113481Sgiacomo.travaglini@arm.com r'::operator Action<void \(.*\)>\' requested here') 23213481Sgiacomo.travaglini@arm.com clang_regex2 = (r'error: field has incomplete type ' 23313481Sgiacomo.travaglini@arm.com r'\'Result\' \(aka \'void\'\)(\r)?\n' 23413481Sgiacomo.travaglini@arm.com r'(.*\n)*?' + 23513481Sgiacomo.travaglini@arm.com _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation ' 23613481Sgiacomo.travaglini@arm.com r'of function template specialization ' 23713481Sgiacomo.travaglini@arm.com r'\'testing::internal::DoBothAction<.*>' 23813481Sgiacomo.travaglini@arm.com r'::operator Action<(?P<return_type>.*) \(.*\)>\' ' 23913481Sgiacomo.travaglini@arm.com r'requested here') 24013481Sgiacomo.travaglini@arm.com diagnosis = """ 24113481Sgiacomo.travaglini@arm.comYou are using an action that returns %(return_type)s, but it needs to return 24213481Sgiacomo.travaglini@arm.comvoid. Please use a void-returning action instead. 24313481Sgiacomo.travaglini@arm.com 24413481Sgiacomo.travaglini@arm.comAll actions but the last in DoAll(...) must return void. Perhaps you need 24513481Sgiacomo.travaglini@arm.comto re-arrange the order of actions in a DoAll(), if you are using one?""" 24613481Sgiacomo.travaglini@arm.com return _GenericDiagnoser( 24713481Sgiacomo.travaglini@arm.com 'NRN', 24813481Sgiacomo.travaglini@arm.com 'Need to Return Nothing', 24913481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis % {'return_type': '*something*'}), 25013481Sgiacomo.travaglini@arm.com (clang_regex1, diagnosis), 25113481Sgiacomo.travaglini@arm.com (clang_regex2, diagnosis)], 25213481Sgiacomo.travaglini@arm.com msg) 25313481Sgiacomo.travaglini@arm.com 25413481Sgiacomo.travaglini@arm.com 25513481Sgiacomo.travaglini@arm.comdef _IncompleteByReferenceArgumentDiagnoser(msg): 25613481Sgiacomo.travaglini@arm.com """Diagnoses the IBRA disease, given the error messages by the compiler.""" 25713481Sgiacomo.travaglini@arm.com 25813481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n' 25913481Sgiacomo.travaglini@arm.com r'.*gtest-printers\.h.*error: invalid application of ' 26013481Sgiacomo.travaglini@arm.com r'\'sizeof\' to incomplete type \'(?P<type>.*)\'') 26113481Sgiacomo.travaglini@arm.com 26213481Sgiacomo.travaglini@arm.com clang_regex = (r'.*gtest-printers\.h.*error: invalid application of ' 26313481Sgiacomo.travaglini@arm.com r'\'sizeof\' to an incomplete type ' 26413481Sgiacomo.travaglini@arm.com r'\'(?P<type>.*)( const)?\'\r?\n' 26513481Sgiacomo.travaglini@arm.com r'(.*\n)*?' + 26613481Sgiacomo.travaglini@arm.com _CLANG_NON_GMOCK_FILE_LINE_RE + 26713481Sgiacomo.travaglini@arm.com r'note: in instantiation of member function ' 26813481Sgiacomo.travaglini@arm.com r'\'testing::internal2::TypeWithoutFormatter<.*>::' 26913481Sgiacomo.travaglini@arm.com r'PrintValue\' requested here') 27013481Sgiacomo.travaglini@arm.com diagnosis = """ 27113481Sgiacomo.travaglini@arm.comIn order to mock this function, Google Mock needs to see the definition 27213481Sgiacomo.travaglini@arm.comof type "%(type)s" - declaration alone is not enough. Either #include 27313481Sgiacomo.travaglini@arm.comthe header that defines it, or change the argument to be passed 27413481Sgiacomo.travaglini@arm.comby pointer.""" 27513481Sgiacomo.travaglini@arm.com 27613481Sgiacomo.travaglini@arm.com return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type', 27713481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis), 27813481Sgiacomo.travaglini@arm.com (clang_regex, diagnosis)], 27913481Sgiacomo.travaglini@arm.com msg) 28013481Sgiacomo.travaglini@arm.com 28113481Sgiacomo.travaglini@arm.com 28213481Sgiacomo.travaglini@arm.comdef _OverloadedFunctionMatcherDiagnoser(msg): 28313481Sgiacomo.travaglini@arm.com """Diagnoses the OFM disease, given the error messages by the compiler.""" 28413481Sgiacomo.travaglini@arm.com 28513481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for ' 28613481Sgiacomo.travaglini@arm.com r'call to \'Truly\(<unresolved overloaded function type>\)') 28713481Sgiacomo.travaglini@arm.com clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function for ' 28813481Sgiacomo.travaglini@arm.com r'call to \'Truly') 28913481Sgiacomo.travaglini@arm.com diagnosis = """ 29013481Sgiacomo.travaglini@arm.comThe argument you gave to Truly() is an overloaded function. Please tell 29113481Sgiacomo.travaglini@arm.comyour compiler which overloaded version you want to use. 29213481Sgiacomo.travaglini@arm.com 29313481Sgiacomo.travaglini@arm.comFor example, if you want to use the version whose signature is 29413481Sgiacomo.travaglini@arm.com bool Foo(int n); 29513481Sgiacomo.travaglini@arm.comyou should write 29613481Sgiacomo.travaglini@arm.com Truly(static_cast<bool (*)(int n)>(Foo))""" 29713481Sgiacomo.travaglini@arm.com return _GenericDiagnoser('OFM', 'Overloaded Function Matcher', 29813481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis), 29913481Sgiacomo.travaglini@arm.com (clang_regex, diagnosis)], 30013481Sgiacomo.travaglini@arm.com msg) 30113481Sgiacomo.travaglini@arm.com 30213481Sgiacomo.travaglini@arm.com 30313481Sgiacomo.travaglini@arm.comdef _OverloadedFunctionActionDiagnoser(msg): 30413481Sgiacomo.travaglini@arm.com """Diagnoses the OFA disease, given the error messages by the compiler.""" 30513481Sgiacomo.travaglini@arm.com 30613481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for call to ' 30713481Sgiacomo.travaglini@arm.com r'\'Invoke\(<unresolved overloaded function type>') 30813481Sgiacomo.travaglini@arm.com clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching ' 30913481Sgiacomo.travaglini@arm.com r'function for call to \'Invoke\'\r?\n' 31013481Sgiacomo.travaglini@arm.com r'(.*\n)*?' 31113481Sgiacomo.travaglini@arm.com r'.*\bgmock-generated-actions\.h:\d+:\d+:\s+' 31213481Sgiacomo.travaglini@arm.com r'note: candidate template ignored:\s+' 31313481Sgiacomo.travaglini@arm.com r'couldn\'t infer template argument \'FunctionImpl\'') 31413481Sgiacomo.travaglini@arm.com diagnosis = """ 31513481Sgiacomo.travaglini@arm.comFunction you are passing to Invoke is overloaded. Please tell your compiler 31613481Sgiacomo.travaglini@arm.comwhich overloaded version you want to use. 31713481Sgiacomo.travaglini@arm.com 31813481Sgiacomo.travaglini@arm.comFor example, if you want to use the version whose signature is 31913481Sgiacomo.travaglini@arm.com bool MyFunction(int n, double x); 32013481Sgiacomo.travaglini@arm.comyou should write something like 32113481Sgiacomo.travaglini@arm.com Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))""" 32213481Sgiacomo.travaglini@arm.com return _GenericDiagnoser('OFA', 'Overloaded Function Action', 32313481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis), 32413481Sgiacomo.travaglini@arm.com (clang_regex, diagnosis)], 32513481Sgiacomo.travaglini@arm.com msg) 32613481Sgiacomo.travaglini@arm.com 32713481Sgiacomo.travaglini@arm.com 32813481Sgiacomo.travaglini@arm.comdef _OverloadedMethodActionDiagnoser(msg): 32913481Sgiacomo.travaglini@arm.com """Diagnoses the OMA disease, given the error messages by the compiler.""" 33013481Sgiacomo.travaglini@arm.com 33113481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for ' 33213481Sgiacomo.travaglini@arm.com r'call to \'Invoke\(.+, <unresolved overloaded function ' 33313481Sgiacomo.travaglini@arm.com r'type>\)') 33413481Sgiacomo.travaglini@arm.com clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function ' 33513481Sgiacomo.travaglini@arm.com r'for call to \'Invoke\'\r?\n' 33613481Sgiacomo.travaglini@arm.com r'(.*\n)*?' 33713481Sgiacomo.travaglini@arm.com r'.*\bgmock-generated-actions\.h:\d+:\d+: ' 33813481Sgiacomo.travaglini@arm.com r'note: candidate function template not viable: ' 33913481Sgiacomo.travaglini@arm.com r'requires .*, but 2 (arguments )?were provided') 34013481Sgiacomo.travaglini@arm.com diagnosis = """ 34113481Sgiacomo.travaglini@arm.comThe second argument you gave to Invoke() is an overloaded method. Please 34213481Sgiacomo.travaglini@arm.comtell your compiler which overloaded version you want to use. 34313481Sgiacomo.travaglini@arm.com 34413481Sgiacomo.travaglini@arm.comFor example, if you want to use the version whose signature is 34513481Sgiacomo.travaglini@arm.com class Foo { 34613481Sgiacomo.travaglini@arm.com ... 34713481Sgiacomo.travaglini@arm.com bool Bar(int n, double x); 34813481Sgiacomo.travaglini@arm.com }; 34913481Sgiacomo.travaglini@arm.comyou should write something like 35013481Sgiacomo.travaglini@arm.com Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))""" 35113481Sgiacomo.travaglini@arm.com return _GenericDiagnoser('OMA', 'Overloaded Method Action', 35213481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis), 35313481Sgiacomo.travaglini@arm.com (clang_regex, diagnosis)], 35413481Sgiacomo.travaglini@arm.com msg) 35513481Sgiacomo.travaglini@arm.com 35613481Sgiacomo.travaglini@arm.com 35713481Sgiacomo.travaglini@arm.comdef _MockObjectPointerDiagnoser(msg): 35813481Sgiacomo.travaglini@arm.com """Diagnoses the MOP disease, given the error messages by the compiler.""" 35913481Sgiacomo.travaglini@arm.com 36013481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + r'error: request for member ' 36113481Sgiacomo.travaglini@arm.com r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', ' 36213481Sgiacomo.travaglini@arm.com r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'') 36313481Sgiacomo.travaglini@arm.com clang_regex = (_CLANG_FILE_LINE_RE + r'error: member reference type ' 36413481Sgiacomo.travaglini@arm.com r'\'(?P<class_name>.*?) *\' is a pointer; ' 36513481Sgiacomo.travaglini@arm.com r'(did you mean|maybe you meant) to use \'->\'\?') 36613481Sgiacomo.travaglini@arm.com diagnosis = """ 36713481Sgiacomo.travaglini@arm.comThe first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*, 36813481Sgiacomo.travaglini@arm.comnot a *pointer* to it. Please write '*(%(mock_object)s)' instead of 36913481Sgiacomo.travaglini@arm.com'%(mock_object)s' as your first argument. 37013481Sgiacomo.travaglini@arm.com 37113481Sgiacomo.travaglini@arm.comFor example, given the mock class: 37213481Sgiacomo.travaglini@arm.com 37313481Sgiacomo.travaglini@arm.com class %(class_name)s : public ... { 37413481Sgiacomo.travaglini@arm.com ... 37513481Sgiacomo.travaglini@arm.com MOCK_METHOD0(%(method)s, ...); 37613481Sgiacomo.travaglini@arm.com }; 37713481Sgiacomo.travaglini@arm.com 37813481Sgiacomo.travaglini@arm.comand the following mock instance: 37913481Sgiacomo.travaglini@arm.com 38013481Sgiacomo.travaglini@arm.com %(class_name)s* mock_ptr = ... 38113481Sgiacomo.travaglini@arm.com 38213481Sgiacomo.travaglini@arm.comyou should use the EXPECT_CALL like this: 38313481Sgiacomo.travaglini@arm.com 38413481Sgiacomo.travaglini@arm.com EXPECT_CALL(*mock_ptr, %(method)s(...));""" 38513481Sgiacomo.travaglini@arm.com 38613481Sgiacomo.travaglini@arm.com return _GenericDiagnoser( 38713481Sgiacomo.travaglini@arm.com 'MOP', 38813481Sgiacomo.travaglini@arm.com 'Mock Object Pointer', 38913481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis), 39013481Sgiacomo.travaglini@arm.com (clang_regex, diagnosis % {'mock_object': 'mock_object', 39113481Sgiacomo.travaglini@arm.com 'method': 'method', 39213481Sgiacomo.travaglini@arm.com 'class_name': '%(class_name)s'})], 39313481Sgiacomo.travaglini@arm.com msg) 39413481Sgiacomo.travaglini@arm.com 39513481Sgiacomo.travaglini@arm.com 39613481Sgiacomo.travaglini@arm.comdef _NeedToUseSymbolDiagnoser(msg): 39713481Sgiacomo.travaglini@arm.com """Diagnoses the NUS disease, given the error messages by the compiler.""" 39813481Sgiacomo.travaglini@arm.com 39913481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' ' 40013481Sgiacomo.travaglini@arm.com r'(was not declared in this scope|has not been declared)') 40113481Sgiacomo.travaglini@arm.com clang_regex = (_CLANG_FILE_LINE_RE + 40213481Sgiacomo.travaglini@arm.com r'error: (use of undeclared identifier|unknown type name|' 40313481Sgiacomo.travaglini@arm.com r'no template named) \'(?P<symbol>[^\']+)\'') 40413481Sgiacomo.travaglini@arm.com diagnosis = """ 40513481Sgiacomo.travaglini@arm.com'%(symbol)s' is defined by Google Mock in the testing namespace. 40613481Sgiacomo.travaglini@arm.comDid you forget to write 40713481Sgiacomo.travaglini@arm.com using testing::%(symbol)s; 40813481Sgiacomo.travaglini@arm.com?""" 40913481Sgiacomo.travaglini@arm.com for m in (list(_FindAllMatches(gcc_regex, msg)) + 41013481Sgiacomo.travaglini@arm.com list(_FindAllMatches(clang_regex, msg))): 41113481Sgiacomo.travaglini@arm.com symbol = m.groupdict()['symbol'] 41213481Sgiacomo.travaglini@arm.com if symbol in _COMMON_GMOCK_SYMBOLS: 41313481Sgiacomo.travaglini@arm.com yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict()) 41413481Sgiacomo.travaglini@arm.com 41513481Sgiacomo.travaglini@arm.com 41613481Sgiacomo.travaglini@arm.comdef _NeedToUseReturnNullDiagnoser(msg): 41713481Sgiacomo.travaglini@arm.com """Diagnoses the NRNULL disease, given the error messages by the compiler.""" 41813481Sgiacomo.travaglini@arm.com 41913481Sgiacomo.travaglini@arm.com gcc_regex = ('instantiated from \'testing::internal::ReturnAction<R>' 42013481Sgiacomo.travaglini@arm.com '::operator testing::Action<Func>\(\) const.*\n' + 42113481Sgiacomo.travaglini@arm.com _GCC_FILE_LINE_RE + r'instantiated from here\n' 42213481Sgiacomo.travaglini@arm.com r'.*error: no matching function for call to \'ImplicitCast_\(' 42313481Sgiacomo.travaglini@arm.com r'(:?long )?int&\)') 42413481Sgiacomo.travaglini@arm.com clang_regex = (r'\bgmock-actions.h:.* error: no matching function for ' 42513481Sgiacomo.travaglini@arm.com r'call to \'ImplicitCast_\'\r?\n' 42613481Sgiacomo.travaglini@arm.com r'(.*\n)*?' + 42713481Sgiacomo.travaglini@arm.com _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation ' 42813481Sgiacomo.travaglini@arm.com r'of function template specialization ' 42913481Sgiacomo.travaglini@arm.com r'\'testing::internal::ReturnAction<(int|long)>::operator ' 43013481Sgiacomo.travaglini@arm.com r'Action<(?P<type>.*)\(\)>\' requested here') 43113481Sgiacomo.travaglini@arm.com diagnosis = """ 43213481Sgiacomo.travaglini@arm.comYou are probably calling Return(NULL) and the compiler isn't sure how to turn 43313481Sgiacomo.travaglini@arm.comNULL into %(type)s. Use ReturnNull() instead. 43413481Sgiacomo.travaglini@arm.comNote: the line number may be off; please fix all instances of Return(NULL).""" 43513481Sgiacomo.travaglini@arm.com return _GenericDiagnoser( 43613481Sgiacomo.travaglini@arm.com 'NRNULL', 'Need to use ReturnNull', 43713481Sgiacomo.travaglini@arm.com [(clang_regex, diagnosis), 43813481Sgiacomo.travaglini@arm.com (gcc_regex, diagnosis % {'type': 'the right type'})], 43913481Sgiacomo.travaglini@arm.com msg) 44013481Sgiacomo.travaglini@arm.com 44113481Sgiacomo.travaglini@arm.com 44213481Sgiacomo.travaglini@arm.comdef _TypeInTemplatedBaseDiagnoser(msg): 44313481Sgiacomo.travaglini@arm.com """Diagnoses the TTB disease, given the error messages by the compiler.""" 44413481Sgiacomo.travaglini@arm.com 44513481Sgiacomo.travaglini@arm.com # This version works when the type is used as the mock function's return 44613481Sgiacomo.travaglini@arm.com # type. 44713481Sgiacomo.travaglini@arm.com gcc_4_3_1_regex_type_in_retval = ( 44813481Sgiacomo.travaglini@arm.com r'In member function \'int .*\n' + _GCC_FILE_LINE_RE + 44913481Sgiacomo.travaglini@arm.com r'error: a function call cannot appear in a constant-expression') 45013481Sgiacomo.travaglini@arm.com gcc_4_4_0_regex_type_in_retval = ( 45113481Sgiacomo.travaglini@arm.com r'error: a function call cannot appear in a constant-expression' 45213481Sgiacomo.travaglini@arm.com + _GCC_FILE_LINE_RE + r'error: template argument 1 is invalid\n') 45313481Sgiacomo.travaglini@arm.com # This version works when the type is used as the mock function's sole 45413481Sgiacomo.travaglini@arm.com # parameter type. 45513481Sgiacomo.travaglini@arm.com gcc_regex_type_of_sole_param = ( 45613481Sgiacomo.travaglini@arm.com _GCC_FILE_LINE_RE + 45713481Sgiacomo.travaglini@arm.com r'error: \'(?P<type>.+)\' was not declared in this scope\n' 45813481Sgiacomo.travaglini@arm.com r'.*error: template argument 1 is invalid\n') 45913481Sgiacomo.travaglini@arm.com # This version works when the type is used as a parameter of a mock 46013481Sgiacomo.travaglini@arm.com # function that has multiple parameters. 46113481Sgiacomo.travaglini@arm.com gcc_regex_type_of_a_param = ( 46213481Sgiacomo.travaglini@arm.com r'error: expected `;\' before \'::\' token\n' 46313481Sgiacomo.travaglini@arm.com + _GCC_FILE_LINE_RE + 46413481Sgiacomo.travaglini@arm.com r'error: \'(?P<type>.+)\' was not declared in this scope\n' 46513481Sgiacomo.travaglini@arm.com r'.*error: template argument 1 is invalid\n' 46613481Sgiacomo.travaglini@arm.com r'.*error: \'.+\' was not declared in this scope') 46713481Sgiacomo.travaglini@arm.com clang_regex_type_of_retval_or_sole_param = ( 46813481Sgiacomo.travaglini@arm.com _CLANG_FILE_LINE_RE + 46913481Sgiacomo.travaglini@arm.com r'error: use of undeclared identifier \'(?P<type>.*)\'\n' 47013481Sgiacomo.travaglini@arm.com r'(.*\n)*?' 47113481Sgiacomo.travaglini@arm.com r'(?P=file):(?P=line):\d+: error: ' 47213481Sgiacomo.travaglini@arm.com r'non-friend class member \'Result\' cannot have a qualified name' 47313481Sgiacomo.travaglini@arm.com ) 47413481Sgiacomo.travaglini@arm.com clang_regex_type_of_a_param = ( 47513481Sgiacomo.travaglini@arm.com _CLANG_FILE_LINE_RE + 47613481Sgiacomo.travaglini@arm.com r'error: C\+\+ requires a type specifier for all declarations\n' 47713481Sgiacomo.travaglini@arm.com r'(.*\n)*?' 47813481Sgiacomo.travaglini@arm.com r'(?P=file):(?P=line):(?P=column): error: ' 47913481Sgiacomo.travaglini@arm.com r'C\+\+ requires a type specifier for all declarations' 48013481Sgiacomo.travaglini@arm.com ) 48113481Sgiacomo.travaglini@arm.com clang_regex_unknown_type = ( 48213481Sgiacomo.travaglini@arm.com _CLANG_FILE_LINE_RE + 48313481Sgiacomo.travaglini@arm.com r'error: unknown type name \'(?P<type>[^\']+)\'' 48413481Sgiacomo.travaglini@arm.com ) 48513481Sgiacomo.travaglini@arm.com 48613481Sgiacomo.travaglini@arm.com diagnosis = """ 48713481Sgiacomo.travaglini@arm.comIn a mock class template, types or typedefs defined in the base class 48813481Sgiacomo.travaglini@arm.comtemplate are *not* automatically visible. This is how C++ works. Before 48913481Sgiacomo.travaglini@arm.comyou can use a type or typedef named %(type)s defined in base class Base<T>, you 49013481Sgiacomo.travaglini@arm.comneed to make it visible. One way to do it is: 49113481Sgiacomo.travaglini@arm.com 49213481Sgiacomo.travaglini@arm.com typedef typename Base<T>::%(type)s %(type)s;""" 49313481Sgiacomo.travaglini@arm.com 49413481Sgiacomo.travaglini@arm.com for diag in _GenericDiagnoser( 49513481Sgiacomo.travaglini@arm.com 'TTB', 'Type in Template Base', 49613481Sgiacomo.travaglini@arm.com [(gcc_4_3_1_regex_type_in_retval, diagnosis % {'type': 'Foo'}), 49713481Sgiacomo.travaglini@arm.com (gcc_4_4_0_regex_type_in_retval, diagnosis % {'type': 'Foo'}), 49813481Sgiacomo.travaglini@arm.com (gcc_regex_type_of_sole_param, diagnosis), 49913481Sgiacomo.travaglini@arm.com (gcc_regex_type_of_a_param, diagnosis), 50013481Sgiacomo.travaglini@arm.com (clang_regex_type_of_retval_or_sole_param, diagnosis), 50113481Sgiacomo.travaglini@arm.com (clang_regex_type_of_a_param, diagnosis % {'type': 'Foo'})], 50213481Sgiacomo.travaglini@arm.com msg): 50313481Sgiacomo.travaglini@arm.com yield diag 50413481Sgiacomo.travaglini@arm.com # Avoid overlap with the NUS pattern. 50513481Sgiacomo.travaglini@arm.com for m in _FindAllMatches(clang_regex_unknown_type, msg): 50613481Sgiacomo.travaglini@arm.com type_ = m.groupdict()['type'] 50713481Sgiacomo.travaglini@arm.com if type_ not in _COMMON_GMOCK_SYMBOLS: 50813481Sgiacomo.travaglini@arm.com yield ('TTB', 'Type in Template Base', diagnosis % m.groupdict()) 50913481Sgiacomo.travaglini@arm.com 51013481Sgiacomo.travaglini@arm.com 51113481Sgiacomo.travaglini@arm.comdef _WrongMockMethodMacroDiagnoser(msg): 51213481Sgiacomo.travaglini@arm.com """Diagnoses the WMM disease, given the error messages by the compiler.""" 51313481Sgiacomo.travaglini@arm.com 51413481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + 51513481Sgiacomo.travaglini@arm.com r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n' 51613481Sgiacomo.travaglini@arm.com r'.*\n' 51713481Sgiacomo.travaglini@arm.com r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>') 51813481Sgiacomo.travaglini@arm.com clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE + 51913481Sgiacomo.travaglini@arm.com r'error:.*array.*negative.*r?\n' 52013481Sgiacomo.travaglini@arm.com r'(.*\n)*?' 52113481Sgiacomo.travaglini@arm.com r'(?P=file):(?P=line):(?P=column): error: too few arguments ' 52213481Sgiacomo.travaglini@arm.com r'to function call, expected (?P<args>\d+), ' 52313481Sgiacomo.travaglini@arm.com r'have (?P<wrong_args>\d+)') 52413481Sgiacomo.travaglini@arm.com clang11_re = (_CLANG_NON_GMOCK_FILE_LINE_RE + 52513481Sgiacomo.travaglini@arm.com r'.*this_method_does_not_take_' 52613481Sgiacomo.travaglini@arm.com r'(?P<wrong_args>\d+)_argument.*') 52713481Sgiacomo.travaglini@arm.com diagnosis = """ 52813481Sgiacomo.travaglini@arm.comYou are using MOCK_METHOD%(wrong_args)s to define a mock method that has 52913481Sgiacomo.travaglini@arm.com%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s, 53013481Sgiacomo.travaglini@arm.comMOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead.""" 53113481Sgiacomo.travaglini@arm.com return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro', 53213481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis), 53313481Sgiacomo.travaglini@arm.com (clang11_re, diagnosis % {'wrong_args': 'm', 53413481Sgiacomo.travaglini@arm.com 'args': 'n'}), 53513481Sgiacomo.travaglini@arm.com (clang_regex, diagnosis)], 53613481Sgiacomo.travaglini@arm.com msg) 53713481Sgiacomo.travaglini@arm.com 53813481Sgiacomo.travaglini@arm.com 53913481Sgiacomo.travaglini@arm.comdef _WrongParenPositionDiagnoser(msg): 54013481Sgiacomo.travaglini@arm.com """Diagnoses the WPP disease, given the error messages by the compiler.""" 54113481Sgiacomo.travaglini@arm.com 54213481Sgiacomo.travaglini@arm.com gcc_regex = (_GCC_FILE_LINE_RE + 54313481Sgiacomo.travaglini@arm.com r'error:.*testing::internal::MockSpec<.* has no member named \'' 54413481Sgiacomo.travaglini@arm.com r'(?P<method>\w+)\'') 54513481Sgiacomo.travaglini@arm.com clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE + 54613481Sgiacomo.travaglini@arm.com r'error: no member named \'(?P<method>\w+)\' in ' 54713481Sgiacomo.travaglini@arm.com r'\'testing::internal::MockSpec<.*>\'') 54813481Sgiacomo.travaglini@arm.com diagnosis = """ 54913481Sgiacomo.travaglini@arm.comThe closing parenthesis of ON_CALL or EXPECT_CALL should be *before* 55013481Sgiacomo.travaglini@arm.com".%(method)s". For example, you should write: 55113481Sgiacomo.travaglini@arm.com EXPECT_CALL(my_mock, Foo(_)).%(method)s(...); 55213481Sgiacomo.travaglini@arm.cominstead of: 55313481Sgiacomo.travaglini@arm.com EXPECT_CALL(my_mock, Foo(_).%(method)s(...));""" 55413481Sgiacomo.travaglini@arm.com return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position', 55513481Sgiacomo.travaglini@arm.com [(gcc_regex, diagnosis), 55613481Sgiacomo.travaglini@arm.com (clang_regex, diagnosis)], 55713481Sgiacomo.travaglini@arm.com msg) 55813481Sgiacomo.travaglini@arm.com 55913481Sgiacomo.travaglini@arm.com 56013481Sgiacomo.travaglini@arm.com_DIAGNOSERS = [ 56113481Sgiacomo.travaglini@arm.com _IncompleteByReferenceArgumentDiagnoser, 56213481Sgiacomo.travaglini@arm.com _MockObjectPointerDiagnoser, 56313481Sgiacomo.travaglini@arm.com _NeedToReturnNothingDiagnoser, 56413481Sgiacomo.travaglini@arm.com _NeedToReturnReferenceDiagnoser, 56513481Sgiacomo.travaglini@arm.com _NeedToReturnSomethingDiagnoser, 56613481Sgiacomo.travaglini@arm.com _NeedToUseReturnNullDiagnoser, 56713481Sgiacomo.travaglini@arm.com _NeedToUseSymbolDiagnoser, 56813481Sgiacomo.travaglini@arm.com _OverloadedFunctionActionDiagnoser, 56913481Sgiacomo.travaglini@arm.com _OverloadedFunctionMatcherDiagnoser, 57013481Sgiacomo.travaglini@arm.com _OverloadedMethodActionDiagnoser, 57113481Sgiacomo.travaglini@arm.com _TypeInTemplatedBaseDiagnoser, 57213481Sgiacomo.travaglini@arm.com _WrongMockMethodMacroDiagnoser, 57313481Sgiacomo.travaglini@arm.com _WrongParenPositionDiagnoser, 57413481Sgiacomo.travaglini@arm.com ] 57513481Sgiacomo.travaglini@arm.com 57613481Sgiacomo.travaglini@arm.com 57713481Sgiacomo.travaglini@arm.comdef Diagnose(msg): 57813481Sgiacomo.travaglini@arm.com """Generates all possible diagnoses given the compiler error message.""" 57913481Sgiacomo.travaglini@arm.com 58013481Sgiacomo.travaglini@arm.com msg = re.sub(r'\x1b\[[^m]*m', '', msg) # Strips all color formatting. 58113481Sgiacomo.travaglini@arm.com # Assuming the string is using the UTF-8 encoding, replaces the left and 58213481Sgiacomo.travaglini@arm.com # the right single quote characters with apostrophes. 58313481Sgiacomo.travaglini@arm.com msg = re.sub(r'(\xe2\x80\x98|\xe2\x80\x99)', "'", msg) 58413481Sgiacomo.travaglini@arm.com 58513481Sgiacomo.travaglini@arm.com diagnoses = [] 58613481Sgiacomo.travaglini@arm.com for diagnoser in _DIAGNOSERS: 58713481Sgiacomo.travaglini@arm.com for diag in diagnoser(msg): 58813481Sgiacomo.travaglini@arm.com diagnosis = '[%s - %s]\n%s' % diag 58913481Sgiacomo.travaglini@arm.com if not diagnosis in diagnoses: 59013481Sgiacomo.travaglini@arm.com diagnoses.append(diagnosis) 59113481Sgiacomo.travaglini@arm.com return diagnoses 59213481Sgiacomo.travaglini@arm.com 59313481Sgiacomo.travaglini@arm.com 59413481Sgiacomo.travaglini@arm.comdef main(): 59513481Sgiacomo.travaglini@arm.com print ('Google Mock Doctor v%s - ' 59613481Sgiacomo.travaglini@arm.com 'diagnoses problems in code using Google Mock.' % _VERSION) 59713481Sgiacomo.travaglini@arm.com 59813481Sgiacomo.travaglini@arm.com if sys.stdin.isatty(): 59913481Sgiacomo.travaglini@arm.com print ('Please copy and paste the compiler errors here. Press c-D when ' 60013481Sgiacomo.travaglini@arm.com 'you are done:') 60113481Sgiacomo.travaglini@arm.com else: 60213481Sgiacomo.travaglini@arm.com print ('Waiting for compiler errors on stdin . . .') 60313481Sgiacomo.travaglini@arm.com 60413481Sgiacomo.travaglini@arm.com msg = sys.stdin.read().strip() 60513481Sgiacomo.travaglini@arm.com diagnoses = Diagnose(msg) 60613481Sgiacomo.travaglini@arm.com count = len(diagnoses) 60713481Sgiacomo.travaglini@arm.com if not count: 60813481Sgiacomo.travaglini@arm.com print (""" 60913481Sgiacomo.travaglini@arm.comYour compiler complained: 61013481Sgiacomo.travaglini@arm.com8<------------------------------------------------------------ 61113481Sgiacomo.travaglini@arm.com%s 61213481Sgiacomo.travaglini@arm.com------------------------------------------------------------>8 61313481Sgiacomo.travaglini@arm.com 61413481Sgiacomo.travaglini@arm.comUh-oh, I'm not smart enough to figure out what the problem is. :-( 61513481Sgiacomo.travaglini@arm.comHowever... 61613481Sgiacomo.travaglini@arm.comIf you send your source code and the compiler's error messages to 61713481Sgiacomo.travaglini@arm.com%s, you can be helped and I can get smarter -- 61813481Sgiacomo.travaglini@arm.comwin-win for us!""" % (msg, _EMAIL)) 61913481Sgiacomo.travaglini@arm.com else: 62013481Sgiacomo.travaglini@arm.com print ('------------------------------------------------------------') 62113481Sgiacomo.travaglini@arm.com print ('Your code appears to have the following',) 62213481Sgiacomo.travaglini@arm.com if count > 1: 62313481Sgiacomo.travaglini@arm.com print ('%s diseases:' % (count,)) 62413481Sgiacomo.travaglini@arm.com else: 62513481Sgiacomo.travaglini@arm.com print ('disease:') 62613481Sgiacomo.travaglini@arm.com i = 0 62713481Sgiacomo.travaglini@arm.com for d in diagnoses: 62813481Sgiacomo.travaglini@arm.com i += 1 62913481Sgiacomo.travaglini@arm.com if count > 1: 63013481Sgiacomo.travaglini@arm.com print ('\n#%s:' % (i,)) 63113481Sgiacomo.travaglini@arm.com print (d) 63213481Sgiacomo.travaglini@arm.com print (""" 63313481Sgiacomo.travaglini@arm.comHow did I do? If you think I'm wrong or unhelpful, please send your 63413481Sgiacomo.travaglini@arm.comsource code and the compiler's error messages to %s. 63513481Sgiacomo.travaglini@arm.comThen you can be helped and I can get smarter -- I promise I won't be upset!""" % 63613481Sgiacomo.travaglini@arm.com _EMAIL) 63713481Sgiacomo.travaglini@arm.com 63813481Sgiacomo.travaglini@arm.com 63913481Sgiacomo.travaglini@arm.comif __name__ == '__main__': 64013481Sgiacomo.travaglini@arm.com main() 641