language/duchain
dumpdotgraph.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "dumpdotgraph.h"
00015
00016 #include "ducontext.h"
00017 #include "topducontext.h"
00018 #include "declaration.h"
00019 #include "duchainpointer.h"
00020 #include "parsingenvironment.h"
00021 #include "identifier.h"
00022 #include "functiondefinition.h"
00023
00024 namespace KDevelop {
00025
00026 QString shortLabel(KDevelop::DUContext* context) {
00027 return QString("q%1").arg((quint64)context);
00028 }
00029
00030 QString shortLabel(KDevelop::Declaration* declaration) {
00031 return QString("q%1").arg((quint64)declaration);
00032 }
00033
00034 QString rangeToString( const KTextEditor::Range& r ) {
00035 return QString("%1:%2->%3:%4").arg(r.start().line()).arg(r.start().column()).arg(r.end().line()).arg(r.end().column());
00036 }
00037
00038
00039 class DumpDotGraphPrivate
00040 {
00041 public:
00042
00043 QString dotGraphInternal(KDevelop::DUContext* contex, bool isMaster, bool shortened);
00044
00045 void addDeclaration(QTextStream& stream, Declaration* decl);
00046
00047 QMap<KUrl,QString> m_hadVersions;
00048 QMap<KDevelop::DUChainBase*, bool> m_hadObjects;
00049 TopDUContext* m_topContext;
00050 };
00051
00052 QString DumpDotGraph::dotGraph(KDevelop::DUContext* context, bool shortened ) {
00053 d->m_hadObjects.clear();
00054 d->m_hadVersions.clear();
00055 d->m_topContext = context->topContext();
00056 return d->dotGraphInternal(context, true, shortened);
00057 }
00058
00059 DumpDotGraph::DumpDotGraph() : d(new DumpDotGraphPrivate()) {
00060
00061 }
00062
00063 DumpDotGraph::~DumpDotGraph() {
00064 delete d;
00065 }
00066
00067 void DumpDotGraphPrivate::addDeclaration(QTextStream& stream, Declaration* dec) {
00068 if( m_hadObjects.contains(dec) )
00069 return;
00070
00071 m_hadObjects[dec] = true;
00072
00073 Declaration* declarationForDefinition = 0;
00074 if(dynamic_cast<FunctionDefinition*>(dec))
00075 declarationForDefinition = static_cast<FunctionDefinition*>(dec)->declaration(m_topContext);
00076
00077 if(!declarationForDefinition) {
00078
00079 stream << shortLabel(dec) <<
00080 "[shape=distortion,label=\"" <<
00081 dec->toString() << " [" <<
00082 dec->qualifiedIdentifier().toString() << "]" << " " <<
00083 rangeToString(dec->range().textRange()) << "\"];\n";
00084 stream << shortLabel(dec->context()) << " -> " << shortLabel(dec) << "[color=green];\n";
00085 if( dec->internalContext() )
00086 stream << shortLabel(dec) << " -> " << shortLabel(dec->internalContext()) << "[label=\"internal\", color=blue];\n";
00087 }else{
00088
00089 stream << shortLabel(dec) << "[shape=regular,color=yellow,label=\"" << declarationForDefinition->toString() << " "<< rangeToString(dec->range().textRange()) << "\"];\n";
00090 stream << shortLabel(dec->context()) << " -> " << shortLabel(dec) << ";\n";
00091
00092 stream << shortLabel(dec) << " -> " << shortLabel(declarationForDefinition) << "[label=\"defines\",color=green];\n";
00093 addDeclaration(stream, declarationForDefinition);
00094
00095 if( dec->internalContext() )
00096 stream << shortLabel(dec) << " -> " << shortLabel(dec->internalContext()) << "[label=\"internal\", color=blue];\n";
00097 }
00098 }
00099
00100
00101 QString DumpDotGraphPrivate::dotGraphInternal(KDevelop::DUContext* context, bool isMaster, bool shortened) {
00102 if( m_hadObjects.contains(context) )
00103 return QString();
00104
00105 m_hadObjects[context] = true;
00106
00107 QTextStream stream;
00108 QString ret;
00109 stream.setString(&ret, QIODevice::WriteOnly);
00110
00111 if( isMaster )
00112 stream << "Digraph chain {\n";
00113
00114 QString shape = "parallelogram";
00115
00116 QString label = "unknown";
00117
00118 if( dynamic_cast<TopDUContext*>(context) )
00119 {
00120 TopDUContext* topCtx = static_cast<TopDUContext*>(context);
00121 if( topCtx->parsingEnvironmentFile() ) {
00122 QString file( topCtx->parsingEnvironmentFile()->url().str() );
00123
00124 KUrl url = KUrl(file);
00125 if(topCtx->parsingEnvironmentFile() && topCtx->parsingEnvironmentFile()->isProxyContext())
00126 url.addPath("_[proxy]_");
00127
00128
00129 if( m_hadVersions.contains(url) ) {
00130 stream << shortLabel(context) << " -> " << m_hadVersions[url] << "[color=blue,label=\"version\"];\n";
00131 file = KUrl(file).fileName();
00132 } else {
00133 m_hadVersions[url] = shortLabel(context);
00134 }
00135
00136 label = file;
00137
00138 if( topCtx->importers().count() != 0 )
00139 label += QString(" imported by %1").arg(topCtx->importers().count());
00140 } else {
00141 label = "unknown file";
00142 }
00143 if(topCtx->parsingEnvironmentFile() && topCtx->parsingEnvironmentFile()->isProxyContext())
00144 label = "Proxy-context " + label;
00145 }else{
00146 label = context->localScopeIdentifier().toString();
00147 label += ' ' + rangeToString(context->range().textRange());
00148 }
00149
00150
00151
00152 if( isMaster && !dynamic_cast<TopDUContext*>(context) ) {
00153
00154 foreach( DUContext* ctx, context->importers() )
00155 stream << dotGraphInternal(ctx, false, true);
00156 }
00157
00158 foreach (const DUContext::Import &parent, context->importedParentContexts()) {
00159 if( parent.context(m_topContext) ) {
00160 stream << dotGraphInternal(parent.context(m_topContext), false, true);
00161 QString label = "imports";
00162 if( (!dynamic_cast<TopDUContext*>(parent.context(m_topContext)) || !dynamic_cast<TopDUContext*>(context)) && !(parent.context(m_topContext)->url() == context->url()) ) {
00163 label += " from " + KUrl(parent.context(m_topContext)->url().str()).fileName() + " to " + KUrl(context->url().str()).fileName();
00164 }
00165
00166 stream << shortLabel(context) << " -> " << shortLabel(parent.context(m_topContext)) << "[style=dotted,label=\"" << label << "\"];\n";
00167 }
00168 }
00169
00170 if( !context->childContexts().isEmpty() )
00171 label += QString(", %1 C.").arg(context->childContexts().count());
00172
00173 if( !shortened ) {
00174 foreach (DUContext* child, context->childContexts()) {
00175 stream << dotGraphInternal(child, false, false);
00176 stream << shortLabel(context) << " -> " << shortLabel(child) << "[style=dotted,color=green];\n";
00177 }
00178 }
00179
00180 if( !context->localDeclarations().isEmpty() )
00181 label += QString(", %1 D.").arg(context->localDeclarations().count());
00182
00183 if(!shortened )
00184 {
00185 foreach (Declaration* dec, context->localDeclarations())
00186 addDeclaration(stream, dec);
00187 }
00188
00189 if( context->owner() ) {
00190 addDeclaration(stream, context->owner());
00191 }
00192
00193 stream << shortLabel(context) << "[shape=" << shape << ",label=\"" << label << "\"" << (isMaster ? QString("color=red") : QString("color=blue")) << "];\n";
00194
00195 if( isMaster )
00196 stream << "}\n";
00197
00198 return ret;
00199 }
00200 }