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 const SmallVector<FileByteRange, 1> &Ranges) 58 : DiagnosticName(DiagnosticName), Message(Message), Notes(Notes), 59 DiagLevel(DiagLevel), BuildDirectory(BuildDirectory), Ranges(Ranges) {} 60 61 const llvm::StringMap<Replacements> *selectFirstFix(const Diagnostic& D) { 62 if (!D.Message.Fix.empty()) 63 return &D.Message.Fix; 64 auto Iter = llvm::find_if(D.Notes, [](const tooling::DiagnosticMessage &D) { 65 return !D.Fix.empty(); 66 }); 67 if (Iter != D.Notes.end()) 68 return &Iter->Fix; 69 return nullptr; 70 } 71 72 } // end namespace tooling 73 } // end namespace clang 74