Esempio n. 1
0
    virtual enum CXChildVisitResult visit(CXCursor cursor, CXCursor parent) {
        CXFile file;
        unsigned int line, column, offset;
        clang_getInstantiationLocation(
                clang_getCursorLocation(cursor),
                &file, &line, &column, &offset);
        CXCursorKind kind = clang_getCursorKind(cursor);
        const char* cursorFilename = clang_getCString(clang_getFileName(file));

        if (!clang_getFileName(file).data || strcmp(cursorFilename, translationUnitFilename) != 0) {
            return CXChildVisit_Continue;
        }

        CXCursor refCursor = clang_getCursorReferenced(cursor);
        if (!clang_equalCursors(refCursor, clang_getNullCursor())) {
            CXFile refFile;
            unsigned int refLine, refColumn, refOffset;
            clang_getInstantiationLocation(
                    clang_getCursorLocation(refCursor),
                    &refFile, &refLine, &refColumn, &refOffset);

            if (clang_getFileName(refFile).data) {
                std::string referencedUsr(clang_getCString(clang_getCursorUSR(refCursor)));
                if (!referencedUsr.empty()) {
                    std::stringstream ss;
                    ss << cursorFilename
                       << ":" << line << ":" << column << ":" << kind;
                    std::string location(ss.str());
                    usrToReferences[referencedUsr].insert(location);
                }
            }
        }
        return CXChildVisit_Recurse;
    }
Esempio n. 2
0
std::string Cursor::get_usr() const
{
	UniqueCXString cx_string(clang_getCursorUSR(m_cx_cursor));
	if ( !cx_string ) {
		CLANGXX_THROW_LogicError("Error retrieving a Unified Symbol Resolution (USR) for the entity referenced by this cursor.");
	}

	return clang_getCString(cx_string.get());
}
Esempio n. 3
0
void ClangParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd,
    uint &line,uint &column,const char *text,int tokenIndex)
{
  CXCursor c = p->cursors[tokenIndex];
  CXCursor r = clang_getCursorReferenced(c);
  if (!clang_equalCursors(r, c))
  {
    c=r; // link to referenced location
  }
  CXCursor t = clang_getSpecializedCursorTemplate(c);
  if (!clang_Cursor_isNull(t) && !clang_equalCursors(t,c))
  {
    c=t; // link to template 
  }
  CXString usr = clang_getCursorUSR(c);
  const char *usrStr = clang_getCString(usr);

  Definition *d = usrStr ? Doxygen::clangUsrMap->find(usrStr) : 0;
  //CXCursorKind kind = clang_getCursorKind(c);
  //if (d==0)
  //{
  //  printf("didn't find definition for '%s' usr='******' kind=%d\n",
  //      text,usrStr,kind);
  //}
  //else
  //{
  //  printf("found definition for '%s' usr='******' name='%s'\n",
  //      text,usrStr,d->name().data());
  //}
  if (d && d->isLinkable())
  {
    if (g_insideBody &&
        g_currentMemberDef && d->definitionType()==Definition::TypeMember && 
        (g_currentMemberDef!=d || g_currentLine<line)) // avoid self-reference
    {
      addDocCrossReference(g_currentMemberDef,(MemberDef*)d);
    }
    writeMultiLineCodeLink(ol,fd,line,column,d,text);
  }
  else
  {
    codifyLines(ol,fd,text,line,column);
  }
  clang_disposeString(usr);
}
void ClangParser::linkIdentifier(CodeOutputInterface &ol, QSharedPointer<FileDef> fd,
                                 uint &line, uint &column, const QString &text, int tokenIndex)
{
   CXCursor c = p->cursors[tokenIndex];
   CXCursor r = clang_getCursorReferenced(c);

   if (! clang_equalCursors(r, c)) {
      // link to referenced location
      c = r; 
   }

   CXCursor t = clang_getSpecializedCursorTemplate(c);
  
   if (! clang_Cursor_isNull(t) && !clang_equalCursors(t, c)) {
      // link to template
      c = t; 
   }

   CXString usr = clang_getCursorUSR(c);
   const char *usrStr = clang_getCString(usr);

   QSharedPointer<Definition> d;

   if (usrStr) {
      d = Doxy_Globals::clangUsrMap.value(usrStr);
   }
   
   if (d && d->isLinkable()) {
      if (g_insideBody && g_currentMemberDef && d->definitionType() == Definition::TypeMember &&
            (g_currentMemberDef != d || g_currentLine < line)) { 

         // avoid self-reference
         addDocCrossReference(g_currentMemberDef, d.dynamicCast<MemberDef>());
      }

      writeMultiLineCodeLink(ol, fd, line, column, d, text);

   } else {
      codifyLines(ol, fd, text, line, column, "");
   }

   clang_disposeString(usr);
}
Esempio n. 5
0
enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
                                   CXClientData ClientData) {
  VisitorData *Data = (VisitorData *)ClientData;
  if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) {
    CXString USR = clang_getCursorUSR(C);
    if (!clang_getCString(USR)) {
      clang_disposeString(USR);
      return CXChildVisit_Continue;
    }
    printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C),
                           clang_getCString(USR));
    PrintCursorExtent(C);
    printf("\n");
    clang_disposeString(USR);

    return CXChildVisit_Recurse;
  }

  return CXChildVisit_Continue;
}
Esempio n. 6
0
static void printCursor(CXCursor cursor)
{
    CXFile file;
    unsigned int off, line, col;
    CXSourceLocation location = clang_getCursorLocation(cursor);
    clang_getSpellingLocation(location, &file, &line, &col, &off);
    CXString fileName = clang_getFileName(file);
    const char *fileNameCStr = clang_getCString(fileName);
    if (fileNameCStr) {
        CXSourceRange range = clang_getCursorExtent(cursor);
        unsigned int start, end;
        clang_getSpellingLocation(clang_getRangeStart(range), 0, 0, 0, &start);
        clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &end);
        printf("%s:%d:%d (%d, %d-%d) ", fileNameCStr, line, col, off, start, end);
    }
    clang_disposeString(fileName);
    printString("kind", clang_getCursorKindSpelling(clang_getCursorKind(cursor)));
    printString("display name", clang_getCursorDisplayName(cursor));
    printString("usr", clang_getCursorUSR(cursor));
    if (clang_isCursorDefinition(cursor))
        printf("definition ");
    printf("\n");
}
Esempio n. 7
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;
}
Esempio n. 8
0
std::string cursor::unified_symbol()
{
    return string(clang_getCursorUSR(cur)).str();
}
Esempio n. 9
0
QCString ClangParser::lookup(uint line,const char *symbol)
{
  //printf("ClangParser::lookup(%d,%s)\n",line,symbol);
  QCString result;
  if (symbol==0) return result;
  static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
  if (!clangAssistedParsing) return result;

  int sl = strlen(symbol);
  uint l = p->getCurrentTokenLine();
  while (l>=line && p->curToken>0)
  {
    if (l==line) // already at the right line
    {
      p->curToken--; // linear search to start of the line
      l = p->getCurrentTokenLine();
    }
    else 
    {
      p->curToken/=2; // binary search backward
      l = p->getCurrentTokenLine();
    }
  }
  bool found=FALSE;
  while (l<=line && p->curToken<p->numTokens && !found)
  {
    CXString tokenString = clang_getTokenSpelling(p->tu, p->tokens[p->curToken]);
    //if (l==line)
    //{
    //  printf("try to match symbol %s with token %s\n",symbol,clang_getCString(tokenString));
    //}
    const char *ts = clang_getCString(tokenString);
    int tl = strlen(ts);
    int startIndex = p->curToken;
    if (l==line && strncmp(ts,symbol,tl)==0) // found partial match at the correct line
    {
      int offset = tl;
      while (offset<sl) // symbol spans multiple tokens
      {
        //printf("found partial match\n");
        p->curToken++;
        if (p->curToken>=p->numTokens)
        {
          break; // end of token stream
        }
        l = p->getCurrentTokenLine();
        clang_disposeString(tokenString);
        tokenString = clang_getTokenSpelling(p->tu, p->tokens[p->curToken]);
        ts = clang_getCString(tokenString);
        tl = ts ? strlen(ts) : 0;
        // skip over any spaces in the symbol
        char c;
        while (offset<sl && ((c=symbol[offset])==' ' || c=='\t' || c=='\r' || c=='\n'))
        {
          offset++;
        }
        if (strncmp(ts,symbol+offset,tl)!=0) // next token matches?
        {
          //printf("no match '%s'<->'%s'\n",ts,symbol+offset);
          break; // no match
        }
        //printf("partial match '%s'<->'%s'\n",ts,symbol+offset);
        offset+=tl;
      }
      if (offset==sl) // symbol matches the token(s)
      {
        CXCursor c = p->cursors[p->curToken];
        CXString usr = clang_getCursorUSR(c);
        //printf("found full match %s usr='******'\n",symbol,clang_getCString(usr));
        result = clang_getCString(usr);
        clang_disposeString(usr);
        found=TRUE;
      }
      else // reset token cursor to start of the search
      {
        p->curToken = startIndex;
      }
    }
    clang_disposeString(tokenString);
    p->curToken++;
    if (p->curToken<p->numTokens)
    {
      l = p->getCurrentTokenLine();
    }
  }
  //if (!found)
  //{
  //  printf("Did not find symbol %s at line %d :-(\n",symbol,line);
  //}
  //else
  //{
  //  printf("Found symbol %s usr=%s\n",symbol,result.data());
  //}
  return result;
}
Esempio n. 10
0
String cursorToString(CXCursor cursor, unsigned flags)
{
    const CXCursorKind kind = clang_getCursorKind(cursor);
    String ret;
    ret.reserve(256);
    ret += eatString(clang_getCursorKindSpelling(kind));
    if (clang_isInvalid(kind))
        return ret;

    switch (RTags::cursorType(kind)) {
    case Reference:
        ret += " r";
        break;
    case Cursor:
        ret += " c";
        break;
    case Other:
        ret += " o";
        break;
    case Include:
        ret += " i";
        break;
    }

    const String name = eatString(clang_getCursorDisplayName(cursor));
    const String other = eatString(clang_getCursorSpelling(cursor));
    if (!name.isEmpty())
        ret += " " + name;
    if (other != name && !other.isEmpty())
        ret += " " + other;

    if (clang_isCursorDefinition(cursor))
        ret += " def";

    if (flags & IncludeUSR)
        ret += " " + eatString(clang_getCursorUSR(cursor));

    CXFile file;
    unsigned off, line, col; //presumedLine, presumedCol, instantiationLoc, expansionLoc;
    CXSourceLocation location = clang_getCursorLocation(cursor);
    clang_getSpellingLocation(location, &file, &line, &col, &off);
    // clang_getPresumedLocation(location, 0, &presumedLine, &presumedCol);
    // clang_getInstantiationLocation(location, 0, 0, 0, &instantiationLoc);
    // clang_getExpansionLocation(location, 0, 0, 0, &expansionLoc);

    const Str fileName(clang_getFileName(file));
    if (fileName.data() && *fileName.data()) {
        ret += ' ';
        ret += fileName.data();
        ret += ',';
        ret += String::number(off);

        if (flags & IncludeRange) {
            ret += " (";
            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);
            ret += String::number(start);
            ret += '-';
            ret += String::number(end);
            ret += ')';
        }

        // if (presumedLine != line || presumedCol != col)
        //     ret += String::snprintf<32>("presumed: %d:%d", presumedLine, presumedCol);
        // if (instantiationLoc != off)
        //     ret += String::snprintf<32>("instantiation: %d", instantiationLoc);
        // if (expansionLoc != off)
        //     ret += String::snprintf<32>("expansion: %d", expansionLoc);

    }
    return ret;
}
Esempio n. 11
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;
}
Esempio n. 12
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;
    }
}
Esempio n. 13
0
json_t* render_type(CXType type) {
  int i;
  CXCursor decl = clang_getTypeDeclaration(type);
  json_t* js = json_object();

  enum CXTypeKind kind = type.kind;
  if (type.kind == CXType_Unexposed) {
    // workaround for libclang bug
    if (clang_getResultType(type).kind != CXType_Invalid) {
      kind = CXType_FunctionProto;
    }
  }


  if (clang_isVolatileQualifiedType(type)) {
    json_object_set_new(js, "volatile", json_true());
  }
  if (clang_isConstQualifiedType(type)) {
    json_object_set_new(js, "const", json_true());
  }
  if (clang_isRestrictQualifiedType(type)) {
    json_object_set_new(js, "restrict", json_true());
  }

  static const struct {
    enum CXTypeKind kind;
    const char* name;
  } PRIMITIVE_TYPES[] = {
    {CXType_Void, "void"},
    {CXType_Bool, "bool"},
    {CXType_Char_U, "char"},
    {CXType_Char_S, "char"},
    {CXType_UChar, "unsigned char"},
    {CXType_SChar, "signed char"},
    {CXType_WChar, "wchar_t"},
    {CXType_Char16, "char16_t"},
    {CXType_Char32, "char32_t"},
    {CXType_Short, "short"},
    {CXType_UShort, "unsigned short"},
    {CXType_Int, "int"},
    {CXType_UInt, "unsigned int"},
    {CXType_Long, "long"},
    {CXType_ULong, "unsigned long"},
    {CXType_LongLong, "unsigned long"},
    {CXType_ULongLong, "unsigned long long"},
    {CXType_Int128, "__int128"},
    {CXType_UInt128, "unsigned __int128"},
    {CXType_Float, "float"},
    {CXType_Double, "double"},
    {CXType_LongDouble, "long double"}
  };


  switch (kind) {
  case CXType_Pointer:
    json_object_set_new(js, "kind", json_string("pointer"));
    json_object_set_new(js, "pointee", render_type(clang_getPointeeType(type)));
    return js;

  case CXType_ConstantArray:
    json_object_set_new(js, "kind", json_string("array"));
    json_object_set_new(js, "element", render_type(clang_getArrayElementType(type)));
    json_object_set_new(js, "length", json_integer(clang_getArraySize(type)));
    return js;
    
  case CXType_FunctionNoProto:
  case CXType_FunctionProto:
    json_object_set_new(js, "kind", json_string("function"));
    json_object_set_new(js, "return", render_type(clang_getResultType(type)));
    switch (clang_getFunctionTypeCallingConv(type)) {
    case CXCallingConv_C:
      json_object_set_new(js, "calling_convention", json_string("cdecl"));
      break;
    case CXCallingConv_X86StdCall:
      json_object_set_new(js, "calling_convention", json_string("stdcall"));
      break;
    case CXCallingConv_X86FastCall:
      json_object_set_new(js, "calling_convention", json_string("fastcall"));
      break;
    case CXCallingConv_X86ThisCall:
      json_object_set_new(js, "calling_convention", json_string("thiscall"));
      break;
    case CXCallingConv_X86Pascal:
      json_object_set_new(js, "calling_convention", json_string("pascal"));
      break;
    case CXCallingConv_AAPCS:
      json_object_set_new(js, "calling_convention", json_string("aapcs"));
      break;
    case CXCallingConv_AAPCS_VFP:
      json_object_set_new(js, "calling_convention", json_string("aapcs-vfp"));
      break;
    default:
      break;
    }
    json_t* arguments = json_array();
    for (i=0; i<clang_getNumArgTypes(type); i++) {
      json_array_append_new(arguments, render_type(clang_getArgType(type, i)));
    }
    json_object_set_new(js, "arguments", arguments);
    return js;

  default:
    if (clang_getCursorKind(decl) != CXCursor_NoDeclFound) {
      json_object_set_new(js, "kind", json_string("ref"));
      json_object_set_new(js, "id", render_string(clang_getCursorUSR(decl)));
    } else {
      int found = 0, i;
      for (i=0; i<sizeof(PRIMITIVE_TYPES)/sizeof(PRIMITIVE_TYPES[0]); i++) {
        if (PRIMITIVE_TYPES[i].kind == kind) {
          json_object_set_new(js, "kind", json_string("primitive"));
          json_object_set_new(js, "primitive", json_string(PRIMITIVE_TYPES[i].name));
          found = 1;
          break;
        }
      }
      if (!found) {
        json_object_set_new(js, "kind", json_string("unknown"));
        json_object_set_new(js, "clang_kind", render_string(clang_getTypeKindSpelling(kind)));
      }
    }
    return js;
  }
}
Esempio n. 14
0
enum CXChildVisitResult visit_program(CXCursor cursor, CXCursor parent, CXClientData data){
  json_t* program = (json_t*)data;
  json_t* js = NULL;
  enum CXChildVisitResult ret = CXChildVisit_Continue;
  switch (clang_getCursorKind(cursor)) {
  case CXCursor_FunctionDecl:
  case CXCursor_VarDecl:
    js = json_object();
    json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor)));
    json_object_set_new(js, "display_name", render_string(clang_getCursorDisplayName(cursor)));
    json_object_set_new(js, "type", render_type(clang_getCursorType(cursor)));
    if (clang_getCursorKind(cursor) == CXCursor_FunctionDecl) {
      json_object_set_new(js, "argument_names", json_array());
      json_object_set_new(js, "kind", json_string("function"));
    } else {
      json_object_set_new(js, "kind", json_string("variable"));
    }
    switch (clang_getCursorLinkage(cursor)) {
    case CXLinkage_Internal:
      json_object_set_new(js, "linkage", json_string("static"));
      break;
    case CXLinkage_UniqueExternal:
      json_object_set_new(js, "linkage", json_string("anonymous"));
      break;
    case CXLinkage_External:
      break;
    default:
      json_object_set_new(js, "linkage", json_string("unknown"));
    }
    clang_visitChildren(cursor, visit_object, (CXClientData)js);
    
    break;
    
  case CXCursor_StructDecl:
  case CXCursor_UnionDecl:
    js = json_object();
    json_object_set_new(js, "kind", json_string(clang_getCursorKind(cursor) == CXCursor_UnionDecl ? 
                                                "union" : "struct"));
    json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor)));
    json_object_set_new(js, "fields", json_array());
    clang_visitChildren(cursor, visit_structure, (CXClientData)js);
    ret = CXChildVisit_Recurse;
    break;

  case CXCursor_EnumDecl:
    js = json_object();
    json_object_set_new(js, "kind", json_string("enum"));
    json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor)));
    json_object_set_new(js, "values", json_array());
    clang_visitChildren(cursor, visit_enum, (CXClientData)js);
    break;

  case CXCursor_TypedefDecl:
    js = json_object();
    json_object_set_new(js, "kind", json_string("typedef"));
    json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor)));
    json_object_set_new(js, "type", render_type(clang_getTypedefDeclUnderlyingType(cursor)));
    ret = CXChildVisit_Recurse;
    break;


  case CXCursor_FieldDecl:
    break;

  case CXCursor_MacroDefinition:
    js = json_object();
    json_object_set_new(js, "kind", json_string("macro"));
    {
      CXToken* tokens;
      unsigned ntokens, i;
      CXString name = clang_getCursorSpelling(cursor);
      char value_buf[1024] = "";
      json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor)));
      clang_tokenize(TU, clang_getCursorExtent(cursor), &tokens, &ntokens);
      for (i=0; i<ntokens; i++) {
        CXString str = clang_getTokenSpelling(TU, tokens[i]);
        CXTokenKind tkind = clang_getTokenKind(tokens[i]);
        if (i == 0 && !strcmp(clang_getCString(name), clang_getCString(str))) {
          // macro name
        } else if (i == ntokens - 1 && 
                   tkind == CXToken_Punctuation && !strcmp("#", clang_getCString(str))) {
          // weird clang terminator thingy
        } else if (tkind == CXToken_Comment) {
          // comment
        } else {
          if (strlen(value_buf) > 0) {
            strncat(value_buf, " ", sizeof(value_buf) - strlen(value_buf) - 1);
          }
          strncat(value_buf, clang_getCString(str), sizeof(value_buf) - strlen(value_buf) - 1);
        }
        clang_disposeString(str);
      }
      clang_disposeTokens(TU, tokens, ntokens);
      if (strlen(value_buf) > 0) {
        long int intval;
        double dblval;
        char* endptr_int;
        char* endptr_dbl;
        intval = strtol(value_buf, &endptr_int, 0);
        dblval = strtod(value_buf, &endptr_dbl);
        if (endptr_int[0] == 0 ||
            (endptr_int[1] == 0 && strchr("UuLl", endptr_int[0]) != NULL)) {
          json_object_set_new(js, "value", json_integer(intval));
        } else if (endptr_dbl[0] == 0 || 
                   (endptr_dbl[1] == 0 && strchr("fF", endptr_dbl[0]) != NULL)) {
          json_object_set_new(js, "value", json_real(dblval));
        } else {
          json_object_set_new(js, "value", json_string(value_buf));
        }
      }
    }
    break;

    /*
  case CXCursor_PreprocessingDirective:
  case CXCursor_MacroExpansion:
    js = json_object();
    json_object_set_new(js, "kind", json_string("macro"));
    json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor)));
    putstring(clang_getCursorSpelling(cursor));
    putstring(clang_getCursorDisplayName(cursor));
    printf("%d\n", clang_getEnumConstantDeclValue(cursor));
    
    ret = CXChildVisit_Recurse;
    */

  default:
    js = json_object();
    json_object_set_new(js, "name", render_string(clang_getCursorSpelling(cursor)));
    json_object_set_new(js, "type", render_type(clang_getCursorType(cursor)));
    json_object_set_new(js, "kind", json_string("wtf"));
    json_object_set_new(js, "wtf", render_string(clang_getCursorKindSpelling(clang_getCursorKind(cursor))));
  }

  if (js) {
    json_t* str;
    if (!json_object_get(program, "")) json_object_set_new(program, "", json_array());
    str = render_string(clang_getCursorUSR(cursor));
    if (strlen(json_string_value(str)) == 0) {
      json_decref(str);
      json_array_append_new(json_object_get(program, ""), js);
    } else {
      json_object_set_with_key_new(program, render_string(clang_getCursorUSR(cursor)), js);
    }
  }

  return ret;
}
QString ClangParser::lookup(uint line, const QString &symbol)
{
   QString result;

   if (symbol.isEmpty()) {
      return result;
   }

   int sl = symbol.length();
   uint l = p->getCurrentTokenLine();

   while (l >= line && p->curToken > 0) {

      if (l == line) { 
         // already at the right line

         p->curToken--;                   // linear search to start of the line
         l = p->getCurrentTokenLine();

      } else {
         p->curToken /= 2;                // binary search backward
         l = p->getCurrentTokenLine();
      }
   }

   bool found = false;

   while (l <= line && p->curToken < p->numTokens && !found) {
      CXString tokenString = clang_getTokenSpelling(p->tu, p->tokens[p->curToken]);
     
      const char *ts = clang_getCString(tokenString);
      int tl = strlen(ts);
      int startIndex = p->curToken;

      if (l == line && strncmp(ts, symbol.toUtf8(), tl) == 0) { 
         // found partial match at the correct line
         int offset = tl;

         while (offset < sl) { 
            // symbol spans multiple tokens

            p->curToken++;

            if (p->curToken >= p->numTokens) {
               break; // end of token stream
            }

            l = p->getCurrentTokenLine();
            clang_disposeString(tokenString);
            tokenString = clang_getTokenSpelling(p->tu, p->tokens[p->curToken]);
            ts = clang_getCString(tokenString);
            tl = ts ? strlen(ts) : 0;

            // skip over any spaces in the symbol
            QChar c;

            while (offset < sl && ((c = symbol[offset]) == ' ' || c == '\t' || c == '\r' || c == '\n')) {
               offset++;
            }

            if (strncmp(ts, symbol.mid(offset).toUtf8(), tl) != 0) { 
               // next token matches?

               break; // no match
            }

            offset += tl;
         }

         if (offset == sl) { 
            // symbol matches the token(s)
            CXCursor c = p->cursors[p->curToken];
            CXString usr = clang_getCursorUSR(c);
           
            result = clang_getCString(usr);
            clang_disposeString(usr);
            found = true;

         } else { 
            // reset token cursor to start of the search
            p->curToken = startIndex;
         }
      }

      clang_disposeString(tokenString);
      p->curToken++;

      if (p->curToken < p->numTokens) {
         l = p->getCurrentTokenLine();
      }
   }
  
   return result;
}
Esempio n. 16
0
Utf8String Cursor::unifiedSymbolResolution() const
{
    return ClangString(clang_getCursorUSR(cxCursor));
}