highlight_group(clang::translation_unit const &trans_unit, clang::token_pack &tokens) { auto &tu(trans_unit.impl); std::vector<CXCursor> cursors(tokens.size()); clang_annotateTokens(tu, tokens.begin(), tokens.size(), cursors.data()); auto cursor(cursors.cbegin()); for(auto token(tokens.cbegin()); token != tokens.cend(); ++token, ++cursor) { CXTokenKind const kind{ clang_getTokenKind(*token) }; clang::string const spell{ clang_getTokenSpelling(tu, *token) }; auto const loc(clang_getTokenLocation(tu, *token)); CXFile file{}; unsigned line{}, column{}, offset{}; clang_getFileLocation(loc, &file, &line, &column, &offset); auto const cur(*cursor); auto const cursor_kind(cur.kind); auto const cursor_type(clang_getCursorType(cur).kind); auto const mapped(clang::token::map_token_kind(kind, cursor_kind, cursor_type)); if(mapped.size()) { //std::cout << spell.c_str() << " : " << mapped << std::endl; emplace_back(mapped, line, column, spell.c_str()); } else { /* std::cout << "unmapped: " << spell.c_str() << std::endl; */ } } }
CXChildVisitResult visitor( CXCursor cursor, CXCursor parent, CXClientData client_data) { ClangTools::TranslationUnit::AstWalker * astWalker = reinterpret_cast<ClangTools::TranslationUnit::AstWalker *>(client_data); std::vector<std::string> & funcNames = *(reinterpret_cast<std::vector<std::string> *>(astWalker->getClientData())); auto sourceLocation = clang_getCursorLocation(cursor); CXFile file; clang_getFileLocation(sourceLocation, &file, 0, 0, 0); auto fileName = clang_getFileName(file); auto fileNameStr = ClangTools::String(fileName); if (fileNameStr != astWalker->getFileName()) { return CXChildVisit_Recurse; } auto func = std::string{}; auto def = bool{false}; if (clang_isCursorDefinition(cursor)) { def = true; } switch (clang_getCursorKind(cursor)) { case CXCursor_FunctionDecl: func = "Function "; break; case CXCursor_FunctionTemplate: func = "FunctionTemplate "; break; case CXCursor_CXXMethod: func = "CXXMethod "; break; default: return CXChildVisit_Recurse; break; } func += clang_isCursorDefinition(cursor) ? "definition: " : "declaration: "; auto semanticParent = clang_getCursorSemanticParent(cursor); auto semanticParentSpelling = clang_getCursorSpelling(semanticParent); func += ClangTools::String(semanticParentSpelling) + "::"; auto cursorSpelling = clang_getCursorSpelling(cursor); func += ClangTools::String(cursorSpelling); auto lexicalParent = clang_getCursorLexicalParent(cursor); auto lexicalParentSpelling = clang_getCursorSpelling(lexicalParent); func += " found in: " + ClangTools::String(lexicalParentSpelling); funcNames.push_back(func); return CXChildVisit_Recurse; }
void SourceLocation::getFileLocation(File* file, unsigned* line, unsigned* column, unsigned* offset) { CXFile* cx_file = nullptr; if (file) { cx_file = &(file->file_); } clang_getFileLocation(location_, cx_file, line, column, offset); }
std::ostream& operator<<( std::ostream& os, CXSourceLocation loc ) { CXFile cxfile; unsigned line, col, off; clang_getFileLocation( loc, &cxfile, &line, &col, &off ); auto filestr = clang_getFileName( cxfile ); os << clang_getCString( filestr ) << ":" << line << ":" << col; clang_disposeString( filestr ); return os; }
SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation) { CXFile cxFile; clang_getFileLocation(cxSourceLocation, &cxFile, &line_, &column_, &offset_); filePath_ = ClangString(clang_getFileName(cxFile)); }
std::string make_vimson_from_tokens(std::vector<Token> tokens) const { return "[" + std::accumulate(std::begin(tokens), std::end(tokens), std::string{}, [&](std::string const& acc, Token const& token){ auto const kind = clang_getTokenKind(token); auto const spell = owned(clang_getTokenSpelling(translation_unit, token)); auto const location = clang_getTokenLocation(translation_unit, token); CXFile file; unsigned int line, column, offset; clang_getFileLocation(location, &file, &line, &column, &offset); auto const source_name = owned(clang_getFileName(file)); return acc + "{'spell':'" + clang_getCString(*spell) + "','kind':'" + get_kind_spelling(kind) + "','file':'" + clang_getCString(*source_name) + "','line':" + std::to_string(line) + ",'column':" + std::to_string(column) + ",'offset':" + std::to_string(offset) + "},"; }) + "]"; }
void printTreeRecursive(struct treeNode* node, CXTranslationUnit cxtup) { depth++; if(node->modified == 0) { CXSourceRange range = clang_getCursorExtent(node->cursor); CXSourceLocation rstart = clang_getRangeStart(range); if(clang_Location_isFromMainFile(rstart) != 0) { enum CXCursorKind cursorkind = clang_getCursorKind(node->cursor); if(depth == 1 && cursorkind != CXCursor_MacroExpansion) { nodenum++; if(cursorkind == CXCursor_StructDecl) { CXToken* currTokens; unsigned int numCurrTokens; clang_tokenize(cxtup, range, &currTokens, &numCurrTokens); CXToken token = currTokens[numCurrTokens-1]; CXString tokenstring = clang_getTokenSpelling(cxtup, token); char* tokenstr = clang_getCString(tokenstring); clang_disposeTokens(cxtup, currTokens, numCurrTokens); //printf("\ntoken: %s\n", tokenstr); if(strcmp(tokenstr, ";")) { clang_disposeString(tokenstring); // Print nothing, do nothing. } else { clang_disposeString(tokenstring); goto PRINT; } } else { PRINT: 1+1; CXToken* tokens; unsigned int numTokens; clang_tokenize(cxtup, range, &tokens, &numTokens); CXString tokenstring; CXSourceRange tokenrange; unsigned* startcol = malloc(sizeof(unsigned)); unsigned* startline = malloc(sizeof(unsigned)); unsigned* endcol = malloc(sizeof(unsigned)); unsigned* endline = malloc(sizeof(unsigned)); for(int i = 0; i<numTokens; i++) { tokenrange = clang_getTokenExtent(cxtup, tokens[i]); tokenstring = clang_getTokenSpelling(cxtup, tokens[i]); CXSourceLocation currend = clang_getRangeEnd(tokenrange); clang_getFileLocation(currend, NULL, endline, endcol, NULL); if(prevcol != 0) { CXSourceLocation currstart = clang_getRangeStart(tokenrange); clang_getFileLocation(currstart, NULL, startline, startcol, NULL); //printf("L%u-%u, C%u-%u", *startline, prevline, *startcol, prevcol); int startl = *startline; int startc = *startcol; for(int i = 0; i < startl-prevline; i++) { printf("\n"); //printf("*startline-prevline = %u, i = %u, prevline = %u\n", start-prevline, i, prevline); } if(startc-prevcol >= 0) { for(int i = 0; i < startc-prevcol; i++) { printf(" "); } } else { for(int i = 1; i < startc; i++) { printf(" "); } } } char* tstr = clang_getCString(tokenstring); /*if(i == 0 && !strcmp(tstr, lastPrintedToken)) { // Do nothing, print nothing. } else {*/ printf("%s", tstr); //} prevline = *endline; prevcol = *endcol; char* str = clang_getCString(tokenstring); strcpy(lastPrintedToken, str); clang_disposeString(tokenstring); } //printf("%i\n", lastPrintedToken); //printf("\n"); clang_disposeTokens(cxtup, tokens, numTokens); free(startcol); free(startline); free(endcol); free(endline); } } } } else if(depth == 1) { //printf("Modified node detected."); if(node->validcursor == false) { //Print modified //printf("%s\n", node->newContent); } else { struct treeNode** nodes = malloc((node->modified) * sizeof(struct treeNode)); //printf("%i\n", sizeof(nodes)) nodes[node->modified-1] = NULL; //printf("nodes[node->modified-1]: %i\n", nodes[node->modified-1]); struct treeNode* next = NULL; int nextnode = 0; int smallestcol = INT_MAX; int smallestline = INT_MAX; int cscol = INT_MIN; int csline = INT_MIN; struct treeListNode* currnode = node->modifiedNodes; CXSourceRange srange; CXSourceLocation sloc; bool first = true; while(nodes[(node->modified)-1] == NULL) { while(currnode != NULL) { if(currnode->node->startline == -1) { srange = clang_getCursorExtent(currnode->node->cursor); sloc = clang_getRangeStart(srange); clang_getFileLocation(sloc, NULL, &(currnode->node->startline), &(currnode->node->startcol), NULL); //printf("Calculated node %i: startline: %i, startcol: %i\n", currnode->node, currnode->node->startline, currnode->node->startcol); } //printf("\ncurrnode->node: %i, nextnode: %i\nnstartline: %i, smallestline: %i ,csline: %i\nnstartcol: %i, smallestcol: %i, cscol: %i\n", currnode->node, nextnode, currnode->node->startline, smallestline, csline, currnode->node->startcol, smallestcol, cscol); if(currnode->node->startline < smallestline) { //printf("\n1\, %i < %i", currnode->node->startline, smallestline); if((currnode->node->startline > csline) || (first == true)) { //printf("\n2, %i > %i", currnode->node->startline); smallestline = currnode->node->startline; smallestcol = currnode->node->startcol; csline = currnode->node->startline; cscol = currnode->node->startcol; next = currnode->node; } } else if(currnode->node->startline == smallestline) { //printf("3\n"); if(currnode->node->startcol < smallestcol) { //printf("4\n"); if((currnode->node->startcol > cscol) || (first == true)) { //printf("5\n"); smallestline = currnode->node->startline; smallestcol = currnode->node->startcol; csline = currnode->node->startline; cscol = currnode->node->startcol; next = currnode->node; } } } //printf("\n6\n"); //printf("currnode->node: %i, nextnode: %i\nnstartline: %i, smallestline: %i ,csline: %i\nnstartcol: %i, smallestcol: %i, cscol: %i\n", currnode->node, nextnode, currnode->node->startline, smallestline, csline, currnode->node->startcol, smallestcol, cscol); currnode = currnode->next; } first = false; //printf("%i ", nodes[nextnode]); //printf("%i\n", next); nodes[nextnode] = next; nextnode++; smallestcol = INT_MAX; smallestline = INT_MAX; currnode = node->modifiedNodes; } for(int i = 0; i <= 1; i++) { //printf("nodenum: %i, nstartline: %i, nstartcol: %i\n", i, nodes[i]->startline, nodes[i]->startcol); } CXSourceRange range = clang_getCursorExtent(node->cursor); CXToken* tokens; unsigned int numTokens; int numNodes = nextnode; nextnode = 0; clang_tokenize(cxtup, range, &tokens, &numTokens); for(int i = 0; i<numTokens; i++) { CXSourceRange tokenrange = clang_getTokenExtent(cxtup, tokens[i]); CXString tokenstring = clang_getTokenSpelling(cxtup, tokens[i]); unsigned startline; unsigned startcol; unsigned endline; unsigned endcol; CXSourceLocation currend = clang_getRangeEnd(tokenrange); clang_getFileLocation(currend, NULL, &endline, &endcol, NULL); if(prevcol != 0) { CXSourceLocation currstart = clang_getRangeStart(tokenrange); clang_getFileLocation(currstart, NULL, &startline, &startcol, NULL); //printf("L%u-%u, C%u-%u", *startline, prevline, *startcol, prevcol); int startl = startline; int startc = startcol; for(int i = 0; i < startl-prevline; i++) { printf("\n"); //printf("*startline-prevline = %u, i = %u, prevline = %u\n", start-prevline, i, prevline); } if(startc-prevcol >= 0) { for(int i = 0; i < startc-prevcol; i++) { printf(" "); } } else { for(int i = 0; i < startc; i++) { printf(" "); } } } char* tstr = clang_getCString(tokenstring); if(i == 0 && !strcmp(tstr, lastPrintedToken)) { // Do nothing, print nothing. } else { //printf("nextstartline: %i, startline: %i\n", nodes[nextnode]->startline, startline); if((nextnode < numNodes) && (nodes[nextnode]->startline == startline) && (nodes[nextnode]->startcol == startcol)) { int* nodenext = &(nodes[nextnode]->cursor); if(nodenext == NULL) { printf("%s\n", nodes[nextnode]->newContent); nextnode++; } else { printf("%s", nodes[nextnode]->newContent); prevline = endline; prevcol = endcol; nextnode++; } } else { printf("%s", tstr); prevline = endline; prevcol = endcol; } } //printf("%i\n", sizeof(nodes)); char* str = clang_getCString(tokenstring); strcpy(lastPrintedToken, str); clang_disposeString(tokenstring); } clang_disposeTokens(cxtup, tokens, numTokens); free(nodes); } } if(node->children != NULL) { struct treeListNode* childlist = node->children; while(childlist != NULL) { printTreeRecursive(childlist->node, cxtup); childlist = childlist->next; } } depth--; }
void source_location::file_location(CXFile *file, unsigned *line, unsigned *column, unsigned *offset) const { clang_getFileLocation(loc, file, line, column, offset); }
// Desired functions: // Go to definition of variable/function // Go to declaration of function/class bool Tokenizer::findToken(eFindTokenTypes ft, size_t origOffset, std::string &fn, size_t &line) { CLangAutoLock lock(mCLangLock, __LINE__, this); CXCursor startCursor = getCursorAtOffset(mTransUnit, mSourceFile, origOffset); DUMP_PARSE("find:start cursor", startCursor); // Instantiating type - <class> <type> - CXCursor_TypeRef // Method declaration - <class> { <method>(); }; CXCursor_NoDeclFound // Method definition - <class>::<method>(){} - CXCursor_CXXMethod // Class/method usage - <class>.<method>() // Instance usage - method(){ int v = typename[4]; } - CXCursor_DeclStmt // clang_getCursorSemanticParent returns method // clang_getCursorDefinition returns invalid if(startCursor.kind == CXCursor_InclusionDirective) { CXFile file = clang_getIncludedFile(startCursor); if(file) { fn = getDisposedString(clang_getFileName(file)); line = 1; } else { /// @todo - need to get the full path. // CXStringDisposer cfn = clang_getCursorSpelling(cursor); // fn = cfn; line = 1; } } else { CXCursor cursor = startCursor; switch(ft) { case FT_FindDecl: cursor = clang_getCursorReferenced(startCursor); DUMP_PARSE("find:decl", cursor); break; case FT_FindDef: // If instantiating a type (CXCursor_TypeRef), this goes to the type declaration. cursor = clang_getCursorDefinition(startCursor); // Method call can return invalid file when the definition is not in this // translation unit. if(clang_getCursorKind(cursor) == CXCursor_InvalidFile) { DUMP_PARSE("find:def-invalid", cursor); cursor = clang_getCursorReferenced(startCursor); } DUMP_PARSE("find:def", cursor); // cursor = clang_getCursor(mTransUnit, clang_getCursorLocation(cursor)); // cursor = clang_getCursorDefinition(cursor); break; // cursor = clang_getCursorReferenced(cursor); // cursor = clang_getCanonicalCursor(cursor); // cursor = clang_getCursorSemanticParent(cursor); // cursor = clang_getCursorLexicalParent(cursor); } if(!clang_Cursor_isNull(cursor)) { CXSourceLocation loc = clang_getCursorLocation(cursor); CXFile file; unsigned int uline; clang_getFileLocation(loc, &file, &uline, nullptr, nullptr); if(file) { line = uline; fn = getDisposedString(clang_getFileName(file)); } } } return(fn.size() > 0); }