Skip to content

Commit e8b8ace

Browse files
committed
* Resolve correct access specifiers for autocomplete listing
1 parent 3844df2 commit e8b8ace

File tree

3 files changed

+167
-21
lines changed

3 files changed

+167
-21
lines changed

clangplugin.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
* A clang based plugin
33
*/
44

5+
#include <sdk.h>
6+
57
#include "clangplugin.h"
68

7-
#include <sdk.h>
89
#include <compilercommandgenerator.h>
910
#include <cbstyledtextctrl.h>
1011
#include <editor_hooks.h>
@@ -225,7 +226,7 @@ std::vector<ClangPlugin::CCToken> ClangPlugin::GetAutocompList(bool isAuto, cbEd
225226
&& stc->GetCharAt(tknEnd - 2) != wxT(':') )
226227
|| ( curChar == wxT('>') // '->'
227228
&& stc->GetCharAt(tknEnd - 2) != wxT('-') )
228-
|| ( wxString(wxT("<\"/")).Find(curChar) != wxNOT_FOUND // #include directive
229+
|| ( wxString(wxT("<\"/")).Find(curChar) != wxNOT_FOUND // #include directive (TODO: enumerate completable include files)
229230
&& !stc->IsPreprocessor(style) ) )
230231
{
231232
return tokens;
@@ -257,9 +258,10 @@ std::vector<ClangPlugin::CCToken> ClangPlugin::GetAutocompList(bool isAuto, cbEd
257258
bool includeCtors = true; // sometimes we get a lot of these
258259
for (int i = tknStart - 1; i > 0; --i)
259260
{
260-
if (!wxIsspace(stc->GetCharAt(i)))
261+
wxChar chr = stc->GetCharAt(i);
262+
if (!wxIsspace(chr))
261263
{
262-
if (stc->GetCharAt(i) == wxT(';') || stc->GetCharAt(i) == wxT('}')) // last non-whitespace character
264+
if (chr == wxT(';') || chr == wxT('}')) // last non-whitespace character
263265
includeCtors = false; // filter out ctors (they are unlikely to be wanted in this situation)
264266
break;
265267
}
@@ -308,12 +310,28 @@ std::vector<ClangPlugin::CCToken> ClangPlugin::GetAutocompList(bool isAuto, cbEd
308310
tknIt != tokens.end(); ++tknIt)
309311
{
310312
usedWeights.insert(tknIt->weight);
311-
if (tknIt->category != -1)
312-
continue;
313-
if (isPP)
314-
tknIt->category = tcPreprocessor;
315-
else if (std::binary_search(m_CppKeywords.begin(), m_CppKeywords.end(), GetActualName(tknIt->name)))
316-
tknIt->category = tcLangKeyword;
313+
switch (tknIt->category)
314+
{
315+
case tcNone:
316+
if (isPP)
317+
tknIt->category = tcPreprocessor;
318+
else if (std::binary_search(m_CppKeywords.begin(), m_CppKeywords.end(), GetActualName(tknIt->name)))
319+
tknIt->category = tcLangKeyword;
320+
break;
321+
322+
case tcClass:
323+
case tcCtorPublic:
324+
case tcDtorPublic:
325+
case tcFuncPublic:
326+
case tcVarPublic:
327+
case tcEnum:
328+
case tcTypedef:
329+
m_Proxy.RefineTokenType(m_TranslUnitId, tknIt->id, tknIt->category);
330+
break;
331+
332+
default:
333+
break;
334+
}
317335
}
318336
// Clang sometimes gives many weight values, which can make completion more difficult
319337
// because results are less alphabetical. Use a compression map on the lower priority

clangproxy.cpp

Lines changed: 138 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
* Communication proxy to libclang-c
33
*/
44

5-
#include "clangproxy.h"
6-
75
#include <sdk.h>
86

7+
#include "clangproxy.h"
8+
99
#include <clang-c/Index.h>
1010
#include <wx/tokenzr.h>
1111

@@ -275,7 +275,7 @@ static CXChildVisitResult ClAST_Visitor(CXCursor cursor, CXCursor parent, CXClie
275275
case CXCursor_Constructor:
276276
case CXCursor_Destructor:
277277
case CXCursor_FunctionTemplate:
278-
//case CXCursor_MacroDefinition:
278+
//case CXCursor_MacroDefinition: // this can crash Clang on Windows
279279
ret = CXChildVisit_Continue;
280280
break;
281281

@@ -642,37 +642,99 @@ int ClangProxy::GetTranslationUnitId(const wxString& filename)
642642
return GetTranslationUnitId(m_Database.GetFilenameId(filename));
643643
}
644644

645-
static TokenCategory GetTokenCategory(CXCursorKind kind)
645+
static TokenCategory GetTokenCategory(CXCursorKind kind, CX_CXXAccessSpecifier access = CX_CXXInvalidAccessSpecifier)
646646
{
647647
switch (kind)
648648
{
649649
case CXCursor_StructDecl:
650650
case CXCursor_UnionDecl:
651651
case CXCursor_ClassDecl:
652652
case CXCursor_ClassTemplate:
653-
return tcClassPublic;
653+
switch (access)
654+
{
655+
case CX_CXXPublic:
656+
return tcClassPublic;
657+
case CX_CXXProtected:
658+
return tcClassProtected;
659+
case CX_CXXPrivate:
660+
return tcClassPrivate;
661+
default:
662+
case CX_CXXInvalidAccessSpecifier:
663+
return tcClass;
664+
}
654665

655666
case CXCursor_Constructor:
656-
return tcCtorPublic;
667+
switch (access)
668+
{
669+
default:
670+
case CX_CXXInvalidAccessSpecifier:
671+
case CX_CXXPublic:
672+
return tcCtorPublic;
673+
case CX_CXXProtected:
674+
return tcCtorProtected;
675+
case CX_CXXPrivate:
676+
return tcCtorPrivate;
677+
}
657678

658679
case CXCursor_Destructor:
659-
return tcDtorPublic;
680+
switch (access)
681+
{
682+
default:
683+
case CX_CXXInvalidAccessSpecifier:
684+
case CX_CXXPublic:
685+
return tcDtorPublic;
686+
case CX_CXXProtected:
687+
return tcDtorProtected;
688+
case CX_CXXPrivate:
689+
return tcDtorPrivate;
690+
}
660691

661692
case CXCursor_FunctionDecl:
662693
case CXCursor_CXXMethod:
663694
case CXCursor_FunctionTemplate:
664-
return tcFuncPublic;
695+
switch (access)
696+
{
697+
default:
698+
case CX_CXXInvalidAccessSpecifier:
699+
case CX_CXXPublic:
700+
return tcFuncPublic;
701+
case CX_CXXProtected:
702+
return tcFuncProtected;
703+
case CX_CXXPrivate:
704+
return tcFuncPrivate;
705+
}
665706

666707
case CXCursor_FieldDecl:
667708
case CXCursor_VarDecl:
668709
case CXCursor_ParmDecl:
669-
return tcVarPublic;
710+
switch (access)
711+
{
712+
default:
713+
case CX_CXXInvalidAccessSpecifier:
714+
case CX_CXXPublic:
715+
return tcVarPublic;
716+
case CX_CXXProtected:
717+
return tcVarProtected;
718+
case CX_CXXPrivate:
719+
return tcVarPrivate;
720+
}
670721

671722
case CXCursor_MacroDefinition:
672723
return tcPreprocessor;
673724

674725
case CXCursor_EnumDecl:
675-
return tcEnumPublic;
726+
switch (access)
727+
{
728+
case CX_CXXPublic:
729+
return tcEnumPublic;
730+
case CX_CXXProtected:
731+
return tcEnumProtected;
732+
case CX_CXXPrivate:
733+
return tcEnumPrivate;
734+
default:
735+
case CX_CXXInvalidAccessSpecifier:
736+
return tcEnum;
737+
}
676738

677739
case CXCursor_EnumConstantDecl:
678740
return tcEnumerator;
@@ -681,7 +743,18 @@ static TokenCategory GetTokenCategory(CXCursorKind kind)
681743
return tcNamespace;
682744

683745
case CXCursor_TypedefDecl:
684-
return tcTypedefPublic;
746+
switch (access)
747+
{
748+
case CX_CXXPublic:
749+
return tcTypedefPublic;
750+
case CX_CXXProtected:
751+
return tcTypedefProtected;
752+
case CX_CXXPrivate:
753+
return tcTypedefPrivate;
754+
default:
755+
case CX_CXXInvalidAccessSpecifier:
756+
return tcTypedef;
757+
}
685758

686759
// TODO: what is this?
687760
// case:
@@ -757,6 +830,8 @@ wxString ClangProxy::DocumentCCToken(int translId, int tknId)
757830

758831
int upperBound = clang_getNumCompletionChunks(token->CompletionString);
759832
wxString doc;
833+
if (token->CursorKind == CXCursor_Namespace)
834+
doc = wxT("namespace ");
760835
for (int i = 0; i < upperBound; ++i)
761836
{
762837
CXCompletionChunkKind kind = clang_getCompletionChunkKind(token->CompletionString, i);
@@ -793,6 +868,18 @@ wxString ClangProxy::DocumentCCToken(int translId, int tknId)
793868
{
794869
CXComment docComment = clang_Cursor_getParsedComment(clTkn);
795870
HTML_Writer::FormatDocumentation(docComment, descriptor, m_CppKeywords);
871+
if (clTkn.kind == CXCursor_EnumConstantDecl)
872+
{
873+
// can possibly yield incorrect results
874+
doc += wxString::Format(wxT("=%d"), static_cast<int>(clang_getEnumConstantDeclValue(clTkn)));
875+
}
876+
else if (clTkn.kind == CXCursor_TypedefDecl)
877+
{
878+
CXString str = clang_getTypeSpelling(clang_getTypedefDeclUnderlyingType(clTkn));
879+
wxString type = wxString::FromUTF8(clang_getCString(str));
880+
if (!type.IsEmpty())
881+
doc.Prepend(wxT("typedef ") + type + wxT(" "));
882+
}
796883
}
797884
}
798885
}
@@ -862,6 +949,30 @@ wxString ClangProxy::GetCCInsertSuffix(int translId, int tknId, const wxString&
862949
return suffix;
863950
}
864951

952+
void ClangProxy::RefineTokenType(int translId, int tknId, int& tknType)
953+
{
954+
const CXCompletionResult* token = m_TranslUnits[translId].GetCCResult(tknId);
955+
if (!token)
956+
return;
957+
wxString identifier;
958+
unsigned tokenHash = HashToken(token->CompletionString, identifier);
959+
if (!identifier.IsEmpty())
960+
{
961+
TokenId tId = m_Database.GetTokenId(identifier, tokenHash);
962+
if (tId != wxNOT_FOUND)
963+
{
964+
const AbstractToken& aTkn = m_Database.GetToken(tId);
965+
CXCursor clTkn = m_TranslUnits[translId].GetTokensAt(m_Database.GetFilename(aTkn.fileId), aTkn.line, aTkn.column);
966+
if (!clang_Cursor_isNull(clTkn) && !clang_isInvalid(clTkn.kind))
967+
{
968+
TokenCategory tkCat = GetTokenCategory(token->CursorKind, clang_getCXXAccessSpecifier(clTkn));
969+
if (tkCat != tcNone)
970+
tknType = tkCat;
971+
}
972+
}
973+
}
974+
}
975+
865976
void ClangProxy::GetTokensAt(const wxString& filename, int line, int column, int translId, wxStringVec& results)
866977
{
867978
CXCursor token = m_TranslUnits[translId].GetTokensAt(filename, line, column);
@@ -902,7 +1013,23 @@ void ClangProxy::GetTokensAt(const wxString& filename, int line, int column, int
9021013
clang_disposeString(str);
9031014
}
9041015
if (!tknStr.IsEmpty())
1016+
{
1017+
if (token.kind == CXCursor_EnumConstantDecl)
1018+
{
1019+
// can possibly yield incorrect results
1020+
tknStr += wxString::Format(wxT("=%d"), static_cast<int>(clang_getEnumConstantDeclValue(token)));
1021+
}
1022+
else if (token.kind == CXCursor_TypedefDecl)
1023+
{
1024+
CXString str = clang_getTypeSpelling(clang_getTypedefDeclUnderlyingType(token));
1025+
wxString type = wxString::FromUTF8(clang_getCString(str));
1026+
if (!type.IsEmpty())
1027+
tknStr.Prepend(wxT("typedef ") + type + wxT(" "));
1028+
}
1029+
else if (token.kind == CXCursor_Namespace)
1030+
tknStr.Prepend(wxT("namespace "));
9051031
results.push_back(tknStr);
1032+
}
9061033
}
9071034

9081035
void ClangProxy::ResolveTokenAt(wxString& filename, int& line, int& column, int translId)

clangproxy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class ClangProxy
8181
void CodeCompleteAt(const wxString& filename, int line, int column, int translId, const std::map<wxString, wxString>& unsavedFiles, std::vector<ClToken>& results);
8282
wxString DocumentCCToken(int translId, int tknId);
8383
wxString GetCCInsertSuffix(int translId, int tknId, const wxString& newLine, std::pair<int, int>& offsets);
84+
void RefineTokenType(int translId, int tknId, int& tknType); // TODO: cache TokenId (if resolved) for DocumentCCToken()
8485

8586
void GetTokensAt(const wxString& filename, int line, int column, int translId, std::vector<wxString>& results);
8687
void ResolveTokenAt(wxString& filename, int& line, int& column, int translId);

0 commit comments

Comments
 (0)