ultimatepp/uppsrc/ide/clang/CurrentFile.cpp
2022-08-18 23:47:15 +02:00

151 lines
4.5 KiB
C++

#include "clang.h"
#define LLOG(x) // LOG(x)
bool current_file_parsing;
CoEvent current_file_event;
CurrentFileContext current_file;
int64 current_file_serial;
int64 current_file_done_serial;
Event<const CppFileInfo&> annotations_done;
void CurrentFileThread()
{
MemoryIgnoreLeaksBlock __;
CurrentFileContext parsed_file;
int64 serial;
Clang clang;
auto DoAnnotations = [&] {
if(!clang.tu || !annotations_done) return;
ClangVisitor v;
v.dolocals = true;
v.WhenFile = [&] (const String& path) { return path == current_file.filename; };
v.Do(clang.tu);
CppFileInfo f;
if(v.info.GetCount()) {
f = pick(v.info[0]);
f.items.RemoveIf([&](int i) { return f.items[i].pos.y < parsed_file.line_delta; });
for(AnnotationItem& m : f.items)
m.pos.y -= parsed_file.line_delta;
f.locals.RemoveIf([&](int i) { return f.locals[i].pos.y < parsed_file.line_delta; });
for(AnnotationItem& m : f.locals)
m.pos.y -= parsed_file.line_delta;
f.refs.RemoveIf([&](int i) { return f.refs[i].pos.y < parsed_file.line_delta; });
for(ReferenceItem& m : f.refs)
m.pos.y -= parsed_file.line_delta;
}
Ctrl::Call([&] {
if(parsed_file.filename == current_file.filename &&
parsed_file.real_filename == current_file.real_filename &&
parsed_file.includes == current_file.includes &&
serial == current_file_serial) {
annotations_done(f);
FileAnnotation fa;
fa.defines = parsed_file.defines;
fa.includes = parsed_file.includes;
fa.items = pick(f.items);
fa.time = Time::Low();
CodeIndex().GetAdd(NormalizePath(parsed_file.real_filename)) = pick(fa);
}
current_file_done_serial = serial;
});
};
while(!Thread::IsShutdownThreads()) {
bool was_parsing;
do {
was_parsing = false;
CurrentFileContext f;
int64 done_serial;
{
GuiLock __;
f = current_file;
serial = current_file_serial;
done_serial = current_file_done_serial;
}
if(f.filename.GetCount()) {
String fn = f.filename;
if(!IsSourceFile(fn))
fn.Cat(".cpp");
if(f.filename != parsed_file.filename || f.real_filename != parsed_file.real_filename ||
f.includes != parsed_file.includes || f.defines != parsed_file.defines ||
!clang.tu) { // TODO: same is in autocomplete
parsed_file = f;
int tm = msecs();
current_file_parsing = true;
clang.Parse(fn, f.content, f.includes, f.defines,
CXTranslationUnit_DetailedPreprocessingRecord|
// CXTranslationUnit_PrecompiledPreamble|
// CXTranslationUnit_CreatePreambleOnFirstParse|
CXTranslationUnit_SkipFunctionBodies|
CXTranslationUnit_LimitSkipFunctionBodiesToPreamble|
CXTranslationUnit_KeepGoing);
// DumpDiagnostics(clang.tu); _DBG_
PutVerbose(String() << "Current file parsed in " << msecs() - tm << " ms");
tm = msecs();
DoAnnotations();
PutVerbose(String() << "Current file parser output processed in " << msecs() - tm << " ms");
current_file_parsing = false;
was_parsing = true;
}
if(Thread::IsShutdownThreads()) break;
if(clang.tu && serial != done_serial) {
TIMESTOP("ReParse");
current_file_parsing = true;
int tm = msecs();
bool b = clang.ReParse(fn, f.content);
PutVerbose(String() << "Current file reparsed in " << msecs() - tm << " ms");
tm = msecs();
if(b)
DoAnnotations();
PutVerbose(String() << "Current file reparsed output processed in " << msecs() - tm << " ms");
current_file_parsing = false;
was_parsing = true;
}
}
}
while(was_parsing);
current_file_event.Wait();
LLOG("Current file Thread::IsShutdownThreads() " << Thread::IsShutdownThreads());
}
LLOG("Current file thread exit");
}
void SetCurrentFile(const CurrentFileContext& ctx, Event<const CppFileInfo&> done)
{
ONCELOCK {
MemoryIgnoreNonMainLeaks();
MemoryIgnoreNonUppThreadsLeaks(); // clangs leaks static memory in threads
Thread::Start([] { CurrentFileThread(); });
Thread::AtShutdown([] {
LLOG("Shutdown current file");
current_file_event.Broadcast();
});
}
GuiLock __;
current_file = ctx;
annotations_done = done;
current_file_event.Broadcast();
current_file_serial++;
}
bool IsCurrentFileDirty()
{
GuiLock __;
return current_file_serial != current_file_done_serial;
}
bool IsCurrentFileParsing()
{
return current_file_parsing;
}
void CancelCurrentFile()
{
GuiLock __;
annotations_done.Clear();
}