//===- unittests/Frontend/TextDiagnosticTest.cpp - ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Frontend/TextDiagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/SmallVectorMemoryBuffer.h" #include "gtest/gtest.h" using namespace llvm; using namespace clang; namespace { /// Prints a diagnostic with the given DiagnosticOptions and the given /// SourceLocation and returns the printed diagnostic text. static std::string PrintDiag(const DiagnosticOptions &Opts, FullSourceLoc Loc) { std::string Out; llvm::raw_string_ostream OS(Out); clang::LangOptions LangOpts; // Owned by TextDiagnostic. DiagnosticOptions *DiagOpts = new DiagnosticOptions(Opts); TextDiagnostic Diag(OS, LangOpts, DiagOpts); // Emit a dummy diagnostic that is just 'message'. Diag.emitDiagnostic(Loc, DiagnosticsEngine::Level::Warning, "message", /*Ranges=*/{}, /*FixItHints=*/{}); OS.flush(); return Out; } TEST(TextDiagnostic, ShowLine) { // Create dummy FileManager and SourceManager. FileSystemOptions FSOpts; FileManager FileMgr(FSOpts); IntrusiveRefCntPtr DiagID(new DiagnosticIDs); DiagnosticsEngine DiagEngine(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()); SourceManager SrcMgr(DiagEngine, FileMgr); // Create a dummy file with some contents to produce a test SourceLocation. const llvm::StringRef file_path = "main.cpp"; const llvm::StringRef main_file_contents = "some\nsource\ncode\n"; const clang::FileEntryRef fe = FileMgr.getVirtualFileRef( file_path, /*Size=*/static_cast(main_file_contents.size()), /*ModificationTime=*/0); llvm::SmallVector buffer; buffer.append(main_file_contents.begin(), main_file_contents.end()); auto file_contents = std::make_unique( std::move(buffer), file_path); SrcMgr.overrideFileContents(fe, std::move(file_contents)); // Create the actual file id and use it as the main file. clang::FileID fid = SrcMgr.createFileID(fe, SourceLocation(), clang::SrcMgr::C_User); SrcMgr.setMainFileID(fid); // Create the source location for the test diagnostic. FullSourceLoc Loc(SrcMgr.translateLineCol(fid, /*Line=*/1, /*Col=*/2), SrcMgr); DiagnosticOptions DiagOpts; DiagOpts.ShowLine = true; DiagOpts.ShowColumn = true; // Hide printing the source line/caret to make the diagnostic shorter and it's // not relevant for this test. DiagOpts.ShowCarets = false; EXPECT_EQ("main.cpp:1:2: warning: message\n", PrintDiag(DiagOpts, Loc)); // Check that ShowLine doesn't influence the Vi/MSVC diagnostic formats as its // a Clang-specific diagnostic option. DiagOpts.setFormat(TextDiagnosticFormat::Vi); DiagOpts.ShowLine = false; EXPECT_EQ("main.cpp +1:2: warning: message\n", PrintDiag(DiagOpts, Loc)); DiagOpts.setFormat(TextDiagnosticFormat::MSVC); DiagOpts.ShowLine = false; EXPECT_EQ("main.cpp(1,2): warning: message\n", PrintDiag(DiagOpts, Loc)); // Reset back to the Clang format. DiagOpts.setFormat(TextDiagnosticFormat::Clang); // Hide line number but show column. DiagOpts.ShowLine = false; EXPECT_EQ("main.cpp:2: warning: message\n", PrintDiag(DiagOpts, Loc)); // Show line number but hide column. DiagOpts.ShowLine = true; DiagOpts.ShowColumn = false; EXPECT_EQ("main.cpp:1: warning: message\n", PrintDiag(DiagOpts, Loc)); } } // anonymous namespace