diff options
Diffstat (limited to 'tools/c-index-test/c-index-test.c')
-rw-r--r-- | tools/c-index-test/c-index-test.c | 606 |
1 files changed, 576 insertions, 30 deletions
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index eb2a406..5df21ec 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -1,12 +1,20 @@ /* c-index-test.c */ #include "clang-c/Index.h" +#include "clang-c/CXCompilationDatabase.h" +#include "llvm/Config/config.h" #include <ctype.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> +#ifdef CLANG_HAVE_LIBXML +#include <libxml/parser.h> +#include <libxml/relaxng.h> +#include <libxml/xmlerror.h> +#endif + /******************************************************************************/ /* Utility functions. */ /******************************************************************************/ @@ -25,8 +33,25 @@ char *basename(const char* path) return((char*)path); } +char *dirname(char* path) +{ + char* base1 = (char*)strrchr(path, '/'); + char* base2 = (char*)strrchr(path, '\\'); + if (base1 && base2) + if (base1 > base2) + *base1 = 0; + else + *base2 = 0; + else if (base1) + *base1 = 0; + else if (base2) + *base2 = 0; + + return path; +} #else extern char *basename(const char *); +extern char *dirname(char *); #endif /** \brief Return the default parsing options. */ @@ -41,6 +66,8 @@ static unsigned getDefaultParsingOptions() { options &= ~CXTranslationUnit_CacheCompletionResults; if (getenv("CINDEXTEST_SKIP_FUNCTION_BODIES")) options |= CXTranslationUnit_SkipFunctionBodies; + if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS")) + options |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion; return options; } @@ -137,6 +164,7 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, (feof(to_file) ? "EOF" : "error"), semi + 1); fclose(to_file); free_remapped_files(*unsaved_files, i); + free(contents); *unsaved_files = 0; *num_unsaved_files = 0; return -1; @@ -158,10 +186,62 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, return 0; } +static const char *parse_comments_schema(int argc, const char **argv) { + const char *CommentsSchemaArg = "-comments-xml-schema="; + const char *CommentSchemaFile = NULL; + + if (argc == 0) + return CommentSchemaFile; + + if (!strncmp(argv[0], CommentsSchemaArg, strlen(CommentsSchemaArg))) + CommentSchemaFile = argv[0] + strlen(CommentsSchemaArg); + + return CommentSchemaFile; +} + /******************************************************************************/ /* Pretty-printing. */ /******************************************************************************/ +static const char *FileCheckPrefix = "CHECK"; + +static void PrintCString(const char *CStr) { + if (CStr != NULL && CStr[0] != '\0') { + for ( ; *CStr; ++CStr) { + const char C = *CStr; + switch (C) { + case '\n': printf("\\n"); break; + case '\r': printf("\\r"); break; + case '\t': printf("\\t"); break; + case '\v': printf("\\v"); break; + case '\f': printf("\\f"); break; + default: putchar(C); break; + } + } + } +} + +static void PrintCStringWithPrefix(const char *Prefix, const char *CStr) { + printf(" %s=[", Prefix); + PrintCString(CStr); + printf("]"); +} + +static void PrintCXStringAndDispose(CXString Str) { + PrintCString(clang_getCString(Str)); + clang_disposeString(Str); +} + +static void PrintCXStringWithPrefix(const char *Prefix, CXString Str) { + PrintCStringWithPrefix(Prefix, clang_getCString(Str)); +} + +static void PrintCXStringWithPrefixAndDispose(const char *Prefix, + CXString Str) { + PrintCStringWithPrefix(Prefix, clang_getCString(Str)); + clang_disposeString(Str); +} + static void PrintRange(CXSourceRange R, const char *str) { CXFile begin_file, end_file; unsigned begin_line, begin_column, end_line, end_column; @@ -180,7 +260,302 @@ static void PrintRange(CXSourceRange R, const char *str) { int want_display_name = 0; -static void PrintCursor(CXCursor Cursor) { +static void printVersion(const char *Prefix, CXVersion Version) { + if (Version.Major < 0) + return; + printf("%s%d", Prefix, Version.Major); + + if (Version.Minor < 0) + return; + printf(".%d", Version.Minor); + + if (Version.Subminor < 0) + return; + printf(".%d", Version.Subminor); +} + +struct CommentASTDumpingContext { + int IndentLevel; +}; + +static void DumpCXCommentInternal(struct CommentASTDumpingContext *Ctx, + CXComment Comment) { + unsigned i; + unsigned e; + enum CXCommentKind Kind = clang_Comment_getKind(Comment); + + Ctx->IndentLevel++; + for (i = 0, e = Ctx->IndentLevel; i != e; ++i) + printf(" "); + + printf("("); + switch (Kind) { + case CXComment_Null: + printf("CXComment_Null"); + break; + case CXComment_Text: + printf("CXComment_Text"); + PrintCXStringWithPrefixAndDispose("Text", + clang_TextComment_getText(Comment)); + if (clang_Comment_isWhitespace(Comment)) + printf(" IsWhitespace"); + if (clang_InlineContentComment_hasTrailingNewline(Comment)) + printf(" HasTrailingNewline"); + break; + case CXComment_InlineCommand: + printf("CXComment_InlineCommand"); + PrintCXStringWithPrefixAndDispose( + "CommandName", + clang_InlineCommandComment_getCommandName(Comment)); + switch (clang_InlineCommandComment_getRenderKind(Comment)) { + case CXCommentInlineCommandRenderKind_Normal: + printf(" RenderNormal"); + break; + case CXCommentInlineCommandRenderKind_Bold: + printf(" RenderBold"); + break; + case CXCommentInlineCommandRenderKind_Monospaced: + printf(" RenderMonospaced"); + break; + case CXCommentInlineCommandRenderKind_Emphasized: + printf(" RenderEmphasized"); + break; + } + for (i = 0, e = clang_InlineCommandComment_getNumArgs(Comment); + i != e; ++i) { + printf(" Arg[%u]=", i); + PrintCXStringAndDispose( + clang_InlineCommandComment_getArgText(Comment, i)); + } + if (clang_InlineContentComment_hasTrailingNewline(Comment)) + printf(" HasTrailingNewline"); + break; + case CXComment_HTMLStartTag: { + unsigned NumAttrs; + printf("CXComment_HTMLStartTag"); + PrintCXStringWithPrefixAndDispose( + "Name", + clang_HTMLTagComment_getTagName(Comment)); + NumAttrs = clang_HTMLStartTag_getNumAttrs(Comment); + if (NumAttrs != 0) { + printf(" Attrs:"); + for (i = 0; i != NumAttrs; ++i) { + printf(" "); + PrintCXStringAndDispose(clang_HTMLStartTag_getAttrName(Comment, i)); + printf("="); + PrintCXStringAndDispose(clang_HTMLStartTag_getAttrValue(Comment, i)); + } + } + if (clang_HTMLStartTagComment_isSelfClosing(Comment)) + printf(" SelfClosing"); + if (clang_InlineContentComment_hasTrailingNewline(Comment)) + printf(" HasTrailingNewline"); + break; + } + case CXComment_HTMLEndTag: + printf("CXComment_HTMLEndTag"); + PrintCXStringWithPrefixAndDispose( + "Name", + clang_HTMLTagComment_getTagName(Comment)); + if (clang_InlineContentComment_hasTrailingNewline(Comment)) + printf(" HasTrailingNewline"); + break; + case CXComment_Paragraph: + printf("CXComment_Paragraph"); + if (clang_Comment_isWhitespace(Comment)) + printf(" IsWhitespace"); + break; + case CXComment_BlockCommand: + printf("CXComment_BlockCommand"); + PrintCXStringWithPrefixAndDispose( + "CommandName", + clang_BlockCommandComment_getCommandName(Comment)); + for (i = 0, e = clang_BlockCommandComment_getNumArgs(Comment); + i != e; ++i) { + printf(" Arg[%u]=", i); + PrintCXStringAndDispose( + clang_BlockCommandComment_getArgText(Comment, i)); + } + break; + case CXComment_ParamCommand: + printf("CXComment_ParamCommand"); + switch (clang_ParamCommandComment_getDirection(Comment)) { + case CXCommentParamPassDirection_In: + printf(" in"); + break; + case CXCommentParamPassDirection_Out: + printf(" out"); + break; + case CXCommentParamPassDirection_InOut: + printf(" in,out"); + break; + } + if (clang_ParamCommandComment_isDirectionExplicit(Comment)) + printf(" explicitly"); + else + printf(" implicitly"); + PrintCXStringWithPrefixAndDispose( + "ParamName", + clang_ParamCommandComment_getParamName(Comment)); + if (clang_ParamCommandComment_isParamIndexValid(Comment)) + printf(" ParamIndex=%u", clang_ParamCommandComment_getParamIndex(Comment)); + else + printf(" ParamIndex=Invalid"); + break; + case CXComment_TParamCommand: + printf("CXComment_TParamCommand"); + PrintCXStringWithPrefixAndDispose( + "ParamName", + clang_TParamCommandComment_getParamName(Comment)); + if (clang_TParamCommandComment_isParamPositionValid(Comment)) { + printf(" ParamPosition={"); + for (i = 0, e = clang_TParamCommandComment_getDepth(Comment); + i != e; ++i) { + printf("%u", clang_TParamCommandComment_getIndex(Comment, i)); + if (i != e - 1) + printf(", "); + } + printf("}"); + } else + printf(" ParamPosition=Invalid"); + break; + case CXComment_VerbatimBlockCommand: + printf("CXComment_VerbatimBlockCommand"); + PrintCXStringWithPrefixAndDispose( + "CommandName", + clang_BlockCommandComment_getCommandName(Comment)); + break; + case CXComment_VerbatimBlockLine: + printf("CXComment_VerbatimBlockLine"); + PrintCXStringWithPrefixAndDispose( + "Text", + clang_VerbatimBlockLineComment_getText(Comment)); + break; + case CXComment_VerbatimLine: + printf("CXComment_VerbatimLine"); + PrintCXStringWithPrefixAndDispose( + "Text", + clang_VerbatimLineComment_getText(Comment)); + break; + case CXComment_FullComment: + printf("CXComment_FullComment"); + break; + } + if (Kind != CXComment_Null) { + const unsigned NumChildren = clang_Comment_getNumChildren(Comment); + unsigned i; + for (i = 0; i != NumChildren; ++i) { + printf("\n// %s: ", FileCheckPrefix); + DumpCXCommentInternal(Ctx, clang_Comment_getChild(Comment, i)); + } + } + printf(")"); + Ctx->IndentLevel--; +} + +static void DumpCXComment(CXComment Comment) { + struct CommentASTDumpingContext Ctx; + Ctx.IndentLevel = 1; + printf("\n// %s: CommentAST=[\n// %s:", FileCheckPrefix, FileCheckPrefix); + DumpCXCommentInternal(&Ctx, Comment); + printf("]"); +} + +typedef struct { + const char *CommentSchemaFile; +#ifdef CLANG_HAVE_LIBXML + xmlRelaxNGParserCtxtPtr RNGParser; + xmlRelaxNGPtr Schema; +#endif +} CommentXMLValidationData; + +static void ValidateCommentXML(const char *Str, + CommentXMLValidationData *ValidationData) { +#ifdef CLANG_HAVE_LIBXML + xmlDocPtr Doc; + xmlRelaxNGValidCtxtPtr ValidationCtxt; + int status; + + if (!ValidationData || !ValidationData->CommentSchemaFile) + return; + + if (!ValidationData->RNGParser) { + ValidationData->RNGParser = + xmlRelaxNGNewParserCtxt(ValidationData->CommentSchemaFile); + ValidationData->Schema = xmlRelaxNGParse(ValidationData->RNGParser); + } + if (!ValidationData->RNGParser) { + printf(" libXMLError"); + return; + } + + Doc = xmlParseDoc((const xmlChar *) Str); + + if (!Doc) { + xmlErrorPtr Error = xmlGetLastError(); + printf(" CommentXMLInvalid [not well-formed XML: %s]", Error->message); + return; + } + + ValidationCtxt = xmlRelaxNGNewValidCtxt(ValidationData->Schema); + status = xmlRelaxNGValidateDoc(ValidationCtxt, Doc); + if (!status) + printf(" CommentXMLValid"); + else if (status > 0) { + xmlErrorPtr Error = xmlGetLastError(); + printf(" CommentXMLInvalid [not vaild XML: %s]", Error->message); + } else + printf(" libXMLError"); + + xmlRelaxNGFreeValidCtxt(ValidationCtxt); + xmlFreeDoc(Doc); +#endif +} + +static void PrintCursorComments(CXTranslationUnit TU, + CXCursor Cursor, + CommentXMLValidationData *ValidationData) { + { + CXString RawComment; + const char *RawCommentCString; + CXString BriefComment; + const char *BriefCommentCString; + + RawComment = clang_Cursor_getRawCommentText(Cursor); + RawCommentCString = clang_getCString(RawComment); + if (RawCommentCString != NULL && RawCommentCString[0] != '\0') { + PrintCStringWithPrefix("RawComment", RawCommentCString); + PrintRange(clang_Cursor_getCommentRange(Cursor), "RawCommentRange"); + + BriefComment = clang_Cursor_getBriefCommentText(Cursor); + BriefCommentCString = clang_getCString(BriefComment); + if (BriefCommentCString != NULL && BriefCommentCString[0] != '\0') + PrintCStringWithPrefix("BriefComment", BriefCommentCString); + clang_disposeString(BriefComment); + } + clang_disposeString(RawComment); + } + + { + CXComment Comment = clang_Cursor_getParsedComment(Cursor); + if (clang_Comment_getKind(Comment) != CXComment_Null) { + PrintCXStringWithPrefixAndDispose("FullCommentAsHTML", + clang_FullComment_getAsHTML(Comment)); + { + CXString XML; + XML = clang_FullComment_getAsXML(TU, Comment); + PrintCXStringWithPrefix("FullCommentAsXML", XML); + ValidateCommentXML(clang_getCString(XML), ValidationData); + clang_disposeString(XML); + } + + DumpCXComment(Comment); + } + } +} + +static void PrintCursor(CXCursor Cursor, + CommentXMLValidationData *ValidationData) { CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor); if (clang_isInvalid(Cursor.kind)) { CXString ks = clang_getCursorKindSpelling(Cursor.kind); @@ -197,6 +572,13 @@ static void PrintCursor(CXCursor Cursor) { unsigned RefNameRangeNr; CXSourceRange CursorExtent; CXSourceRange RefNameRange; + int AlwaysUnavailable; + int AlwaysDeprecated; + CXString UnavailableMessage; + CXString DeprecatedMessage; + CXPlatformAvailability PlatformAvailability[2]; + int NumPlatformAvailability; + int I; ks = clang_getCursorKindSpelling(Cursor.kind); string = want_display_name? clang_getCursorDisplayName(Cursor) @@ -249,6 +631,47 @@ static void PrintCursor(CXCursor Cursor) { break; } + NumPlatformAvailability + = clang_getCursorPlatformAvailability(Cursor, + &AlwaysDeprecated, + &DeprecatedMessage, + &AlwaysUnavailable, + &UnavailableMessage, + PlatformAvailability, 2); + if (AlwaysUnavailable) { + printf(" (always unavailable: \"%s\")", + clang_getCString(UnavailableMessage)); + } else if (AlwaysDeprecated) { + printf(" (always deprecated: \"%s\")", + clang_getCString(DeprecatedMessage)); + } else { + for (I = 0; I != NumPlatformAvailability; ++I) { + if (I >= 2) + break; + + printf(" (%s", clang_getCString(PlatformAvailability[I].Platform)); + if (PlatformAvailability[I].Unavailable) + printf(", unavailable"); + else { + printVersion(", introduced=", PlatformAvailability[I].Introduced); + printVersion(", deprecated=", PlatformAvailability[I].Deprecated); + printVersion(", obsoleted=", PlatformAvailability[I].Obsoleted); + } + if (clang_getCString(PlatformAvailability[I].Message)[0]) + printf(", message=\"%s\"", + clang_getCString(PlatformAvailability[I].Message)); + printf(")"); + } + } + for (I = 0; I != NumPlatformAvailability; ++I) { + if (I >= 2) + break; + clang_disposeCXPlatformAvailability(PlatformAvailability + I); + } + + clang_disposeString(DeprecatedMessage); + clang_disposeString(UnavailableMessage); + if (clang_CXXMethod_isStatic(Cursor)) printf(" (static)"); if (clang_CXXMethod_isVirtual(Cursor)) @@ -336,6 +759,8 @@ static void PrintCursor(CXCursor Cursor) { if (!clang_equalRanges(CursorExtent, RefNameRange)) PrintRange(RefNameRange, "RefName"); } + + PrintCursorComments(TU, Cursor, ValidationData); } } @@ -458,17 +883,16 @@ void PrintMemoryUsage(CXTranslationUnit TU) { /* Logic for testing traversal. */ /******************************************************************************/ -static const char *FileCheckPrefix = "CHECK"; - static void PrintCursorExtent(CXCursor C) { CXSourceRange extent = clang_getCursorExtent(C); PrintRange(extent, "Extent"); } -/* Data used by all of the visitors. */ -typedef struct { +/* Data used by the visitors. */ +typedef struct { CXTranslationUnit TU; enum CXCursorKind *Filter; + CommentXMLValidationData ValidationData; } VisitorData; @@ -482,7 +906,7 @@ enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor, clang_getSpellingLocation(Loc, 0, &line, &column, 0); printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Cursor), line, column); - PrintCursor(Cursor); + PrintCursor(Cursor, &Data->ValidationData); PrintCursorExtent(Cursor); printf("\n"); return CXChildVisit_Recurse; @@ -535,7 +959,7 @@ static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor, } else if (Ref.kind != CXCursor_FunctionDecl) { printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Ref), curLine, curColumn); - PrintCursor(Ref); + PrintCursor(Ref, &Data->ValidationData); printf("\n"); } } @@ -622,7 +1046,7 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p, } if (linkage) { - PrintCursor(cursor); + PrintCursor(cursor, NULL); printf("linkage=%s\n", linkage); } @@ -638,7 +1062,7 @@ static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p, if (!clang_isInvalid(clang_getCursorKind(cursor))) { CXType T = clang_getCursorType(cursor); CXString S = clang_getTypeKindSpelling(T.kind); - PrintCursor(cursor); + PrintCursor(cursor, NULL); printf(" typekind=%s", clang_getCString(S)); if (clang_isConstQualifiedType(T)) printf(" const"); @@ -698,7 +1122,8 @@ static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p, static int perform_test_load(CXIndex Idx, CXTranslationUnit TU, const char *filter, const char *prefix, CXCursorVisitor Visitor, - PostVisitTU PV) { + PostVisitTU PV, + const char *CommentSchemaFile) { if (prefix) FileCheckPrefix = prefix; @@ -729,6 +1154,11 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU, Data.TU = TU; Data.Filter = ck; + Data.ValidationData.CommentSchemaFile = CommentSchemaFile; +#ifdef CLANG_HAVE_LIBXML + Data.ValidationData.RNGParser = NULL; + Data.ValidationData.Schema = NULL; +#endif clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data); } @@ -760,7 +1190,7 @@ int perform_test_load_tu(const char *file, const char *filter, return 1; } - result = perform_test_load(Idx, TU, filter, prefix, Visitor, PV); + result = perform_test_load(Idx, TU, filter, prefix, Visitor, PV, NULL); clang_disposeIndex(Idx); return result; } @@ -770,6 +1200,7 @@ int perform_test_load_source(int argc, const char **argv, PostVisitTU PV) { CXIndex Idx; CXTranslationUnit TU; + const char *CommentSchemaFile; struct CXUnsavedFile *unsaved_files = 0; int num_unsaved_files = 0; int result; @@ -779,6 +1210,11 @@ int perform_test_load_source(int argc, const char **argv, !strcmp(filter, "local-display"))? 1 : 0, /* displayDiagnosics=*/0); + if ((CommentSchemaFile = parse_comments_schema(argc, argv))) { + argc--; + argv++; + } + if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) { clang_disposeIndex(Idx); return -1; @@ -796,7 +1232,8 @@ int perform_test_load_source(int argc, const char **argv, return 1; } - result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV); + result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV, + CommentSchemaFile); free_remapped_files(unsaved_files, num_unsaved_files); clang_disposeIndex(Idx); return result; @@ -860,7 +1297,7 @@ int perform_test_reparse_source(int argc, const char **argv, int trials, return -1; } - result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV); + result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV, NULL); free_remapped_files(unsaved_files, num_unsaved_files); clang_disposeIndex(Idx); @@ -880,7 +1317,7 @@ static void print_cursor_file_scan(CXTranslationUnit TU, CXCursor cursor, printf("-%s", prefix); PrintExtent(stdout, start_line, start_col, end_line, end_col); printf(" "); - PrintCursor(cursor); + PrintCursor(cursor, NULL); printf("\n"); } @@ -1104,6 +1541,8 @@ void print_completion_result(CXCompletionResult *completion_result, unsigned annotationCount; enum CXCursorKind ParentKind; CXString ParentName; + CXString BriefComment; + const char *BriefCommentCString; fprintf(file, "%s:", clang_getCString(ks)); clang_disposeString(ks); @@ -1155,6 +1594,14 @@ void print_completion_result(CXCompletionResult *completion_result, } clang_disposeString(ParentName); } + + BriefComment = clang_getCompletionBriefComment( + completion_result->CompletionString); + BriefCommentCString = clang_getCString(BriefComment); + if (BriefCommentCString && *BriefCommentCString != '\0') { + fprintf(file, "(brief comment: %s)", BriefCommentCString); + } + clang_disposeString(BriefComment); fprintf(file, "\n"); } @@ -1267,6 +1714,8 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { if (getenv("CINDEXTEST_CODE_COMPLETE_PATTERNS")) completionOptions |= CXCodeComplete_IncludeCodePatterns; + if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS")) + completionOptions |= CXCodeComplete_IncludeBriefComments; if (timing_only) input += strlen("-code-completion-timing="); @@ -1465,7 +1914,7 @@ static int inspect_cursor_at(int argc, const char **argv) { unsigned line, column; clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0); printf("%d:%d ", line, column); - PrintCursor(Cursor); + PrintCursor(Cursor, NULL); PrintCursorExtent(Cursor); Spelling = clang_getCursorSpelling(Cursor); cspell = clang_getCString(Spelling); @@ -1484,6 +1933,9 @@ static int inspect_cursor_at(int argc, const char **argv) { clang_disposeString(Spelling); if (clang_Cursor_getObjCSelectorIndex(Cursor) != -1) printf(" Selector index=%d",clang_Cursor_getObjCSelectorIndex(Cursor)); + if (clang_Cursor_isDynamicCall(Cursor)) + printf(" Dynamic-call"); + if (completionString != NULL) { printf("\nCompletion string: "); print_completion_string(completionString, stdout); @@ -1507,7 +1959,7 @@ static enum CXVisitorResult findFileRefsVisit(void *context, if (clang_Range_isNull(range)) return CXVisit_Continue; - PrintCursor(cursor); + PrintCursor(cursor, NULL); PrintRange(range, ""); printf("\n"); return CXVisit_Continue; @@ -1591,7 +2043,7 @@ static int find_file_refs_at(int argc, const char **argv) { if (I + 1 == Repeats) { CXCursorAndRangeVisitor visitor = { 0, findFileRefsVisit }; - PrintCursor(Cursor); + PrintCursor(Cursor, NULL); printf("\n"); clang_findReferencesInFile(Cursor, file, visitor); free(Locations[Loc].filename); @@ -1789,7 +2241,7 @@ static void printEntityInfo(const char *cb, for (i = 0; i != info->numAttributes; ++i) { const CXIdxAttrInfo *Attr = info->attributes[i]; printf(" <attribute>: "); - PrintCursor(Attr->cursor); + PrintCursor(Attr->cursor, NULL); } } @@ -1797,7 +2249,7 @@ static void printBaseClassInfo(CXClientData client_data, const CXIdxBaseClassInfo *info) { printEntityInfo(" <base>", client_data, info->base); printf(" | cursor: "); - PrintCursor(info->cursor); + PrintCursor(info->cursor, NULL); printf(" | loc: "); printCXIndexLoc(info->loc, client_data); } @@ -1809,7 +2261,7 @@ static void printProtocolList(const CXIdxObjCProtocolRefListInfo *ProtoInfo, printEntityInfo(" <protocol>", client_data, ProtoInfo->protocols[i]->protocol); printf(" | cursor: "); - PrintCursor(ProtoInfo->protocols[i]->cursor); + PrintCursor(ProtoInfo->protocols[i]->cursor, NULL); printf(" | loc: "); printCXIndexLoc(ProtoInfo->protocols[i]->loc, client_data); printf("\n"); @@ -1899,7 +2351,7 @@ static void index_indexDeclaration(CXClientData client_data, printEntityInfo("[indexDeclaration]", client_data, info->entityInfo); printf(" | cursor: "); - PrintCursor(info->cursor); + PrintCursor(info->cursor, NULL); printf(" | loc: "); printCXIndexLoc(info->loc, client_data); printf(" | semantic-container: "); @@ -1914,7 +2366,7 @@ static void index_indexDeclaration(CXClientData client_data, for (i = 0; i != info->numAttributes; ++i) { const CXIdxAttrInfo *Attr = info->attributes[i]; printf(" <attribute>: "); - PrintCursor(Attr->cursor); + PrintCursor(Attr->cursor, NULL); printf("\n"); } @@ -1937,7 +2389,7 @@ static void index_indexDeclaration(CXClientData client_data, printEntityInfo(" <ObjCCategoryInfo>: class", client_data, CatInfo->objcClass); printf(" | cursor: "); - PrintCursor(CatInfo->classCursor); + PrintCursor(CatInfo->classCursor, NULL); printf(" | loc: "); printCXIndexLoc(CatInfo->classLoc, client_data); printf("\n"); @@ -1981,7 +2433,7 @@ static void index_indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo *info) { printEntityInfo("[indexEntityReference]", client_data, info->referencedEntity); printf(" | cursor: "); - PrintCursor(info->cursor); + PrintCursor(info->cursor, NULL); printf(" | loc: "); printCXIndexLoc(info->loc, client_data); printEntityInfo(" | <parent>:", client_data, info->parentEntity); @@ -2051,7 +2503,6 @@ static int index_file(int argc, const char **argv) { return 1; } idxAction = 0; - result = 1; index_data.check_prefix = check_prefix; index_data.first_check_printed = 0; @@ -2148,8 +2599,10 @@ int perform_token_annotation(int argc, const char **argv) { &second_line, &second_column))) return errorCode; - if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) + if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) { + free(filename); return -1; + } CIdx = clang_createIndex(0, 1); TU = clang_parseTranslationUnit(CIdx, argv[argc - 1], @@ -2167,8 +2620,10 @@ int perform_token_annotation(int argc, const char **argv) { } errorCode = 0; - if (checkForErrors(TU) != 0) - return -1; + if (checkForErrors(TU) != 0) { + errorCode = -1; + goto teardown; + } if (getenv("CINDEXTEST_EDITING")) { for (i = 0; i < 5; ++i) { @@ -2247,7 +2702,7 @@ int perform_token_annotation(int argc, const char **argv) { PrintExtent(stdout, start_line, start_column, end_line, end_column); if (!clang_isInvalid(cursors[i].kind)) { printf(" "); - PrintCursor(cursors[i]); + PrintCursor(cursors[i], NULL); } printf("\n"); } @@ -2263,6 +2718,89 @@ int perform_token_annotation(int argc, const char **argv) { return errorCode; } +static int +perform_test_compilation_db(const char *database, int argc, const char **argv) { + CXCompilationDatabase db; + CXCompileCommands CCmds; + CXCompileCommand CCmd; + CXCompilationDatabase_Error ec; + CXString wd; + CXString arg; + int errorCode = 0; + char *tmp; + unsigned len; + char *buildDir; + int i, j, a, numCmds, numArgs; + + len = strlen(database); + tmp = (char *) malloc(len+1); + memcpy(tmp, database, len+1); + buildDir = dirname(tmp); + + db = clang_CompilationDatabase_fromDirectory(buildDir, &ec); + + if (db) { + + if (ec!=CXCompilationDatabase_NoError) { + printf("unexpected error %d code while loading compilation database\n", ec); + errorCode = -1; + goto cdb_end; + } + + for (i=0; i<argc && errorCode==0; ) { + if (strcmp(argv[i],"lookup")==0){ + CCmds = clang_CompilationDatabase_getCompileCommands(db, argv[i+1]); + + if (!CCmds) { + printf("file %s not found in compilation db\n", argv[i+1]); + errorCode = -1; + break; + } + + numCmds = clang_CompileCommands_getSize(CCmds); + + if (numCmds==0) { + fprintf(stderr, "should not get an empty compileCommand set for file" + " '%s'\n", argv[i+1]); + errorCode = -1; + break; + } + + for (j=0; j<numCmds; ++j) { + CCmd = clang_CompileCommands_getCommand(CCmds, j); + + wd = clang_CompileCommand_getDirectory(CCmd); + printf("workdir:'%s'", clang_getCString(wd)); + clang_disposeString(wd); + + printf(" cmdline:'"); + numArgs = clang_CompileCommand_getNumArgs(CCmd); + for (a=0; a<numArgs; ++a) { + if (a) printf(" "); + arg = clang_CompileCommand_getArg(CCmd, a); + printf("%s", clang_getCString(arg)); + clang_disposeString(arg); + } + printf("'\n"); + } + + clang_CompileCommands_dispose(CCmds); + + i += 2; + } + } + clang_CompilationDatabase_dispose(db); + } else { + printf("database loading failed with error code %d.\n", ec); + errorCode = -1; + } + +cdb_end: + free(tmp); + + return errorCode; +} + /******************************************************************************/ /* USR printing. */ /******************************************************************************/ @@ -2703,6 +3241,8 @@ static void print_usage(void) { " c-index-test -print-usr-file <file>\n" " c-index-test -write-pch <file> <compiler arguments>\n"); fprintf(stderr, + " c-index-test -compilation-db [lookup <filename>] database\n"); + fprintf(stderr, " c-index-test -read-diagnostics <file>\n\n"); fprintf(stderr, " <symbol filter> values:\n%s", @@ -2788,7 +3328,9 @@ int cindextest_main(int argc, const char **argv) { return print_usrs_file(argv[2]); else if (argc > 2 && strcmp(argv[1], "-write-pch") == 0) return write_pch_file(argv[2], argc - 3, argv + 3); - + else if (argc > 2 && strcmp(argv[1], "-compilation-db") == 0) + return perform_test_compilation_db(argv[argc-1], argc - 3, argv + 2); + print_usage(); return 1; } @@ -2815,6 +3357,10 @@ void thread_runner(void *client_data_v) { int main(int argc, const char **argv) { thread_info client_data; +#ifdef CLANG_HAVE_LIBXML + LIBXML_TEST_VERSION +#endif + if (getenv("CINDEXTEST_NOTHREADS")) return cindextest_main(argc, argv); |