1 //===--- Diagnostic.cpp - Framework for clang diagnostics tools ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Implements classes to support/store diagnostics refactoring. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Tooling/Core/Diagnostic.h" 14 #include "clang/Basic/SourceLocation.h" 15 #include "clang/Basic/SourceManager.h" 16 #include "llvm/ADT/STLExtras.h" 17 18 namespace clang { 19 namespace tooling { 20 21 DiagnosticMessage::DiagnosticMessage(llvm::StringRef Message) 22 : Message(Message), FileOffset(0) {} 23 24 DiagnosticMessage::DiagnosticMessage(llvm::StringRef Message, 25 const SourceManager &Sources, 26 SourceLocation Loc) 27 : Message(Message), FileOffset(0) { 28 assert(Loc.isValid() && Loc.isFileID()); 29 FilePath = std::string(Sources.getFilename(Loc)); 30 31 // Don't store offset in the scratch space. It doesn't tell anything to the 32 // user. Moreover, it depends on the history of macro expansions and thus 33 // prevents deduplication of warnings in headers. 34 if (!FilePath.empty()) 35 FileOffset = Sources.getFileOffset(Loc); 36 } 37 38 FileByteRange::FileByteRange( 39 const SourceManager &Sources, CharSourceRange Range) 40 : FileOffset(0), Length(0) { 41 FilePath = std::string(Sources.getFilename(Range.getBegin())); 42 if (!FilePath.empty()) { 43 FileOffset = Sources.getFileOffset(Range.getBegin()); 44 Length = Sources.getFileOffset(Range.getEnd()) - FileOffset; 45 } 46 } 47 48 Diagnostic::Diagnostic(llvm::StringRef DiagnosticName, 49 Diagnostic::Level DiagLevel, StringRef BuildDirectory) 50 : DiagnosticName(DiagnosticName), DiagLevel(DiagLevel), 51 BuildDirectory(BuildDirectory) {} 52 53 Diagnostic::Diagnostic(llvm::StringRef DiagnosticName, 54 const DiagnosticMessage &Message, 55 const SmallVector<DiagnosticMessage, 1> &Notes, 56 Level DiagLevel, llvm::StringRef BuildDirectory) 57 : DiagnosticName(DiagnosticName), Message(Message), Notes(Notes), 58 DiagLevel(DiagLevel), BuildDirectory(BuildDirectory) {} 59 60 const llvm::StringMap<Replacements> *selectFirstFix(const Diagnostic& D) { 61 if (!D.Message.Fix.empty()) 62 return &D.Message.Fix; 63 auto Iter = llvm::find_if(D.Notes, [](const tooling::DiagnosticMessage &D) { 64 return !D.Fix.empty(); 65 }); 66 if (Iter != D.Notes.end()) 67 return &Iter->Fix; 68 return nullptr; 69 } 70 71 } // end namespace tooling 72 } // end namespace clang 73