1 //
2 // Copyright 2020 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
25 #include "pxr/usd/usdUtils/conditionalAbortDiagnosticDelegate.h"
26 #include "pxr/base/arch/debugger.h"
27 #include "pxr/base/tf/patternMatcher.h"
28 #include "pxr/base/tf/stackTrace.h"
29
30 #include <cstdio>
31
32 PXR_NAMESPACE_OPEN_SCOPE
33
34 // Helper function to print diagnostics in same format as TfDiagnosticMgr
35 void _PrintDiagnostic(const TfEnum &code, const TfCallContext &ctx,
36 const std::string& msg, const TfDiagnosticInfo &info);
37
38 // Helper function to construct patternMatchers
constructPatternFilters(const std::vector<std::string> & filters)39 std::vector<TfPatternMatcher> constructPatternFilters(
40 const std::vector<std::string>& filters) {
41 std::vector<TfPatternMatcher> patternMatchers;
42 patternMatchers.reserve(filters.size());
43 for (const std::string& filter : filters) {
44 patternMatchers.push_back(TfPatternMatcher(filter, true, true));
45 if (!patternMatchers.back().IsValid()) {
46 TF_WARN("Invalid pattern string: %s", filter.c_str());
47 }
48 }
49 return patternMatchers;
50 }
51
52 UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters::
UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters(const std::vector<std::string> & stringFilters,const std::vector<std::string> & codePathFilters)53 UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters(
54 const std::vector<std::string>& stringFilters,
55 const std::vector<std::string>& codePathFilters) :
56 _stringFilters(stringFilters), _codePathFilters(codePathFilters) {}
57
58 void
SetStringFilters(const std::vector<std::string> & stringFilters)59 UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters::SetStringFilters(
60 const std::vector<std::string>& stringFilters)
61 {
62 _stringFilters = stringFilters;
63 }
64
65 void
SetCodePathFilters(const std::vector<std::string> & codePathFilters)66 UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters::SetCodePathFilters(
67 const std::vector<std::string>& codePathFilters)
68 {
69 _codePathFilters = codePathFilters;
70 }
71
72 UsdUtilsConditionalAbortDiagnosticDelegate::
UsdUtilsConditionalAbortDiagnosticDelegate(const UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters & includeFilters,const UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters & excludeFilters)73 UsdUtilsConditionalAbortDiagnosticDelegate(
74 const UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters&
75 includeFilters,
76 const UsdUtilsConditionalAbortDiagnosticDelegateErrorFilters&
77 excludeFilters) :
78 _includePatternStringFilters(constructPatternFilters(
79 includeFilters.GetStringFilters())),
80 _includePatternCodePathFilters(constructPatternFilters(
81 includeFilters.GetCodePathFilters())),
82 _excludePatternStringFilters(constructPatternFilters(
83 excludeFilters.GetStringFilters())),
84 _excludePatternCodePathFilters(constructPatternFilters(
85 excludeFilters.GetCodePathFilters()))
86 {
87 TfDiagnosticMgr::GetInstance().AddDelegate(this);
88 }
89
90 UsdUtilsConditionalAbortDiagnosticDelegate::
~UsdUtilsConditionalAbortDiagnosticDelegate()91 ~UsdUtilsConditionalAbortDiagnosticDelegate()
92 {
93 TfDiagnosticMgr::GetInstance().RemoveDelegate(this);
94 }
95
96 bool
_RuleMatcher(const TfDiagnosticBase & err,const std::vector<TfPatternMatcher> & stringPatternFilters,const std::vector<TfPatternMatcher> & codePathPatternFilters)97 UsdUtilsConditionalAbortDiagnosticDelegate::_RuleMatcher(
98 const TfDiagnosticBase& err,
99 const std::vector<TfPatternMatcher>& stringPatternFilters,
100 const std::vector<TfPatternMatcher>& codePathPatternFilters)
101 {
102 const std::string& sourceFileName = err.GetSourceFileName();
103 if (!sourceFileName.empty()) {
104 for (const TfPatternMatcher& codePathPattern : codePathPatternFilters) {
105 if (codePathPattern.Match(sourceFileName)) {
106 return true;
107 }
108 }
109 }
110 const std::string& errorString = err.GetCommentary();
111 if (!errorString.empty()) {
112 for (const TfPatternMatcher& stringPattern : stringPatternFilters) {
113 if (stringPattern.Match(errorString)) {
114 return true;
115 }
116 }
117 }
118 return false;
119 }
120
121 void
IssueError(const TfError & err)122 UsdUtilsConditionalAbortDiagnosticDelegate::IssueError(const TfError& err)
123 {
124 // if matching in include rules and NOT in exclude rules then abort
125 if (_RuleMatcher(err, _includePatternStringFilters,
126 _includePatternCodePathFilters) &&
127 !_RuleMatcher(err, _excludePatternStringFilters,
128 _excludePatternCodePathFilters)) {
129 TfLogCrash("Aborted by UsdUtilsConditionalAbortDiagnosticDelegate On "
130 "Error", err.GetCommentary(), std::string(),
131 err.GetContext(), true);
132 ArchAbort(false);
133 } else if (!err.GetQuiet()) {
134 _PrintDiagnostic(err.GetDiagnosticCode(), err.GetContext(),
135 err.GetCommentary(), err.GetInfo<TfError>());
136 }
137 }
138
139 void
IssueFatalError(const TfCallContext & ctx,const std::string & msg)140 UsdUtilsConditionalAbortDiagnosticDelegate::IssueFatalError(
141 const TfCallContext &ctx,
142 const std::string &msg)
143 {
144 TfLogCrash("FATAL ERROR", msg, std::string() /*additionalInfo*/,
145 ctx, true /*logToDB*/);
146 ArchAbort(/*logging=*/ false);
147 }
148
149 void
IssueStatus(const TfStatus & status)150 UsdUtilsConditionalAbortDiagnosticDelegate::IssueStatus(const TfStatus& status)
151 {
152 _PrintDiagnostic(status.GetDiagnosticCode(), status.GetContext(),
153 status.GetCommentary(), status.GetInfo<TfStatus>());
154 }
155
156 void
IssueWarning(const TfWarning & warning)157 UsdUtilsConditionalAbortDiagnosticDelegate::IssueWarning(const TfWarning&
158 warning)
159 {
160 // if matching in include rules and NOT in exclude rules then abort
161 if (_RuleMatcher(warning, _includePatternStringFilters,
162 _includePatternCodePathFilters) &&
163 !_RuleMatcher(warning, _excludePatternStringFilters,
164 _excludePatternCodePathFilters)) {
165 TfLogCrash("Aborted by UsdUtilsConditionalAbortDiagnosticDelegate On "
166 "Warning", warning.GetCommentary(), std::string(),
167 warning.GetContext(), true);
168 ArchAbort(false);
169 } else if (!warning.GetQuiet()) {
170 _PrintDiagnostic(warning.GetDiagnosticCode(), warning.GetContext(),
171 warning.GetCommentary(), warning.GetInfo<TfWarning>());
172 }
173 }
174
_PrintDiagnostic(const TfEnum & code,const TfCallContext & ctx,const std::string & msg,const TfDiagnosticInfo & info)175 void _PrintDiagnostic(const TfEnum &code, const TfCallContext &ctx,
176 const std::string& msg, const TfDiagnosticInfo &info) {
177 std::fprintf(stderr, "%s",
178 TfDiagnosticMgr::FormatDiagnostic(code, ctx, msg, info).c_str());
179 }
180
181 PXR_NAMESPACE_CLOSE_SCOPE
182
183