@@ -45,6 +45,7 @@ class TranslationUnit
4545 Reparse (0 , nullptr ); // seems to improve performance for some reason?
4646
4747 clang_visitChildren (clang_getTranslationUnitCursor (m_ClTranslUnit), ClAST_Visitor, database);
48+ database->Shrink ();
4849 }
4950
5051 // move ctor
@@ -617,11 +618,18 @@ ClangProxy::~ClangProxy()
617618void ClangProxy::CreateTranslationUnit (const wxString& filename, const wxString& commands)
618619{
619620 wxStringTokenizer tokenizer (commands);
621+ std::vector<wxString> unknownOptions;
622+ unknownOptions.push_back (wxT (" -Wno-unused-local-typedefs" ));
623+ unknownOptions.push_back (wxT (" -Wzero-as-null-pointer-constant" ));
624+ std::sort (unknownOptions.begin (), unknownOptions.end ());
620625 std::vector<wxCharBuffer> argsBuffer;
621626 std::vector<const char *> args;
622627 while (tokenizer.HasMoreTokens ())
623628 {
624- argsBuffer.push_back (tokenizer.GetNextToken ().ToUTF8 ());
629+ const wxString& compilerSwitch = tokenizer.GetNextToken ();
630+ if (std::binary_search (unknownOptions.begin (), unknownOptions.end (), compilerSwitch))
631+ continue ;
632+ argsBuffer.push_back (compilerSwitch.ToUTF8 ());
625633 args.push_back (argsBuffer.back ().data ());
626634 }
627635 m_TranslUnits.push_back (TranslationUnit (filename, args, m_ClIndex, &m_Database));
@@ -973,6 +981,188 @@ void ClangProxy::RefineTokenType(int translId, int tknId, int& tknType)
973981 }
974982}
975983
984+ static CXChildVisitResult ClCallTipCtorAST_Visitor (CXCursor cursor, CXCursor parent, CXClientData client_data)
985+ {
986+ switch (cursor.kind )
987+ {
988+ case CXCursor_Constructor:
989+ {
990+ std::vector<CXCursor>* tokenSet = static_cast <std::vector<CXCursor>*>(client_data);
991+ tokenSet->push_back (cursor);
992+ break ;
993+ }
994+
995+ case CXCursor_FunctionDecl:
996+ case CXCursor_CXXMethod:
997+ case CXCursor_FunctionTemplate:
998+ {
999+ CXString str = clang_getCursorSpelling (cursor);
1000+ if (strcmp (clang_getCString (str), " operator()" ) == 0 )
1001+ {
1002+ std::vector<CXCursor>* tokenSet = static_cast <std::vector<CXCursor>*>(client_data);
1003+ tokenSet->push_back (cursor);
1004+ }
1005+ clang_disposeString (str);
1006+ break ;
1007+ }
1008+
1009+ default :
1010+ break ;
1011+ }
1012+ return CXChildVisit_Continue;
1013+ }
1014+
1015+ void ClangProxy::GetCallTipsAt (const wxString& filename, int line, int column, int translId, const wxString& tokenStr, std::vector<wxStringVec>& results)
1016+ {
1017+ std::vector<CXCursor> tokenSet;
1018+ if (column > static_cast <int >(tokenStr.Length ()))
1019+ {
1020+ column -= tokenStr.Length () / 2 ;
1021+ CXCursor token = m_TranslUnits[translId].GetTokensAt (filename, line, column);
1022+ if (!clang_Cursor_isNull (token))
1023+ {
1024+ CXCursor resolve = clang_getCursorDefinition (token);
1025+ if (clang_Cursor_isNull (resolve) || clang_isInvalid (token.kind ))
1026+ {
1027+ resolve = clang_getCursorReferenced (token);
1028+ if (!clang_Cursor_isNull (resolve) && !clang_isInvalid (token.kind ))
1029+ token = resolve;
1030+ }
1031+ else
1032+ token = resolve;
1033+ tokenSet.push_back (token);
1034+ }
1035+ }
1036+ // TODO: searching the database is very inexact, but necessary, as clang
1037+ // does not resolve the token when the code is invalid (incomplete)
1038+ std::vector<TokenId> tknIds = m_Database.GetTokenMatches (tokenStr);
1039+ for (std::vector<TokenId>::const_iterator itr = tknIds.begin (); itr != tknIds.end (); ++itr)
1040+ {
1041+ const AbstractToken& aTkn = m_Database.GetToken (*itr);
1042+ CXCursor token = m_TranslUnits[translId].GetTokensAt (m_Database.GetFilename (aTkn.fileId ), aTkn.line , aTkn.column );
1043+ if (!clang_Cursor_isNull (token) && !clang_isInvalid (token.kind ))
1044+ tokenSet.push_back (token);
1045+ }
1046+ std::set<wxString> uniqueTips;
1047+ for (size_t tknIdx = 0 ; tknIdx < tokenSet.size (); ++tknIdx)
1048+ {
1049+ CXCursor token = tokenSet[tknIdx];
1050+ switch (GetTokenCategory (token.kind , CX_CXXPublic))
1051+ {
1052+ case tcVarPublic:
1053+ {
1054+ token = clang_getTypeDeclaration (clang_getCursorResultType (token));
1055+ if (!clang_Cursor_isNull (token) && !clang_isInvalid (token.kind ))
1056+ tokenSet.push_back (token);
1057+ break ;
1058+ }
1059+
1060+ case tcTypedefPublic:
1061+ {
1062+ token = clang_getTypeDeclaration (clang_getTypedefDeclUnderlyingType (token));
1063+ if (!clang_Cursor_isNull (token) && !clang_isInvalid (token.kind ))
1064+ tokenSet.push_back (token);
1065+ break ;
1066+ }
1067+
1068+ case tcClassPublic:
1069+ {
1070+ // search for constructors and 'operator()'
1071+ clang_visitChildren (token, &ClCallTipCtorAST_Visitor, &tokenSet);
1072+ break ;
1073+ }
1074+
1075+ case tcCtorPublic:
1076+ {
1077+ if (clang_getCXXAccessSpecifier (token) == CX_CXXPrivate)
1078+ break ;
1079+ // fall through
1080+ }
1081+ case tcFuncPublic:
1082+ {
1083+ const CXCompletionString& clCompStr = clang_getCursorCompletionString (token);
1084+ wxStringVec entry;
1085+ int upperBound = clang_getNumCompletionChunks (clCompStr);
1086+ entry.push_back (wxEmptyString);
1087+ for (int chunkIdx = 0 ; chunkIdx < upperBound; ++chunkIdx)
1088+ {
1089+ CXCompletionChunkKind kind = clang_getCompletionChunkKind (clCompStr, chunkIdx);
1090+ if (kind == CXCompletionChunk_TypedText)
1091+ {
1092+ CXString str = clang_getCompletionParent (clCompStr, nullptr );
1093+ wxString parent = wxString::FromUTF8 (clang_getCString (str));
1094+ if (!parent.IsEmpty ())
1095+ entry[0 ] += parent + wxT (" ::" );
1096+ clang_disposeString (str);
1097+ }
1098+ else if (kind == CXCompletionChunk_LeftParen)
1099+ {
1100+ if (entry[0 ].IsEmpty () || !entry[0 ].EndsWith (wxT (" operator" )))
1101+ break ;
1102+ }
1103+ CXString str = clang_getCompletionChunkText (clCompStr, chunkIdx);
1104+ entry[0 ] += wxString::FromUTF8 (clang_getCString (str));
1105+ if (kind == CXCompletionChunk_ResultType)
1106+ {
1107+ if (entry[0 ].Length () > 2 && entry[0 ][entry[0 ].Length () - 2 ] == wxT (' ' ))
1108+ entry[0 ].RemoveLast (2 ) += entry[0 ].Last ();
1109+ entry[0 ] += wxT (' ' );
1110+ }
1111+ clang_disposeString (str);
1112+ }
1113+ entry[0 ] += wxT (' (' );
1114+ int numArgs = clang_Cursor_getNumArguments (token);
1115+ for (int argIdx = 0 ; argIdx < numArgs; ++argIdx)
1116+ {
1117+ CXCursor arg = clang_Cursor_getArgument (token, argIdx);
1118+
1119+ wxString tknStr;
1120+ const CXCompletionString& argStr = clang_getCursorCompletionString (arg);
1121+ upperBound = clang_getNumCompletionChunks (argStr);
1122+ for (int chunkIdx = 0 ; chunkIdx < upperBound; ++chunkIdx)
1123+ {
1124+ CXCompletionChunkKind kind = clang_getCompletionChunkKind (argStr, chunkIdx);
1125+ if (kind == CXCompletionChunk_TypedText)
1126+ {
1127+ CXString str = clang_getCompletionParent (argStr, nullptr );
1128+ wxString parent = wxString::FromUTF8 (clang_getCString (str));
1129+ if (!parent.IsEmpty ())
1130+ tknStr += parent + wxT (" ::" );
1131+ clang_disposeString (str);
1132+ }
1133+ CXString str = clang_getCompletionChunkText (argStr, chunkIdx);
1134+ tknStr += wxString::FromUTF8 (clang_getCString (str));
1135+ if (kind == CXCompletionChunk_ResultType)
1136+ {
1137+ if (tknStr.Length () > 2 && tknStr[tknStr.Length () - 2 ] == wxT (' ' ))
1138+ tknStr.RemoveLast (2 ) += tknStr.Last ();
1139+ tknStr += wxT (' ' );
1140+ }
1141+ clang_disposeString (str);
1142+ }
1143+
1144+ entry.push_back (tknStr.Trim ());
1145+ }
1146+ entry.push_back (wxT (' )' ));
1147+ wxString composit;
1148+ for (wxStringVec::const_iterator itr = entry.begin ();
1149+ itr != entry.end (); ++itr)
1150+ {
1151+ composit += *itr;
1152+ }
1153+ if (uniqueTips.find (composit) != uniqueTips.end ())
1154+ break ;
1155+ uniqueTips.insert (composit);
1156+ results.push_back (entry);
1157+ break ;
1158+ }
1159+
1160+ default :
1161+ break ;
1162+ }
1163+ }
1164+ }
1165+
9761166void ClangProxy::GetTokensAt (const wxString& filename, int line, int column, int translId, wxStringVec& results)
9771167{
9781168 CXCursor token = m_TranslUnits[translId].GetTokensAt (filename, line, column);
0 commit comments