示例#1
0
DocumentationData TranslationUnit::GetDocsForLocationInFile(
  int line,
  int column,
  const std::vector< UnsavedFile > &unsaved_files,
  bool reparse ) {

  if ( reparse )
    Reparse( unsaved_files );

  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return DocumentationData();

  CXCursor cursor = GetCursor( line, column );

  if ( !CursorIsValid( cursor ) )
    return DocumentationData();

  // If the original cursor is a reference, then we return the documentation
  // for the type/method/etc. that is referenced
  CXCursor referenced_cursor = clang_getCursorReferenced( cursor );

  if ( CursorIsValid( referenced_cursor ) )
    cursor = referenced_cursor;

  // We always want the documentation associated with the canonical declaration
  CXCursor canonical_cursor = clang_getCanonicalCursor( cursor );

  if ( !CursorIsValid( canonical_cursor ) )
    return DocumentationData();

  return DocumentationData( canonical_cursor );
}
示例#2
0
Location TranslationUnit::GetDeclarationLocation(
  int line,
  int column,
  const std::vector< UnsavedFile > &unsaved_files,
  bool reparse ) {
  if ( reparse )
    Reparse( unsaved_files );

  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return Location();

  CXCursor cursor = GetCursor( line, column );

  if ( !CursorIsValid( cursor ) )
    return Location();

  CXCursor referenced_cursor = clang_getCursorReferenced( cursor );

  if ( !CursorIsValid( referenced_cursor ) )
    return Location();

  CXCursor canonical_cursor = clang_getCanonicalCursor( referenced_cursor );

  if ( !CursorIsValid( canonical_cursor ) )
    return Location( clang_getCursorLocation( referenced_cursor ) );

  return Location( clang_getCursorLocation( canonical_cursor ) );
}
示例#3
0
CXChildVisitResult DumpThread::visitor(CXCursor cursor, CXCursor, CXClientData userData)
{
    DumpThread *that = reinterpret_cast<DumpThread*>(userData);
    assert(that);
    CXSourceLocation location = clang_getCursorLocation(cursor);
    if (!clang_equalLocations(location, nullLocation)) {
        CXString file;
        unsigned line, col;
        clang_getPresumedLocation(location, &file, &line, &col);
        Path path = RTags::eatString(file);
        if (!path.isEmpty()) {
            uint32_t &fileId = that->mFiles[path];
            if (!fileId) {
                const Path resolved = path.resolved();
                fileId = Location::insertFile(resolved);
                that->mFiles[path] = that->mFiles[resolved] = fileId;
            }
            if (that->mQueryFlags & QueryMessage::DumpIncludeHeaders || fileId == that->mSource.fileId) {
                const Location loc(fileId, line, col);
                String message;
                message.reserve(256);
                if (!(that->mQueryFlags & QueryMessage::NoContext))
                    message += loc.context();

                CXSourceRange range = clang_getCursorExtent(cursor);
                CXSourceLocation rangeEnd = clang_getRangeEnd(range);
                unsigned endLine, endColumn;
                clang_getPresumedLocation(rangeEnd, 0, &endLine, &endColumn);
                if (endLine == line) {
                    message += String::format<32>(" // %d-%d, %d: ", col, endColumn, that->mIndentLevel);
                } else {
                    message += String::format<32>(" // %d-%d:%d, %d: ", col, endLine, endColumn, that->mIndentLevel);
                }
                message += RTags::cursorToString(cursor, RTags::AllCursorToStringFlags);
                message.append(" " + RTags::typeName(cursor) + " ");
                CXCursor ref = clang_getCursorReferenced(cursor);
                if (clang_equalCursors(ref, cursor)) {
                    message.append("refs self");
                } else if (!clang_equalCursors(ref, nullCursor)) {
                    message.append("refs ");
                    message.append(RTags::cursorToString(ref, RTags::AllCursorToStringFlags));
                }

                CXCursor canonical = clang_getCanonicalCursor(cursor);
                if (!clang_equalCursors(canonical, cursor) && !clang_equalCursors(canonical, nullCursor)) {
                    message.append("canonical ");
                    message.append(RTags::cursorToString(canonical, RTags::AllCursorToStringFlags));
                }

                that->writeToConnetion(message);
            }
        }
    }
    ++that->mIndentLevel;
    clang_visitChildren(cursor, DumpThread::visitor, userData);
    --that->mIndentLevel;
    return CXChildVisit_Continue;
}
示例#4
0
int main(int argc, char *argv[])
{
  auto index = clang_createIndex(0, 0);
  auto options = clang_defaultEditingTranslationUnitOptions();
  char const *args[] = { "-x", "c++", "-std=c++11" };
  auto arg_count = sizeof( args ) / sizeof( *args );
  filename = argv[1];
  
  CXUnsavedFile *unsaved_files = NULL;
  auto unsaved_file_count = 0;
  
  tu = clang_parseTranslationUnit(index, filename.c_str(), args, arg_count,
				  unsaved_files, unsaved_file_count,
				  options );
  
  if ( !tu ) {
    std::cout << "Translation Unit Parse Failed!\n";
    return -1;
  }

  std::stringstream ss( argv[2] );
  int line, col;

  ss >> line;
  ss.get();
  ss >> col;
  std::cout << "Hello " << line << ":" << col << "\n";

  auto file = clang_getFile( tu, filename.c_str() );
  auto location = clang_getLocation( tu, file, line, col );

  
  clang_visitChildren( clang_getTranslationUnitCursor( tu ), visitor,
		       reinterpret_cast<CXClientData>(0) );
  
  auto cursor = clang_getCursor( tu, location );
  auto refcursor = clang_getCursorReferenced( cursor );
  auto rrefcursor = clang_getCursorReferenced( refcursor );
  auto arf = clang_getTypeKindSpelling( clang_getCursorType( cursor ).kind );
  auto foo = clang_getCanonicalCursor( cursor );
  auto semparent = clang_getCursorSemanticParent( cursor );
  auto lexparent = clang_getCursorLexicalParent( cursor );

  std::cout << cursor << "\n";
  std::cout << refcursor << "\n";
  std::cout << rrefcursor << "\n";
  std::cout << clang_getCString(arf) << "\n";
  std::cout << foo << "\n";
  std::cout << "Parent: " << semparent << "\n";
  std::cout << "LexParent: " << lexparent << "\n";
  
  //clang_visitChildren( semparent, visitor, reinterpret_cast<CXClientData>(0) );
  clang_disposeString( arf );

  return 0;
}
示例#5
0
Cursor Cursor::canonical() const
{
	if ( !m_canonical ) {
		CXCursor cx_cursor(clang_getCanonicalCursor(m_cx_cursor));
		if ( is_null(cx_cursor) ) {
			CLANGXX_THROW_LogicError("Error retrieving the canonical cursor corresponding to this cursor.");
		}
		m_canonical.reset(new Cursor(std::move(cx_cursor), m_translation_unit));
	}
	return *m_canonical;
}
示例#6
0
Location TranslationUnit::GetDeclarationLocationForCursor( CXCursor cursor ) {
  CXCursor referenced_cursor = clang_getCursorReferenced( cursor );

  if ( !CursorIsValid( referenced_cursor ) ) {
    return Location();
  }

  CXCursor canonical_cursor = clang_getCanonicalCursor( referenced_cursor );

  if ( !CursorIsValid( canonical_cursor ) ) {
    return Location( clang_getCursorLocation( referenced_cursor ) );
  }

  return Location( clang_getCursorLocation( canonical_cursor ) );
}
示例#7
0
CXChildVisitResult DumpThread::visit(const CXCursor &cursor)
{
    if (isAborted())
        return CXChildVisit_Break;
    const Location location = createLocation(cursor);
    if (!location.isNull()) {
        if (mQueryFlags & QueryMessage::DumpCheckIncludes) {
            checkIncludes(location, cursor);
            return CXChildVisit_Recurse;
        } else {
            Flags<Location::ToStringFlag> locationFlags;
            if (mQueryFlags & QueryMessage::NoColor)
                locationFlags |= Location::NoColor;

            CXSourceRange range = clang_getCursorExtent(cursor);
            CXSourceLocation rangeEnd = clang_getRangeEnd(range);
            unsigned int endLine, endColumn;
            clang_getPresumedLocation(rangeEnd, 0, &endLine, &endColumn);
            if (!(mQueryFlags & QueryMessage::DumpIncludeHeaders) && location.fileId() != mSource.fileId) {
                return CXChildVisit_Continue;
            }

            String message;
            message.reserve(256);

            if (!(mQueryFlags & QueryMessage::NoContext)) {
                message = location.context(locationFlags);
            }

            if (endLine == location.line()) {
                message += String::format<32>(" // %d-%d, %d: ", location.column(), endColumn, mIndentLevel);
            } else {
                message += String::format<32>(" // %d-%d:%d, %d: ", location.column(), endLine, endColumn, mIndentLevel);
            }
            message += RTags::cursorToString(cursor, RTags::AllCursorToStringFlags);
            message.append(" " + RTags::typeName(cursor));;
            if (clang_getCursorKind(cursor) == CXCursor_VarDecl) {
                const std::shared_ptr<RTags::Auto> autoResolved = RTags::resolveAuto(cursor);
                if (autoResolved && !clang_equalCursors(autoResolved->cursor, nullCursor)) {
                    message += "auto resolves to " + RTags::cursorToString(autoResolved->cursor, RTags::AllCursorToStringFlags);
                }
            }
            CXCursor ref = clang_getCursorReferenced(cursor);
            if (clang_equalCursors(ref, cursor)) {
                message.append("refs self");
            } else if (!clang_equalCursors(ref, nullCursor)) {
                message.append("refs ");
                message.append(RTags::cursorToString(ref, RTags::AllCursorToStringFlags));
            }

            CXCursor canonical = clang_getCanonicalCursor(cursor);
            if (!clang_equalCursors(canonical, cursor) && !clang_equalCursors(canonical, nullCursor)) {
                message.append("canonical ");
                message.append(RTags::cursorToString(canonical, RTags::AllCursorToStringFlags));
            }

            CXCursor specialized = clang_getSpecializedCursorTemplate(cursor);
            if (!clang_equalCursors(specialized, cursor) && !clang_equalCursors(specialized, nullCursor)) {
                message.append("specialized ");
                message.append(RTags::cursorToString(specialized, RTags::AllCursorToStringFlags));
            }

            writeToConnetion(message);
        }
    }
    ++mIndentLevel;
    clang_visitChildren(cursor, DumpThread::visitor, this);
    if (isAborted())
        return CXChildVisit_Break;
    --mIndentLevel;
    return CXChildVisit_Continue;
}
示例#8
0
cursor cursor::getCanonical()
{
    return { clang_getCanonicalCursor(cur) };
}
示例#9
0
bool ClangIndexer::handleCursor(const CXCursor &cursor, CXCursorKind kind, const Location &location)
{
    // error() << "Got a cursor" << cursor;
    std::shared_ptr<CursorInfo> &info = mData->symbols[location];
    if (!info)
        info = std::make_shared<CursorInfo>();

    if (!info->symbolLength) {
        // if (mLogFile) {
        //     String out;
        //     Log(&out) << cursor << a;
        //     fwrite(out.constData(), 1, out.size(), mLogFile);
        //     fwrite("\n", 1, 1, mLogFile);
        // }
        CXStringScope name = clang_getCursorSpelling(cursor);
        const char *cstr = name.data();
        info->symbolLength = cstr ? strlen(cstr) : 0;
        info->type = clang_getCursorType(cursor).kind;
        if (!info->symbolLength) {
            // this is for these constructs:
            // typedef struct {
            //    int a;
            // } foobar;
            //
            // We end up not getting a spelling for the cursor

            switch (kind) {
            case CXCursor_ClassDecl:
                info->symbolLength = 5;
                info->symbolName = "class";
                break;
            case CXCursor_UnionDecl:
                info->symbolLength = 5;
                info->symbolName = "union";
                break;
            case CXCursor_StructDecl:
                info->symbolLength = 6;
                info->symbolName = "struct";
                break;
            default:
                mData->symbols.remove(location);
                return false;
            }
        } else {
            info->symbolName = addNamePermutations(cursor, location);
        }

        CXSourceRange range = clang_getCursorExtent(cursor);
        CXSourceLocation rangeStart = clang_getRangeStart(range);
        CXSourceLocation rangeEnd = clang_getRangeEnd(range);
        unsigned startLine, startColumn, endLine, endColumn;
        clang_getPresumedLocation(rangeStart, 0, &startLine, &startColumn);
        clang_getPresumedLocation(rangeEnd, 0, &endLine, &endColumn);
        info->startLine = startLine;
        info->startColumn = startColumn;
        info->endLine = endLine;
        info->endColumn = endColumn;

        if (kind == CXCursor_EnumConstantDecl) {
#if CINDEX_VERSION_MINOR > 1
            info->enumValue = clang_getEnumConstantDeclValue(cursor);
#else
            info->definition = 1;
#endif
        } else {
            info->definition = clang_isCursorDefinition(cursor);
        }
        info->kind = kind;
        // apparently some function decls will give a different usr for
        // their definition and their declaration.  Using the canonical
        // cursor's usr allows us to join them. Check JSClassRelease in
        // JavaScriptCore for an example.
        const String usr = RTags::eatString(clang_getCursorUSR(clang_getCanonicalCursor(cursor)));
        if (!usr.isEmpty())
            mData->usrMap[usr].insert(location);

        switch (info->kind) {
        case CXCursor_Constructor:
        case CXCursor_Destructor: {
            Location parentLocation = createLocation(clang_getCursorSemanticParent(cursor));
            // consider doing this for only declaration/inline definition since
            // declaration and definition should know of one another
            if (parentLocation.isValid()) {
                std::shared_ptr<CursorInfo> &parent = mData->symbols[parentLocation];
                if (!parent)
                    parent = std::make_shared<CursorInfo>();
                parent->references.insert(location);
                info->references.insert(parentLocation);
            }
            break; }
        case CXCursor_CXXMethod: {
            List<CursorInfo*> infos;
            infos.append(info.get());
            addOverriddenCursors(cursor, location, infos);
            break; }
        default:
            break;
        }
    }

    return true;
}
示例#10
0
void ClangIndexer::handleReference(const CXCursor &cursor, CXCursorKind kind, const Location &location, const CXCursor &ref, const CXCursor &parent)
{
    const CXCursorKind refKind = clang_getCursorKind(ref);
    if (clang_isInvalid(refKind)) {
        superclassTemplateMemberFunctionUgleHack(cursor, kind, location, ref, parent);
        return;
    }

    bool isOperator = false;
    if (kind == CXCursor_CallExpr && (refKind == CXCursor_CXXMethod
                                      || refKind == CXCursor_ConversionFunction
                                      || refKind == CXCursor_FunctionDecl
                                      || refKind == CXCursor_FunctionTemplate)) {
        // these are bullshit, for this construct:
        // foo.bar();
        // the position of the cursor is at the foo, not the bar.
        // They are not interesting for followLocation, renameSymbol or find
        // references so we toss them.
        // For functions it can be the position of the namespace.
        // E.g. Foo::bar(); cursor is on Foo
        // For constructors they happen to be the only thing we have that
        // actually refs the constructor and not the class so we have to keep
        // them for that.
        return;
    }

    switch (refKind) {
    case CXCursor_Constructor:
        if (isImplicit(ref))
            return;
        break;
    case CXCursor_CXXMethod:
    case CXCursor_FunctionDecl:
    case CXCursor_FunctionTemplate: {
        CXStringScope scope = clang_getCursorDisplayName(ref);
        const char *data = scope.data();
        if (data) {
            const int len = strlen(data);
            if (len > 8 && !strncmp(data, "operator", 8) && !isalnum(data[8]) && data[8] != '_') {
                if (isImplicit(ref))
                    return; // eat implicit operator calls
                isOperator = true;
            }
        }
        break; }
    default:
        break;
    }

    const Location reffedLoc = createLocation(ref);
    if (!reffedLoc.isValid()) {
        if (kind == CXCursor_ObjCMessageExpr) {
            mData->pendingReferenceMap[RTags::eatString(clang_getCursorUSR(clang_getCanonicalCursor(ref)))].insert(location);
            // insert it, we'll hook up the target and references later
            handleCursor(cursor, kind, location);
        }
        return;
    }

    std::shared_ptr<CursorInfo> &refInfo = mData->symbols[reffedLoc];
    if ((!refInfo || !refInfo->symbolLength) && !handleCursor(ref, refKind, reffedLoc))
        return;

    refInfo->references.insert(location);

    std::shared_ptr<CursorInfo> &info = mData->symbols[location];
    if (!info)
        info = std::make_shared<CursorInfo>();
    info->targets.insert(reffedLoc);

    // We need the new cursor to replace the symbolLength. This is important
    // in the following case:
    // struct R { R(const &r); ... }
    // R foo();
    // ...
    // R r = foo();

    // The first cursor on foo() will be a reference to the copy constructor and
    // this cursor will have a symbolLength of 1. Thus you won't be able to jump
    // to foo from the o. This is fixed by making sure the newer target, if
    // better, gets to decide on the symbolLength

    // The !isCursor is var decls and field decls where we set up a target even
    // if they're not considered references

    if (!RTags::isCursor(info->kind) && (!info->symbolLength || info->bestTarget(mData->symbols)->kind == refKind)) {
        CXSourceRange range = clang_getCursorExtent(cursor);
        CXSourceLocation rangeStart = clang_getRangeStart(range);
        CXSourceLocation rangeEnd = clang_getRangeEnd(range);
        unsigned startLine, startColumn, endLine, endColumn;
        clang_getPresumedLocation(rangeStart, 0, &startLine, &startColumn);
        clang_getPresumedLocation(rangeEnd, 0, &endLine, &endColumn);
        info->startLine = startLine;
        info->startColumn = startColumn;
        info->endLine = endLine;
        info->endColumn = endColumn;
        info->definition = false;
        info->kind = kind;
        if (isOperator) {
            unsigned start, end;
            clang_getSpellingLocation(rangeStart, 0, 0, 0, &start);
            clang_getSpellingLocation(rangeEnd, 0, 0, 0, &end);
            info->symbolLength = end - start;
        } else {
            info->symbolLength = refInfo->symbolLength;
        }
        info->symbolName = refInfo->symbolName;
        info->type = clang_getCursorType(cursor).kind;
    }
}
示例#11
0
Cursor Cursor::canonical() const
{
    return clang_getCanonicalCursor(cxCursor);
}