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