]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blob - visualizer.cpp
ef02cb56894794d1ee295508c4a21bf2c405c28d
[boost-statechart-viewer.git] / visualizer.cpp
1 #include <iostream>
2
3 #include "llvm/Support/raw_ostream.h"
4 #include "llvm/System/Host.h"
5 #include "llvm/Config/config.h"
6
7 #include "clang/Frontend/DiagnosticOptions.h"
8 #include "clang/Frontend/TextDiagnosticPrinter.h"
9
10 #include "clang/Basic/LangOptions.h"
11 #include "clang/Basic/FileSystemOptions.h"
12
13 #include "clang/Index/TranslationUnit.h"
14 #include "clang/Basic/SourceManager.h"
15 #include "clang/Lex/HeaderSearch.h"
16 #include "clang/Basic/FileManager.h"
17
18 #include "clang/Frontend/HeaderSearchOptions.h"
19 #include "clang/Frontend/Utils.h"
20
21 #include "clang/Basic/TargetOptions.h"
22 #include "clang/Basic/TargetInfo.h"
23
24 #include "clang/Lex/Preprocessor.h"
25 #include "clang/Frontend/PreprocessorOptions.h"
26 #include "clang/Frontend/FrontendOptions.h"
27
28 #include "clang/Frontend/CompilerInvocation.h"
29
30 #include "clang/Basic/IdentifierTable.h"
31 #include "clang/Basic/Builtins.h"
32
33 #include "clang/AST/ASTContext.h"
34 #include "clang/AST/ASTConsumer.h"
35 #include "clang/Sema/Sema.h"
36 #include "clang/AST/DeclBase.h"
37 #include "clang/AST/Type.h"
38 #include "clang/AST/Decl.h"
39 #include "clang/Sema/Lookup.h"
40 #include "clang/Sema/Ownership.h"
41 #include "clang/AST/DeclGroup.h"
42
43 #include "clang/Parse/Parser.h"
44
45 #include "clang/Parse/ParseAST.h"
46 #include "clang/Basic/Version.h"
47
48 //my own header files
49 #include "stringoper.h"
50
51 using namespace clang;
52
53
54 class FindStates : public ASTConsumer
55 {
56         public:
57         SourceLocation loc;
58         FullSourceLoc *fSloc;
59         
60         virtual void Initialize(ASTContext &ctx)//run after the AST is constructed
61         {       
62                 SourceManager &sman = ctx.getSourceManager();
63                 fSloc = new FullSourceLoc(loc, sman);
64         }
65
66         virtual void HandleTopLevelDecl(DeclGroupRef DGR)// traverse all top level declarations
67         {
68                 SourceLocation loc;
69                 const SourceManager &sman = fSloc->getManager();
70                 std::string line;
71                 std::string super_class, output;
72                 llvm::raw_string_ostream x(output);
73                 for (DeclGroupRef::iterator i = DGR.begin(), e = DGR.end(); i != e; ++i) 
74                 {
75                         const Decl *decl = *i;
76                         loc = decl->getLocation();
77                         if(loc.isValid())
78                         {
79                                 const NamedDecl *namedDecl = dyn_cast<NamedDecl>(decl);
80                                 //std::cout<<decl->getDeclKindName()<<"\n";
81                                 if(!sman.isInSystemHeader(loc))
82                                 {
83                                         if (const TagDecl *tagDecl = dyn_cast<TagDecl>(decl))
84                                         {
85                                                 if(tagDecl->isStruct() || tagDecl->isClass()) //is it a structure or class      
86                                                 {
87                                                         const CXXRecordDecl *cRecDecl = dyn_cast<CXXRecordDecl>(decl);
88                                                         line = cut_commentary(clean_spaces(get_line_of_code(sman.getCharacterData(loc))));
89                                                         if(is_derived(line))
90                                                         {
91                                                                 if(find_states(cRecDecl, line))
92                                                                 {                               
93                                                                         const DeclContext *declCont = tagDecl->castToDeclContext(tagDecl);                                      
94                                                                         std::cout << "New state: " << namedDecl->getNameAsString() << "\n";
95                                                                         find_transitions(namedDecl->getNameAsString(), declCont);
96                                                                 }
97                                                         }
98                                                 }       
99                                         }
100                                         if(const NamespaceDecl *namespaceDecl = dyn_cast<NamespaceDecl>(decl))
101                                         {
102                                         
103                                                         DeclContext *declCont = namespaceDecl->castToDeclContext(namespaceDecl);
104                                                         //declCont->dumpDeclContext();                          
105                                                         recursive_visit(declCont);
106                                         
107                                         }
108                                 }
109                         }
110                 }
111         }
112         void recursive_visit(const DeclContext *declCont) //recursively visit all decls inside namespace
113         {
114                 const SourceManager &sman = fSloc->getManager();
115                 std::string line;
116                 SourceLocation loc;
117                 for (DeclContext::decl_iterator i = declCont->decls_begin(), e = declCont->decls_end(); i != e; ++i)
118                 {
119                         const Decl *decl = *i;
120                         const NamedDecl *namedDecl = dyn_cast<NamedDecl>(decl);
121                         
122                         //std::cout<<"a "<<decl->getDeclKindName()<<"\n";
123                         loc = decl->getLocation();
124                         if(loc.isValid())
125                         {                       
126                                 if (const TagDecl *tagDecl = dyn_cast<TagDecl>(decl))
127                                 {
128                                         if(tagDecl->isStruct() || tagDecl->isClass()) //is it a structure or class      
129                                         {
130                                                 const CXXRecordDecl *cRecDecl = dyn_cast<CXXRecordDecl>(decl);
131                                                 line = cut_commentary(clean_spaces(get_line_of_code(sman.getCharacterData(loc))));
132                                                 if(is_derived(line))
133                                                 {
134                                                         if(find_states(cRecDecl, line))
135                                                         {                               
136                                                                 const DeclContext *declCont = tagDecl->castToDeclContext(tagDecl);                                      
137                                                                 std::cout << "New state: " << namedDecl->getNameAsString() << "\n";
138                                                                 find_transitions(namedDecl->getNameAsString(), declCont);
139                                                         }
140                                                 }
141                                         }       
142                                 }
143                                 if(const NamespaceDecl *namespaceDecl = dyn_cast<NamespaceDecl>(decl))
144                                 {
145                                         DeclContext *declCont = namespaceDecl->castToDeclContext(namespaceDecl);
146                                         //declCont->dumpDeclContext();                          
147                                         recursive_visit(declCont);
148                                 }
149                         }
150                 } 
151         }
152         bool find_states(const CXXRecordDecl *cRecDecl, std::string line)
153         {       
154                 std::string super_class = get_super_class(line), base;
155                 if(cRecDecl->getNumBases()>1)
156                 {
157                         for(int i = 0; i<cRecDecl->getNumBases();i++ )
158                         {
159                                 if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
160                                 else base = super_class;
161                                 if(is_state(base)) return true;
162                                 else
163                                 {
164                                         super_class = get_next_base(super_class);
165                                 }
166                         }
167                         return false;
168                 }
169                 else
170                 { 
171                         if(is_state(super_class)) return true;
172                         else return false;
173                 }
174         }
175
176         void find_transitions (const std::string name_of_state,const DeclContext *declCont) // traverse all methods for finding declarations of transitions
177         {       
178                 std::string output, line, event, dest, params;  
179                 llvm::raw_string_ostream x(output);
180                 int pos;                
181                 for (DeclContext::decl_iterator i = declCont->decls_begin(), e = declCont->decls_end(); i != e; ++i) 
182                 {
183                         const Decl *decl = *i;
184                         //decl->dump();
185                         
186                         if (const TypedefDecl *typeDecl = dyn_cast<TypedefDecl>(decl)) 
187                         {
188                                 const NamedDecl *namedDecl = dyn_cast<NamedDecl>(decl);
189                                 decl->print(x);
190                                 output = x.str();
191                                 if(count(output)==1)
192                                 {
193                                         line = clean_spaces(cut_typedef(output));
194                                         params = get_transition_params(line);
195                                         pos = params.find(",");
196                                         event = params.substr(0,pos);
197                                         dest = params.substr(pos+1);
198                                         if(is_transition(line)) std::cout << "New transition: " << name_of_state<<" -> "<<event<<" -> "<< dest<<"\n";
199                                 }
200                         }
201                 }       
202         }       
203 };
204
205 int main(int argc, char *argv[])
206 {
207         DiagnosticOptions diagnosticOptions;
208         TextDiagnosticPrinter *tdp = new TextDiagnosticPrinter(llvm::nulls(), diagnosticOptions);
209         llvm::IntrusiveRefCntPtr<DiagnosticIDs> dis(new DiagnosticIDs());
210         Diagnostic diag(dis,tdp);
211         FileSystemOptions fileSysOpt;     
212         LangOptions lang;
213         lang.BCPLComment=1;
214         lang.CPlusPlus=1; 
215         FileManager fm (fileSysOpt);
216
217         SourceManager sm ( diag, fm);
218         HeaderSearch *headers = new HeaderSearch(fm);
219         CompilerInvocation::setLangDefaults(lang, IK_ObjCXX);
220
221         HeaderSearchOptions hsopts;
222         hsopts.ResourceDir=LLVM_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
223         hsopts.AddPath("/home/petr/Dokumenty/BOOST/boost_1_44_0",
224                         clang::frontend::Angled,
225                         false,
226                         false,
227                         true);
228         TargetOptions to;
229         to.Triple = llvm::sys::getHostTriple();
230         TargetInfo *ti = TargetInfo::CreateTargetInfo(diag, to);
231         clang::ApplyHeaderSearchOptions(
232         *headers,
233         hsopts,
234         lang,
235         ti->getTriple());
236         Preprocessor pp(diag, lang, *ti, sm, *headers);
237         FrontendOptions f;
238         PreprocessorOptions ppio;
239         InitializePreprocessor(pp, ppio,hsopts,f);
240         const FileEntry *file = fm.getFile("test.cpp");
241         sm.createMainFileID(file);
242         IdentifierTable tab(lang);
243         SelectorTable sel;
244         Builtin::Context builtins(*ti);
245         FindStates c;
246         ASTContext ctx(lang, sm, *ti, tab, sel, builtins,0);
247         tdp->BeginSourceFile(lang, &pp);
248         ParseAST(pp, &c, ctx, false, false);
249         tdp->EndSourceFile();
250         return 0;
251
252 }