118 lines · cpp
1//===--- StandaloneDiagnostic.h - Serializable Diagnostic ------------- ---===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Frontend/StandaloneDiagnostic.h"10#include "clang/Lex/Lexer.h"11 12namespace clang {13 14StandaloneDiagnostic::SourceOffsetRange::SourceOffsetRange(15 CharSourceRange Range, const SourceManager &SrcMgr,16 const LangOptions &LangOpts) {17 const auto FileRange = Lexer::makeFileCharRange(Range, SrcMgr, LangOpts);18 Begin = SrcMgr.getFileOffset(FileRange.getBegin());19 End = SrcMgr.getFileOffset(FileRange.getEnd());20}21 22StandaloneDiagnostic::StandaloneFixIt::StandaloneFixIt(23 const SourceManager &SrcMgr, const LangOptions &LangOpts,24 const FixItHint &FixIt)25 : RemoveRange(FixIt.RemoveRange, SrcMgr, LangOpts),26 InsertFromRange(FixIt.InsertFromRange, SrcMgr, LangOpts),27 CodeToInsert(FixIt.CodeToInsert),28 BeforePreviousInsertions(FixIt.BeforePreviousInsertions) {}29 30StandaloneDiagnostic::StandaloneDiagnostic(const LangOptions &LangOpts,31 const StoredDiagnostic &InDiag)32 : Level(InDiag.getLevel()), ID(InDiag.getID()),33 Message(InDiag.getMessage()) {34 const FullSourceLoc &FullLoc = InDiag.getLocation();35 // This is not an invalid diagnostic; invalid SourceLocations are used to36 // represent diagnostics without a specific SourceLocation.37 if (FullLoc.isInvalid())38 return;39 40 const auto &SrcMgr = FullLoc.getManager();41 FileKind = SrcMgr.getFileCharacteristic(static_cast<SourceLocation>(FullLoc));42 const auto FileLoc = SrcMgr.getFileLoc(static_cast<SourceLocation>(FullLoc));43 FileOffset = SrcMgr.getFileOffset(FileLoc);44 Filename = SrcMgr.getFilename(FileLoc);45 assert(!Filename.empty() && "diagnostic with location has no source file?");46 47 Ranges.reserve(InDiag.getRanges().size());48 for (const auto &Range : InDiag.getRanges())49 Ranges.emplace_back(Range, SrcMgr, LangOpts);50 51 FixIts.reserve(InDiag.getFixIts().size());52 for (const auto &FixIt : InDiag.getFixIts())53 FixIts.emplace_back(SrcMgr, LangOpts, FixIt);54}55 56StoredDiagnostic57translateStandaloneDiag(FileManager &FileMgr, SourceManager &SrcMgr,58 const StandaloneDiagnostic &StandaloneDiag,59 llvm::StringMap<SourceLocation> &SrcLocCache) {60 const auto FileRef = FileMgr.getOptionalFileRef(StandaloneDiag.Filename);61 if (!FileRef)62 return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID,63 StandaloneDiag.Message);64 65 // Try to get FileLoc from cache first66 SourceLocation FileLoc;67 auto It = SrcLocCache.find(StandaloneDiag.Filename);68 if (It != SrcLocCache.end()) {69 FileLoc = It->getValue();70 }71 72 // Cache miss - compute and cache the location73 if (FileLoc.isInvalid()) {74 const auto FileID =75 SrcMgr.getOrCreateFileID(*FileRef, StandaloneDiag.FileKind);76 FileLoc = SrcMgr.getLocForStartOfFile(FileID);77 78 if (FileLoc.isInvalid())79 return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID,80 StandaloneDiag.Message);81 82 SrcLocCache[StandaloneDiag.Filename] = FileLoc;83 }84 85 const auto DiagLoc = FileLoc.getLocWithOffset(StandaloneDiag.FileOffset);86 const FullSourceLoc Loc(DiagLoc, SrcMgr);87 88 auto ConvertOffsetRange =89 [&](const StandaloneDiagnostic::SourceOffsetRange &Range) {90 return CharSourceRange(91 SourceRange(FileLoc.getLocWithOffset(Range.Begin),92 FileLoc.getLocWithOffset(Range.End)),93 /*IsTokenRange*/ false);94 };95 96 SmallVector<CharSourceRange, 4> TranslatedRanges;97 TranslatedRanges.reserve(StandaloneDiag.Ranges.size());98 transform(StandaloneDiag.Ranges, std::back_inserter(TranslatedRanges),99 ConvertOffsetRange);100 101 SmallVector<FixItHint, 2> TranslatedFixIts;102 TranslatedFixIts.reserve(StandaloneDiag.FixIts.size());103 for (const auto &FixIt : StandaloneDiag.FixIts) {104 FixItHint TranslatedFixIt;105 TranslatedFixIt.CodeToInsert = FixIt.CodeToInsert;106 TranslatedFixIt.RemoveRange = ConvertOffsetRange(FixIt.RemoveRange);107 TranslatedFixIt.InsertFromRange = ConvertOffsetRange(FixIt.InsertFromRange);108 TranslatedFixIt.BeforePreviousInsertions = FixIt.BeforePreviousInsertions;109 TranslatedFixIts.push_back(std::move(TranslatedFixIt));110 }111 112 return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID,113 StandaloneDiag.Message, Loc, TranslatedRanges,114 TranslatedFixIts);115}116 117} // namespace clang118