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 18namespace clang { 19namespace tooling { 20 21DiagnosticMessage::DiagnosticMessage(llvm::StringRef Message) 22 : Message(Message), FileOffset(0) {} 23 24DiagnosticMessage::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 38FileByteRange::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 48Diagnostic::Diagnostic(llvm::StringRef DiagnosticName, 49 Diagnostic::Level DiagLevel, StringRef BuildDirectory) 50 : DiagnosticName(DiagnosticName), DiagLevel(DiagLevel), 51 BuildDirectory(BuildDirectory) {} 52 53Diagnostic::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 61const 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