Ejemplo n.º 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;
    }
Ejemplo n.º 2
0
void ClangIndexer::handleInclude(const CXCursor &cursor, CXCursorKind kind, const Location &location)
{
    assert(kind == CXCursor_InclusionDirective);
    (void)kind;
    CXFile includedFile = clang_getIncludedFile(cursor);
    if (includedFile) {
        const Location refLoc = createLocation(includedFile, 1, 1);
        if (!refLoc.isNull()) {
            {
                String include = "#include ";
                const Path path = refLoc.path();
                assert(mSource.fileId);
                mData->dependencies[refLoc.fileId()].insert(mSource.fileId);
                mData->symbolNames[(include + path)].insert(location);
                mData->symbolNames[(include + path.fileName())].insert(location);
            }
            std::shared_ptr<CursorInfo> &info = mData->symbols[location];
            if (!info)
                info = std::make_shared<CursorInfo>();
            info->targets.insert(refLoc);
            info->kind = cursor.kind;
            info->definition = false;
            info->symbolName = "#include " + RTags::eatString(clang_getCursorDisplayName(cursor));
            info->symbolLength = info->symbolName.size() + 2;
            // this fails for things like:
            // # include    <foobar.h>
        }
    }
}
Ejemplo n.º 3
0
	static CXChildVisitResult parseFunctionMember (CXCursor cursor, CXCursor parent, CXClientData clientData) {
		auto functionDef = static_cast<FunctionDefinition*>(clientData);
		auto displayName = CXStringToString(clang_getCursorDisplayName(cursor));
		auto kind = clang_getCursorKind(cursor);

		std::map<std::string, std::string> location;
		getSourceLocation(cursor, functionDef->getContext(), location);
//		std::cerr << "function: " << displayName << " kind: " << kind << ", " << hyperloop::toJSON(location) << std::endl;

		switch (kind) {
			case CXCursor_ParmDecl: {
				auto argType = clang_getCursorType(cursor);
				auto typeValue= CXStringToString(clang_getTypeSpelling(argType));
				auto encoding = CXStringToString(clang_getDeclObjCTypeEncoding(cursor));
				functionDef->addArgument(displayName, argType, typeValue, encoding);
				break;
			}
			case CXCursor_ObjCClassRef:
			case CXCursor_TypeRef:
			case CXCursor_UnexposedAttr:
			case CXCursor_CompoundStmt:
			case CXCursor_AsmLabelAttr:
			case CXCursor_ConstAttr:
			case CXCursor_PureAttr: {
				break;
			}
			default: {
				std::cerr << "not handled, function: " << displayName << " kind: " << kind << std::endl;
				break;
			}
		}
		return CXChildVisit_Continue;
	}
Ejemplo n.º 4
0
void IndexerJob::handleInclude(const CXCursor &cursor, CXCursorKind kind, const Location &location)
{
    assert(kind == CXCursor_InclusionDirective);
    (void)kind;
    CXFile includedFile = clang_getIncludedFile(cursor);
    if (includedFile) {
        const Location refLoc(includedFile, 0);
        if (!refLoc.isNull()) {
            {
                String include = "#include ";
                const Path path = refLoc.path();
                mData->symbolNames[(include + path)].insert(location);
                mData->symbolNames[(include + path.fileName())].insert(location);
            }
            CursorInfo &info = mData->symbols[location];
            info.targets.insert(refLoc);
            info.kind = cursor.kind;
            info.definition = false;
            info.symbolName = "#include " + RTags::eatString(clang_getCursorDisplayName(cursor));
            info.symbolLength = info.symbolName.size() + 2;
            // this fails for things like:
            // # include    <foobar.h>
        }
    }
}
Ejemplo n.º 5
0
OovString Tokenizer::getClassNameAtLocation(size_t origOffset)
    {
    CLangAutoLock lock(mCLangLock, __LINE__, this);
    CXCursor classCursor = getCursorAtOffset(mTransUnit, mSourceFile, origOffset);
    std::string className = getDisposedString(clang_getCursorDisplayName(classCursor));
    return ModelData::getBaseType(className);
    }
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
enum CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData data)
{
  enum CXCursorKind cKind = clang_getCursorKind(cursor);
  CXString nameString = clang_getCursorDisplayName(cursor);
  CXString typeString = clang_getCursorKindSpelling(cKind);
  printf("Name:%s, Kind:%s\n", clang_getCString(nameString), clang_getCString(typeString));
  clang_disposeString(nameString);
  clang_disposeString(typeString);
  return CXChildVisit_Continue;
}
Ejemplo n.º 8
0
std::string Cursor::displayname() const
{
	if ( m_displayname.empty() ) {
		UniqueCXString cx_string(clang_getCursorDisplayName(m_cx_cursor));
		if ( !cx_string ) {
			CLANGXX_THROW_LogicError("Error retrieving the display name for the entity referenced by this cursor.");
		}
		m_displayname = clang_getCString(cx_string.get());
	}
	return m_displayname;
}
void QAnnotatedTokenSet::dump(std::string &str){
    Q_D(QAnnotatedTokenSet);
    CXString displayName = clang_getCursorDisplayName(d->cursor);
    str.append("Cursor :");
    str.append(clang_getCString(displayName));
    str.append("\n Tokens :");
    clang_disposeString(displayName);

    for ( QAnnotatedTokenSet::Iterator it = begin(); it != end(); ++it ){
        CXString tokenString           = clang_getTokenSpelling(d->translationUnit, (*it)->token().token);
        CXSourceLocation tokenLocation = clang_getTokenLocation(d->translationUnit, (*it)->token().token);
        unsigned int column, line;
        clang_getSpellingLocation(tokenLocation, 0, &line, &column, 0);
        std::stringstream stream;
        stream << " (" << line << "," << column << ") \"";
        str.append(stream.str() + clang_getCString(tokenString) + "\"");
        clang_disposeString(tokenString);
    }
    str.append("\n");
}
Ejemplo n.º 10
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");
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
Utf8String Cursor::displayName() const
{
    return ClangString(clang_getCursorDisplayName(cxCursor));
}
Ejemplo n.º 13
0
void IndexerJob::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, 0);
    if (!reffedLoc.isValid())
        return;

    CursorInfo &refInfo = mData->symbols[reffedLoc];
    if (!refInfo.symbolLength && !handleCursor(ref, refKind, reffedLoc))
        return;

    refInfo.references.insert(location);

    CursorInfo &info = mData->symbols[location];
    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);
        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;
        info.definition = false;
        info.kind = kind;
        info.symbolLength = isOperator ? end - start : refInfo.symbolLength;
        info.symbolName = refInfo.symbolName;
        info.type = clang_getCursorType(cursor).kind;
        switch (kind) {
        case CXCursor_CallExpr:
            nestedClassConstructorCallUgleHack(parent, info, refKind, reffedLoc);
            // see rtags/tests/nestedClassConstructorCallUgleHack/
            break;
        default:
            break;
        }
    }
    Set<Location> &val = mData->references[location];
    val.insert(reffedLoc);
}
Ejemplo 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;
}
Ejemplo n.º 15
0
 String Cursor::GetDisplayName() const
 {
     return clang_getCursorDisplayName(cursor_);
 }
Ejemplo n.º 16
0
std::string cursor::display_name()
{
    return string(clang_getCursorDisplayName(cur)).str();
}
std::string Generator::stringize(const CXType &type, const std::string &varName, bool makeConstReference) const
{
    std::string result;

    if (makeConstReference) {
        switch (type.kind) {
        case CXType_LValueReference:
        case CXType_RValueReference:
        case CXType_Pointer:
        case CXType_Enum:
        case CXType_Bool:
        case CXType_Char_S:
        case CXType_Char_U:
        case CXType_Char16:
        case CXType_Int:
        case CXType_Long:
        case CXType_LongLong:
        case CXType_Float:
        case CXType_Double:
        case CXType_LongDouble:
            makeConstReference = false;
            break;
        default:
            break;
        }
    }

    if (makeConstReference || clang_isConstQualifiedType(type))
        result += "const ";

    switch (type.kind) {
    case CXType_Void:
        result += "void";
        if (!varName.empty())
            result += ' ';
        break;
    case CXType_Bool:
        result += "bool";
        if (!varName.empty())
            result += ' ';
        break;

    case CXType_Int:
        result += "int";
        if (!varName.empty())
            result += ' ';
        break;

    case CXType_Float:
        result += "float";
        if (!varName.empty())
            result += ' ';
        break;

    case CXType_Double:
        result += "double";
        if (!varName.empty())
            result += ' ';
        break;

    case CXType_Pointer: {
        CXType pointee = clang_getPointeeType(type);
        result += stringize(pointee);
        result += " *";
    }
        break;

    case CXType_LValueReference: {
        CXType pointee = clang_getPointeeType(type);
        result += stringize(pointee);
    }
        break;
    case CXType_Record:
    case CXType_Enum: {
        result += stringize(clang_getTypeDeclaration(type));
        if (!varName.empty())
            result += ' ';
    }
        break;

    case CXType_Unexposed:
        result += stringize(clang_getCursorDisplayName(clang_getTypeDeclaration(type)));
        if (!varName.empty())
            result += ' ';
        break;
    case CXType_Overload:
        result += "<CXType_Overload>";
        reportWarning("stringize: CXType_Overload not handled: " + stringize(clang_getCursorDisplayName(clang_getTypeDeclaration(type))));
        break;
    case CXType_Dependent:
        result += "<CXType_Dependent>";
        reportWarning("stringize: CXType_Dependent not handled: " + stringize(clang_getCursorDisplayName(clang_getTypeDeclaration(type))));
        break;
    case CXType_Invalid:
        result += "<CXType_Invalid>";
        reportWarning("stringize: CXType_Invalid not handled: " + stringize(clang_getCursorDisplayName(clang_getTypeDeclaration(type))));
        break;
    default:
        result += "<other CXTypeKind>";
        reportWarning("stringize: such CXTypeKind not handled: " + stringize(clang_getCursorDisplayName(clang_getTypeDeclaration(type))));
        break;
    }

    if (makeConstReference) {
        result += "&";
    }

    result += varName;
    return result;
}
Ejemplo n.º 18
0
enum CXChildVisitResult
	visitor(
		CXCursor cursor,
		CXCursor parent,
		CXClientData client_data
	)
{
	enum CXCursorKind kind = clang_getCursorKind(cursor);
#if 0
	CXString str = clang_getCursorKindSpelling(kind);
	printf("%s\n", getCString(str));
	disposeString(str);
#endif
	if (kind != CXCursor_FunctionDecl) {
		return CXChildVisit_Recurse;
	}

	CXString str;
	CXType retType = clang_getCursorResultType(cursor);
	str = clang_getTypeSpelling(retType);
	printf("%s\n", clang_getCString(str));
	clang_disposeString(str);

	CXString funcSpelling = clang_getCursorSpelling(cursor);
	const char* funcSpellingCStr = clang_getCString(funcSpelling);
	const char* prefix = (const char*) client_data;
	size_t prefixLen = strlen(prefix);
	if (strncmp(prefix, funcSpellingCStr, prefixLen) == 0) {
		funcSpellingCStr += prefixLen;
	}
	printf("\t%s(\n", funcSpellingCStr);

	int nArgs = clang_Cursor_getNumArguments(cursor);
	argNames.resize(nArgs);
	char nameBuff[32];
	for (int i=0; i<nArgs; ++i) {
		CXCursor arg = clang_Cursor_getArgument(cursor, i);
		CXType type = clang_getCursorType(arg);
		CXString typeSpelling = clang_getTypeSpelling(type);
		CXString name = clang_getCursorDisplayName(arg);
		argNames[i] = name;
		const char* nameStr = getArgNameCString(nameBuff, name, i);
		printf("\t\t%s %s", clang_getCString(typeSpelling), nameStr);
		clang_disposeString(typeSpelling);
		if (i+1 != nArgs) {
			printf(",");
		}
		printf("\n");
	}
	printf("\t)\n");
	printf("{\n");
	printf("\t");
	if (retType.kind != CXType_Void) {
		printf("return ");
	}
	printf("%s(", funcSpelling);

	for (int i=0; i<nArgs; ++i) {
		const char* nameStr = getArgNameCString(nameBuff, argNames[i], i);
		printf("%s", nameStr);
		if (i+1 != nArgs) {
			printf(", ");
		}
		clang_disposeString(argNames[i]);
	}

	printf(");\n");
	printf("}\n");
	clang_disposeString(funcSpelling);
	return CXChildVisit_Continue;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
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;
    }
}