Skip to content

Commit

Permalink
[clang][ExtractAPI] Refactor ExtractAPIVisitor to make it more extens…
Browse files Browse the repository at this point in the history
…ible

Use CRTP to enable creating statically dispatched subclasses of
ExtractAPIVisitor.
This enables adding extension points and customising the behavior more
easily.

This is used in CXExtractAPI.cpp to create a specialized visitor for
Libclang as well as streamlining the batch implementation in ExtractAPIConsumer.cpp

[clang][ExtractAPI] Improve tests for clang_getSymbolGraphForCursor

Adds a new mode to c-index-test that can fetch a single symbol symbol
graph for a given source location. This way we can be more precise when
writing tests for clang_getSymbolGraphForCursor.
Additionaly this makes it easier to debug the function.

Differential Revision: https://reviews.llvm.org/D146656
  • Loading branch information
daniel-grumberg committed Mar 27, 2023
1 parent ea35740 commit 21750a1
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 86 deletions.
177 changes: 91 additions & 86 deletions clang/test/Index/extract-api-cursor.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Test is line- and column-sensitive. Run lines are below

/// Foo docs
struct Foo {
/// Bar docs
Expand Down Expand Up @@ -25,91 +27,94 @@ @interface Derived: Base
- (void)derivedMethodWithValue:(id<Protocol>)value;
@end

/// This won't show up in docs because we can't serialize it
@interface Derived ()
/// Derived method in category docs, won't show up either.
- (void)derivedMethodInCategory;
@implementation Derived
- (void)derivedMethodWithValue:(id<Protocol>)value {
int a = 5;
}
@end

// RUN: c-index-test -single-symbol-sgfs local %s | FileCheck %s

// Checking for Foo
// CHECK: "parentContexts":[]
// CHECK-SAME: "relatedSymbols":[]
// CHECK-SAME: "relationships":[]
// CHECK-SAME: "text":"Foo docs"
// CHECK-SAME: "kind":{"displayName":"Structure","identifier":"objective-c.struct"}
// CHECK-SAME: "title":"Foo"

// Checking for bar
// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.struct","name":"Foo","usr":"c:@S@Foo"}]
// CHECK-SAME: "relatedSymbols":[]
// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:@S@Foo@FI@bar","target":"c:@S@Foo"
// CHECK-SAME: "text":"Bar docs"
// CHECK-SAME: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"}
// CHECK-SAME: "title":"bar"

// Checking for Base
// CHECK-NEXT: "parentContexts":[]
// CHECK-SAME: "relatedSymbols":[]
// CHECK-SAME: "relationships":[]
// CHECK-SAME: "text":"Base docs"
// CHECK-SAME: "kind":{"displayName":"Class","identifier":"objective-c.class"}
// CHECK-SAME: "title":"Base"

// Checking for baseProperty
// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.class","name":"Base","usr":"c:objc(cs)Base"}]
// CHECK-SAME: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c"
// CHECK-SAME: "isSystem":false
// CHECK-SAME: "usr":"c:@S@Foo"}]
// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Base(py)baseProperty","target":"c:objc(cs)Base"
// CHECK-SAME: "text":"Base property docs"
// CHECK-SAME: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"}
// CHECK-SAME: "title":"baseProperty"

// Checking for baseMethodWithArg
// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.class","name":"Base","usr":"c:objc(cs)Base"}]
// CHECK-SAME: "relatedSymbols":[]
// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Base(im)baseMethodWithArg:","target":"c:objc(cs)Base"
// CHECK-SAME: "text":"Base method docs"
// CHECK-SAME: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-SAME: "title":"baseMethodWithArg:"

// Checking for Protocol
// CHECK-NEXT: "parentContexts":[]
// CHECK-SAME: "relatedSymbols":[]
// CHECK-SAME: "relationships":[]
// CHECK-SAME: "text":"Protocol docs"
// CHECK-SAME: "kind":{"displayName":"Protocol","identifier":"objective-c.protocol"}
// CHECK-SAME: "title":"Protocol"

// Checking for protocolProperty
// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.protocol","name":"Protocol","usr":"c:objc(pl)Protocol"}]
// CHECK-SAME: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c"
// CHECK-SAME: "isSystem":false
// CHECK-SAME: "usr":"c:@S@Foo"}]
// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:objc(pl)Protocol(py)protocolProperty","target":"c:objc(pl)Protocol"
// CHECK-SAME: "text":"Protocol property docs"
// CHECK-SAME: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"}
// CHECK-SAME: "title":"protocolProperty"

// Checking for Derived
// CHECK-NEXT: "parentContexts":[]
// CHECK-SAME: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c"
// CHECK-SAME: "isSystem":false
// CHECK-SAME: "usr":"c:objc(cs)Base"}]
// CHECK-SAME: "relationships":[{"kind":"inheritsFrom","source":"c:objc(cs)Derived","target":"c:objc(cs)Base"
// CHECK-SAME: "text":"Derived docs"
// CHECK-SAME: "kind":{"displayName":"Class","identifier":"objective-c.class"}
// CHECK-SAME: "title":"Derived"

// Checking for derivedMethodWithValue
// CHECK-NEXT: "parentContexts":[{"kind":"objective-c.class","name":"Derived","usr":"c:objc(cs)Derived"}]
// CHECK-SAME: "relatedSymbols":[]
// CHECK-SAME: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)derivedMethodWithValue:","target":"c:objc(cs)Derived"
// CHECK-SAME: "text":"Derived method docs"
// CHECK-SAME: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-SAME: "title":"derivedMethodWithValue:"

// CHECK-NOT: This won't show up in docs because we can't serialize it
// CHECK-NOT: Derived method in category docs, won't show up either.
// RUN: c-index-test -single-symbol-sgf-at=%s:4:9 local %s | FileCheck -check-prefix=CHECK-FOO %s
// CHECK-FOO: "parentContexts":[]
// CHECK-FOO: "relatedSymbols":[]
// CHECK-FOO: "relationships":[]
// CHECK-FOO: "text":"Foo docs"
// CHECK-FOO: "kind":{"displayName":"Structure","identifier":"objective-c.struct"}
// CHECK-FOO: "title":"Foo"

// RUN: c-index-test -single-symbol-sgf-at=%s:6:9 local %s | FileCheck -check-prefix=CHECK-BAR %s
// CHECK-BAR: "parentContexts":[{"kind":"objective-c.struct","name":"Foo","usr":"c:@S@Foo"}]
// CHECK-BAR: "relatedSymbols":[]
// CHECK-BAR: "relationships":[{"kind":"memberOf","source":"c:@S@Foo@FI@bar","target":"c:@S@Foo"
// CHECK-BAR: "text":"Bar docs"
// CHECK-BAR: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"}
// CHECK-BAR: "title":"bar"

// RUN: c-index-test -single-symbol-sgf-at=%s:10:11 local %s | FileCheck -check-prefix=CHECK-BASE %s
// CHECK-BASE: "parentContexts":[]
// CHECK-BASE: "relatedSymbols":[]
// CHECK-BASE: "relationships":[]
// CHECK-BASE: "text":"Base docs"
// CHECK-BASE: "kind":{"displayName":"Class","identifier":"objective-c.class"}
// CHECK-BASE: "title":"Base"

// RUN: c-index-test -single-symbol-sgf-at=%s:12:25 local %s | FileCheck -check-prefix=CHECK-BASE-PROP %s
// CHECK-BASE-PROP: "parentContexts":[{"kind":"objective-c.class","name":"Base","usr":"c:objc(cs)Base"}]
// CHECK-BASE-PROP: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c"
// CHECK-BASE-PROP: "isSystem":false
// CHECK-BASE-PROP: "usr":"c:@S@Foo"}]
// CHECK-BASE-PROP: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Base(py)baseProperty","target":"c:objc(cs)Base"
// CHECK-BASE-PROP: "text":"Base property docs"
// CHECK-BASE-PROP: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"}
// CHECK-BASE-PROP: "title":"baseProperty"

// RUN: c-index-test -single-symbol-sgf-at=%s:15:9 local %s | FileCheck -check-prefix=CHECK-BASE-METHOD %s
// CHECK-BASE-METHOD: "parentContexts":[{"kind":"objective-c.class","name":"Base","usr":"c:objc(cs)Base"}]
// CHECK-BASE-METHOD: "relatedSymbols":[]
// CHECK-BASE-METHOD: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Base(im)baseMethodWithArg:","target":"c:objc(cs)Base"
// CHECK-BASE-METHOD: "text":"Base method docs"
// CHECK-BASE-METHOD: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-BASE-METHOD: "title":"baseMethodWithArg:"

// RUN: c-index-test -single-symbol-sgf-at=%s:19:11 local %s | FileCheck -check-prefix=CHECK-PROTOCOL %s
// CHECK-PROTOCOL: "parentContexts":[]
// CHECK-PROTOCOL: "relatedSymbols":[]
// CHECK-PROTOCOL: "relationships":[]
// CHECK-PROTOCOL: "text":"Protocol docs"
// CHECK-PROTOCOL: "kind":{"displayName":"Protocol","identifier":"objective-c.protocol"}
// CHECK-PROTOCOL: "title":"Protocol"

// RUN: c-index-test -single-symbol-sgf-at=%s:21:27 local %s | FileCheck -check-prefix=CHECK-PROTOCOL-PROP %s
// CHECK-PROTOCOL-PROP: "parentContexts":[{"kind":"objective-c.protocol","name":"Protocol","usr":"c:objc(pl)Protocol"}]
// CHECK-PROTOCOL-PROP: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c"
// CHECK-PROTOCOL-PROP: "isSystem":false
// CHECK-PROTOCOL-PROP: "usr":"c:@S@Foo"}]
// CHECK-PROTOCOL-PROP: "relationships":[{"kind":"memberOf","source":"c:objc(pl)Protocol(py)protocolProperty","target":"c:objc(pl)Protocol"
// CHECK-PROTOCOL-PROP: "text":"Protocol property docs"
// CHECK-PROTOCOL-PROP: "kind":{"displayName":"Instance Property","identifier":"objective-c.property"}
// CHECK-PROTOCOL-PROP: "title":"protocolProperty"

// RUN: c-index-test -single-symbol-sgf-at=%s:25:15 local %s | FileCheck -check-prefix=CHECK-DERIVED %s
// CHECK-DERIVED: "parentContexts":[]
// CHECK-DERIVED: "relatedSymbols":[{"accessLevel":"public","declarationLanguage":"objective-c"
// CHECK-DERIVED: "isSystem":false
// CHECK-DERIVED: "usr":"c:objc(cs)Base"}]
// CHECK-DERIVED: "relationships":[{"kind":"inheritsFrom","source":"c:objc(cs)Derived","target":"c:objc(cs)Base"
// CHECK-DERIVED: "text":"Derived docs"
// CHECK-DERIVED: "kind":{"displayName":"Class","identifier":"objective-c.class"}
// CHECK-DERIVED: "title":"Derived"

// RUN: c-index-test -single-symbol-sgf-at=%s:27:11 local %s | FileCheck -check-prefix=CHECK-DERIVED-METHOD %s
// CHECK-DERIVED-METHOD: "parentContexts":[{"kind":"objective-c.class","name":"Derived","usr":"c:objc(cs)Derived"}]
// CHECK-DERIVED-METHOD: "relatedSymbols":[]
// CHECK-DERIVED-METHOD: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)derivedMethodWithValue:","target":"c:objc(cs)Derived"
// CHECK-DERIVED-METHOD: "text":"Derived method docs"
// CHECK-DERIVED-METHOD: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-DERIVED-METHOD: "title":"derivedMethodWithValue:"

// RUN: c-index-test -single-symbol-sgf-at=%s:31:11 local %s | FileCheck -check-prefix=CHECK-DERIVED-METHOD-IMPL %s
// CHECK-DERIVED-METHOD-IMPL: "parentContexts":[{"kind":"objective-c.class","name":"Derived","usr":"c:objc(cs)Derived"}]
// CHECK-DERIVED-METHOD-IMPL: "relatedSymbols":[]
// CHECK-DERIVED-METHOD-IMPL: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)derivedMethodWithValue:","target":"c:objc(cs)Derived"
// CHECK-DERIVED-METHOD-IMPL: "text":"Derived method docs"
// CHECK-DERIVED-METHOD-IMPL: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-DERIVED-METHOD-IMPL: "title":"derivedMethodWithValue:"
20 changes: 20 additions & 0 deletions clang/tools/c-index-test/c-index-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "clang-c/BuildSystem.h"
#include "clang-c/CXCompilationDatabase.h"
#include "clang-c/CXErrorCode.h"
#include "clang-c/CXSourceLocation.h"
#include "clang-c/CXString.h"
#include "clang-c/Documentation.h"
#include "clang-c/Index.h"
Expand Down Expand Up @@ -4881,6 +4882,21 @@ static int perform_test_single_symbol_sgf(const char *input, int argc,
return result;
}

static void inspect_single_symbol_sgf_cursor(CXCursor Cursor) {
CXSourceLocation CursorLoc;
CXString SGFData;
const char *SGF;
unsigned line, column;
CursorLoc = clang_getCursorLocation(Cursor);
clang_getSpellingLocation(CursorLoc, 0, &line, &column, 0);
printf("%d:%d: ", line, column);

SGFData = clang_getSymbolGraphForCursor(Cursor);
SGF = clang_getCString(SGFData);
if (SGF)
printf("%s\n", SGF);
}

/******************************************************************************/
/* Command line processing. */
/******************************************************************************/
Expand Down Expand Up @@ -4940,6 +4956,7 @@ static void print_usage(void) {
" c-index-test -print-usr-file <file>\n");
fprintf(stderr,
" c-index-test -single-symbol-sgfs <symbol filter> {<args>*}\n"
" c-index-test -single-symbol-sgf-at=<site> {<args>*}\n"
" c-index-test -single-symbol-sgf-for=<usr> {<args>}*\n");
fprintf(stderr,
" c-index-test -write-pch <file> <compiler arguments>\n"
Expand Down Expand Up @@ -5076,6 +5093,9 @@ int cindextest_main(int argc, const char **argv) {
else if (argc > 3 && strcmp(argv[1], "-single-symbol-sgfs") == 0)
return perform_test_load_source(argc - 3, argv + 3, argv[2],
PrintSingleSymbolSGFs, NULL);
else if (argc > 2 && strstr(argv[1], "-single-symbol-sgf-at=") == argv[1])
return inspect_cursor_at(
argc, argv, "-single-symbol-sgf-at=", inspect_single_symbol_sgf_cursor);
else if (argc > 2 && strstr(argv[1], "-single-symbol-sgf-for=") == argv[1])
return perform_test_single_symbol_sgf(argv[1], argc - 2, argv + 2);

Expand Down

0 comments on commit 21750a1

Please sign in to comment.