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" |
#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_, |
clang_tokenize(tu->tu_, |
||||||
range->range_, |
range->range_, |
||||||
&tokens_, |
&tokens_, |
||||||
&num_tokens_); |
&num_tokens_); |
||||||
for (int i = 0; i < num_tokens_; i++) { |
for (int i = 0; i < num_tokens_; i++) { |
||||||
tks.push_back(clang::Token(tokens_[i])); |
push_back(clang::Token(tokens_[i])); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
clang::Tokens::~Tokens() { |
clang::Tokens::~Tokens() { |
||||||
// instead of using clang_disposeTokens() the implementation
|
clang_disposeTokens(tu.tu_, tokens_, size()); |
||||||
// of the latter method is just free(token_) the same as
|
} |
||||||
// delete(tokens_) eliminating the need of tu*
|
|
||||||
delete tokens_; |
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(); |
||||||
} |
} |
||||||
|
|
||||||
std::vector<clang::Token>& clang::Tokens::tokens() { |
return comment_string; |
||||||
return tks; |
|
||||||
} |
} |
||||||
@ -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