std::vector<diagnostic> translation_unit::diagnose() { // Get all the diagnostics uint32_t n = clang_getNumDiagnostics(mUnit); if (n == 0) return {}; std::vector<diagnostic> ret; ret.reserve(n); for (uint32_t i = 0; i < n; ++i) { CXFile file; uint32_t row = 0, col = 0, offset = 0; CXDiagnostic diag = clang_getDiagnostic(mUnit, i); CXSourceLocation loc = clang_getDiagnosticLocation(diag); clang_getExpansionLocation( loc, &file, &row, &col, &offset ); ret.push_back({ { cx2std(clang_getFileName(file)), row, col }, clang_getDiagnosticSeverity(diag), diagnostic_text(diag), diagnostic_summary(diag) }); clang_disposeDiagnostic(diag); } return ret; }
void wci_getCursorFile(char* cuin, char* cxsout) { CXCursor cu = wci_get_CXCursor(cuin); CXSourceLocation loc = clang_getCursorLocation( cu ); CXFile cxfile; clang_getExpansionLocation(loc, &cxfile, 0, 0, 0); wci_save_CXString(clang_getFileName(cxfile), cxsout); }
static void dumpDiagnostics(const CXTranslationUnit &tu) { std::cout << "(\n"; std::string file; for (unsigned i = 0, diagnosticCount = clang_getNumDiagnostics(tu); i < diagnosticCount; ++i) { CXDiagnostic diagnostic = clang_getDiagnostic(tu, i); CXSourceLocation location = clang_getDiagnosticLocation(diagnostic); unsigned line, column, offset; if (clang_equalLocations(location, clang_getNullLocation())) { file.clear(); line = 0; column = 0; offset = 0; } else { CXFile cxFile; // clang_getInstantiationLocation() has been marked deprecated and // is aimed to be replaced by clang_getExpansionLocation(). #if CINDEX_VERSION >= 6 clang_getExpansionLocation(location, &cxFile, &line, &column, &offset); #else clang_getInstantiationLocation(location, &cxFile, &line, &column, &offset); #endif file = cxStringToStd(clang_getFileName(cxFile)); } const char *severity = diagnosticSeverity(diagnostic); std::string message = cxStringToStd(clang_getDiagnosticSpelling(diagnostic)); std::cout << '(' << support::quoted(file) // << ' ' << line // << ' ' << column // << ' ' << offset // << ' ' << severity // << ' ' << support::quoted(message) // << ")\n"; clang_disposeDiagnostic(diagnostic); } std::cout << ")\n"; }
void TokenRange::tokenize(CXTranslationUnit transUnit) { CXCursor cursor = clang_getTranslationUnitCursor(transUnit); CXSourceRange range = clang_getCursorExtent(cursor); CXToken *tokens = 0; unsigned int numTokens = 0; clang_tokenize(transUnit, range, &tokens, &numTokens); resize(numTokens); if(numTokens > 0) { for (size_t i = 0; i < numTokens-1; i++) { at(i).setKind(clang_getTokenKind(tokens[i])); CXSourceRange tokRange = clang_getTokenExtent(transUnit, tokens[i]); clang_getExpansionLocation(clang_getRangeStart(tokRange), NULL, NULL, NULL, &at(i).mStartOffset); clang_getExpansionLocation(clang_getRangeEnd(tokRange), NULL, NULL, NULL, &at(i).mEndOffset); } } clang_disposeTokens(transUnit, tokens, numTokens); }
location translation_unit::definition_location_at(uint32_t row, uint32_t col) { CXCursor cursor = get_cursor_at(row, col); CXCursor ref = clang_getCursorDefinition( cursor ); if (clang_Cursor_isNull(ref) || clang_isInvalid(clang_getCursorKind(ref))) return {"", 0, 0}; CXSourceLocation loc = clang_getCursorLocation(ref); CXFile file; uint32_t nrow, ncol, offset = 0; clang_getExpansionLocation( loc, &file, &nrow, &ncol, &offset ); return { cx2std(clang_getFileName(file)), nrow, ncol }; }
// FIXME: change this to just printing comments, and call write_token() // directly from write_html() for non-comments. void Html_File::write_comment_split(FILE* f, CXFile file, CXToken tok) { unsigned line; unsigned column; unsigned offset; CXSourceLocation loc = clang_getTokenLocation(tu_file_->tu(), tok); clang_getExpansionLocation(loc, &file, &line, &column, &offset); CXTokenKind kind = clang_getTokenKind(tok); CXString s = clang_getTokenSpelling(tu_file_->tu(), tok); std::string sub = clang_getCString(s); clang_disposeString(s); // actually split up multi-line comments and send one at // a time -- that way each line gets line numbers. if (kind == CXToken_Comment || kind == CXToken_Literal) { std::string str = sub.c_str(); if (kind == CXToken_Comment) str = fix(sub.c_str()); size_t i; size_t begin = 0; for (i = 0; i < str.length(); ++i) { if (str[i] == '\n') { sub = str.substr(begin, i-begin); if (begin) line++; column = 1; begin = i + 1; write_token(f, file, tok, sub.c_str(), line, column); } } if (begin) { line++; column = 1; } sub = str.substr(begin, i-begin); } write_token(f, file, tok, sub.c_str(), line, column); }
void Html_File::write_token(FILE* f, CXFile file, CXToken tok, const char* str, unsigned line, unsigned column) { static bool preprocessor = false; static bool include = false; CXSourceLocation tloc = clang_getTokenLocation(tu_file_->tu(), tok); CXCursor c = clang_getCursor(tu_file_->tu(), tloc); if (cur_line_ <= line) cur_column_ = 1; for (; cur_line_ <= line; ++cur_line_) fprintf (f, "\n<a name=\"l%05i\"></a>%05i", cur_line_, cur_line_); for (; cur_column_ <= column; ++cur_column_) fprintf (f , " "); switch (clang_getTokenKind(tok)) { case (CXToken_Punctuation): if (str[0] == '#') preprocessor = true; fprintf(f, "%s", str); break; case (CXToken_Keyword): fprintf(f, "<span class=\"keyword\">%s</span>", str); break; case (CXToken_Comment): fprintf(f, "<span class=\"comment\">%s</span>", str); break; case (CXToken_Literal): { //include = false; // disable include links for now if (include) { include = false; // found an include file std::string t; const char* p = str; while (*p) { if (*p != '"') t += *p; ++p; } // first, use this file's path, then all the include paths bool found_include = false; char path[PATH_MAX]; std::string includefile = realpath(dirname(tu_file_->source_filename()), path); includefile += "/" + t; struct stat st; if (stat(includefile.c_str(), &st) == 0) { found_include = true; } else { for (std::vector<std::string>::const_iterator i = includes_.begin(), e = includes_.end(); i != e; ++i) { includefile = realpath((*i).c_str(), path); includefile += "/" + t; if (stat(includefile.c_str(), &st) == 0) { found_include = true; break; } } } if (found_include) { if (files_.find(includefile) != files_.end()) { t = make_filename(includefile, html_dir_, prefix_, ".html", false); fprintf(f, "<a class=\"code\" href=\"%s\" title="">%s</a>", t.c_str(), str); break; } std::map<std::string, Definition>::iterator i = defmap_.find(includefile); if (i != defmap_.end()) { t = i->second.file.c_str(); fprintf(f, "<a class=\"code\" href=\"%s\" title="">%s</a>", t.c_str(), str); break; } } } // not an include or include not found std::string s = fix(str); fprintf(f, "%s", s.c_str() ); break; } case (CXToken_Identifier): { if (preprocessor) { preprocessor = false; if (strcmp(str, "include") == 0) include = true; fprintf(f, "<span class=\"code\">%s</span>", str); break; } if (clang_isUnexposed(c.kind)) { fprintf(f, "<span class=\"code\">%s</span>", str); fprintf(f, "<!-- origin line: %i : %s : kind = %i -->", __LINE__, str, c.kind); break; } // Calling clang_getCursorDefinition() does not work properly // for template classes, i.e., it will find the method // declaration, not the definition, if they differ. However, // once you have the declaration's location, you can use it // get that cursor, and find the definition that way. CXSourceLocation decloc = clang_getCursorLocation(clang_getCursorDefinition(c)); CXCursor cref = clang_getCursorDefinition(clang_getCursor(tu_file_->tu(), decloc)); if (clang_isUnexposed(cref.kind)) { fprintf(f, "<span class=\"code\">%s</span>", str); fprintf(f, "<!-- origin line: %i : (ref) %s : kind = %i -->", __LINE__, str, cref.kind); break; } std::string rfile; std::string html_dir; unsigned refl = line; bool found = false; if (!clang_Cursor_isNull(cref) && cref.kind != CXCursor_Namespace) { CXSourceLocation refloc = clang_getCursorLocation(cref); if (!clang_equalLocations(tloc, refloc)) { CXFile cxfile; unsigned col; unsigned off; clang_getExpansionLocation(refloc, &cxfile, &refl, &col, &off); if (cxfile == file) { found = true; fprintf(f, "<!-- origin line: %i : (ref) %s : kind = %i -->", __LINE__, str, cref.kind); } else { CXString cxfn = clang_getFileName(cxfile); const char* fn = clang_getCString(cxfn); if (fn) { if (files_.find(fn) != files_.end()) { rfile = fn; found = true; fprintf(f, "<!-- origin line: %i : (ref) %s : kind = %i -->", __LINE__, str, cref.kind); } } clang_disposeString(cxfn); } } } else if (!clang_isDeclaration(c.kind) && c.kind != CXCursor_Namespace) { CXCursor ref = clang_getCursorReferenced(c); if (ref.kind != CXCursor_Namespace) { std::string fsn = munge_fullyscopedname(fullyScopedName(ref)); if (fsn.empty()) { fprintf(f, "<!-- origin line: %i : (fsn empty) %s : kind = %i -->", __LINE__, str, c.kind); } else { std::map<std::string, Definition>::iterator r = defmap_.find(fsn); if (r != defmap_.end()) { found = true; fprintf(f, "<!-- origin line: %i : %s : kind = %i -->", __LINE__, fsn.c_str(), c.kind); rfile = r->second.file.c_str(); html_dir = r->second.html_path.c_str(); refl = r->second.line; } } } } // since we are linking to lines, no need to link to same line if (found && (!rfile.empty() || refl != line)) { if (!rfile.empty()) rfile = make_filename(rfile, html_dir, prefix_, ".html", !html_dir.empty()); fprintf(f, "<a class=\"code\" href=\"%s#l%05i\" title="">%s</a>", rfile.c_str(), refl , str); break; } fprintf(f, "<span class=\"code\">%s</span>", str); break; } } cur_column_ += strlen(str); }
void source_location::expansion_location(CXFile *file, unsigned *line, unsigned *column, unsigned *offset) const { clang_getExpansionLocation(loc, file, line, column, offset); }