mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-25 14:22:54 -06:00
refactoring part 1
This commit is contained in:
parent
a7cbd047e8
commit
8a5af27cf7
7 changed files with 344 additions and 561 deletions
3
uppsrc/ide/clang/AutoComplete.cpp
Normal file
3
uppsrc/ide/clang/AutoComplete.cpp
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#include "clang.h"
|
||||
|
||||
void foo() {}
|
||||
|
|
@ -1,10 +1,32 @@
|
|||
#include "clang.h"
|
||||
|
||||
// TODO: Remove
|
||||
|
||||
#define LLOG(x)
|
||||
|
||||
CXChildVisitResult current_file_visitor2( CXCursor cursor, CXCursor p, CXClientData clientData )
|
||||
{
|
||||
#if 0
|
||||
auto Dump = [&] {
|
||||
#if 1
|
||||
SourceLocation location(cxlocation);
|
||||
LOG("=====================");
|
||||
// DDUMP(location);
|
||||
// DDUMP((int)cursorKind);
|
||||
DDUMP(GetCursorKindName(cursorKind));
|
||||
DDUMP(name);
|
||||
DDUMP(type);
|
||||
DDUMP(pid);
|
||||
DDUMP(CleanupId(pid));
|
||||
DDUMP(scope);
|
||||
DDUMP(nspace);
|
||||
DDUMP(clang_isCursorDefinition(cursor));
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static Index<unsigned> visited;
|
||||
unsigned h = clang_hashCursor(cursor);
|
||||
if(visited.Find(h) >= 0)
|
||||
|
|
|
|||
|
|
@ -14,196 +14,6 @@ Event<const Vector<AutoCompleteItem>&> autocomplete_done;
|
|||
bool do_annotations;
|
||||
Event<const Vector<AnnotationItem>&> annotations_done;
|
||||
|
||||
CXChildVisitResult current_file_visitor( CXCursor cursor, CXCursor p, CXClientData clientData)
|
||||
{
|
||||
CXSourceLocation cxlocation = clang_getCursorLocation(cursor);
|
||||
bool valid = clang_Location_isFromMainFile(cxlocation);
|
||||
|
||||
|
||||
// TODO: change this for MT
|
||||
static CXPrintingPolicy pp_id = clang_getCursorPrintingPolicy(cursor);
|
||||
ONCELOCK {
|
||||
for(int i = 0; i <= CXPrintingPolicy_LastProperty; i++)
|
||||
clang_PrintingPolicy_setProperty(pp_id, (CXPrintingPolicyProperty)i, 0);
|
||||
|
||||
for(CXPrintingPolicyProperty p : {
|
||||
CXPrintingPolicy_SuppressSpecifiers,
|
||||
CXPrintingPolicy_SuppressTagKeyword,
|
||||
CXPrintingPolicy_SuppressUnwrittenScope,
|
||||
CXPrintingPolicy_SuppressInitializers,
|
||||
CXPrintingPolicy_SuppressStrongLifetime,
|
||||
CXPrintingPolicy_SuppressLifetimeQualifiers,
|
||||
CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors,
|
||||
CXPrintingPolicy_TerseOutput,
|
||||
CXPrintingPolicy_SuppressImplicitBase,
|
||||
CXPrintingPolicy_FullyQualifiedName })
|
||||
clang_PrintingPolicy_setProperty(pp_id, p, 1);
|
||||
};
|
||||
|
||||
if(valid) {
|
||||
String m;
|
||||
|
||||
CXCursor parent = clang_getCursorSemanticParent(cursor);
|
||||
CXCursorKind cursorKind = clang_getCursorKind(cursor);
|
||||
CXCursorKind parentKind = clang_getCursorKind(parent);
|
||||
|
||||
String name = GetCursorSpelling(cursor);
|
||||
String type = GetTypeSpelling(cursor);
|
||||
String id = FetchString(clang_getCursorPrettyPrinted(cursor, pp_id));
|
||||
CXCursor p = parent;
|
||||
String scope;
|
||||
String nspace;
|
||||
for(;;) {
|
||||
CXCursorKind k = clang_getCursorKind(p);
|
||||
if(findarg(k, CXCursor_Namespace, CXCursor_ClassTemplate, CXCursor_StructDecl, CXCursor_UnionDecl, CXCursor_ClassDecl) < 0)
|
||||
break;
|
||||
String q = GetCursorSpelling(p);
|
||||
scope = scope.GetCount() ? q + "::" + scope : q;
|
||||
if(k == CXCursor_Namespace)
|
||||
nspace = nspace.GetCount() ? q + "::" + nspace : q;
|
||||
p = clang_getCursorSemanticParent(p);
|
||||
}
|
||||
int q = scope.Find('('); // 'Struct::(unnamed enum at C:\u\upp.src\upptst\Annotations\main.cpp:47:2)'
|
||||
if(q >= 0)
|
||||
scope.Trim(q);
|
||||
if(scope.GetCount() && *scope.Last() != ':')
|
||||
scope << "::";
|
||||
|
||||
auto Dump = [&] {
|
||||
#if 1
|
||||
SourceLocation location(cxlocation);
|
||||
LOG("=====================");
|
||||
// DDUMP(location);
|
||||
// DDUMP((int)cursorKind);
|
||||
DDUMP(GetCursorKindName(cursorKind));
|
||||
DDUMP(name);
|
||||
DDUMP(type);
|
||||
DDUMP(id);
|
||||
DDUMP(CleanupId(id));
|
||||
DDUMP(scope);
|
||||
DDUMP(nspace);
|
||||
DDUMP(clang_isCursorDefinition(cursor));
|
||||
static CXPrintingPolicy pp = clang_getCursorPrintingPolicy(cursor);
|
||||
ONCELOCK {
|
||||
for(int i = 0; i <= CXPrintingPolicy_LastProperty; i++)
|
||||
clang_PrintingPolicy_setProperty(pp, (CXPrintingPolicyProperty)i, 0);
|
||||
|
||||
for(CXPrintingPolicyProperty p : {
|
||||
CXPrintingPolicy_SuppressSpecifiers,
|
||||
CXPrintingPolicy_SuppressTagKeyword,
|
||||
// CXPrintingPolicy_IncludeTagDefinition,
|
||||
// CXPrintingPolicy_SuppressScope,
|
||||
CXPrintingPolicy_SuppressUnwrittenScope,
|
||||
CXPrintingPolicy_SuppressInitializers,
|
||||
// CXPrintingPolicy_ConstantArraySizeAsWritten,
|
||||
// CXPrintingPolicy_AnonymousTagLocations,
|
||||
CXPrintingPolicy_SuppressStrongLifetime,
|
||||
CXPrintingPolicy_SuppressLifetimeQualifiers,
|
||||
CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors,
|
||||
// CXPrintingPolicy_Bool,
|
||||
// CXPrintingPolicy_Restrict,
|
||||
// CXPrintingPolicy_Alignof,
|
||||
// CXPrintingPolicy_UnderscoreAlignof,
|
||||
// CXPrintingPolicy_UseVoidForZeroParams,
|
||||
CXPrintingPolicy_TerseOutput,
|
||||
// CXPrintingPolicy_PolishForDeclaration,
|
||||
// CXPrintingPolicy_Half,
|
||||
// CXPrintingPolicy_MSWChar,
|
||||
// CXPrintingPolicy_IncludeNewlines,
|
||||
// CXPrintingPolicy_MSVCFormatting,
|
||||
// CXPrintingPolicy_ConstantsAsWritten,
|
||||
CXPrintingPolicy_SuppressImplicitBase,
|
||||
CXPrintingPolicy_FullyQualifiedName })
|
||||
clang_PrintingPolicy_setProperty(pp, p, 1);
|
||||
};
|
||||
{
|
||||
// DTIMING("PrettyPrinting");
|
||||
// DDUMP(FetchString(clang_getCursorPrettyPrinted(cursor, pp)));
|
||||
}
|
||||
// DDUMP(FetchString(clang_Cursor_getMangling(cursor)));
|
||||
// DDUMP(CxxDemangle(FetchString(clang_Cursor_getMangling(cursor))));
|
||||
// DDUMP(GetCursorKindName(parentKind));
|
||||
// DDUMP(GetCursorSpelling(parent));
|
||||
// DDUMP(GetTypeSpelling(parent));
|
||||
#endif
|
||||
};
|
||||
|
||||
Dump();
|
||||
|
||||
bool external = false;
|
||||
if(findarg(parentKind, CXCursor_FunctionTemplate, CXCursor_FunctionDecl, CXCursor_CXXMethod,
|
||||
CXCursor_Constructor, CXCursor_Destructor) >= 0)
|
||||
valid = false; // local variable
|
||||
else
|
||||
switch(cursorKind) {
|
||||
case CXCursor_StructDecl:
|
||||
case CXCursor_UnionDecl:
|
||||
case CXCursor_ClassDecl:
|
||||
case CXCursor_FunctionTemplate:
|
||||
case CXCursor_FunctionDecl:
|
||||
case CXCursor_Constructor:
|
||||
case CXCursor_Destructor:
|
||||
case CXCursor_CXXMethod:
|
||||
m = id;
|
||||
break;
|
||||
case CXCursor_VarDecl:
|
||||
external = clang_Cursor_hasVarDeclExternalStorage(cursor);
|
||||
case CXCursor_FieldDecl:
|
||||
case CXCursor_ClassTemplate:
|
||||
m << scope << name;
|
||||
break;
|
||||
case CXCursor_ConversionFunction:
|
||||
m << scope << "operator " << type;
|
||||
break;
|
||||
case CXCursor_MacroDefinition:
|
||||
m = name;
|
||||
break;
|
||||
case CXCursor_EnumConstantDecl:
|
||||
m << scope << name;
|
||||
break;
|
||||
case CXCursor_EnumDecl:
|
||||
// case CXCursor_ParmDecl:
|
||||
case CXCursor_TypedefDecl:
|
||||
case CXCursor_Namespace:
|
||||
case CXCursor_UnexposedDecl:
|
||||
// case CXCursor_NamespaceAlias:
|
||||
break;
|
||||
default:
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if(valid) {
|
||||
// Dump();
|
||||
if(m.GetCount()) {
|
||||
CXFile file;
|
||||
unsigned line_;
|
||||
unsigned column_;
|
||||
unsigned offset_;
|
||||
clang_getExpansionLocation(cxlocation, &file, &line_, &column_, &offset_);
|
||||
AnnotationItem& r = static_cast<Vector<AnnotationItem> *>(clientData)->Add();
|
||||
r.kind = cursorKind;
|
||||
r.name = name;
|
||||
r.line = line_;
|
||||
r.id = CleanupId(m);
|
||||
r.definition = clang_isCursorDefinition(cursor);
|
||||
r.external = external;
|
||||
r.nspace = nspace;
|
||||
static CXPrintingPolicy pp;
|
||||
ONCELOCK {
|
||||
pp = clang_getCursorPrintingPolicy(cursor);
|
||||
for(int i = 0; i <= CXPrintingPolicy_LastProperty; i++)
|
||||
clang_PrintingPolicy_setProperty(pp, (CXPrintingPolicyProperty)i, 0);
|
||||
clang_PrintingPolicy_setProperty(pp, CXPrintingPolicy_TerseOutput, 1);
|
||||
clang_PrintingPolicy_setProperty(pp, CXPrintingPolicy_SuppressScope, 1);
|
||||
}
|
||||
r.pretty = CleanupPretty(FetchString(clang_getCursorPrettyPrinted(cursor, pp)));
|
||||
}
|
||||
}
|
||||
}
|
||||
clang_visitChildren(cursor, current_file_visitor, clientData);
|
||||
return CXChildVisit_Continue;
|
||||
}
|
||||
|
||||
void ReadAutocomplete(const CXCompletionString& string, String& name, String& signature)
|
||||
{
|
||||
const int chunkCount = clang_getNumCompletionChunks(string);
|
||||
|
|
@ -227,30 +37,38 @@ void ReadAutocomplete(const CXCompletionString& string, String& name, String& si
|
|||
}
|
||||
}
|
||||
|
||||
struct CurrentFileVisitor : ClangVisitor {
|
||||
Vector<AnnotationItem> item;
|
||||
virtual void Item() {
|
||||
AnnotationItem& r = item.Add();
|
||||
r.kind = GetKind();
|
||||
r.name = GetName();
|
||||
r.line = GetLine();
|
||||
r.id = GetId();
|
||||
r.definition = IsDefinition();
|
||||
r.external = IsExtern();
|
||||
r.nspace = GetNamespace();
|
||||
}
|
||||
};
|
||||
|
||||
void CurrentFileThread()
|
||||
{
|
||||
MemoryIgnoreLeaksBlock __;
|
||||
|
||||
CurrentFileContext parsed_file;
|
||||
CXTranslationUnit tu = nullptr;
|
||||
int64 serial;
|
||||
|
||||
auto DisposeTU = [&] {
|
||||
if(tu) clang_disposeTranslationUnit(tu);
|
||||
tu = nullptr;
|
||||
};
|
||||
|
||||
Clang clang;
|
||||
|
||||
auto DoAnnotations = [&] {
|
||||
if(!tu || !annotations_done) return;
|
||||
Vector<AnnotationItem> item;
|
||||
{ TIMESTOP("DoAnnotations");
|
||||
clang_visitChildren(clang_getTranslationUnitCursor(tu), current_file_visitor, &item);
|
||||
}
|
||||
if(!clang.tu || !annotations_done) return;
|
||||
CurrentFileVisitor v;
|
||||
v.Do(clang.tu);
|
||||
Ctrl::Call([&] {
|
||||
if(parsed_file.filename == current_file.filename &&
|
||||
parsed_file.real_filename == current_file.real_filename &&
|
||||
parsed_file.includes == current_file.includes)
|
||||
annotations_done(item);
|
||||
annotations_done(v.item);
|
||||
do_annotations = false;
|
||||
});
|
||||
};
|
||||
|
|
@ -266,76 +84,71 @@ void CurrentFileThread()
|
|||
annotations_do = do_annotations;
|
||||
macros = autocomplete_macros;
|
||||
}
|
||||
String fn = f.filename;
|
||||
if(!IsSourceFile(fn))
|
||||
fn.Cat(".cpp");
|
||||
if(f.filename != parsed_file.filename || f.includes != parsed_file.includes ||
|
||||
f.real_filename != parsed_file.real_filename || !tu) {
|
||||
parsed_file = f;
|
||||
DisposeTU();
|
||||
String cmdline;
|
||||
cmdline << fn << " -DflagDEBUG -DflagDEBUG_FULL -DflagBLITZ -DflagWIN32 -DflagMAIN -DflagGUI -xc++ -std=c++17 ";
|
||||
for(String s : Split(f.includes, ';'))
|
||||
cmdline << " -I" << s;
|
||||
tu = Clang(cmdline, { { ~fn, f.content } },
|
||||
CXTranslationUnit_DetailedPreprocessingRecord|
|
||||
CXTranslationUnit_PrecompiledPreamble|
|
||||
CXTranslationUnit_CreatePreambleOnFirstParse|
|
||||
CXTranslationUnit_KeepGoing|
|
||||
CXTranslationUnit_RetainExcludedConditionalBlocks);
|
||||
DoAnnotations();
|
||||
annotations_do = false;
|
||||
// DumpDiagnostics(tu);
|
||||
}
|
||||
if(Thread::IsShutdownThreads()) break;
|
||||
CXUnsavedFile ufile = { ~fn, ~f.content, (unsigned)f.content.GetCount() };
|
||||
if(autocomplete_do && tu) {
|
||||
CXCodeCompleteResults *results;
|
||||
{
|
||||
TIMESTOP("clang_codeCompleteAt");
|
||||
results = clang_codeCompleteAt(tu, fn, autocomplete_pos.y, autocomplete_pos.x, &ufile, 1,
|
||||
macros ? CXCodeComplete_IncludeMacros : 0);
|
||||
}
|
||||
// DumpDiagnostics(tu);
|
||||
if(results) {
|
||||
Vector<AutoCompleteItem> item;
|
||||
for(int i = 0; i < results->NumResults; i++) {
|
||||
const CXCompletionString& string = results->Results[i].CompletionString;
|
||||
int kind = results->Results[i].CursorKind;
|
||||
if(kind == CXCursor_MacroDefinition && !macros) // we probably want this only on Ctrl+Space
|
||||
continue;
|
||||
if(kind == CXCursor_NotImplemented)
|
||||
continue;
|
||||
String name;
|
||||
String signature;
|
||||
ReadAutocomplete(string, name, signature);
|
||||
AutoCompleteItem& m = item.Add();
|
||||
m.name = name;
|
||||
m.parent = FetchString(clang_getCompletionParent(string, NULL));
|
||||
m.signature = CleanupPretty(signature);
|
||||
m.kind = kind;
|
||||
m.priority = clang_getCompletionPriority(string);
|
||||
}
|
||||
clang_disposeCodeCompleteResults(results);
|
||||
Ctrl::Call([&] {
|
||||
if(serial == autocomplete_serial)
|
||||
autocomplete_done(item);
|
||||
});
|
||||
}
|
||||
GuiLock __;
|
||||
do_autocomplete = false;
|
||||
}
|
||||
if(Thread::IsShutdownThreads()) break;
|
||||
if(annotations_do && tu) {
|
||||
TIMESTOP("ReParse");
|
||||
if(clang_reparseTranslationUnit(tu, 1, &ufile, 0))
|
||||
DisposeTU();
|
||||
else
|
||||
if(f.filename.GetCount()) {
|
||||
String fn = f.filename;
|
||||
if(!IsSourceFile(fn))
|
||||
fn.Cat(".cpp");
|
||||
if(f.filename != parsed_file.filename || f.includes != parsed_file.includes ||
|
||||
f.real_filename != parsed_file.real_filename || !clang.tu) {
|
||||
parsed_file = f;
|
||||
clang.Dispose();
|
||||
clang.Parse(fn, f.content, f.includes, String(),
|
||||
CXTranslationUnit_DetailedPreprocessingRecord|
|
||||
CXTranslationUnit_PrecompiledPreamble|
|
||||
CXTranslationUnit_CreatePreambleOnFirstParse|
|
||||
CXTranslationUnit_KeepGoing|
|
||||
CXTranslationUnit_RetainExcludedConditionalBlocks);
|
||||
DoAnnotations();
|
||||
annotations_do = false;
|
||||
// DumpDiagnostics(tu);
|
||||
}
|
||||
if(Thread::IsShutdownThreads()) break;
|
||||
CXUnsavedFile ufile = { ~fn, ~f.content, (unsigned)f.content.GetCount() };
|
||||
if(autocomplete_do && clang.tu) {
|
||||
CXCodeCompleteResults *results;
|
||||
{
|
||||
TIMESTOP("clang_codeCompleteAt");
|
||||
results = clang_codeCompleteAt(clang.tu, fn, autocomplete_pos.y, autocomplete_pos.x, &ufile, 1,
|
||||
macros ? CXCodeComplete_IncludeMacros : 0);
|
||||
}
|
||||
// DumpDiagnostics(tu);
|
||||
if(results) {
|
||||
Vector<AutoCompleteItem> item;
|
||||
for(int i = 0; i < results->NumResults; i++) {
|
||||
const CXCompletionString& string = results->Results[i].CompletionString;
|
||||
int kind = results->Results[i].CursorKind;
|
||||
if(kind == CXCursor_MacroDefinition && !macros) // we probably want this only on Ctrl+Space
|
||||
continue;
|
||||
if(kind == CXCursor_NotImplemented)
|
||||
continue;
|
||||
String name;
|
||||
String signature;
|
||||
ReadAutocomplete(string, name, signature);
|
||||
AutoCompleteItem& m = item.Add();
|
||||
m.name = name;
|
||||
m.parent = FetchString(clang_getCompletionParent(string, NULL));
|
||||
m.signature = CleanupPretty(signature);
|
||||
m.kind = kind;
|
||||
m.priority = clang_getCompletionPriority(string);
|
||||
}
|
||||
clang_disposeCodeCompleteResults(results);
|
||||
Ctrl::Call([&] {
|
||||
if(serial == autocomplete_serial)
|
||||
autocomplete_done(item);
|
||||
});
|
||||
}
|
||||
GuiLock __;
|
||||
do_autocomplete = false;
|
||||
}
|
||||
if(Thread::IsShutdownThreads()) break;
|
||||
if(annotations_do && clang.tu) {
|
||||
TIMESTOP("ReParse");
|
||||
if(clang.ReParse(fn, f.content))
|
||||
DoAnnotations();
|
||||
}
|
||||
}
|
||||
current_file_event.Wait(500);
|
||||
}
|
||||
DisposeTU();
|
||||
}
|
||||
|
||||
void StartCurrentFileParserThread()
|
||||
|
|
|
|||
144
uppsrc/ide/clang/Visitor.cpp
Normal file
144
uppsrc/ide/clang/Visitor.cpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#include "clang.h"
|
||||
|
||||
void ClangVisitor::ProcessNode(CXCursor c)
|
||||
{
|
||||
cursor = c;
|
||||
CXSourceLocation cxlocation = clang_getCursorLocation(cursor);
|
||||
bool annotation = clang_Location_isFromMainFile(cxlocation);
|
||||
|
||||
if(annotation) {
|
||||
String m;
|
||||
|
||||
CXCursor parent = clang_getCursorSemanticParent(cursor);
|
||||
CXCursorKind cursorKind = clang_getCursorKind(cursor);
|
||||
CXCursorKind parentKind = clang_getCursorKind(parent);
|
||||
|
||||
name = GetCursorSpelling(cursor);
|
||||
type = GetTypeSpelling(cursor);
|
||||
String pid = FetchString(clang_getCursorPrettyPrinted(cursor, pp_id));
|
||||
|
||||
CXCursor p = parent;
|
||||
scope.Clear();
|
||||
nspace.Clear();
|
||||
for(;;) {
|
||||
CXCursorKind k = clang_getCursorKind(p);
|
||||
if(findarg(k, CXCursor_Namespace, CXCursor_ClassTemplate, CXCursor_StructDecl, CXCursor_UnionDecl, CXCursor_ClassDecl) < 0)
|
||||
break;
|
||||
String q = GetCursorSpelling(p);
|
||||
scope = scope.GetCount() ? q + "::" + scope : q;
|
||||
if(k == CXCursor_Namespace)
|
||||
nspace = nspace.GetCount() ? q + "::" + nspace : q;
|
||||
p = clang_getCursorSemanticParent(p);
|
||||
}
|
||||
int q = scope.Find('('); // 'Struct::(unnamed enum at C:\u\upp.src\upptst\Annotations\main.cpp:47:2)'
|
||||
if(q >= 0)
|
||||
scope.Trim(q);
|
||||
if(scope.GetCount() && *scope.Last() != ':')
|
||||
scope << "::";
|
||||
|
||||
external = false;
|
||||
if(findarg(parentKind, CXCursor_FunctionTemplate, CXCursor_FunctionDecl, CXCursor_CXXMethod,
|
||||
CXCursor_Constructor, CXCursor_Destructor) >= 0)
|
||||
annotation = false; // local variable
|
||||
else
|
||||
switch(cursorKind) {
|
||||
case CXCursor_StructDecl:
|
||||
case CXCursor_UnionDecl:
|
||||
case CXCursor_ClassDecl:
|
||||
case CXCursor_FunctionTemplate:
|
||||
case CXCursor_FunctionDecl:
|
||||
case CXCursor_Constructor:
|
||||
case CXCursor_Destructor:
|
||||
case CXCursor_CXXMethod:
|
||||
m = id;
|
||||
break;
|
||||
case CXCursor_VarDecl:
|
||||
external = clang_Cursor_hasVarDeclExternalStorage(cursor);
|
||||
case CXCursor_FieldDecl:
|
||||
case CXCursor_ClassTemplate:
|
||||
m << scope << name;
|
||||
break;
|
||||
case CXCursor_ConversionFunction:
|
||||
m << scope << "operator " << type;
|
||||
break;
|
||||
case CXCursor_MacroDefinition:
|
||||
m = name;
|
||||
break;
|
||||
case CXCursor_EnumConstantDecl:
|
||||
m << scope << name;
|
||||
break;
|
||||
case CXCursor_EnumDecl:
|
||||
// case CXCursor_ParmDecl:
|
||||
case CXCursor_TypedefDecl:
|
||||
case CXCursor_Namespace:
|
||||
case CXCursor_UnexposedDecl:
|
||||
// case CXCursor_NamespaceAlias:
|
||||
// break;
|
||||
default:
|
||||
annotation = false;
|
||||
break;
|
||||
}
|
||||
if(annotation) {
|
||||
// Dump();
|
||||
if(m.GetCount()) {
|
||||
CXFile file;
|
||||
unsigned line_;
|
||||
unsigned column_;
|
||||
unsigned offset_;
|
||||
clang_getExpansionLocation(cxlocation, &file, &line_, &column_, &offset_);
|
||||
line = line_;
|
||||
column = column_;
|
||||
kind = cursorKind;
|
||||
pretty = CleanupPretty(FetchString(clang_getCursorPrettyPrinted(cursor, pp_pretty)));
|
||||
id = CleanupId(m);
|
||||
Item();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CXChildVisitResult clang_visitor(CXCursor cursor, CXCursor p, CXClientData clientData) {
|
||||
ClangVisitor *v = (ClangVisitor *)clientData;
|
||||
v->ProcessNode(cursor);
|
||||
clang_visitChildren(cursor, clang_visitor, clientData);
|
||||
return CXChildVisit_Continue;
|
||||
}
|
||||
|
||||
void ClangVisitor::Do(CXTranslationUnit tu)
|
||||
{
|
||||
if(!tu) return;
|
||||
CXCursor cursor = clang_getTranslationUnitCursor(tu);
|
||||
pp_id = clang_getCursorPrintingPolicy(cursor);
|
||||
pp_pretty = clang_getCursorPrintingPolicy(cursor);
|
||||
for(int i = 0; i <= CXPrintingPolicy_LastProperty; i++) {
|
||||
clang_PrintingPolicy_setProperty(pp_id, (CXPrintingPolicyProperty)i, 0);
|
||||
clang_PrintingPolicy_setProperty(pp_pretty, (CXPrintingPolicyProperty)i, 0);
|
||||
}
|
||||
|
||||
for(CXPrintingPolicyProperty p : {
|
||||
CXPrintingPolicy_SuppressSpecifiers,
|
||||
CXPrintingPolicy_SuppressTagKeyword,
|
||||
CXPrintingPolicy_SuppressUnwrittenScope,
|
||||
CXPrintingPolicy_SuppressInitializers,
|
||||
CXPrintingPolicy_SuppressStrongLifetime,
|
||||
CXPrintingPolicy_SuppressLifetimeQualifiers,
|
||||
CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors,
|
||||
CXPrintingPolicy_TerseOutput,
|
||||
CXPrintingPolicy_SuppressImplicitBase,
|
||||
CXPrintingPolicy_FullyQualifiedName })
|
||||
clang_PrintingPolicy_setProperty(pp_id, p, 1);
|
||||
|
||||
clang_PrintingPolicy_setProperty(pp_pretty, CXPrintingPolicy_TerseOutput, 1);
|
||||
clang_PrintingPolicy_setProperty(pp_pretty, CXPrintingPolicy_SuppressScope, 1);
|
||||
initialized = true;
|
||||
clang_visitChildren(cursor, clang_visitor, this);
|
||||
}
|
||||
|
||||
ClangVisitor::~ClangVisitor()
|
||||
{
|
||||
if(initialized) {
|
||||
clang_PrintingPolicy_dispose(pp_id);
|
||||
clang_PrintingPolicy_dispose(pp_pretty);
|
||||
}
|
||||
}
|
||||
|
|
@ -42,316 +42,64 @@ SourceLocation::SourceLocation(CXSourceLocation location)
|
|||
filename = FetchString(clang_getFileName(file));
|
||||
}
|
||||
|
||||
CXChildVisitResult visitor( CXCursor cursor, CXCursor /* parent */, CXClientData clientData )
|
||||
void Clang::Dispose()
|
||||
{
|
||||
#if 0
|
||||
static Index<unsigned> visited;
|
||||
unsigned h = clang_hashCursor(cursor);
|
||||
if(visited.Find(h) >= 0)
|
||||
return CXChildVisit_Continue;
|
||||
visited.Add(h);
|
||||
#endif
|
||||
CXSourceLocation cxlocation = clang_getCursorLocation( cursor );
|
||||
SourceLocation location = cxlocation;
|
||||
// if( clang_Location_isFromMainFile( location ) == 0 )
|
||||
// return CXChildVisit_Continue;
|
||||
|
||||
CXCursorKind cursorKind = clang_getCursorKind( cursor );
|
||||
|
||||
unsigned int curLevel = *( reinterpret_cast<unsigned int*>(clientData));
|
||||
unsigned int nextLevel = curLevel + 1;
|
||||
|
||||
if(curLevel > 100000 && curLevel - 100000 > 2)
|
||||
return CXChildVisit_Continue;
|
||||
|
||||
if (1 || findarg(cursorKind, CXCursorKind::CXCursor_FunctionDecl, CXCursorKind::CXCursor_CXXMethod,
|
||||
CXCursorKind::CXCursor_FunctionTemplate, CXCursorKind::CXCursor_Constructor) >= 0
|
||||
|| clang_Location_isFromMainFile(cxlocation)) {
|
||||
|
||||
String indent = curLevel > 100000 ? String('=', curLevel - 100000) : String('-', curLevel);
|
||||
LOG(indent << " " << GetCursorKindName(cursorKind)
|
||||
<< " '" << GetCursorSpelling(cursor) << "' "
|
||||
<< " '" << GetTypeSpelling(cursor) << "' " << location);
|
||||
String h = FetchString(clang_getCursorUSR(cursor));
|
||||
if(h.GetCount())
|
||||
LOG(indent << " USR: " << h);
|
||||
CXCursor c2 = clang_getCursorReferenced(cursor);
|
||||
if(!clang_Cursor_isNull(c2)) {
|
||||
LOG(indent << "Referenced: " << GetCursorSpelling(c2) << ' ' << GetCursorKindName(clang_getCursorKind(c2)));
|
||||
String h = FetchString(clang_getCursorUSR(c2));
|
||||
if(h.GetCount())
|
||||
LOG(indent << "->USR: " << h);
|
||||
// int h = nextLevel < 100000 ? nextLevel + 100000 : nextLevel;
|
||||
// clang_visitChildren(c2, visitor, &h);
|
||||
}
|
||||
// clang_visitChildren(cursor, visitor, &nextLevel);
|
||||
}
|
||||
|
||||
return CXChildVisit_Continue;
|
||||
if(tu) clang_disposeTranslationUnit(tu);
|
||||
tu = nullptr;
|
||||
}
|
||||
|
||||
CXTranslationUnit Clang(const String& cmdline_, Vector<Tuple2<String, String>> file, unsigned options)
|
||||
bool Clang::Parse(const String& filename, const String& content, const String& includes, const String& defines, dword options)
|
||||
{
|
||||
static CXIndex index = clang_createIndex(0, 0);
|
||||
if (!index) {
|
||||
LLOG("createIndex failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
String cmdline = cmdline_;
|
||||
if(!index) return false;
|
||||
|
||||
String cmdline;
|
||||
|
||||
cmdline << filename << " -DflagDEBUG -DflagDEBUG_FULL -DflagBLITZ -DflagWIN32 -DflagMAIN -DflagGUI -xc++ -std=c++17 ";
|
||||
cmdline << RedefineMacros();
|
||||
|
||||
Vector<String> sa = Split(cmdline, ' ');
|
||||
|
||||
Buffer<const char *> argv(sa.GetCount());
|
||||
int i = 0;
|
||||
for(const String& s : sa)
|
||||
argv[i++] = ~s;
|
||||
|
||||
CXTranslationUnit tu;
|
||||
Vector<String> args;
|
||||
for(const String& s : Split(includes, ';'))
|
||||
args.Add("-I" + s);
|
||||
|
||||
Buffer<CXUnsavedFile> ufile(file.GetCount());
|
||||
CXUnsavedFile *t = ufile;
|
||||
for(const auto& f : file) {
|
||||
t->Filename = ~f.a;
|
||||
t->Contents = ~f.b;
|
||||
t->Length = f.b.GetCount();
|
||||
t++;
|
||||
}
|
||||
for(const String& s : Split(defines, ';'))
|
||||
args.Add("-D" + s);
|
||||
|
||||
args.Append(Split(cmdline, ' '));
|
||||
|
||||
tu = clang_parseTranslationUnit(index, nullptr, argv, sa.GetCount(), ufile, file.GetCount(), options);
|
||||
Vector<const char *> argv;
|
||||
|
||||
for(const String& s : args)
|
||||
argv.Add(~s);
|
||||
|
||||
CXUnsavedFile ufile = { ~filename, ~content, (unsigned)content.GetCount() };
|
||||
|
||||
tu = clang_parseTranslationUnit(index, nullptr, argv, argv.GetCount(), &ufile, 1, options);
|
||||
|
||||
DumpDiagnostics(tu);
|
||||
|
||||
return tu;
|
||||
}
|
||||
|
||||
#if 0
|
||||
String PrecompileHeader(String& content, const Vector<String>& includes)
|
||||
bool Clang::ReParse(const String& filename, const String& content)
|
||||
{
|
||||
String out;
|
||||
String hdr;
|
||||
|
||||
StringStream ss(content);
|
||||
while(!ss.IsEof()) {
|
||||
String l0 = ss.GetLine();
|
||||
String l = TrimLeft(ss.GetLine()); // todo COMMENTS!
|
||||
if(l.GetCount() == 0)
|
||||
continue;
|
||||
if(l.StartsWith("#include")) {
|
||||
hdr << l << "\n";
|
||||
out << "\n";
|
||||
}
|
||||
else {
|
||||
out << l0 << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(hdr.GetCount() == 0)
|
||||
return Null;
|
||||
|
||||
out << LoadStream(ss);
|
||||
content = out;
|
||||
|
||||
String pch_header2 = "c:/xxx/$pch.h";
|
||||
String pch_file = pch_header2 + ".pch";
|
||||
SaveFile(pch_header2, hdr); // CLANG needs a copy of header
|
||||
|
||||
String cmdline;
|
||||
for(String s : includes)
|
||||
cmdline << " -I" << s;
|
||||
|
||||
cmdline << " -xc++ ";
|
||||
cmdline << pch_header2;
|
||||
/*
|
||||
CXTranslationUnit tu;
|
||||
{
|
||||
TIMING("Precompile");
|
||||
|
||||
tu = Clang(cmdline, Vector<Tuple<String, String>>(), CXTranslationUnit_ForSerialization);
|
||||
if(tu) {
|
||||
clang_saveTranslationUnit(tu, pch_file, clang_defaultSaveOptions(tu));
|
||||
clang_disposeTranslationUnit(tu);
|
||||
content = out;
|
||||
return pch_file;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return Null;
|
||||
}
|
||||
|
||||
void ClangFile(const String& filename, const String& content_, const Vector<String>& includes, int line, int column)
|
||||
{
|
||||
String content = content_;
|
||||
// String pch = PrecompileHeader(content, includes);
|
||||
|
||||
String cmdline;
|
||||
|
||||
// if(pch.GetCount())
|
||||
// cmdline << "-include-pch " << pch << ' ';
|
||||
|
||||
cmdline << filename << RedefineMacros() << " -DflagDEBUG -DflagDEBUG_FULL -DflagBLITZ -DflagWIN32 -xc++ -std=c++17 ";
|
||||
;
|
||||
|
||||
// if(pch.GetCount())
|
||||
// cmdline << " -I" + GetFileFolder(pch) + " -include " + GetFileName(pch) + " -Winvalid-pch ";
|
||||
|
||||
for(String s : includes)
|
||||
cmdline << " -I" << s;
|
||||
|
||||
DDUMP(cmdline);
|
||||
|
||||
CXTranslationUnit tu;
|
||||
{
|
||||
RTIMING("Translate");
|
||||
tu = Clang(cmdline, { { filename, content } }, CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CreatePreambleOnFirstParse|CXTranslationUnit_KeepGoing|CXTranslationUnit_RetainExcludedConditionalBlocks);
|
||||
}
|
||||
|
||||
// CXCursor rootCursor = clang_getTranslationUnitCursor(tu);
|
||||
// unsigned int treeLevel = 0;
|
||||
// clang_visitChildren(rootCursor, visitor, &treeLevel);
|
||||
|
||||
|
||||
unsigned int completionFlags = (CXCodeComplete_IncludeCodePatterns|CXCodeComplete_IncludeBriefComments);
|
||||
// completionFlags |= CXCodeComplete_IncludeMacros;
|
||||
|
||||
CXUnsavedFile ufile = { ~filename, ~content, (unsigned)content.GetCount() };
|
||||
CXCodeCompleteResults *results;
|
||||
{
|
||||
RTIMING("Complete");
|
||||
DDUMP(line);
|
||||
DDUMP(column);
|
||||
DDUMP(filename);
|
||||
results = clang_codeCompleteAt(tu, filename, line, column, &ufile, 1, completionFlags);
|
||||
if(clang_reparseTranslationUnit(tu, 1, &ufile, 0)) {
|
||||
Dispose();
|
||||
return false;
|
||||
}
|
||||
if (results) {
|
||||
RTIMING("Parse results");
|
||||
DLOG("=====================================");
|
||||
DDUMP(FetchString(clang_codeCompleteGetContainerUSR(results)));
|
||||
for (unsigned int i = 0; i < results->NumResults; ++i) {
|
||||
const CXCursorKind kind = results->Results[i].CursorKind;
|
||||
const CXCompletionString& string = results->Results[i].CompletionString;
|
||||
/*
|
||||
const CXAvailabilityKind availabilityKind = clang_getCompletionAvailability(string);
|
||||
if (!(options.options & Server::CompletionsNoFilter)) {
|
||||
switch (availabilityKind) {
|
||||
case CXAvailability_Available:
|
||||
break;
|
||||
case CXAvailability_Deprecated:
|
||||
break;
|
||||
case CXAvailability_NotAccessible:
|
||||
continue;
|
||||
case CXAvailability_NotAvailable: // protected members are erroneously flagged as NotAvailable in clang 3.6
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if(kind == CXCursor_MacroDefinition) // we probably want this only on Ctrl+Space
|
||||
continue;
|
||||
|
||||
String name;
|
||||
String signature;
|
||||
int args = -1;
|
||||
|
||||
const int priority = clang_getCompletionPriority(string);
|
||||
const int chunkCount = clang_getNumCompletionChunks(string);
|
||||
for (int j=0; j<chunkCount; ++j) {
|
||||
const CXCompletionChunkKind chunkKind = clang_getCompletionChunkKind(string, j);
|
||||
String text = FetchString(clang_getCompletionChunkText(string, j));
|
||||
if (chunkKind == CXCompletionChunk_TypedText) {
|
||||
name = text;
|
||||
signature << text;
|
||||
args = signature.GetCount();
|
||||
}
|
||||
else
|
||||
if (chunkKind == CXCompletionChunk_Placeholder) {
|
||||
signature << text;
|
||||
} else {
|
||||
signature << text;
|
||||
if (chunkKind == CXCompletionChunk_ResultType) {
|
||||
signature << ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
String annotation;
|
||||
const unsigned int annotations = clang_getCompletionNumAnnotations(string);
|
||||
for (unsigned j=0; j<annotations; ++j)
|
||||
MergeWith(annotation, ", ", FetchString(clang_getCompletionAnnotation(string, j)));
|
||||
*/
|
||||
DLOG(GetCursorKindName(kind) << ", @" << priority << " " << name << ": " << signature);
|
||||
if(args >= 0)
|
||||
DLOG(" Args: " << signature.Mid(args));
|
||||
DLOG(" Parent: " << FetchString(clang_getCompletionParent(string, NULL)));
|
||||
|
||||
/*
|
||||
DLOG(" Annotation: " << annotation);
|
||||
if (candidate) {
|
||||
candidate->kind = RTags::eatString(clang_getCursorKindSpelling(kind));
|
||||
candidate->priority = priority;
|
||||
candidate->parent = RTags::eatString(clang_getCompletionParent(string, nullptr));
|
||||
candidate->brief_comment = RTags::eatString(clang_getCompletionBriefComment(string));
|
||||
candidates.push_back(candidate);
|
||||
const unsigned int annotations = clang_getCompletionNumAnnotations(string);
|
||||
for (unsigned j=0; j<annotations; ++j) {
|
||||
const CXStringScope annotation = clang_getCompletionAnnotation(string, j);
|
||||
const char *cstr = clang_getCString(annotation);
|
||||
if (strlen(cstr)) {
|
||||
if (!candidate->annotation.empty())
|
||||
candidate->annotation += ' ';
|
||||
candidate->annotation + cstr;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
// if (options.options & Server::CompletionDiagnostics)
|
||||
// processDiagnostics(request, results, cache->translationUnit->unit);
|
||||
clang_disposeCodeCompleteResults(results);
|
||||
}
|
||||
|
||||
clang_disposeTranslationUnit(tu);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
Vector<String> sa = Split(cmdline, ' ');
|
||||
|
||||
Buffer<const char *> argv(sa.GetCount());
|
||||
int i = 0;
|
||||
for(const String& s : sa)
|
||||
argv[i++] = ~s;
|
||||
|
||||
CXIndex index = clang_createIndex(0, 0);
|
||||
if (!index)
|
||||
Panic("createIndex failed");
|
||||
Clang::Clang()
|
||||
{
|
||||
index = clang_createIndex(0, 0);
|
||||
}
|
||||
|
||||
unsigned options = clang_defaultEditingTranslationUnitOptions();
|
||||
|
||||
DDUMP(options);
|
||||
|
||||
CXTranslationUnit tu;
|
||||
{
|
||||
TIMING("Parse");
|
||||
CXUnsavedFile file = { ~filename, ~content, (unsigned)content.GetCount() };
|
||||
tu = clang_parseTranslationUnit(index, nullptr, argv, sa.GetCount(), nullptr, 0, options);
|
||||
|
||||
if(!tu) {
|
||||
DLOG("Parse failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(0) {
|
||||
TIMING("Reparse");
|
||||
int failure = clang_reparseTranslationUnit(tu, 0, nullptr, options);
|
||||
|
||||
if (failure)
|
||||
Panic("Reparse failed");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
Clang::~Clang()
|
||||
{
|
||||
Dispose();
|
||||
clang_disposeIndex(index);
|
||||
}
|
||||
|
||||
void DumpDiagnostics(CXTranslationUnit tu)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ struct SourceLocation {
|
|||
SourceLocation(CXSourceLocation location);
|
||||
};
|
||||
|
||||
void ClangFile(const String& filename, const String& content, const Vector<String>& includes, int line, int column);
|
||||
String RedefineMacros();
|
||||
CXTranslationUnit Clang(const String& cmdline, Vector<Tuple2<String, String>> file, unsigned options = 0);
|
||||
|
||||
enum AdditionalKinds {
|
||||
KIND_INCLUDEFILE = -1000,
|
||||
|
|
@ -93,6 +91,18 @@ struct CurrentFileContext {
|
|||
String content;
|
||||
};
|
||||
|
||||
struct Clang {
|
||||
CXIndex index = nullptr;
|
||||
CXTranslationUnit tu = nullptr;
|
||||
|
||||
void Dispose();
|
||||
bool Parse(const String& filename, const String& content, const String& includes, const String& defines, dword options);
|
||||
bool ReParse(const String& filename, const String& content);
|
||||
|
||||
Clang();
|
||||
~Clang();
|
||||
};
|
||||
|
||||
// void CurrentFileVisit(CXTranslationUnit tu);
|
||||
|
||||
void StartCurrentFileParserThread();
|
||||
|
|
@ -104,6 +114,47 @@ String CleanupPretty(const String& signature);
|
|||
|
||||
bool IsSourceFile(const String& path);
|
||||
|
||||
class ClangVisitor {
|
||||
bool initialized = false;
|
||||
CXPrintingPolicy pp_id, pp_pretty;
|
||||
|
||||
CXCursor cursor;
|
||||
int kind;
|
||||
String name;
|
||||
String id;
|
||||
String type;
|
||||
String scope;
|
||||
String nspace;
|
||||
String pretty;
|
||||
bool external;
|
||||
bool annotation;
|
||||
int line;
|
||||
int column;
|
||||
|
||||
void ProcessNode(CXCursor c);
|
||||
|
||||
friend CXChildVisitResult clang_visitor(CXCursor cursor, CXCursor p, CXClientData clientData);
|
||||
|
||||
public:
|
||||
virtual void Item() = 0;
|
||||
|
||||
int GetKind() const { return kind; }
|
||||
String GetId() const { return id; }
|
||||
String GetName() const { return name; }
|
||||
String GetType() const { return type; }
|
||||
String GetScope() const { return scope; }
|
||||
String GetNamespace() const { return nspace; }
|
||||
String GetPretty() const { return pretty; }
|
||||
bool IsDefinition() const { return clang_isCursorDefinition(cursor); }
|
||||
bool IsExtern() const { return external; }
|
||||
bool IsAnnotation() const { return annotation; }
|
||||
int GetLine() const { return line; }
|
||||
int GetColumn() const { return column; }
|
||||
|
||||
void Do(CXTranslationUnit tu);
|
||||
~ClangVisitor();
|
||||
};
|
||||
|
||||
void SetCurrentFile(const CurrentFileContext& ctx, Event<const Vector<AnnotationItem>&> done);
|
||||
void StartAutoComplete(const CurrentFileContext& ctx, int line, int column, bool macros,
|
||||
Event<const Vector<AutoCompleteItem>&> done);
|
||||
|
|
|
|||
|
|
@ -16,5 +16,7 @@ file
|
|||
Signature.cpp,
|
||||
clang.cpp,
|
||||
Codebase.cpp,
|
||||
Visitor.cpp,
|
||||
AutoComplete.cpp,
|
||||
CurrentFile.cpp;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue