New diagnostics

This commit is contained in:
Fangrui Song 2018-08-28 22:49:53 -07:00
parent a66533b023
commit fea457616a
4 changed files with 238 additions and 247 deletions

View File

@ -22,6 +22,7 @@ using namespace llvm;
#include <algorithm>
#include <thread>
namespace ccls {
namespace {
std::string StripFileType(const std::string &path) {
@ -292,6 +293,38 @@ void BuildDetailString(const CodeCompletionString &CCS, lsCompletionItem &item,
}
}
bool LocationInRange(SourceLocation L, CharSourceRange R,
const SourceManager &M) {
assert(R.isCharRange());
if (!R.isValid() || M.getFileID(R.getBegin()) != M.getFileID(R.getEnd()) ||
M.getFileID(R.getBegin()) != M.getFileID(L))
return false;
return L != R.getEnd() && M.isPointWithin(L, R.getBegin(), R.getEnd());
}
CharSourceRange DiagnosticRange(const clang::Diagnostic &D, const LangOptions &L) {
auto &M = D.getSourceManager();
auto Loc = M.getFileLoc(D.getLocation());
// Accept the first range that contains the location.
for (const auto &CR : D.getRanges()) {
auto R = Lexer::makeFileCharRange(CR, M, L);
if (LocationInRange(Loc, R, M))
return R;
}
// The range may be given as a fixit hint instead.
for (const auto &F : D.getFixItHints()) {
auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L);
if (LocationInRange(Loc, R, M))
return R;
}
// If no suitable range is found, just use the token at the location.
auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
if (!R.isValid()) // Fall back to location only, let the editor deal with it.
R = CharSourceRange::getCharRange(Loc);
return R;
}
class CaptureCompletionResults : public CodeCompleteConsumer {
std::shared_ptr<clang::GlobalCodeCompletionAllocator> Alloc;
CodeCompletionTUInfo CCTUInfo;
@ -360,23 +393,83 @@ public:
CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
};
void TryEnsureDocumentParsed(ClangCompleteManager *manager,
std::shared_ptr<CompletionSession> session,
std::unique_ptr<ClangTranslationUnit> *tu,
bool diagnostic) {
// Nothing to do. We already have a translation unit.
if (*tu)
class StoreDiags : public DiagnosticConsumer {
const LangOptions *LangOpts;
std::optional<Diag> last;
std::vector<Diag> output;
void Flush() {
if (!last)
return;
bool mentions = last->inside_main || last->edits.size();
if (!mentions)
for (auto &N : last->notes)
if (N.inside_main)
mentions = true;
if (mentions)
output.push_back(std::move(*last));
last.reset();
}
public:
std::vector<Diag> Take() {
return std::move(output);
}
void BeginSourceFile(const LangOptions &Opts, const Preprocessor *) override {
LangOpts = &Opts;
}
void EndSourceFile() override {
Flush();
}
void HandleDiagnostic(DiagnosticsEngine::Level Level,
const Diagnostic &Info) override {
DiagnosticConsumer::HandleDiagnostic(Level, Info);
SourceLocation L = Info.getLocation();
if (!L.isValid()) return;
const SourceManager &SM = Info.getSourceManager();
bool inside_main = SM.isInMainFile(L);
auto fillDiagBase = [&](DiagBase &d) {
llvm::SmallString<64> Message;
Info.FormatDiagnostic(Message);
d.range =
FromCharSourceRange(SM, *LangOpts, DiagnosticRange(Info, *LangOpts));
d.message = Message.str();
d.inside_main = inside_main;
d.file = SM.getFilename(Info.getLocation());
d.level = Level;
d.category = DiagnosticIDs::getCategoryNumberForDiag(Info.getID());
};
const auto &args = session->file.args;
WorkingFiles::Snapshot snapshot = session->wfiles->AsSnapshot(
{StripFileType(session->file.filename)});
auto addFix = [&](bool SyntheticMessage) -> bool {
if (!inside_main)
return false;
for (const FixItHint &FixIt : Info.getFixItHints()) {
if (!SM.isInMainFile(FixIt.RemoveRange.getBegin()))
return false;
lsTextEdit edit;
edit.newText = FixIt.CodeToInsert;
auto r = FromCharSourceRange(SM, *LangOpts, FixIt.RemoveRange);
edit.range =
lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}};
last->edits.push_back(std::move(edit));
}
return true;
};
LOG_S(INFO) << "create " << (diagnostic ? "diagnostic" : "completion")
<< " TU for " << session->file.filename;
*tu = ClangTranslationUnit::Create(session->file.filename, args, snapshot,
diagnostic);
}
if (Level == DiagnosticsEngine::Note || Level == DiagnosticsEngine::Remark) {
if (Info.getFixItHints().size()) {
addFix(false);
} else {
Note &n = last->notes.emplace_back();
fillDiagBase(n);
}
} else {
Flush();
last = Diag();
fillDiagBase(*last);
if (!Info.getFixItHints().empty())
addFix(true);
}
}
};
std::unique_ptr<CompilerInvocation>
buildCompilerInvocation(const std::vector<std::string> &args,
@ -389,12 +482,61 @@ buildCompilerInvocation(const std::vector<std::string> &args,
std::unique_ptr<CompilerInvocation> CI =
createInvocationFromCommandLine(cargs, Diags, VFS);
if (CI) {
CI->getFrontendOpts().DisableFree = false;
CI->getLangOpts()->CommentOpts.ParseAllComments = true;
CI->getLangOpts()->SpellChecking = false;
}
return CI;
}
std::unique_ptr<CompilerInstance>
BuildCompilerInstance(CompletionSession &session,
std::unique_ptr<CompilerInvocation> CI,
DiagnosticConsumer &DC,
const WorkingFiles::Snapshot &snapshot,
std::vector<std::unique_ptr<llvm::MemoryBuffer>> &Bufs) {
for (auto &file : snapshot.files) {
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content));
if (file.filename == session.file.filename) {
if (auto Preamble = session.GetPreamble()) {
#if LLVM_VERSION_MAJOR >= 7
Preamble->Preamble.OverridePreamble(*CI, session.FS,
Bufs.back().get());
#else
Preamble->Preamble.AddImplicitPreamble(*CI, session->FS,
Bufs.back().get());
#endif
} else {
CI->getPreprocessorOpts().addRemappedFile(
CI->getFrontendOpts().Inputs[0].getFile(), Bufs.back().get());
}
} else {
CI->getPreprocessorOpts().addRemappedFile(file.filename,
Bufs.back().get());
}
}
auto Clang = std::make_unique<CompilerInstance>(session.PCH);
Clang->setInvocation(std::move(CI));
Clang->setVirtualFileSystem(session.FS);
Clang->createDiagnostics(&DC, false);
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
if (!Clang->hasTarget())
return nullptr;
return Clang;
}
bool Parse(CompilerInstance &Clang) {
SyntaxOnlyAction Action;
if (!Action.BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0]))
return false;
if (!Action.Execute())
return false;
Action.EndSourceFile();
return true;
}
void CompletionPreloadMain(ClangCompleteManager *completion_manager) {
while (true) {
// Fetching the completion request blocks until we have a request.
@ -449,56 +591,23 @@ void CompletionQueryMain(ClangCompleteManager *completion_manager) {
#endif
CCOpts.IncludeCodePatterns = true;
auto &FOpts = CI->getFrontendOpts();
FOpts.DisableFree = false;
FOpts.CodeCompleteOpts = CCOpts;
FOpts.CodeCompletionAt.FileName = session->file.filename;
FOpts.CodeCompletionAt.Line = request->position.line + 1;
FOpts.CodeCompletionAt.Column = request->position.character + 1;
StoreDiags DC;
WorkingFiles::Snapshot snapshot =
completion_manager->working_files_->AsSnapshot({StripFileType(path)});
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Bufs;
for (auto &file : snapshot.files) {
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content));
if (file.filename == session->file.filename) {
if (auto Preamble = session->GetPreamble()) {
#if LLVM_VERSION_MAJOR >= 7
Preamble->Preamble.OverridePreamble(*CI, session->FS,
Bufs.back().get());
#else
Preamble->Preamble.AddImplicitPreamble(*CI, session->FS,
Bufs.back().get());
#endif
}
else {
CI->getPreprocessorOpts().addRemappedFile(
CI->getFrontendOpts().Inputs[0].getFile(), Bufs.back().get());
}
} else {
CI->getPreprocessorOpts().addRemappedFile(file.filename,
Bufs.back().get());
}
}
auto Clang = BuildCompilerInstance(*session, std::move(CI), DC, snapshot, Bufs);
if (!Clang)
continue;
IgnoringDiagConsumer DC;
auto Clang = std::make_unique<CompilerInstance>(session->PCH);
Clang->setInvocation(std::move(CI));
Clang->createDiagnostics(&DC, false);
auto Consumer = new CaptureCompletionResults(CCOpts);
Clang->setCodeCompletionConsumer(Consumer);
Clang->setVirtualFileSystem(session->FS);
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
if (!Clang->hasTarget())
if (!Parse(*Clang))
continue;
SyntaxOnlyAction Action;
if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
continue;
if (!Action.Execute())
continue;
Action.EndSourceFile();
for (auto &Buf : Bufs)
Buf.release();
@ -518,51 +627,31 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) {
std::shared_ptr<CompletionSession> session = manager->TryGetSession(
path, true /*mark_as_completion*/, true /*create_if_needed*/);
// At this point, we must have a translation unit. Block until we have one.
std::lock_guard<std::mutex> lock(session->diagnostics.lock);
TryEnsureDocumentParsed(manager, session, &session->diagnostics.tu, true);
// It is possible we failed to create the document despite
// |TryEnsureDocumentParsed|.
ClangTranslationUnit *tu = session->diagnostics.tu.get();
if (!tu)
std::unique_ptr<CompilerInvocation> CI =
buildCompilerInvocation(session->file.args, session->FS);
if (!CI)
continue;
StoreDiags DC;
WorkingFiles::Snapshot snapshot =
manager->working_files_->AsSnapshot({StripFileType(path)});
llvm::CrashRecoveryContext CRC;
if (tu->Reparse(CRC, snapshot)) {
LOG_S(ERROR) << "Reparsing translation unit for diagnostics failed for "
<< path;
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Bufs;
auto Clang = BuildCompilerInstance(*session, std::move(CI), DC, snapshot, Bufs);
if (!Clang)
continue;
}
if (!Parse(*Clang))
continue;
for (auto &Buf : Bufs)
Buf.release();
auto &LangOpts = tu->Unit->getLangOpts();
std::vector<lsDiagnostic> ls_diags;
for (ASTUnit::stored_diag_iterator I = tu->Unit->stored_diag_begin(),
E = tu->Unit->stored_diag_end();
I != E; ++I) {
FullSourceLoc FLoc = I->getLocation();
if (!FLoc.isValid()) // why?
for (auto &d : DC.Take()) {
if (!d.inside_main)
continue;
const FileEntry *FE = FLoc.getFileEntry();
if (!FE || FileName(*FE) != path)
continue;
const auto &SM = FLoc.getManager();
SourceRange R;
for (const auto &CR : I->getRanges()) {
auto RT = Lexer::makeFileCharRange(CR, SM, LangOpts);
if (SM.isPointWithin(FLoc, RT.getBegin(), RT.getEnd())) {
R = CR.getAsRange();
break;
}
}
Range r = R.isValid() ? FromCharRange(SM, LangOpts, R)
: FromTokenRange(SM, LangOpts, {FLoc, FLoc});
lsDiagnostic ls_diag;
ls_diag.range =
lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}};
switch (I->getLevel()) {
lsDiagnostic &ls_diag = ls_diags.emplace_back();
ls_diag.range = lsRange{{d.range.start.line, d.range.start.column},
{d.range.end.line, d.range.end.column}};
ls_diag.message = d.message;
switch (d.level) {
case DiagnosticsEngine::Ignored:
// llvm_unreachable
case DiagnosticsEngine::Note:
@ -576,16 +665,8 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) {
case DiagnosticsEngine::Fatal:
ls_diag.severity = lsDiagnosticSeverity::Error;
}
ls_diag.message = I->getMessage().str();
for (const FixItHint &FixIt : I->getFixIts()) {
lsTextEdit edit;
edit.newText = FixIt.CodeToInsert;
r = FromCharSourceRange(SM, LangOpts, FixIt.RemoveRange);
edit.range =
lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}};
ls_diag.fixits_.push_back(edit);
}
ls_diags.push_back(ls_diag);
ls_diag.code = d.category;
ls_diag.fixits_ = d.edits;
}
manager->on_diagnostic_(path, ls_diags);
}
@ -594,15 +675,15 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) {
} // namespace
std::shared_ptr<PreambleData> CompletionSession::GetPreamble() {
std::lock_guard<std::mutex> lock(completion.lock);
return completion.preamble;
std::lock_guard<std::mutex> lock(mutex);
return preamble;
}
void CompletionSession::BuildPreamble(CompilerInvocation &CI) {
std::shared_ptr<PreambleData> OldP = GetPreamble();
std::string contents = wfiles->GetContent(file.filename);
std::string content = wfiles->GetContent(file.filename);
std::unique_ptr<llvm::MemoryBuffer> Buf =
llvm::MemoryBuffer::getMemBuffer(contents);
llvm::MemoryBuffer::getMemBuffer(content);
auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), Buf.get(), 0);
if (OldP && OldP->Preamble.CanReuse(CI, Buf.get(), Bounds, FS.get()))
return;
@ -612,19 +693,20 @@ void CompletionSession::BuildPreamble(CompilerInvocation &CI) {
CI.getPreprocessorOpts().WriteCommentListToPCH = false;
#endif
DiagnosticConsumer DC;
IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDE =
CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
&DC, false);
StoreDiags DC;
IntrusiveRefCntPtr<DiagnosticsEngine> DE =
CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(), &DC, false);
PreambleCallbacks PP;
if (auto NewPreamble = PrecompiledPreamble::Build(
CI, Buf.get(), Bounds, *PreambleDE, FS, PCH, true, PP)) {
std::lock_guard<std::mutex> lock(completion.lock);
completion.preamble =
std::make_shared<PreambleData>(std::move(*NewPreamble));
if (auto NewPreamble = PrecompiledPreamble::Build(CI, Buf.get(), Bounds,
*DE, FS, PCH, true, PP)) {
std::lock_guard<std::mutex> lock(mutex);
preamble =
std::make_shared<PreambleData>(std::move(*NewPreamble), DC.Take());
}
}
} // namespace ccls
ClangCompleteManager::ClangCompleteManager(Project *project,
WorkingFiles *working_files,
OnDiagnostic on_diagnostic,
@ -636,17 +718,17 @@ ClangCompleteManager::ClangCompleteManager(Project *project,
PCH(std::make_shared<PCHContainerOperations>()) {
std::thread([&]() {
set_thread_name("comp-query");
CompletionQueryMain(this);
ccls::CompletionQueryMain(this);
})
.detach();
std::thread([&]() {
set_thread_name("comp-preload");
CompletionPreloadMain(this);
ccls::CompletionPreloadMain(this);
})
.detach();
std::thread([&]() {
set_thread_name("diag-query");
DiagnosticQueryMain(this);
ccls::DiagnosticQueryMain(this);
})
.detach();
}
@ -734,43 +816,42 @@ bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession(
}
// No CompletionSession, create new one.
auto session = std::make_shared<CompletionSession>(
auto session = std::make_shared<ccls::CompletionSession>(
project_->FindCompilationEntryForFile(filename), working_files_, PCH);
preloaded_sessions_.Insert(session->file.filename, session);
return true;
}
std::shared_ptr<CompletionSession>
std::shared_ptr<ccls::CompletionSession>
ClangCompleteManager::TryGetSession(const std::string &filename,
bool mark_as_completion,
bool create_if_needed) {
std::lock_guard<std::mutex> lock(sessions_lock_);
// Try to find a preloaded session.
std::shared_ptr<CompletionSession> preloaded_session =
std::shared_ptr<ccls::CompletionSession> preloaded =
preloaded_sessions_.TryGet(filename);
if (preloaded_session) {
if (preloaded) {
// If this request is for a completion, we should move it to
// |completion_sessions|.
if (mark_as_completion) {
preloaded_sessions_.TryTake(filename);
completion_sessions_.Insert(filename, preloaded_session);
completion_sessions_.Insert(filename, preloaded);
}
return preloaded_session;
return preloaded;
}
// Try to find a completion session. If none create one.
std::shared_ptr<CompletionSession> completion_session =
std::shared_ptr<ccls::CompletionSession> session =
completion_sessions_.TryGet(filename);
if (!completion_session && create_if_needed) {
completion_session = std::make_shared<CompletionSession>(
if (!session && create_if_needed) {
session = std::make_shared<ccls::CompletionSession>(
project_->FindCompilationEntryForFile(filename), working_files_, PCH);
completion_sessions_.Insert(filename, completion_session);
completion_sessions_.Insert(filename, session);
}
return completion_session;
return session;
}
void ClangCompleteManager::FlushSession(const std::string &filename) {

View File

@ -19,27 +19,33 @@
#include <mutex>
#include <string>
namespace ccls {
struct DiagBase {
Range range;
std::string message;
std::string file;
clang::DiagnosticsEngine::Level level = clang::DiagnosticsEngine::Note;
unsigned category;
bool inside_main = false;
};
struct Note : DiagBase {};
struct Diag : DiagBase {
std::vector<Note> notes;
std::vector<lsTextEdit> edits;
};
struct PreambleData {
PreambleData(clang::PrecompiledPreamble P) : Preamble(std::move(P)) {}
PreambleData(clang::PrecompiledPreamble P, std::vector<Diag> diags)
: Preamble(std::move(P)), diags(std::move(diags)) {}
clang::PrecompiledPreamble Preamble;
std::vector<Diag> diags;
};
struct CompletionSession
: public std::enable_shared_from_this<CompletionSession> {
// Translation unit for clang.
struct Tu {
// When |tu| was last parsed.
std::optional<std::chrono::time_point<std::chrono::high_resolution_clock>>
last_parsed_at;
// Acquired when |tu| is being used.
std::mutex lock;
std::unique_ptr<ClangTranslationUnit> tu;
};
struct CU {
std::mutex lock;
std::mutex mutex;
std::shared_ptr<PreambleData> preamble;
};
std::vector<Diag> diags;
Project::Entry file;
WorkingFiles *wfiles;
@ -49,9 +55,6 @@ struct CompletionSession
clang::vfs::getRealFileSystem();
std::shared_ptr<clang::PCHContainerOperations> PCH;
CU completion;
Tu diagnostics;
CompletionSession(const Project::Entry &file, WorkingFiles *wfiles,
std::shared_ptr<clang::PCHContainerOperations> PCH)
: file(file), wfiles(wfiles), PCH(PCH) {}
@ -59,6 +62,7 @@ struct CompletionSession
std::shared_ptr<PreambleData> GetPreamble();
void BuildPreamble(clang::CompilerInvocation &CI);
};
}
struct ClangCompleteManager {
using OnDiagnostic = std::function<void(
@ -118,8 +122,8 @@ struct ClangCompleteManager {
bool EnsureCompletionOrCreatePreloadSession(const std::string &filename);
// Tries to find an edit session for |filename|. This will move the session
// from view to edit.
std::shared_ptr<CompletionSession> TryGetSession(const std::string &filename,
bool mark_as_completion,
std::shared_ptr<ccls::CompletionSession>
TryGetSession(const std::string &filename, bool mark_as_completion,
bool create_if_needed);
// Flushes all saved sessions with the supplied filename
@ -137,7 +141,7 @@ struct ClangCompleteManager {
OnDiagnostic on_diagnostic_;
OnDropped on_dropped_;
using LruSessionCache = LruCache<std::string, CompletionSession>;
using LruSessionCache = LruCache<std::string, ccls::CompletionSession>;
// CompletionSession instances which are preloaded, ie, files which the user
// has viewed but not requested code completion for.

View File

@ -4,12 +4,8 @@
#include "clang_tu.h"
#include "clang_utils.h"
#include "log.hh"
#include "platform.h"
#include "utils.h"
#include "working_files.h"
#include <llvm/Support/CrashRecoveryContext.h>
#include <clang/Lex/Lexer.h>
using namespace clang;
#include <assert.h>
@ -55,72 +51,3 @@ Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts,
return FromCharSourceRange(SM, LangOpts, CharSourceRange::getTokenRange(R),
UniqueID);
}
std::vector<ASTUnit::RemappedFile>
GetRemapped(const WorkingFiles::Snapshot &snapshot) {
std::vector<ASTUnit::RemappedFile> Remapped;
for (auto &file : snapshot.files) {
std::unique_ptr<llvm::MemoryBuffer> MB =
llvm::MemoryBuffer::getMemBufferCopy(file.content, file.filename);
Remapped.emplace_back(file.filename, MB.release());
}
return Remapped;
}
std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
const std::string &filepath, const std::vector<std::string> &args,
const WorkingFiles::Snapshot &snapshot, bool diagnostic) {
std::vector<const char *> Args;
for (auto &arg : args)
Args.push_back(arg.c_str());
Args.push_back("-fallow-editor-placeholders");
if (!diagnostic)
Args.push_back("-fno-spell-checking");
auto ret = std::make_unique<ClangTranslationUnit>();
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
CompilerInstance::createDiagnostics(new DiagnosticOptions));
std::vector<ASTUnit::RemappedFile> Remapped = GetRemapped(snapshot);
ret->PCHCO = std::make_shared<PCHContainerOperations>();
std::unique_ptr<ASTUnit> ErrUnit, Unit;
llvm::CrashRecoveryContext CRC;
auto parse = [&]() {
Unit.reset(ASTUnit::LoadFromCommandLine(
Args.data(), Args.data() + Args.size(),
/*PCHContainerOpts=*/ret->PCHCO, Diags,
/*ResourceFilePath=*/g_config->clang.resourceDir,
/*OnlyLocalDecls=*/false,
/*CaptureDiagnostics=*/diagnostic, Remapped,
/*RemappedFilesKeepOriginalName=*/true, 0,
diagnostic ? TU_Complete : TU_Prefix,
/*CacheCodeCompletionResults=*/true, g_config->index.comments,
/*AllowPCHWithCompilerErrors=*/true,
#if LLVM_VERSION_MAJOR >= 7
SkipFunctionBodiesScope::None,
#else
!diagnostic,
#endif
/*SingleFileParse=*/false,
/*UserFilesAreVolatile=*/true, false,
ret->PCHCO->getRawReader().getFormat(), &ErrUnit));
};
if (!CRC.RunSafely(parse)) {
LOG_S(ERROR) << "clang crashed for " << filepath << "\n"
<< StringJoin(args, " ") + " -fsyntax-only";
return {};
}
if (!Unit && !ErrUnit)
return {};
ret->Unit = std::move(Unit);
return ret;
}
int ClangTranslationUnit::Reparse(llvm::CrashRecoveryContext &CRC,
const WorkingFiles::Snapshot &snapshot) {
int ret = 1;
(void)CRC.RunSafely(
[&]() { ret = Unit->Reparse(PCHCO, GetRemapped(snapshot)); });
return ret;
}

View File

@ -3,19 +3,10 @@
#pragma once
#include "position.h"
#include "working_files.h"
#include <clang/Frontend/ASTUnit.h>
#include <clang/Frontend/CompilerInstance.h>
#include <llvm/Support/CrashRecoveryContext.h>
#include <clang/Basic/SourceManager.h>
#include <memory>
#include <stdlib.h>
#include <string>
#include <vector>
std::vector<clang::ASTUnit::RemappedFile>
GetRemapped(const WorkingFiles::Snapshot &snapshot);
Range FromCharSourceRange(const clang::SourceManager &SM,
const clang::LangOptions &LangOpts,
@ -29,15 +20,3 @@ Range FromCharRange(const clang::SourceManager &SM,
Range FromTokenRange(const clang::SourceManager &SM,
const clang::LangOptions &LangOpts, clang::SourceRange R,
llvm::sys::fs::UniqueID *UniqueID = nullptr);
struct ClangTranslationUnit {
static std::unique_ptr<ClangTranslationUnit>
Create(const std::string &filepath, const std::vector<std::string> &args,
const WorkingFiles::Snapshot &snapshot, bool diagnostic);
int Reparse(llvm::CrashRecoveryContext &CRC,
const WorkingFiles::Snapshot &snapshot);
std::shared_ptr<clang::PCHContainerOperations> PCHCO;
std::unique_ptr<clang::ASTUnit> Unit;
};