File indexing completed on 2024-05-12 04:39:12

0001 /*
0002     SPDX-FileCopyrightText: 2013 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "debugvisitor.h"
0008 #include "util/clangtypes.h"
0009 #include "util/clangutils.h"
0010 
0011 namespace {
0012 
0013 struct ClientData
0014 {
0015     QTextStream* out;
0016     ParseSession* session;
0017     CXFile file;
0018     uint depth;
0019 };
0020 
0021 CXChildVisitResult visitCursor(CXCursor cursor, CXCursor /*parent*/, CXClientData d)
0022 {
0023     auto data = static_cast<ClientData*>(d);
0024 
0025     const auto kind = clang_getCursorKind(cursor);
0026 
0027     const auto location = clang_getCursorLocation(cursor);
0028     CXFile file;
0029     clang_getFileLocation(location, &file, nullptr, nullptr, nullptr);
0030     // don't skip MemberRefExpr with invalid location, see also:
0031     // http://lists.cs.uiuc.edu/pipermail/cfe-dev/2015-May/043114.html
0032     if (!ClangUtils::isFileEqual(file, data->file) && (file || kind != CXCursor_MemberRefExpr)) {
0033         return CXChildVisit_Continue;
0034     }
0035 
0036     (*data->out) << QByteArray(data->depth * 2, ' ');
0037 
0038     ClangString kindName(clang_getCursorKindSpelling(kind));
0039     (*data->out) << kindName << " (" << kind << ") ";
0040 
0041     auto type = clang_getCursorType(cursor);
0042     if (type.kind != CXType_Invalid) {
0043         ClangString typeName(clang_getTypeSpelling(type));
0044         (*data->out) << "| type: \"" << typeName << '\"' << " (" << type.kind << ") ";
0045     }
0046 
0047     auto canonicalType = clang_getCanonicalType(type);
0048     if (canonicalType.kind != CXType_Invalid
0049         && !clang_equalTypes(type, canonicalType)) {
0050         ClangString typeName(clang_getTypeSpelling(canonicalType));
0051         (*data->out) << "| canonical type: \"" << typeName << '\"' << " (" << canonicalType.kind << ") ";
0052     }
0053 
0054     auto typedefType = clang_getTypedefDeclUnderlyingType(cursor);
0055     if (typedefType.kind != CXType_Invalid
0056         && !clang_equalTypes(type, typedefType)) {
0057         ClangString typeName(clang_getTypeSpelling(typedefType));
0058         (*data->out) << "| typedef type: \"" << typeName << '\"' << " (" << typedefType.kind << ") ";
0059     }
0060 
0061     ClangString displayName(clang_getCursorDisplayName(cursor));
0062     if (!displayName.isEmpty()) {
0063         (*data->out) << "| display: \"" << displayName << "\" ";
0064     }
0065 
0066     auto cursorExtent = ClangRange(clang_getCursorExtent(cursor)).toRange();
0067     ClangString fileName(clang_getFileName(file));
0068     (*data->out) << "| loc: " << fileName << '@' << '['
0069         << '(' << cursorExtent.start().line()+1 << ',' << cursorExtent.start().column()+1 << "),"
0070         << '(' << cursorExtent.end().line()+1 << ',' << cursorExtent.end().column()+1 << ")] ";
0071 
0072     auto spellingNameRange = ClangRange(clang_Cursor_getSpellingNameRange(cursor, 0, 0)).toRange();
0073     (*data->out) << "| sp-name-range: ["
0074         << '(' << spellingNameRange.start().line()+1 << ',' << spellingNameRange.start().column()+1 << "),"
0075         << '(' << spellingNameRange.end().line()+1 << ',' << spellingNameRange.end().column()+1 << ")] ";
0076 
0077     if (clang_isDeclaration(kind)) {
0078         (*data->out) << "| isDecl";
0079     } else {
0080         auto referenced = clang_getCursorReferenced(cursor);
0081         if (kind != CXCursor_UnexposedExpr && !clang_equalCursors(clang_getNullCursor(), referenced)) {
0082             (*data->out) << "| isUse";
0083         }
0084     }
0085 
0086     (*data->out) << Qt::endl;
0087 
0088     ClientData childData{data->out, data->session, data->file, data->depth + 1};
0089     clang_visitChildren(cursor, &visitCursor, &childData);
0090 
0091     return CXChildVisit_Continue;
0092 }
0093 
0094 }
0095 
0096 DebugVisitor::DebugVisitor(ParseSession* session)
0097     : m_session(session)
0098 {
0099 
0100 }
0101 
0102 void DebugVisitor::visit(CXTranslationUnit unit, CXFile file)
0103 {
0104     auto cursor = clang_getTranslationUnitCursor(unit);
0105     QTextStream out(stdout);
0106     ClientData data {&out, m_session, file, 0};
0107     clang_visitChildren(cursor, &visitCursor, &data);
0108 }