mirror of https://gitlab.com/cppit/libclangmm
26 changed files with 339 additions and 59 deletions
@ -0,0 +1,46 @@
|
||||
#include "Diagnostic.h" |
||||
#include "SourceLocation.h" |
||||
#include "Tokens.h" |
||||
|
||||
clang::Diagnostic::Diagnostic(clang::TranslationUnit& tu, CXDiagnostic& clang_diagnostic) { |
||||
severity=clang_getDiagnosticSeverity(clang_diagnostic); |
||||
severity_spelling=get_severity_spelling(severity); |
||||
spelling=clang_getCString(clang_getDiagnosticSpelling(clang_diagnostic)); |
||||
clang::SourceLocation location(clang_getDiagnosticLocation(clang_diagnostic)); |
||||
std::string tmp_path; |
||||
unsigned line, column, offset; |
||||
location.get_location_info(&tmp_path, &line, &column, &offset); |
||||
path=tmp_path; |
||||
start_location.line=line; |
||||
start_location.column=column; |
||||
start_location.offset=offset; |
||||
|
||||
clang::SourceRange range(&location, &location); |
||||
clang::Tokens tokens(&tu, &range); |
||||
if(tokens.size()==1) { |
||||
auto& token=tokens[0]; |
||||
clang::SourceRange range=token.get_source_range(&tu); |
||||
clang::SourceLocation location(&range, false); |
||||
location.get_location_info(NULL, &line, &column, &offset); |
||||
end_location.line=line; |
||||
end_location.column=column; |
||||
end_location.offset=offset; |
||||
} |
||||
} |
||||
|
||||
const std::string clang::Diagnostic::get_severity_spelling(unsigned severity) { |
||||
switch(severity) { |
||||
case CXDiagnostic_Ignored: |
||||
return "Ignored"; |
||||
case CXDiagnostic_Note: |
||||
return "Note"; |
||||
case CXDiagnostic_Warning: |
||||
return "Warning"; |
||||
case CXDiagnostic_Error: |
||||
return "Error"; |
||||
case CXDiagnostic_Fatal: |
||||
return "Fatal"; |
||||
default: |
||||
return ""; |
||||
} |
||||
} |
||||
@ -0,0 +1,28 @@
|
||||
#ifndef DIAGNOSTIC_H_ |
||||
#define DIAGNOSTIC_H_ |
||||
#include <string> |
||||
#include <vector> |
||||
#include <clang-c/Index.h> |
||||
#include "TranslationUnit.h" |
||||
|
||||
namespace clang {
|
||||
class Diagnostic { |
||||
public: |
||||
class LocationData { |
||||
public: |
||||
unsigned line, column, offset; |
||||
}; |
||||
|
||||
Diagnostic(clang::TranslationUnit& tu, CXDiagnostic& clang_diagnostic); |
||||
|
||||
static const std::string get_severity_spelling(unsigned severity); |
||||
|
||||
unsigned severity; |
||||
std::string severity_spelling; |
||||
std::string spelling; |
||||
std::string path; |
||||
LocationData start_location, end_location; |
||||
}; |
||||
} |
||||
|
||||
#endif // DIAGNOSTIC_H_
|
||||
@ -1,21 +1,136 @@
|
||||
#include "Tokens.h" |
||||
clang::Tokens::Tokens(clang::TranslationUnit *tu, clang::SourceRange *range) { |
||||
#include <iostream> |
||||
using namespace std; |
||||
|
||||
clang::Tokens::Tokens(clang::TranslationUnit *tu, clang::SourceRange *range): tu(*tu) { |
||||
clang_tokenize(tu->tu_, |
||||
range->range_, |
||||
&tokens_, |
||||
&num_tokens_); |
||||
for (int i = 0; i < num_tokens_; i++) { |
||||
tks.push_back(clang::Token(tokens_[i])); |
||||
push_back(clang::Token(tokens_[i])); |
||||
} |
||||
} |
||||
|
||||
clang::Tokens::~Tokens() { |
||||
// instead of using clang_disposeTokens() the implementation
|
||||
// of the latter method is just free(token_) the same as
|
||||
// delete(tokens_) eliminating the need of tu*
|
||||
delete tokens_; |
||||
clang_disposeTokens(tu.tu_, tokens_, size()); |
||||
} |
||||
|
||||
std::vector<clang::Token>& clang::Tokens::tokens() { |
||||
return tks; |
||||
void clang::Tokens::update_types(clang::TranslationUnit *tu) { |
||||
clang_cursors.clear(); |
||||
clang_cursors.reserve(size()); |
||||
clang_annotateTokens(tu->tu_, tokens_, size(), clang_cursors.data()); |
||||
|
||||
for(size_t c=0;c<size();c++) { |
||||
auto referenced=clang_getCursorReferenced(clang_cursors[c]); |
||||
if(!clang_Cursor_isNull(referenced)) { |
||||
auto type=clang_getCursorType(referenced); |
||||
auto cxstr=clang_getTypeSpelling(type); |
||||
std::string spelling=clang_getCString(cxstr); |
||||
clang_disposeString(cxstr); |
||||
std::string auto_end=""; |
||||
//TODO fix const auto
|
||||
if((spelling.size()>=4 && spelling.substr(0, 4)=="auto")) { |
||||
auto_end=spelling.substr(4); |
||||
auto type=clang_getCanonicalType(clang_getCursorType(clang_cursors[c])); |
||||
auto cxstr=clang_getTypeSpelling(type); |
||||
spelling=clang_getCString(cxstr); |
||||
clang_disposeString(cxstr); |
||||
if(spelling.find(" ")==std::string::npos) |
||||
spelling+=auto_end; |
||||
} |
||||
|
||||
(*this)[c].type=spelling; |
||||
//std::cout << clang_getCString(clang_getTypeSpelling(type)) << ": " << type.kind << endl;
|
||||
////auto cursor=clang_getTypeDeclaration(type);
|
||||
////tks[c].type=clang_getCString(clang_getCursorSpelling(cursor));
|
||||
////auto type=clang_getCursorType(referenced);
|
||||
|
||||
} |
||||
//Testing:
|
||||
/*if(tks[c].get_token_spelling(tu)=="text_view") {
|
||||
cout << tks[c].get_token_spelling(tu) << endl; |
||||
auto kind=clang_getCursorKind(cursors[c].cursor_); |
||||
cout << " " << kind << endl; |
||||
cout << " Decl: " << clang_isDeclaration(kind) << endl; |
||||
cout << " Attr: " << clang_isAttribute(kind) << endl; |
||||
cout << " Ref: " << clang_isReference(kind) << endl; |
||||
cout << " Expr: " << clang_isExpression(kind) << endl; |
||||
auto referenced=clang_getCursorReferenced(cursors[c].cursor_); |
||||
if(!clang_Cursor_isNull(referenced)) { |
||||
cout << " " << clang_getCursorKind(referenced) << endl; |
||||
|
||||
clang::Cursor referenced_cursor; |
||||
referenced_cursor.cursor_=referenced; |
||||
auto range=clang::SourceRange(&referenced_cursor); |
||||
|
||||
auto location=clang::SourceLocation(&range, true); |
||||
std::string path; |
||||
unsigned line, column, offset; |
||||
location.get_location_info(&path, &line, &column, &offset); |
||||
cout << " start: " << path << ", " << line << ", " << column << endl; |
||||
|
||||
location=clang::SourceLocation(&range, false); |
||||
location.get_location_info(&path, &line, &column, &offset); |
||||
cout << " start: " << path << ", " << line << ", " << column << endl; |
||||
|
||||
auto type=clang_getCursorType(referenced); |
||||
cout << " " << clang_getCString(clang_getTypeSpelling(type)) << endl; |
||||
} |
||||
}*/ |
||||
} |
||||
} |
||||
|
||||
std::string clang::Tokens::get_brief_comments(size_t cursor_id) { |
||||
std::string comment_string; |
||||
auto referenced=clang_getCursorReferenced(clang_cursors[cursor_id]); |
||||
auto comment=clang_Cursor_getParsedComment(referenced); |
||||
if(clang_Comment_getKind(comment)==CXComment_FullComment) { |
||||
size_t para_c=0; |
||||
for(unsigned c=0;c<clang_Comment_getNumChildren(comment);c++) { |
||||
auto child_comment=clang_Comment_getChild(comment, c); |
||||
if(clang_Comment_getKind(child_comment)==CXComment_Paragraph) { |
||||
para_c++; |
||||
if(para_c>=2) |
||||
break; |
||||
for(unsigned c=0;c<clang_Comment_getNumChildren(child_comment);c++) { |
||||
auto grandchild_comment=clang_Comment_getChild(child_comment, c); |
||||
if(clang_Comment_getKind(grandchild_comment)==CXComment_Text) { |
||||
auto cxstr=clang_TextComment_getText(grandchild_comment); |
||||
comment_string+=clang_getCString(cxstr); |
||||
comment_string+="\n"; |
||||
clang_disposeString(cxstr); |
||||
size_t dot_position=comment_string.find("."); |
||||
if(dot_position!=std::string::npos) |
||||
return comment_string.substr(0, dot_position); |
||||
} |
||||
if(clang_Comment_getKind(grandchild_comment)==CXComment_InlineCommand) { |
||||
auto cxstr=clang_InlineCommandComment_getCommandName(grandchild_comment); |
||||
if(comment_string.size()>0) |
||||
comment_string.pop_back(); |
||||
if(clang_InlineCommandComment_getNumArgs(grandchild_comment)==0) |
||||
comment_string+=clang_getCString(cxstr); |
||||
clang_disposeString(cxstr); |
||||
for(unsigned arg_c=0;arg_c<clang_InlineCommandComment_getNumArgs(grandchild_comment);arg_c++) { |
||||
auto cxstr=clang_InlineCommandComment_getArgText(grandchild_comment, arg_c); |
||||
if(cxstr.data!=NULL) { |
||||
if(arg_c>0) |
||||
comment_string+=" "; |
||||
comment_string+=clang_getCString(cxstr); |
||||
clang_disposeString(cxstr); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
/*cout << " " << clang_Comment_getKind(child_comment) << ", children: " << clang_Comment_getNumChildren(child_comment) << endl;
|
||||
auto cxstr=clang_FullComment_getAsHTML(child_comment); |
||||
cout << " " << clang_getCString(cxstr) << endl; |
||||
clang_disposeString(cxstr);*/ |
||||
} |
||||
while(comment_string.size()>0 && (comment_string.back()=='\n' || comment_string.back()==' ')) |
||||
comment_string.pop_back(); |
||||
} |
||||
|
||||
return comment_string; |
||||
} |
||||
@ -0,0 +1,32 @@
|
||||
#include <boost/test/unit_test.hpp> |
||||
#include "clangmm.h" |
||||
#include <iostream> |
||||
#include <fstream> |
||||
|
||||
using namespace std; |
||||
|
||||
BOOST_AUTO_TEST_CASE(diagnostics_test) { |
||||
std::string path("./case/main_error.cpp"); |
||||
|
||||
clang::Index index(0, 0); |
||||
|
||||
std::map<std::string, std::string> map_buffers; |
||||
ifstream ifs(path, ifstream::in); |
||||
stringstream ss; |
||||
ss << ifs.rdbuf(); |
||||
|
||||
map_buffers["./case/main_error.cpp"]=ss.str(); |
||||
|
||||
std::vector<std::string> args;
|
||||
clang::TranslationUnit tu(&index, path, args, map_buffers); |
||||
|
||||
tu.update_diagnostics(); |
||||
BOOST_CHECK(tu.diagnostics.size()==1); |
||||
BOOST_CHECK(tu.diagnostics[0].spelling=="use of undeclared identifier 'undeclared_variable'"); |
||||
BOOST_CHECK(tu.diagnostics[0].path=="./case/main_error.cpp"); |
||||
BOOST_CHECK(tu.diagnostics[0].severity==3); |
||||
BOOST_CHECK(tu.diagnostics[0].start_location.line==5); |
||||
BOOST_CHECK(tu.diagnostics[0].end_location.line==5); |
||||
BOOST_CHECK(tu.diagnostics[0].start_location.column==16); |
||||
BOOST_CHECK(tu.diagnostics[0].end_location.column==35);
|
||||
} |
||||
Loading…
Reference in new issue