示例#1
0
std::string libclang_vim::stringize_extent(CXCursor const& cursor) {
    auto const r = clang_getCursorExtent(cursor);
    if (clang_Range_isNull(r))
        return "";
    return "'start':{" + stringize_location(clang_getRangeStart(r)) +
           "},'end':{" + stringize_location(clang_getRangeEnd(r)) + "}";
}
示例#2
0
void
ast_json::record_extent(json_t& obj, CXSourceRange extent)
{
    CXSourceLocation startlocation = clang_getRangeStart( extent );
    CXSourceLocation endlocation   = clang_getRangeEnd( extent );

    // Get exact source locations
    unsigned int startline = 0, startcolumn = 0, startoffset = 0;
    unsigned int endline   = 0, endcolumn   = 0, endoffset   = 0;

    clang_getSpellingLocation(
        startlocation, nullptr, &startline, &startcolumn, &startoffset );

    clang_getSpellingLocation(
          endlocation, nullptr,   &endline,   &endcolumn,   &endoffset );

    // Record source location
    obj[node::START_LINE] = startline;
    obj[node::START_COLUMN] = startcolumn;
    obj[node::START_OFFSET] = startoffset;

    obj[node::END_LINE] = endline;
    obj[node::END_COLUMN] = endcolumn;
    obj[node::END_OFFSET] = endoffset;
}
void Highlight::highlightBlock(const QString &text)
{
    CXToken *tokens;
    unsigned tokenCount;
    clang_tokenize(cx_tu,range, &tokens, &tokenCount);

    if (tokenCount > 0)
    {
      CXCursor *cursors = NULL;
      cursors = (CXCursor *)calloc(sizeof(CXCursor), tokenCount);
      clang_annotateTokens(cx_tu, tokens, tokenCount, cursors);

      for (unsigned i=0 ; i<tokenCount ; i++)
      {
        CXSourceRange sr = clang_getTokenExtent(cx_tu, tokens[i]);
        unsigned start, end;
        CXSourceLocation s = clang_getRangeStart(sr);
        CXSourceLocation e = clang_getRangeEnd(sr);
        clang_getInstantiationLocation(s, 0, 0, 0, &start);
        clang_getInstantiationLocation(e, 0, 0, 0, &end);
        qDebug()<<"start:"<<start<<"end:"<<end;
    /*    if(start >end) {
            int tmp = start;
            start = end;
            end = tmp;
        }
*/

        switch (cursors[i].kind)
        {
        case CXCursor_FirstRef... CXCursor_LastRef:

          break;
        case CXCursor_MacroDefinition:

          break;
        case CXCursor_MacroInstantiation:

          break;
        case CXCursor_FirstDecl...CXCursor_LastDecl:

          break;
        case CXCursor_ObjCMessageExpr:

          break;
        case CXCursor_DeclRefExpr:

          break;
        case CXCursor_PreprocessingDirective: {

        }
          break;
        default:
          break;
        }
     /*   if(cursors[i].kind == CXCursor_FunctionDecl)
            setFormat(start, end-start, m_formatSingleLineComment);*/
      }
    }
示例#4
0
std::string libclang_vim::stringize_range(CXSourceRange const& range) {
    if (clang_Range_isNull(range)) {
        return "";
    }
    return "'range':{'start':{" +
           stringize_location(clang_getRangeStart(range)) + "},'end':{" +
           stringize_location(clang_getRangeEnd(range)) + "}},";
}
示例#5
0
CXChildVisitResult DumpThread::visitor(CXCursor cursor, CXCursor, CXClientData userData)
{
    DumpThread *that = reinterpret_cast<DumpThread*>(userData);
    assert(that);
    CXSourceLocation location = clang_getCursorLocation(cursor);
    if (!clang_equalLocations(location, nullLocation)) {
        CXString file;
        unsigned line, col;
        clang_getPresumedLocation(location, &file, &line, &col);
        Path path = RTags::eatString(file);
        if (!path.isEmpty()) {
            uint32_t &fileId = that->mFiles[path];
            if (!fileId) {
                const Path resolved = path.resolved();
                fileId = Location::insertFile(resolved);
                that->mFiles[path] = that->mFiles[resolved] = fileId;
            }
            if (that->mQueryFlags & QueryMessage::DumpIncludeHeaders || fileId == that->mSource.fileId) {
                const Location loc(fileId, line, col);
                String message;
                message.reserve(256);
                if (!(that->mQueryFlags & QueryMessage::NoContext))
                    message += loc.context();

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

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

                that->writeToConnetion(message);
            }
        }
    }
    ++that->mIndentLevel;
    clang_visitChildren(cursor, DumpThread::visitor, userData);
    --that->mIndentLevel;
    return CXChildVisit_Continue;
}
示例#6
0
void ClangIndexer::superclassTemplateMemberFunctionUgleHack(const CXCursor &cursor, CXCursorKind kind,
                                                            const Location &location, const CXCursor &ref,
                                                            const CXCursor &parent)
{
    // This is for references to superclass template functions. Awful awful
    // shit. See https://github.com/Andersbakken/rtags/issues/62 and commit
    // for details. I really should report this as a bug.
    if (kind == CXCursor_MemberRefExpr && clang_getCursorKind(parent) == CXCursor_CallExpr) {
        const CXCursor templateRef = RTags::findChild(cursor, CXCursor_TemplateRef);
        if (templateRef == CXCursor_TemplateRef) {
            const CXCursor classTemplate = clang_getCursorReferenced(templateRef);
            if (classTemplate == CXCursor_ClassTemplate) {
                FILE *f = fopen(location.path().constData(), "r");
                if (f) {
                    const CXSourceRange range = clang_getCursorExtent(cursor);
                    const CXSourceLocation end = clang_getRangeEnd(range);
                    unsigned offset;
                    clang_getSpellingLocation(end, 0, 0, 0, &offset);

                    String name;
                    while (offset > 0) {
                        fseek(f, --offset, SEEK_SET);
                        char ch = static_cast<char>(fgetc(f));
                        if (isalnum(ch) || ch == '_' || ch == '~') {
                            name.prepend(ch);
                        } else {
                            break;
                        }
                    }
                    fclose(f);
                    if (!name.isEmpty()) {
                        RTags::Filter out;
                        out.kinds.insert(CXCursor_MemberRefExpr);
                        const int argCount = RTags::children(parent, RTags::Filter(), out).size();
                        RTags::Filter in(RTags::Filter::And);
                        in.names.insert(name);
                        in.argumentCount = argCount;
                        const List<CXCursor> alternatives = RTags::children(classTemplate, in);
                        switch (alternatives.size()) {
                        case 1:
                            // ### not sure this is correct with line/col
                            handleReference(cursor, kind, Location(location.fileId(), location.line(), location.column() + 1), alternatives.first(), parent);
                            break;
                        case 0:
                            break;
                        default:
                            warning() << "Can't decide which of these cursors are right for me"
                                      << cursor << alternatives
                                      << "Need to parse types";
                            break;
                        }
                    }
                }
            }
        }
    }
}
示例#7
0
void PrintDiagnostic(CXDiagnostic Diagnostic) {
  FILE *out = stderr;
  CXFile file;
  CXString Msg;
  unsigned display_opts = CXDiagnostic_DisplaySourceLocation
    | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges;
  unsigned i, num_fixits;

  if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored)
    return;

  Msg = clang_formatDiagnostic(Diagnostic, display_opts);
  fprintf(stderr, "%s\n", clang_getCString(Msg));
  clang_disposeString(Msg);

  clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
                                 &file, 0, 0, 0);
  if (!file)
    return;

  num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
  for (i = 0; i != num_fixits; ++i) {
    CXSourceRange range;
    CXString insertion_text = clang_getDiagnosticFixIt(Diagnostic, i, &range);
    CXSourceLocation start = clang_getRangeStart(range);
    CXSourceLocation end = clang_getRangeEnd(range);
    unsigned start_line, start_column, end_line, end_column;
    CXFile start_file, end_file;
    clang_getInstantiationLocation(start, &start_file, &start_line,
                                   &start_column, 0);
    clang_getInstantiationLocation(end, &end_file, &end_line, &end_column, 0);
    if (clang_equalLocations(start, end)) {
      /* Insertion. */
      if (start_file == file)
        fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
                clang_getCString(insertion_text), start_line, start_column);
    } else if (strcmp(clang_getCString(insertion_text), "") == 0) {
      /* Removal. */
      if (start_file == file && end_file == file) {
        fprintf(out, "FIX-IT: Remove ");
        PrintExtent(out, start_line, start_column, end_line, end_column);
        fprintf(out, "\n");
      }
    } else {
      /* Replacement. */
      if (start_file == end_file) {
        fprintf(out, "FIX-IT: Replace ");
        PrintExtent(out, start_line, start_column, end_line, end_column);
        fprintf(out, " with \"%s\"\n", clang_getCString(insertion_text));
      }
      break;
    }
    clang_disposeString(insertion_text);
  }
}
示例#8
0
static void PrintCursorExtent(CXCursor C) {
  CXSourceRange extent = clang_getCursorExtent(C);
  CXFile begin_file, end_file;
  unsigned begin_line, begin_column, end_line, end_column;

  clang_getInstantiationLocation(clang_getRangeStart(extent),
                                 &begin_file, &begin_line, &begin_column, 0);
  clang_getInstantiationLocation(clang_getRangeEnd(extent),
                                 &end_file, &end_line, &end_column, 0);
  if (!begin_file || !end_file)
    return;

  printf(" Extent=");
  PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
}
示例#9
0
static CXChildVisitResult visitTranslationUnit(CXCursor cursor, CXCursor parent,
        CXClientData client_data)
    {
    visitTranslationUnitData *data = static_cast<visitTranslationUnitData*>(client_data);
    CXSourceRange range = clang_getCursorExtent(cursor);
    CXSourceLocation startLoc = clang_getRangeStart(range);
    CXSourceLocation endLoc = clang_getRangeEnd(range);
    CXFile file;
    unsigned startOffset;
    unsigned endOffset;
    clang_getSpellingLocation(startLoc, &file, nullptr, nullptr, &startOffset);
    clang_getSpellingLocation(endLoc, &file, nullptr, nullptr, &endOffset);
    // Use the smallest cursor that surrounds the desired location.
    unsigned size = endOffset - startOffset;
    if(clangFilesEqual(file, data->mFile) &&
            startOffset < data->mDesiredOffset && endOffset > data->mDesiredOffset)
        {
        if(size < data->mSize)
            {
            data->mCursor = cursor;
            data->mSize = size;

            fprintf(sLog.mFp, "GOOD:\n   ");
            }
        }
    CXStringDisposer sp = clang_getCursorSpelling(cursor);
    CXStringDisposer kind = clang_getCursorKindSpelling(cursor.kind);
    std::string fn;
    if(file)
        {
        CXStringDisposer s = clang_getFileName(file);
        fn = s;
        }
    fprintf(sLog.mFp, "%s %s off %d size %d des offset %d file %s\n",
            kind.c_str(), sp.c_str(), startOffset,
            size, data->mDesiredOffset, fn.c_str());
    DUMP_PARSE("visitTU", cursor);
//    clang_visitChildren(cursor, ::visitTranslationUnit, client_data);
//    return CXChildVisit_Continue;
    return CXChildVisit_Recurse;
    }
示例#10
0
void TokenRange::tokenize(CXTranslationUnit transUnit)
    {
    CXCursor cursor = clang_getTranslationUnitCursor(transUnit);
    CXSourceRange range = clang_getCursorExtent(cursor);

    CXToken *tokens = 0;
    unsigned int numTokens = 0;
    clang_tokenize(transUnit, range, &tokens, &numTokens);
    resize(numTokens);
    if(numTokens > 0)
        {
        for (size_t i = 0; i < numTokens-1; i++)
            {
            at(i).setKind(clang_getTokenKind(tokens[i]));
            CXSourceRange tokRange = clang_getTokenExtent(transUnit, tokens[i]);
            clang_getExpansionLocation(clang_getRangeStart(tokRange), NULL, NULL,
                NULL, &at(i).mStartOffset);
            clang_getExpansionLocation(clang_getRangeEnd(tokRange), NULL, NULL,
                NULL, &at(i).mEndOffset);
            }
        }
    clang_disposeTokens(transUnit, tokens, numTokens);
    }
示例#11
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");
}
示例#12
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);
}
示例#13
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;
}
示例#14
0
Range::Range( const CXSourceRange &range ) {
  start_ = Location( clang_getRangeStart( range ) );
  end_ = Location( clang_getRangeEnd( range ) );
}
示例#15
0
void printTreeRecursive(struct treeNode* node, CXTranslationUnit cxtup) {
    depth++;
    if(node->modified == 0) {
        CXSourceRange range = clang_getCursorExtent(node->cursor);
        CXSourceLocation rstart = clang_getRangeStart(range);
        if(clang_Location_isFromMainFile(rstart) != 0) {
	    enum CXCursorKind cursorkind = clang_getCursorKind(node->cursor);
	    if(depth == 1 && cursorkind != CXCursor_MacroExpansion) {
	        nodenum++;
		if(cursorkind == CXCursor_StructDecl) {
		    CXToken* currTokens;
		    unsigned int numCurrTokens;
		    clang_tokenize(cxtup, range, &currTokens, &numCurrTokens);
		    CXToken token = currTokens[numCurrTokens-1];
		    CXString tokenstring = clang_getTokenSpelling(cxtup, token);
		    char* tokenstr = clang_getCString(tokenstring);
		    clang_disposeTokens(cxtup, currTokens, numCurrTokens);
		    //printf("\ntoken: %s\n", tokenstr);
		    if(strcmp(tokenstr, ";")) {
		        clang_disposeString(tokenstring);
			// Print nothing, do nothing.
		    } else {
		        clang_disposeString(tokenstring);
			goto PRINT;
		    }
		} else {
		PRINT:
		    1+1;
		    CXToken* tokens;
		    unsigned int numTokens;
		    clang_tokenize(cxtup, range, &tokens, &numTokens);
		    CXString tokenstring;
		    CXSourceRange tokenrange;
		    unsigned* startcol = malloc(sizeof(unsigned));
		    unsigned* startline = malloc(sizeof(unsigned));
		    unsigned* endcol = malloc(sizeof(unsigned));
		    unsigned* endline = malloc(sizeof(unsigned));
		    for(int i = 0; i<numTokens; i++) {
		        tokenrange = clang_getTokenExtent(cxtup, tokens[i]);
			tokenstring = clang_getTokenSpelling(cxtup, tokens[i]);
			CXSourceLocation currend = clang_getRangeEnd(tokenrange);
			clang_getFileLocation(currend, NULL, endline, endcol, NULL);
			if(prevcol != 0) {
			    CXSourceLocation currstart = clang_getRangeStart(tokenrange);
			    clang_getFileLocation(currstart, NULL, startline, startcol, NULL);
			    //printf("L%u-%u, C%u-%u", *startline, prevline, *startcol, prevcol);
			    int startl = *startline;
			    int startc = *startcol;
			    for(int i = 0; i < startl-prevline; i++) {
			        printf("\n");
				//printf("*startline-prevline = %u, i = %u, prevline = %u\n", start-prevline, i, prevline);
			    }
			    if(startc-prevcol >= 0) {
			        for(int i = 0; i < startc-prevcol; i++) {
				    printf(" ");
				}
			    } else {
			        for(int i = 1; i < startc; i++) {
				    printf(" ");
				}
			    }
			}
			char* tstr = clang_getCString(tokenstring);
			/*if(i == 0 && !strcmp(tstr, lastPrintedToken)) {	    
			    // Do nothing, print nothing.
			    } else {*/
			    printf("%s", tstr);
			    //}
			prevline = *endline;
			prevcol = *endcol;
			char* str = clang_getCString(tokenstring);
			strcpy(lastPrintedToken, str);
			clang_disposeString(tokenstring);
		    }
		    //printf("%i\n", lastPrintedToken);
		    //printf("\n");
		    clang_disposeTokens(cxtup, tokens, numTokens);
		    free(startcol);
		    free(startline);
		    free(endcol);
		    free(endline);
		}
	    }
	}
    } else if(depth == 1) {
      //printf("Modified node detected.");
        if(node->validcursor == false) {
	    //Print modified
	    //printf("%s\n", node->newContent);
        } else {
	    struct treeNode** nodes = malloc((node->modified) * sizeof(struct treeNode));
	    //printf("%i\n", sizeof(nodes))
	    nodes[node->modified-1] = NULL;
	    //printf("nodes[node->modified-1]: %i\n", nodes[node->modified-1]);
	    struct treeNode* next = NULL;
	    int nextnode = 0;
	    int smallestcol = INT_MAX;
	    int smallestline = INT_MAX;
	    int cscol = INT_MIN;
	    int csline = INT_MIN;
	    struct treeListNode* currnode = node->modifiedNodes;
	    CXSourceRange srange;
	    CXSourceLocation sloc;
	    bool first = true;
	    while(nodes[(node->modified)-1] == NULL) {
	        while(currnode != NULL) {
		    if(currnode->node->startline == -1) {
		        srange = clang_getCursorExtent(currnode->node->cursor);
			sloc = clang_getRangeStart(srange);
			clang_getFileLocation(sloc, NULL, &(currnode->node->startline), &(currnode->node->startcol), NULL);
			//printf("Calculated node %i: startline: %i, startcol: %i\n", currnode->node, currnode->node->startline, currnode->node->startcol);
		    }
		    //printf("\ncurrnode->node: %i, nextnode: %i\nnstartline: %i, smallestline: %i ,csline: %i\nnstartcol: %i, smallestcol: %i, cscol: %i\n", currnode->node, nextnode, currnode->node->startline, smallestline, csline, currnode->node->startcol, smallestcol, cscol);
		    if(currnode->node->startline < smallestline) {
		      //printf("\n1\, %i < %i", currnode->node->startline, smallestline);
		        if((currnode->node->startline > csline) || (first == true)) {
			  //printf("\n2, %i > %i", currnode->node->startline);
			    smallestline = currnode->node->startline;
			    smallestcol = currnode->node->startcol;
			    csline = currnode->node->startline;
			    cscol = currnode->node->startcol;
			    next = currnode->node;
			}
		    } else if(currnode->node->startline == smallestline) {
		      //printf("3\n");
		        if(currnode->node->startcol < smallestcol) {
			  //printf("4\n");
			    if((currnode->node->startcol > cscol) || (first == true)) {
			      //printf("5\n");
			        smallestline = currnode->node->startline;
				smallestcol = currnode->node->startcol;
				csline = currnode->node->startline;
				cscol = currnode->node->startcol;
				next = currnode->node;
			    }
			}
		    }
		    //printf("\n6\n");
		    //printf("currnode->node: %i, nextnode: %i\nnstartline: %i, smallestline: %i ,csline: %i\nnstartcol: %i, smallestcol: %i, cscol: %i\n", currnode->node, nextnode, currnode->node->startline, smallestline, csline, currnode->node->startcol, smallestcol, cscol);
		    currnode = currnode->next;
		}
		first = false;
		//printf("%i ", nodes[nextnode]);
		//printf("%i\n", next);
		nodes[nextnode] = next;
		nextnode++;
		smallestcol = INT_MAX;
		smallestline = INT_MAX;
		currnode = node->modifiedNodes;
	    }
	    for(int i = 0; i <= 1; i++) {
	      //printf("nodenum: %i, nstartline: %i, nstartcol: %i\n", i, nodes[i]->startline, nodes[i]->startcol);
	    }
	    CXSourceRange range = clang_getCursorExtent(node->cursor);
	    CXToken* tokens;
	    unsigned int numTokens;
	    int numNodes = nextnode;
	    nextnode = 0;
	    clang_tokenize(cxtup, range, &tokens, &numTokens);
	    for(int i = 0; i<numTokens; i++) {
	        CXSourceRange tokenrange = clang_getTokenExtent(cxtup, tokens[i]);
	        CXString tokenstring = clang_getTokenSpelling(cxtup, tokens[i]);
		unsigned startline;
		unsigned startcol;
		unsigned endline;
		unsigned endcol;
	        CXSourceLocation currend = clang_getRangeEnd(tokenrange);
	        clang_getFileLocation(currend, NULL, &endline, &endcol, NULL);
	        if(prevcol != 0) {
		    CXSourceLocation currstart = clang_getRangeStart(tokenrange);
		    clang_getFileLocation(currstart, NULL, &startline, &startcol, NULL);
		    //printf("L%u-%u, C%u-%u", *startline, prevline, *startcol, prevcol);
		    int startl = startline;
		    int startc = startcol;
		    for(int i = 0; i < startl-prevline; i++) {
		        printf("\n");
		        //printf("*startline-prevline = %u, i = %u, prevline = %u\n", start-prevline, i, prevline);
		    }
		    if(startc-prevcol >= 0) {
		        for(int i = 0; i < startc-prevcol; i++) {
			    printf(" ");
		        }
		    } else {
		        for(int i = 0; i < startc; i++) {
			printf(" ");
			}
		    }
		}
		char* tstr = clang_getCString(tokenstring);
		if(i == 0 && !strcmp(tstr, lastPrintedToken)) {	    
		    // Do nothing, print nothing.
		} else {
		  //printf("nextstartline: %i, startline: %i\n", nodes[nextnode]->startline, startline);
		  if((nextnode < numNodes) && (nodes[nextnode]->startline == startline) && (nodes[nextnode]->startcol == startcol)) {
		        int* nodenext = &(nodes[nextnode]->cursor);
		        if(nodenext == NULL) {
			    printf("%s\n", nodes[nextnode]->newContent);
			    nextnode++;
			} else {
			    printf("%s", nodes[nextnode]->newContent);
			    prevline = endline;
			    prevcol = endcol;
			    nextnode++;
			}
		    } else {
		        printf("%s", tstr);
			prevline = endline;
			prevcol = endcol;
		    }
		}
		//printf("%i\n", sizeof(nodes));
		char* str = clang_getCString(tokenstring);
		strcpy(lastPrintedToken, str);
		clang_disposeString(tokenstring);  
	    }
	    clang_disposeTokens(cxtup, tokens, numTokens);
	    free(nodes);
	}
    }
    if(node->children != NULL) {
        struct treeListNode* childlist = node->children;
	while(childlist != NULL) {
	    printTreeRecursive(childlist->node, cxtup);
	    childlist = childlist->next;
	}
    }
    depth--;
}
示例#16
0
 SourceLocation getEnd() const
 {
     return getSourceLocation(clang_getRangeEnd(m_range));
 }
示例#17
0
source_location source_range::end()
{
    return { clang_getRangeEnd(range) };
}
示例#18
0
void TokenizeSource(CXTranslationUnit tu)
{
    CXSourceRange range =
	    clang_getCursorExtent( clang_getTranslationUnitCursor(tu) );
  
    CXToken *tokens;
    unsigned int token_count;
  
    clang_tokenize( tu, range, &tokens, &token_count );

    //CXCursor cursors[ token_count ];
    //clang_annotateTokens( tu, tokens, token_count, cursors );
    auto cursors = my_annotateTokens( tu, tokens, token_count );
  
    for ( auto t = 0u; t < token_count; ++t ) {
	auto tkind = clang_getTokenKind(tokens[t] );
	auto tspelling = tkind == CXToken_Identifier ?
		CursorKindSpelling( cursors[ t ] ) :
		TokenKindSpelling( tkind );
	auto textent = clang_getTokenExtent( tu, tokens[t] );
	auto tstartloc = clang_getRangeStart( textent );
	auto tendloc = clang_getRangeEnd( textent );

	auto tokspell = clang_getTokenSpelling( tu, tokens[ t ] );
	std::cout << "TokenSpelling: " << tokspell << "\n";
	std::cout << "Cursor: " << cursors[ t ] << "\n";

	// if ( !( cursors[t].kind >= CXCursor_FirstInvalid &&
	// 	    cursors[t].kind <= CXCursor_LastInvalid ) ) {
	//   auto rr = clang_getCursorExtent( cursors[ t ] );
	//   std::cout << "Range: " << rr << "\n";
	// }
    
	// std::cout << clang_getCursorDisplayName( cursors[ t ] ) << "\n";
	// std::cout << "USR: "******"\n";

	unsigned int startoffset, endoffset;
	clang_getSpellingLocation( tstartloc, nullptr, nullptr, nullptr, &startoffset );
	clang_getSpellingLocation( tendloc, nullptr, nullptr, nullptr, &endoffset );
    
	// TODO: testing this hack for int -> identifier instead of keyword
	// but this loses const to an identifier also! fvck!
	if ( tspelling == "Keyword" ) {
	    auto type = clang_getCursorType( cursors[ t ] );
	    auto typekind = type.kind;
	    CXString typespelling;

	    if ( cursors[t].kind == CXCursor_FunctionDecl ||
		 cursors[t].kind == CXCursor_CXXMethod ) {
		type = clang_getResultType( type );
		typekind = type.kind;
		typespelling = clang_getTypeSpelling( type );
	    }
	    else
		typespelling = clang_getTypeSpelling( type );
      
	    // std::cout << "Type = " << type << " kind: " << typekind << "\n";
	    // std::cout << clang_getCString(typespelling) << " <-> " << clang_getCString(tokspell) << "\n";
	    // std::cout << " Const? " << clang_isConstQualifiedType( type ) << "\n";
      
	    if ( (( typekind >= CXType_FirstBuiltin && typekind <= CXType_LastBuiltin ) &&
		  ( std::string(clang_getCString(typespelling)) ==
		    std::string(clang_getCString(tokspell) ) )) ||
		 //	   ( cursors[t].kind == CXCursor_VarDecl ) ||
		 ( cursors[t].kind == CXCursor_ParmDecl ) )
		tspelling = "Identifier";
	}

	//if ( tspelling != "Punctuation" )
	std::cout
		<< startoffset << ":" << endoffset << " @ "
		<< tspelling  << "\n";

	clang_disposeString( tokspell );
    }

    std::cout << "\n" << end_pattern << "\n";

    clang_disposeTokens( tu, tokens, token_count );
}
示例#19
0
std::ostream& operator<<( std::ostream& os, CXSourceRange range )
{
    auto beg = clang_getRangeStart( range );
    auto end = clang_getRangeEnd( range );
    return os << beg << " -> " << end << "\n";
}
示例#20
0
void TextEdit::slotReparse()
{
    //connect(this,SIGNAL(textChanged()), this,SLOT(slotReparse()));
    QTextCursor tc = textCursor();
    tc.select(QTextCursor::WordUnderCursor);
    QString prefix = tc.selectedText();
    completionList->clear();
    qDebug()<<prefix;

    //clang_disposeTranslationUnit(cx_tu);
    struct CXUnsavedFile unsaved_file;
    unsaved_file.Filename = "/tmp/a.m";
    unsaved_file.Contents = strdup(this->toPlainText().toStdString().c_str());
    unsaved_file.Length = this->toPlainText().length();

    clang_reparseTranslationUnit(
        cx_tu, 1, &unsaved_file, CXTranslationUnit_PrecompiledPreamble);

    CXFile file = clang_getFile(cx_tu, unsaved_file.Filename);

    CXSourceLocation start = clang_getLocationForOffset(cx_tu, file, 0);
    CXSourceLocation end = clang_getLocationForOffset(cx_tu, file, this->toPlainText().length());
    CXSourceRange range= clang_getRange(start,end);
    CXToken *tokens;
    unsigned tokenCount;
    clang_tokenize(cx_tu,range, &tokens, &tokenCount);

    if (tokenCount > 0)
    {
      CXCursor *cursors = NULL;
      cursors = (CXCursor *)calloc(sizeof(CXCursor), tokenCount);
      clang_annotateTokens(cx_tu, tokens, tokenCount, cursors);

      for (unsigned i=0 ; i<tokenCount ; i++)
      {
        CXSourceRange sr = clang_getTokenExtent(cx_tu, tokens[i]);
        unsigned start, end;
        CXSourceLocation s = clang_getRangeStart(sr);
        CXSourceLocation e = clang_getRangeEnd(sr);
        clang_getInstantiationLocation(s, 0, 0, 0, &start);
        clang_getInstantiationLocation(e, 0, 0, 0, &end);
        qDebug()<<"start:"<<start<<"end:"<<end;
    /*    if(start >end) {
            int tmp = start;
            start = end;
            end = tmp;
        }
*/

        switch (cursors[i].kind)
        {
        case CXCursor_FirstRef... CXCursor_LastRef:

          break;
        case CXCursor_MacroDefinition:

          break;
        case CXCursor_MacroInstantiation:

          break;
        case CXCursor_FirstDecl...CXCursor_LastDecl:

          break;
        case CXCursor_ObjCMessageExpr:

          break;
        case CXCursor_DeclRefExpr:

          break;
        case CXCursor_PreprocessingDirective: {

        }
          break;
        default:
          break;
        }
     /*   if(cursors[i].kind == CXCursor_FunctionDecl)
            setFormat(start, end-start, m_formatSingleLineComment);*/
      }
    }
示例#21
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;
}
示例#22
0
bool IndexerJob::diagnose(int build, int *errorCount)
{
    if (errorCount)
        *errorCount = 0;
    if (!mUnits.at(build).second) {
        abort();
        return false;
    }

    List<String> compilationErrors;
    const unsigned diagnosticCount = clang_getNumDiagnostics(mUnits.at(build).second);
    const unsigned options = Server::instance()->options().options;

    for (unsigned i=0; i<diagnosticCount; ++i) {
        CXDiagnostic diagnostic = clang_getDiagnostic(mUnits.at(build).second, i);
        int logLevel = INT_MAX;
        const CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(diagnostic);
        switch (severity) {
        case CXDiagnostic_Fatal:
        case CXDiagnostic_Error:
            if (errorCount)
                ++*errorCount;
            logLevel = Error;
            break;
        case CXDiagnostic_Warning:
            logLevel = Warning;
            break;
        case CXDiagnostic_Note:
            logLevel = Debug;
            break;
        case CXDiagnostic_Ignored:
            break;
        }

        const unsigned diagnosticOptions = (CXDiagnostic_DisplaySourceLocation|
                                            CXDiagnostic_DisplayColumn|
                                            CXDiagnostic_DisplaySourceRanges|
                                            CXDiagnostic_DisplayOption|
                                            CXDiagnostic_DisplayCategoryId|
                                            CXDiagnostic_DisplayCategoryName);
        const uint32_t fileId = createLocation(clang_getDiagnosticLocation(diagnostic), 0).fileId();
        if (mVisitedFiles.contains(fileId)) {
            const String text = RTags::eatString(clang_formatDiagnostic(diagnostic, diagnosticOptions));
            if (testLog(logLevel) || testLog(CompilationError)) {
                log(logLevel, "%s: %s => %s", mSourceInformation.sourceFile.constData(), mClangLines.at(build).constData(), text.constData());
                compilationErrors.append(text);
            }

            const unsigned fixItCount = clang_getDiagnosticNumFixIts(diagnostic);
            RegExp rx;
            if (options & Server::IgnorePrintfFixits) {
                rx = "^%[A-Za-z0-9]\\+$";
            }
            for (unsigned f=0; f<fixItCount; ++f) {
                CXSourceRange range;
                const String string = RTags::eatString(clang_getDiagnosticFixIt(diagnostic, f, &range));
                unsigned startOffset;
                CXFile file;
                clang_getSpellingLocation(clang_getRangeStart(range), &file, 0, 0, &startOffset);
                unsigned endOffset;
                clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &endOffset);
                const Location loc(file, startOffset);
                if (options & Server::IgnorePrintfFixits && rx.indexIn(string) == 0) {
                    error("Ignored fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                          startOffset, endOffset, string.constData());
                } else {
                    error("Fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                          startOffset, endOffset, string.constData());
                    compilationErrors.append(String::format<128>("Fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                                                                 startOffset, endOffset, string.constData()));
                    mData->fixIts[loc.fileId()].insert(FixIt(startOffset, endOffset, string));
                }
            }
        }

        clang_disposeDiagnostic(diagnostic);
    }
    if (testLog(CompilationError))
        sendDiagnostics(compilationErrors);
    return !isAborted();
}
示例#23
0
Range::Range(CXCursor cursor)
	: range(clang_getCursorExtent(cursor))
	, start(clang_getRangeStart(range))
	, end(clang_getRangeEnd(range))
{}
示例#24
0
void PrintDiagnostic(CXDiagnostic Diagnostic) {
  FILE *out = stderr;
  CXFile file;
  CXString text;
  unsigned display_opts = CXDiagnostic_DisplaySourceLocation
    | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges;
  unsigned i, num_fixits;

  clang_displayDiagnostic(Diagnostic, out, display_opts);
  if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored)
    return;

  clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
                                 &file, 0, 0, 0);
  if (!file)
    return;

  num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
  for (i = 0; i != num_fixits; ++i) {
    switch (clang_getDiagnosticFixItKind(Diagnostic, i)) {
    case CXFixIt_Insertion: {
      CXSourceLocation insertion_loc;
      CXFile insertion_file;
      unsigned insertion_line, insertion_column;
      text = clang_getDiagnosticFixItInsertion(Diagnostic, i, &insertion_loc);
      clang_getInstantiationLocation(insertion_loc, &insertion_file,
                                     &insertion_line, &insertion_column, 0);
      if (insertion_file == file)
        fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
                clang_getCString(text), insertion_line, insertion_column);
      clang_disposeString(text);
      break;
    }
      
    case CXFixIt_Removal: {
      CXFile start_file, end_file;
      unsigned start_line, start_column, end_line, end_column;
      CXSourceRange remove_range
        = clang_getDiagnosticFixItRemoval(Diagnostic, i);
      clang_getInstantiationLocation(clang_getRangeStart(remove_range),
                                     &start_file, &start_line, &start_column,
                                     0);
      clang_getInstantiationLocation(clang_getRangeEnd(remove_range),
                                     &end_file, &end_line, &end_column, 0);
      if (start_file == file && end_file == file) {
        fprintf(out, "FIX-IT: Remove ");
        PrintExtent(out, start_line, start_column, end_line, end_column);
        fprintf(out, "\n");
      }
      break;
    }
      
    case CXFixIt_Replacement: {
      CXFile start_file, end_file;
      unsigned start_line, start_column, end_line, end_column;
      CXSourceRange remove_range;
      text = clang_getDiagnosticFixItReplacement(Diagnostic, i,&remove_range);
      clang_getInstantiationLocation(clang_getRangeStart(remove_range),
                                     &start_file, &start_line, &start_column,
                                     0);
      clang_getInstantiationLocation(clang_getRangeEnd(remove_range),
                                     &end_file, &end_line, &end_column, 0);
      if (start_file == end_file) {
        fprintf(out, "FIX-IT: Replace ");
        PrintExtent(out, start_line, start_column, end_line, end_column);
        fprintf(out, " with \"%s\"\n", clang_getCString(text));
      }
      clang_disposeString(text);
      break;
    }
    }
  }
}
示例#25
0
bool ClangIndexer::diagnose()
{
    if (!mClangUnit) {
        return false;
    }

    List<String> compilationErrors;
    const unsigned diagnosticCount = clang_getNumDiagnostics(mClangUnit);

    Map<Location, XmlEntry> xmlEntries;

    for (unsigned i=0; i<diagnosticCount; ++i) {
        CXDiagnostic diagnostic = clang_getDiagnostic(mClangUnit, i);
        const CXSourceLocation diagLoc = clang_getDiagnosticLocation(diagnostic);
        const Location loc = createLocation(diagLoc, 0);
        const uint32_t fileId = loc.fileId();
        if (mData->visited.value(fileId)) {
            const String msg = RTags::eatString(clang_getDiagnosticSpelling(diagnostic));
            const CXDiagnosticSeverity sev = clang_getDiagnosticSeverity(diagnostic);
            XmlEntry::Type type = XmlEntry::None;
            switch (sev) {
            case CXDiagnostic_Warning:
                type = XmlEntry::Warning;
                break;
            case CXDiagnostic_Error:
            case CXDiagnostic_Fatal:
                type = XmlEntry::Error;
                break;
            default:
                break;
            }
            if (type != XmlEntry::None) {
                const unsigned rangeCount = clang_getDiagnosticNumRanges(diagnostic);
                bool ok = false;
                for (unsigned rangePos = 0; rangePos < rangeCount; ++rangePos) {
                    const CXSourceRange range = clang_getDiagnosticRange(diagnostic, rangePos);
                    const CXSourceLocation start = clang_getRangeStart(range);
                    const CXSourceLocation end = clang_getRangeEnd(range);

                    unsigned startOffset, endOffset;
                    clang_getSpellingLocation(start, 0, 0, 0, &startOffset);
                    clang_getSpellingLocation(end, 0, 0, 0, &endOffset);
                    if (!rangePos && !startOffset && !endOffset) {
                        // huh, range invalid? fall back to diag location
                        break;
                    } else {
                        unsigned int line, column;
                        clang_getPresumedLocation(start, 0, &line, &column);
                        const Location key(loc.fileId(), line, column);
                        xmlEntries[key] = XmlEntry(type, msg, endOffset - startOffset);
                        ok = true;
                        break;
                    }
                }
                if (!ok) {
                    unsigned line, column;
                    clang_getPresumedLocation(diagLoc, 0, &line, &column);
                    const Location key(loc.fileId(), line, column);
                    xmlEntries[key] = XmlEntry(type, msg);
                    // no length
                }
            }
            // logDirect(RTags::CompilationError, msg.constData());

            const unsigned fixItCount = clang_getDiagnosticNumFixIts(diagnostic);
            for (unsigned f=0; f<fixItCount; ++f) {
                CXSourceRange range;
                const CXStringScope stringScope = clang_getDiagnosticFixIt(diagnostic, f, &range);
                CXSourceLocation start = clang_getRangeStart(range);

                unsigned line, column;
                CXString file;
                clang_getPresumedLocation(start, &file, &line, &column);
                CXStringScope fileScope(file);

                const Location loc = createLocation(clang_getCString(file), line, column);
                if (mData->visited.value(loc.fileId())) {
                    unsigned int startOffset, endOffset;
                    CXSourceLocation end = clang_getRangeEnd(range);
                    clang_getSpellingLocation(start, 0, 0, 0, &startOffset);
                    clang_getSpellingLocation(end, 0, 0, 0, &endOffset);
                    const char *string = clang_getCString(stringScope);
                    error("Fixit for %s:%d:%d: Replace %d characters with [%s]", loc.path().constData(),
                          line, column, endOffset - startOffset, string);
                    XmlEntry &entry = xmlEntries[Location(loc.fileId(), line, column)];
                    entry.type = XmlEntry::Fixit;
                    if (entry.message.isEmpty()) {
                        entry.message = String::format<64>("did you mean '%s'?", string);
                    }
                    entry.length = endOffset - startOffset;
                    mData->fixIts[loc.fileId()].insert(FixIt(line, column, endOffset - startOffset, string));
                }
            }
        }

        clang_disposeDiagnostic(diagnostic);
    }

    mData->xmlDiagnostics = "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle>";
    if (!xmlEntries.isEmpty()) {
        Map<Location, XmlEntry>::const_iterator entry = xmlEntries.begin();
        const Map<Location, XmlEntry>::const_iterator end = xmlEntries.end();

        const char *severities[] = { "none", "warning", "error", "fixit" };

        uint32_t lastFileId = 0;
        while (entry != end) {
            const Location &loc = entry->first;
            const XmlEntry &xmlEntry = entry->second;
            if (loc.fileId() != lastFileId) {
                if (lastFileId)
                    mData->xmlDiagnostics += "</file>";
                lastFileId = loc.fileId();
                mData->xmlDiagnostics += String::format<128>("<file name=\"%s\">", loc.path().constData());
            }
            mData->xmlDiagnostics += String::format("<error line=\"%d\" column=\"%d\" %sseverity=\"%s\" message=\"%s\"/>",
                                                    loc.line(), loc.column(),
                                                    (xmlEntry.length <= 0 ? ""
                                                     : String::format<32>("length=\"%d\" ", xmlEntry.length).constData()),
                                                    severities[xmlEntry.type], xmlEscape(xmlEntry.message).constData());
            ++entry;
        }
        if (lastFileId)
            mData->xmlDiagnostics += "</file>";
    }

    for (Hash<uint32_t, bool>::const_iterator it = mData->visited.begin(); it != mData->visited.end(); ++it) {
        if (it->second) {
            const Map<Location, XmlEntry>::const_iterator x = xmlEntries.lower_bound(Location(it->first, 0, 0));
            if (x == xmlEntries.end() || x->first.fileId() != it->first) {
                const String fn = Location::path(it->first);
                mData->xmlDiagnostics += String::format("<file name=\"%s\"/>", fn.constData());
            }
        }
    }

    mData->xmlDiagnostics += "</checkstyle>";
    return true;
}
示例#26
0
int perform_token_annotation(int argc, const char **argv) {
  const char *input = argv[1];
  char *filename = 0;
  unsigned line, second_line;
  unsigned column, second_column;
  CXIndex CIdx;
  CXTranslationUnit TU = 0;
  int errorCode;
  struct CXUnsavedFile *unsaved_files = 0;
  int num_unsaved_files = 0;
  CXToken *tokens;
  unsigned num_tokens;
  CXSourceRange range;
  CXSourceLocation startLoc, endLoc;
  CXFile file = 0;
  CXCursor *cursors = 0;
  unsigned i;

  input += strlen("-test-annotate-tokens=");
  if ((errorCode = parse_file_line_column(input, &filename, &line, &column,
                                          &second_line, &second_column)))
    return errorCode;

  if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files))
    return -1;

  CIdx = clang_createIndex(0, 1);
  TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1],
                                                 argc - num_unsaved_files - 3,
                                                 argv + num_unsaved_files + 2,
                                                 num_unsaved_files,
                                                 unsaved_files);
  if (!TU) {
    fprintf(stderr, "unable to parse input\n");
    clang_disposeIndex(CIdx);
    free(filename);
    free_remapped_files(unsaved_files, num_unsaved_files);
    return -1;
  }
  errorCode = 0;

  file = clang_getFile(TU, filename);
  if (!file) {
    fprintf(stderr, "file %s is not in this translation unit\n", filename);
    errorCode = -1;
    goto teardown;
  }

  startLoc = clang_getLocation(TU, file, line, column);
  if (clang_equalLocations(clang_getNullLocation(), startLoc)) {
    fprintf(stderr, "invalid source location %s:%d:%d\n", filename, line,
            column);
    errorCode = -1;
    goto teardown;
  }

  endLoc = clang_getLocation(TU, file, second_line, second_column);
  if (clang_equalLocations(clang_getNullLocation(), endLoc)) {
    fprintf(stderr, "invalid source location %s:%d:%d\n", filename,
            second_line, second_column);
    errorCode = -1;
    goto teardown;
  }

  range = clang_getRange(startLoc, endLoc);
  clang_tokenize(TU, range, &tokens, &num_tokens);
  cursors = (CXCursor *)malloc(num_tokens * sizeof(CXCursor));
  clang_annotateTokens(TU, tokens, num_tokens, cursors);
  for (i = 0; i != num_tokens; ++i) {
    const char *kind = "<unknown>";
    CXString spelling = clang_getTokenSpelling(TU, tokens[i]);
    CXSourceRange extent = clang_getTokenExtent(TU, tokens[i]);
    unsigned start_line, start_column, end_line, end_column;

    switch (clang_getTokenKind(tokens[i])) {
    case CXToken_Punctuation: kind = "Punctuation"; break;
    case CXToken_Keyword: kind = "Keyword"; break;
    case CXToken_Identifier: kind = "Identifier"; break;
    case CXToken_Literal: kind = "Literal"; break;
    case CXToken_Comment: kind = "Comment"; break;
    }
    clang_getInstantiationLocation(clang_getRangeStart(extent),
                                   0, &start_line, &start_column, 0);
    clang_getInstantiationLocation(clang_getRangeEnd(extent),
                                   0, &end_line, &end_column, 0);
    printf("%s: \"%s\" ", kind, clang_getCString(spelling));
    PrintExtent(stdout, start_line, start_column, end_line, end_column);
    if (!clang_isInvalid(cursors[i].kind)) {
      printf(" ");
      PrintCursor(cursors[i]);
    }
    printf("\n");
  }
  free(cursors);

 teardown:
  PrintDiagnostics(TU);
  clang_disposeTranslationUnit(TU);
  clang_disposeIndex(CIdx);
  free(filename);
  free_remapped_files(unsaved_files, num_unsaved_files);
  return errorCode;
}
示例#27
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;
    }
}
示例#28
0
 SourceLocation SourceRange::GetEnd() const
 {
     return clang_getRangeEnd(sourceRange_);
 }
示例#29
0
CXChildVisitResult DumpThread::visit(const CXCursor &cursor)
{
    if (isAborted())
        return CXChildVisit_Break;
    const Location location = createLocation(cursor);
    if (!location.isNull()) {
        if (mQueryFlags & QueryMessage::DumpCheckIncludes) {
            checkIncludes(location, cursor);
            return CXChildVisit_Recurse;
        } else {
            Flags<Location::ToStringFlag> locationFlags;
            if (mQueryFlags & QueryMessage::NoColor)
                locationFlags |= Location::NoColor;

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

            String message;
            message.reserve(256);

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

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

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

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

            writeToConnetion(message);
        }
    }
    ++mIndentLevel;
    clang_visitChildren(cursor, DumpThread::visitor, this);
    if (isAborted())
        return CXChildVisit_Break;
    --mIndentLevel;
    return CXChildVisit_Continue;
}
示例#30
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;
}