1 // 2 // Copyright 2016 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 #ifndef PXR_BASE_TF_DIAGNOSTIC_BASE_H 25 #define PXR_BASE_TF_DIAGNOSTIC_BASE_H 26 27 /// \file tf/diagnosticBase.h 28 29 #include "pxr/pxr.h" 30 #include "pxr/base/tf/callContext.h" 31 #include "pxr/base/tf/enum.h" 32 #include "pxr/base/tf/refBase.h" 33 #include "pxr/base/tf/stringUtils.h" 34 #include "pxr/base/tf/weakPtr.h" 35 36 #include "pxr/base/arch/inttypes.h" 37 #include "pxr/base/arch/attributes.h" 38 #include "pxr/base/arch/function.h" 39 40 #include <boost/any.hpp> 41 #include <cstdarg> 42 #include <string> 43 44 PXR_NAMESPACE_OPEN_SCOPE 45 46 typedef boost::any TfDiagnosticInfo; 47 48 class TfDiagnosticMgr; 49 50 /// \class TfDiagnosticBase 51 /// \ingroup group_tf_TfError 52 /// 53 /// Represents the base class of an object representing a diagnostic message. 54 /// 55 /// This forms the base class for specific types associated with errors, 56 /// warnings and status messages. It associates a diagnostic code (which is an 57 /// enum value) with the message. It can also hold on to arbitrary information 58 /// associated with the message in a TfDiagnosticInfo. 59 /// 60 /// See \ref page_tf_TfError in the C++ API reference for a detailed example. 61 /// For a description of how to post an error, warning or a status message see 62 /// \c TF_ERROR(), \c TF_WARN and \c TF_STATUS also in the C++ API reference. 63 /// 64 class TfDiagnosticBase { 65 public: 66 67 /// Return the call context where the message was issued. GetContext()68 const TfCallContext &GetContext() const { 69 return _context; 70 } 71 72 /// Return the source file name that the diagnostic message was posted from. GetSourceFileName()73 std::string GetSourceFileName() const { 74 return _context.GetFile(); 75 } 76 77 /// Return the source line number that the diagnostic message was posted 78 /// from. GetSourceLineNumber()79 size_t GetSourceLineNumber() const { 80 return _context.GetLine(); 81 } 82 83 /// Return the commentary string describing this diagnostic message. GetCommentary()84 std::string const &GetCommentary() const { 85 return _commentary; 86 } 87 88 /// Return the source function that the diagnostic message was posted from. GetSourceFunction()89 std::string GetSourceFunction() const { 90 return ArchGetPrettierFunctionName(_context.GetFunction(), 91 _context.GetPrettyFunction()); 92 } 93 94 /// Add to the commentary string describing this diagnostic message. 95 /// 96 /// Note: each string added to the commentary is separated from 97 /// the previous one with a newline. This means that 98 /// you the string \c s should \e not end with a newline. Thus, 99 /// \code 100 /// cout << e.GetCommentary() << "\n"; 101 /// \endcode 102 /// always prints the entire commentary string as a newline 103 /// separated sequence of messages. AugmentCommentary(const std::string & s)104 void AugmentCommentary(const std::string& s) { 105 if (_commentary.empty()) 106 _commentary = s; 107 else { 108 _commentary += "\n"; 109 _commentary += s; 110 } 111 } 112 113 /// Return the diagnostic code posted. GetDiagnosticCode()114 TfEnum GetDiagnosticCode() const { 115 return _code; 116 } 117 118 119 /// Return the diagnostic code posted as a string. 120 /// 121 /// If the enum value posted with the message has been registered 122 /// with \c TF_ADD_ENUM_NAME(), then \c GetDiagnosticCodeAsString() will 123 /// return the symbolic name of the enum. 124 /// 125 /// If the enum has not been registered, then code of the form 126 /// \code 127 /// TF_ERROR(PUCE).Post("is an ugly color"); 128 /// \endcode 129 /// will still result in \c GetDiagnosticCodeAsString() returning the string 130 /// "PUCE"; however, code of the form 131 /// \code 132 /// MyErrorCode c = PUCE; 133 /// TF_ERROR(c).Post("is still ugly"); 134 /// \endcode 135 /// will result in \c GetDiagnosticCodeAsString() returning the 136 /// (uninformative) string "c". GetDiagnosticCodeAsString()137 const std::string& GetDiagnosticCodeAsString() const { 138 return _codeString; 139 } 140 141 /// Return a (possibly NULL) const pointer to the info object associated 142 /// with this message. 143 /// 144 /// If this message was posted without supplying an \c info argument to 145 /// Post(), e.g. 146 /// \code 147 /// TF_ERROR(SOME_CODE).Post("something went wrong"); 148 /// \endcode 149 /// 150 /// then \c GetInfo() returns NULL. Otherwise, when info is supplied, 151 /// e.g. 152 /// \code 153 /// T myInfo = ... 154 /// TF_ERROR(SOME_CODE).Post("something went wrong")->SetInfo(myInfo); 155 /// \endcode 156 /// 157 /// then a const pointer to a copy of myInfo in the above example is 158 /// returned by GetInfo<T>(). If the type T doesn't match the held type 159 /// then GetInfo() returns NULL. 160 template <typename T> GetInfo()161 const T* GetInfo() const { 162 return boost::any_cast<T>(&_info); 163 } 164 165 /// Set the info object associated with this diagnostic message. 166 /// \see GetInfo() SetInfo(TfDiagnosticInfo any)167 void SetInfo(TfDiagnosticInfo any) { 168 _info = any; 169 } 170 171 /// Return true if the message was posted via \c PostQuietly(). 172 /// 173 /// Notices sent from \c PostQuietly() are indicating that an immediate 174 /// printout of the error is not desirable, because someone higher up on 175 /// the stack may actually handle this error. This is rare, but it does 176 /// happen on occasion. GetQuiet()177 bool GetQuiet() const { 178 return _quiet; 179 } 180 181 /// Return the commentary string. 182 std::string GetPrettyPrintString() const; 183 184 /// Return true if this diagnostic's code is a fatal code. 185 bool IsFatal() const; 186 187 /// Return true if this diagnostic's code is either a fatal or nonfatal 188 /// coding error. 189 bool IsCodingError() const; 190 191 /// Construct an instance. 192 TfDiagnosticBase(TfEnum code, char const *codeString, 193 TfCallContext const &context, 194 const std::string& commentary, 195 TfDiagnosticInfo info, bool quiet); 196 197 protected: 198 TfCallContext _context; 199 200 std::string _commentary; 201 TfEnum _code; 202 std::string _codeString; 203 TfDiagnosticInfo _info; 204 size_t _serial = 0; 205 bool _quiet = false; 206 207 friend class TfDiagnosticMgr; 208 friend class TfErrorTransport; 209 friend class TfErrorMark; 210 }; 211 212 PXR_NAMESPACE_CLOSE_SCOPE 213 214 #endif // PXR_BASE_TF_DIAGNOSTIC_BASE_H 215