示例#1
0
void Tokenizer::getMethodNameAtLocation(size_t origOffset, OovString &className,
        OovString &methodName)
    {
    CLangAutoLock lock(mCLangLock, __LINE__, this);
    CXCursor startCursor = getCursorAtOffset(mTransUnit, mSourceFile, origOffset);
    std::string method = getDisposedString(clang_getCursorDisplayName(startCursor));
    size_t pos = method.find('(');
    if(pos != std::string::npos)
        {
        method.erase(pos);
        }
    methodName = method;

    // Attempt to go to the definition from the following places:
    //  A header file method declaration or inline definition.
    //  A source file where the method is defined.
    //  A call to a method through a pointer, or directly (self)

    // Attempt to go directly to the definition, it will work if it is in this
    // translation unit.
    CXCursor methodDefCursor = clang_getCursorDefinition(startCursor);
    CXCursor classCursor = startCursor;         // Just default to something.

    // Method call can return invalid file when the definition is not in this
    // translation unit.
    if(clang_getCursorKind(methodDefCursor) != CXCursor_InvalidFile)
        {
        // In this translation unit (either header or source)
        // At this point, the semantic parent of the method definition is
        // the class.
        classCursor = clang_getCursorSemanticParent(methodDefCursor);
        }
    else
        {
        // In a file that isn't in this translation unit
        if(startCursor.kind == CXCursor_CXXMethod)
            {
            classCursor = clang_getCursorSemanticParent(startCursor);
            }
        else    // Handle a call - The cursor is usually a compound statement?
            {
            // The definition was not available, so instead, look for the
            // declaration and class from through the referenced cursor.
            CXCursor refCursor = clang_getCursorReferenced(startCursor);
            classCursor = clang_getCursorSemanticParent(refCursor);
            }
        }

    std::string classCursorStr = getDisposedString(clang_getCursorDisplayName(classCursor));
    className = classCursorStr;
    }
示例#2
0
std::string TranslationUnit::GetEnclosingFunctionAtLocation(
  const std::string &filename,
  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 "Internal error: no translation unit";
  }

  CXCursor cursor = GetCursor( filename, line, column );

  if ( !CursorIsValid( cursor ) ) {
    return "Internal error: cursor not valid";
  }

  CXCursor parent = clang_getCursorSemanticParent( cursor );

  std::string parent_str =
    CXStringToString( clang_getCursorDisplayName( parent ) );

  if ( parent_str.empty() ) {
    return "Unknown semantic parent";
  }

  return parent_str;
}
CXChildVisitResult visitor(
        CXCursor cursor, CXCursor parent, CXClientData client_data)
{
    ClangTools::TranslationUnit::AstWalker * astWalker =
        reinterpret_cast<ClangTools::TranslationUnit::AstWalker *>(client_data);
    std::vector<std::string> & funcNames =
        *(reinterpret_cast<std::vector<std::string> *>(astWalker->getClientData()));

    auto sourceLocation = clang_getCursorLocation(cursor);
    CXFile file;
    clang_getFileLocation(sourceLocation, &file, 0, 0, 0);
    auto fileName = clang_getFileName(file);
    auto fileNameStr = ClangTools::String(fileName);

    if (fileNameStr != astWalker->getFileName())
    {
        return CXChildVisit_Recurse;
    }

    auto func = std::string{};
    auto def = bool{false};

    if (clang_isCursorDefinition(cursor))
    {
        def = true;
    }

    switch (clang_getCursorKind(cursor))
    {
        case CXCursor_FunctionDecl:
            func = "Function ";
            break;
        case CXCursor_FunctionTemplate:
            func = "FunctionTemplate ";
            break;
        case CXCursor_CXXMethod:
            func = "CXXMethod ";
            break;
        default:
            return CXChildVisit_Recurse;
            break;
    }

    func += clang_isCursorDefinition(cursor) ? "definition: " : "declaration: ";

    auto semanticParent = clang_getCursorSemanticParent(cursor);
    auto semanticParentSpelling = clang_getCursorSpelling(semanticParent);
    func += ClangTools::String(semanticParentSpelling) + "::";

    auto cursorSpelling = clang_getCursorSpelling(cursor);
    func += ClangTools::String(cursorSpelling);

    auto lexicalParent = clang_getCursorLexicalParent(cursor);
    auto lexicalParentSpelling = clang_getCursorSpelling(lexicalParent);
    func += " found in: " + ClangTools::String(lexicalParentSpelling);

    funcNames.push_back(func);

    return CXChildVisit_Recurse;
}
示例#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::semantic_parent() const
{
	if ( !m_semantic_parent ) {
		CXCursor cx_cursor(clang_getCursorSemanticParent(m_cx_cursor));
		if ( is_null(cx_cursor) ) {
			CLANGXX_THROW_LogicError("Error determining the semantic parent of this cursor.");
		}
		m_semantic_parent.reset(new Cursor(std::move(cx_cursor), m_translation_unit));
	}
	return *m_semantic_parent;
}
示例#6
0
SEXP R_clang_getCursorSemanticParent(SEXP r_cursor)
{
    SEXP r_ans = R_NilValue;
    CXCursor cursor = * GET_REF(r_cursor, CXCursor);
    
    CXCursor ans;
    ans = clang_getCursorSemanticParent(cursor);
    
    r_ans = R_makeCXCursor(ans) ;
    
    return(r_ans);
} 
示例#7
0
std::string libclang_vim::stringize_parent(CXCursor const& cursor,
                                           CXCursor const& parent) {
    auto const semantic_parent = clang_getCursorSemanticParent(cursor);
    auto const lexical_parent = clang_getCursorLexicalParent(cursor);
    cxstring_ptr parent_name = clang_getCursorSpelling(parent);
    cxstring_ptr semantic_parent_name =
        clang_getCursorSpelling(semantic_parent);
    cxstring_ptr lexical_parent_name = clang_getCursorSpelling(lexical_parent);

    return stringize_key_value("parent", parent_name) +
           stringize_key_value("semantic_parent", semantic_parent_name) +
           stringize_key_value("lexical_parent", lexical_parent_name);
}
示例#8
0
bool IndexerJob::handleCursor(const CXCursor &cursor, CXCursorKind kind, const Location &location)
{
    CursorInfo &info = mData->symbols[location];
    if (!info.symbolLength || !RTags::isCursor(info.kind)) {
        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);
        unsigned start, end;
        clang_getSpellingLocation(clang_getRangeStart(range), 0, 0, 0, &start);
        clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &end);
        info.start = start;
        info.end = end;

        if (kind == CXCursor_EnumConstantDecl) {
#if CLANG_VERSION_MINOR > 1
            info.enumValue = clang_getEnumConstantDeclValue(cursor);
#else
            info.definition = clang_isCursorDefinition(cursor);
#endif
        } else{
            info.definition = clang_isCursorDefinition(cursor);
        }
        info.kind = kind;
        const String usr = RTags::eatString(clang_getCursorUSR(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()) {
                CursorInfo &parent = mData->symbols[parentLocation];
                parent.references.insert(location);
                info.references.insert(parentLocation);
            }
            break; }
        case CXCursor_CXXMethod: {
            List<CursorInfo*> infos;
            infos.append(&info);
            addOverriddenCursors(cursor, location, infos);
            break; }
        default:
            break;
        }
    }

    return true;
}
示例#9
0
String IndexerJob::addNamePermutations(const CXCursor &cursor, const Location &location)
{
    CXCursorKind kind = clang_getCursorKind(cursor);
    const CXCursorKind originalKind = kind;
    char buf[1024];
    int pos = sizeof(buf) - 1;
    buf[pos] = '\0';
    int cutoff = -1;

    CXCursor c = cursor;
    bool hasTemplates = false;
    do {
        CXStringScope displayName(clang_getCursorDisplayName(c));
        const char *name = displayName.data();
        if (!name)
            break;
        const int len = strlen(name);
        if (!len)
            break;

        if (kind == CXCursor_ClassTemplate)
            hasTemplates = true;
        if (pos != sizeof(buf) - 1 && (pos -= 2) >= 0) {
            memset(buf + pos, ':', 2);
        }
        pos -= len;
        if (pos < 0) {
            error("SymbolName too long. Giving up");
            return String();
        }
        memcpy(buf + pos, name, len);

        c = clang_getCursorSemanticParent(c);
        kind = clang_getCursorKind(c);
        if (cutoff == -1) {
            switch (kind) {
            case CXCursor_ClassDecl:
            case CXCursor_ClassTemplate:
            case CXCursor_StructDecl:
                break;
            case CXCursor_Namespace:
                // namespaces can include all namespaces in their symbolname
                if (originalKind == CXCursor_Namespace)
                    break;
            default:
                cutoff = pos;
                break;
            }
        }
    } while (RTags::needsQualifiers(kind));

    String type;
    switch (originalKind) {
    case CXCursor_ClassDecl:
    case CXCursor_StructDecl:
    case CXCursor_ClassTemplate:
        break;
    default:
        type = typeName(cursor);
        break;
    }
    if (cutoff == -1)
        cutoff = pos;
    String ret;
    for (int i=0; i<2; ++i) {
        char *ch = buf + pos;
        while (true) {
            const String name(ch, sizeof(buf) - (ch - buf) - 1);
            mData->symbolNames[name].insert(location);
            if (!type.isEmpty()) {
                mData->symbolNames[type + name].insert(location);
            }

            ch = strstr(ch + 1, "::");
            if (ch) {
                ch += 2;
            } else {
                break;
            }
        }
        if (i == 0) {
            ret.assign(buf + cutoff, sizeof(buf) - cutoff - 1);
            if (!type.isEmpty())
                ret.prepend(type);
        }


        if (!hasTemplates) {
            break;
        } else if (i == 0) {
            char *start = strchr(buf + pos, '<');
            assert(start);
            char *end = strchr(start, '>');
            const int templateSize = (end - start) + 1;
            assert(end);
            memmove(buf + pos + templateSize, buf + pos, start - (buf + pos));
            pos += templateSize;
        }
    }

    return ret;
}
示例#10
0
static inline bool isImplicit(const CXCursor &cursor)
{
    return clang_equalLocations(clang_getCursorLocation(cursor),
                                clang_getCursorLocation(clang_getCursorSemanticParent(cursor)));
}
示例#11
0
cursor cursor::semanticParent() const
{
    return { clang_getCursorSemanticParent(cur) };
}
示例#12
0
 Cursor Cursor::GetSemanticParent() const
 {
     return clang_getCursorSemanticParent(cursor_);
 }
示例#13
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;
}
示例#14
0
String ClangIndexer::addNamePermutations(const CXCursor &cursor, const Location &location)
{
    CXCursorKind kind = clang_getCursorKind(cursor);
    const CXCursorKind originalKind = kind;
    char buf[32768];
    int pos = sizeof(buf) - 1;
    buf[pos] = '\0';
    int cutoff = -1;

    CXCursor c = cursor;
    do {
        CXStringScope displayName(clang_getCursorDisplayName(c));
        const char *name = displayName.data();
        if (!name)
            break;
        const int len = strlen(name);
        if (!len)
            break;

        if (pos != sizeof(buf) - 1 && (pos -= 2) >= 0) {
            memset(buf + pos, ':', 2);
        }
        pos -= len;
        if (pos < 0) {
            error("SymbolName too long. Giving up");
            return String();
        }
        memcpy(buf + pos, name, len);

        c = clang_getCursorSemanticParent(c);
        kind = clang_getCursorKind(c);
        if (cutoff == -1) {
            switch (kind) {
            case CXCursor_ClassDecl:
            case CXCursor_ClassTemplate:
            case CXCursor_StructDecl:
                break;
            case CXCursor_Namespace:
                // namespaces can include all namespaces in their symbolname
                if (originalKind == CXCursor_Namespace)
                    break;
            default:
                cutoff = pos;
                break;
            }
        }
    } while (RTags::needsQualifiers(kind));

    String type;
    switch (originalKind) {
    case CXCursor_ClassDecl:
    case CXCursor_StructDecl:
    case CXCursor_ClassTemplate:
        break;
    default:
        type = RTags::typeName(cursor);
        break;
    }
    if (cutoff == -1)
        cutoff = pos;

    String ret;
    int templateStart, templateEnd, colonColonCount;
    int colonColons[512];
    ::tokenize(buf, pos,
               &templateStart, &templateEnd,
               &colonColonCount, colonColons);

    // i == 0 --> with templates,
    // i == 1 without templates or without EnumConstantDecl part
    for (int i=0; i<2; ++i) {
        for (int j=0; j<colonColonCount; ++j) {
            const char *ch = buf + colonColons[j];
            const String name(ch, sizeof(buf) - (ch - buf) - 1);
            mData->symbolNames[name].insert(location);
            if (!type.isEmpty() && (originalKind != CXCursor_ParmDecl || !strchr(ch, '('))) {
                // We only want to add the type to the final declaration for ParmDecls
                // e.g.
                // void foo(int)::bar
                // and
                // int bar
                //
                // not
                // int void foo(int)::bar
                // or
                // void foo(int)::int bar

                mData->symbolNames[type + name].insert(location);
            }
        }

        if (i == 0) {
            // create actual symbol name that will go into CursorInfo. This doesn't include namespaces etc
            if (!type.isEmpty()) {
                ret = type;
                ret.append(buf + cutoff, sizeof(buf) - cutoff - 1);
            } else {
                ret.assign(buf + cutoff, sizeof(buf) - cutoff - 1);
            }
        }

        if (i == 1 || (templateStart == -1 && originalKind != CXCursor_EnumConstantDecl)) {
            // nothing more to do
            break;
        }

        if (originalKind == CXCursor_EnumConstantDecl) { // remove CXCursor_EnumDecl
            // struct A { enum B { C } };
            // Will by default generate a A::B::C symbolname.
            // This code removes the B:: part from it
            if (colonColonCount > 2) {
                const char *last = buf + colonColons[colonColonCount - 1];
                const char *secondLast = buf + colonColons[colonColonCount - 2];
                const int len = (last - secondLast);
                memmove(buf + pos + len, buf + pos, secondLast - (buf + pos));
                pos += len;
                // ### We could/should just move the colon colon values but this
                // should be pretty quick and I don't want to write the code to
                // do it.
                ::tokenize(buf, pos,
                           &templateStart, &templateEnd,
                           &colonColonCount, colonColons);
            }
        } else { // remove templates
            assert(templateStart != -1);
            assert(templateEnd != -1);
            const int templateSize = (templateEnd - templateStart) + 1;
            memmove(buf + pos + templateSize, buf + pos, (buf + templateStart) - (buf + pos));
            pos += templateSize;
        }
    }

    return ret;
}
示例#15
0
Cursor Cursor::semanticParent() const
{
    return clang_getCursorSemanticParent(cxCursor);
}