]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blob - visualizer.cpp
b781be350bb2ff356406bc6d8fc9ba759e1330b1
[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 #include "llvm/Support/CommandLine.h"
49
50 //my own header files
51 #include "stringoper.h"
52 #include "commandlineopt.h"
53
54 using namespace clang;
55
56
57 class FindStates : public ASTConsumer
58 {
59         public:
60         SourceLocation loc;
61         FullSourceLoc *fSloc;
62         
63         virtual void Initialize(ASTContext &ctx)//run after the AST is constructed
64         {       
65                 SourceManager &sman = ctx.getSourceManager();
66                 fSloc = new FullSourceLoc(loc, sman);
67         }
68
69         virtual void HandleTopLevelDecl(DeclGroupRef DGR)// traverse all top level declarations
70         {
71                 SourceLocation loc;
72                 const SourceManager &sman = fSloc->getManager();
73                 std::string line;
74                 std::string super_class, output;
75                 llvm::raw_string_ostream x(output);
76                 for (DeclGroupRef::iterator i = DGR.begin(), e = DGR.end(); i != e; ++i) 
77                 {
78                         const Decl *decl = *i;
79                         loc = decl->getLocation();
80                         if(loc.isValid())
81                         {
82                                 const NamedDecl *namedDecl = dyn_cast<NamedDecl>(decl);
83                                 //std::cout<<decl->getDeclKindName()<<"\n";
84                                 if(!sman.isInSystemHeader(loc))
85                                 {
86                                         if (const TagDecl *tagDecl = dyn_cast<TagDecl>(decl))
87                                         {
88                                                 if(tagDecl->isStruct() || tagDecl->isClass()) //is it a structure or class      
89                                                 {
90                                                         const CXXRecordDecl *cRecDecl = dyn_cast<CXXRecordDecl>(decl);
91                                                         line = cut_commentary(clean_spaces(get_line_of_code(sman.getCharacterData(loc))));
92                                                         if(is_derived(line))
93                                                         {
94                                                                 if(find_states(cRecDecl, line))
95                                                                 {                               
96                                                                         const DeclContext *declCont = tagDecl->castToDeclContext(tagDecl);                                      
97                                                                         std::cout << "New state: " << namedDecl->getNameAsString() << "\n";
98                                                                         find_transitions(namedDecl->getNameAsString(), declCont);
99                                                                 }
100                                                         }
101                                                 }       
102                                         }
103                                         if(const NamespaceDecl *namespaceDecl = dyn_cast<NamespaceDecl>(decl))
104                                         {
105                                         
106                                                         DeclContext *declCont = namespaceDecl->castToDeclContext(namespaceDecl);
107                                                         //declCont->dumpDeclContext();                          
108                                                         recursive_visit(declCont);
109                                         
110                                         }
111                                 }
112                         }
113                 }
114         }
115         void recursive_visit(const DeclContext *declCont) //recursively visit all decls inside namespace
116         {
117                 const SourceManager &sman = fSloc->getManager();
118                 std::string line;
119                 SourceLocation loc;
120                 for (DeclContext::decl_iterator i = declCont->decls_begin(), e = declCont->decls_end(); i != e; ++i)
121                 {
122                         const Decl *decl = *i;
123                         const NamedDecl *namedDecl = dyn_cast<NamedDecl>(decl);
124                         
125                         //std::cout<<"a "<<decl->getDeclKindName()<<"\n";
126                         loc = decl->getLocation();
127                         if(loc.isValid())
128                         {                       
129                                 if (const TagDecl *tagDecl = dyn_cast<TagDecl>(decl))
130                                 {
131                                         if(tagDecl->isStruct() || tagDecl->isClass()) //is it a structure or class      
132                                         {
133                                                 const CXXRecordDecl *cRecDecl = dyn_cast<CXXRecordDecl>(decl);
134                                                 line = cut_commentary(clean_spaces(get_line_of_code(sman.getCharacterData(loc))));
135                                                 if(is_derived(line))
136                                                 {
137                                                         if(find_states(cRecDecl, line))
138                                                         {                               
139                                                                 const DeclContext *declCont = tagDecl->castToDeclContext(tagDecl);                                      
140                                                                 std::cout << "New state: " << namedDecl->getNameAsString() << "\n";
141                                                                 find_transitions(namedDecl->getNameAsString(), declCont);
142                                                         }
143                                                 }
144                                         }       
145                                 }
146                                 if(const NamespaceDecl *namespaceDecl = dyn_cast<NamespaceDecl>(decl))
147                                 {
148                                         DeclContext *declCont = namespaceDecl->castToDeclContext(namespaceDecl);
149                                         //declCont->dumpDeclContext();                          
150                                         recursive_visit(declCont);
151                                 }
152                         }
153                 } 
154         }
155         bool find_states(const CXXRecordDecl *cRecDecl, std::string line)
156         {       
157                 std::string super_class = get_super_class(line), base;
158                 if(cRecDecl->getNumBases()>1)
159                 {
160                         for(int i = 0; i<cRecDecl->getNumBases();i++ )
161                         {
162                                 if(i!=cRecDecl->getNumBases()-1) base = get_first_base(super_class);
163                                 else base = super_class;
164                                 if(is_state(base)) return true;
165                                 else
166                                 {
167                                         super_class = get_next_base(super_class);
168                                 }
169                         }
170                         return false;
171                 }
172                 else
173                 { 
174                         if(is_state(super_class)) return true;
175                         else return false;
176                 }
177         }
178
179         void find_transitions (const std::string name_of_state,const DeclContext *declCont) // traverse all methods for finding declarations of transitions
180         {       
181                 std::string output, line, event, dest, params, base;    
182                 llvm::raw_string_ostream x(output);
183                 int pos;
184                 int num;                
185                 for (DeclContext::decl_iterator i = declCont->decls_begin(), e = declCont->decls_end(); i != e; ++i) 
186                 {
187                         const Decl *decl = *i;
188                         
189                         if (const TypedefDecl *typeDecl = dyn_cast<TypedefDecl>(decl)) 
190                         {
191                                         decl->print(x);
192                                         output = x.str();
193                                         line = clean_spaces(cut_typedef(output));
194                                         num = count(output);                                    
195                                         if(num>1)
196                                         {
197                                                 num-=1;
198                                                 if(is_list(line))
199                                                 {
200                                                         line = get_inner_part(line);
201                                                 }
202                                         }
203                                         for(int j = 0;j<num;j++)
204                                         {
205                                                 if(j!=num-1) base = get_first_base(line);                       
206                                                 else base = line;
207                                                 if(is_transition(base))
208                                                 {
209                                                         params = get_transition_params(line);
210                                                         pos = params.find(",");
211                                                         event = params.substr(0,pos);
212                                                         dest = params.substr(pos+1);
213                                                         std::cout << "New transition: " << name_of_state<<" -> "<<event<<" -> "<< dest<<"\n";
214                                                         line = get_next_base(line);
215                                                 }
216                                                 else
217                                                 {
218                                                         line = get_next_base(line);
219                                                 }
220                                         }
221                         }
222                 }       
223         }       
224 };
225
226 int main(int argc, char *argv[])
227 {
228         llvm::cl::ParseCommandLineOptions(argc, argv);  
229         DiagnosticOptions diagnosticOptions;
230         TextDiagnosticPrinter *tdp = new TextDiagnosticPrinter(llvm::nulls(), diagnosticOptions);
231         llvm::IntrusiveRefCntPtr<DiagnosticIDs> dis(new DiagnosticIDs());
232         Diagnostic diag(dis,tdp);
233         FileSystemOptions fileSysOpt;     
234         LangOptions lang;
235         lang.BCPLComment=1;
236         lang.CPlusPlus=1; 
237         FileManager fm (fileSysOpt);
238
239         SourceManager sm ( diag, fm);
240         HeaderSearch *headers = new HeaderSearch(fm);
241         CompilerInvocation::setLangDefaults(lang, IK_ObjCXX);
242
243         HeaderSearchOptions hsopts;
244         hsopts.ResourceDir=LLVM_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
245         for(int i = 0; i<includeFiles.size();i++)
246         {       
247                 hsopts.AddPath(includeFiles[i],
248                                 clang::frontend::Angled,
249                                 false,
250                                 false,
251                                 true);
252         }
253         TargetOptions to;
254         to.Triple = llvm::sys::getHostTriple();
255         TargetInfo *ti = TargetInfo::CreateTargetInfo(diag, to);
256         clang::ApplyHeaderSearchOptions(
257         *headers,
258         hsopts,
259         lang,
260         ti->getTriple());
261         Preprocessor pp(diag, lang, *ti, sm, *headers);
262         FrontendOptions f;
263         PreprocessorOptions ppio;
264         InitializePreprocessor(pp, ppio,hsopts,f);
265         const FileEntry *file = fm.getFile("test.cpp");
266         sm.createMainFileID(file);
267         IdentifierTable tab(lang);
268         SelectorTable sel;
269         Builtin::Context builtins(*ti);
270         FindStates c;
271         ASTContext ctx(lang, sm, *ti, tab, sel, builtins,0);
272         tdp->BeginSourceFile(lang, &pp);
273         ParseAST(pp, &c, ctx, false, false);
274         tdp->EndSourceFile();
275         return 0;
276
277 }