From 61f40dbac56f38ae23d1eed97f5cc7322915d187 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Fri, 31 Aug 2012 00:11:22 +0200 Subject: [PATCH] Handle custom reactions --- src/visualizer.cpp | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/visualizer.cpp b/src/visualizer.cpp index 1644414..e720998 100644 --- a/src/visualizer.cpp +++ b/src/visualizer.cpp @@ -234,6 +234,28 @@ public: } }; +class FindTransitVisitor : public RecursiveASTVisitor +{ + Model::Model &model; + const CXXRecordDecl *SrcState; + const Type *EventType; +public: + explicit FindTransitVisitor(Model::Model &model, const CXXRecordDecl *SrcState, const Type *EventType) + : model(model), SrcState(SrcState), EventType(EventType) {} + + bool VisitMemberExpr(MemberExpr *E) { + if (E->getMemberNameInfo().getAsString() != "transit") + return true; + if (E->hasExplicitTemplateArgs()) { + const Type *DstStateType = E->getExplicitTemplateArgs()[0].getArgument().getAsType().getTypePtr(); + CXXRecordDecl *DstState = DstStateType->getAsCXXRecordDecl(); + CXXRecordDecl *Event = EventType->getAsCXXRecordDecl(); + Model::Transition *T = new Model::Transition(SrcState->getName(), DstState->getName(), Event->getName()); + model.transitions.push_back(T); + } + return true; + } +}; class Visitor : public RecursiveASTVisitor { @@ -263,6 +285,23 @@ public: DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { return Diags.Report(Loc, DiagID); } + void HandleCustomReaction(const CXXRecordDecl *SrcState, const Type *EventType) + { + IdentifierInfo& II = ASTCtx->Idents.get("react"); + // TODO: Lookup for react even in base classes - probably by using Sema::LookupQualifiedName() + for (DeclContext::lookup_const_result ReactRes = SrcState->lookup(DeclarationName(&II)); + ReactRes.first != ReactRes.second; ++ReactRes.first) { + if (CXXMethodDecl *React = dyn_cast(*ReactRes.first)) + if (const ParmVarDecl *p = React->getParamDecl(0)) { + const Type *ParmType = p->getType().getTypePtr(); + if (ParmType->isLValueReferenceType()) + ParmType = dyn_cast(ParmType)->getPointeeType().getTypePtr(); + if (ParmType == EventType) + FindTransitVisitor(model, SrcState, EventType).TraverseStmt(React->getBody()); + } + } + } + void HandleReaction(const Type *T, const SourceLocation Loc, CXXRecordDecl *SrcState) { // TODO: Improve Loc tracking @@ -280,10 +319,7 @@ public: model.transitions.push_back(T); } else if (name == "boost::statechart::custom_reaction") { const Type *EventType = TST->getArg(0).getAsType().getTypePtr(); - CXXRecordDecl *Event = EventType->getAsCXXRecordDecl(); - - Model::Transition *T = new Model::Transition(SrcState->getName(), "\"??? custom\"", Event->getName()); - model.transitions.push_back(T); + HandleCustomReaction(SrcState, EventType); } else if (name == "boost::statechart::deferral") { const Type *EventType = TST->getArg(0).getAsType().getTypePtr(); CXXRecordDecl *Event = EventType->getAsCXXRecordDecl(); @@ -337,6 +373,7 @@ public: // Either we saw a reference to forward declared state // before, or we create a new state. if (!(state = model.removeFromUnknownContexts(name))) + // TODO: Fix the value of name state = new Model::State(name); CXXRecordDecl *Context = getTemplateArgDecl(Base->getType().getTypePtr(), 1); -- 2.39.2