6

I am using libclang to parse a objective c source code file. The following code finds all Objective-C instance method declarations, but it also finds declarations in the includes:

 enum CXCursorKind curKind  = clang_getCursorKind(cursor);
 CXString curKindName  = clang_getCursorKindSpelling(curKind);

 const char *funcDecl="ObjCInstanceMethodDecl";

 if(strcmp(clang_getCString(curKindName),funcDecl)==0{


 }

How can I skip everything, which comes from header includes? I am only interested in my own Objective-C instance method declarations in the source file, not in any of the includes.

e.g. the following should not be included

...

Location: /System/Library/Frameworks/Foundation.framework/Headers/NSObject.h:15:9:315
Type: 
TypeKind: Invalid
CursorKind: ObjCInstanceMethodDecl

...
Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
mc_plectrum
  • 363
  • 4
  • 12

2 Answers2

14

Answering this question because I couldn't believe that hard-coding paths comparisons was the only solution, and indeed, there is a clang_Location_isFromMainFile function that does exactly what you want, so that you can filter unwanted results in the visitor, like this :

if (clang_Location_isFromMainFile (clang_getCursorLocation (cursor)) == 0) {
  return CXChildVisit_Continue;
}
raph.amiard
  • 2,755
  • 2
  • 20
  • 23
0

The only way I know would be to skip unwanted paths during the AST visit. You can for example put something like the following in your visitor function. Returning CXChildVisit_Continue avoids visiting the entire file.

CXFile file;
unsigned int line, column, offset;
CXString fileName;
char * canonicalPath = NULL;

clang_getExpansionLocation (clang_getCursorLocation (cursor),
                            &file, &line, &column, &offset);

fileName = clang_getFileName (file);
if (clang_getCString (fileName)) {
  canonicalPath = realpath (clang_getCString (fileName), NULL);
}
clang_disposeString (fileName);

if (strcmp(canonicalPath, "/canonical/path/to/your/source/file") != 0) {
  return CXChildVisit_Continue;
}

Also, why compare CursorKindSpelling instead of the CursorKind directly?

François Févotte
  • 19,520
  • 4
  • 51
  • 74
  • clang_getFileName(file) is missing – mc_plectrum Sep 30 '13 at 05:11
  • Unfortunately the cursor now does not reach the method declarations of my sourcefile. – mc_plectrum Sep 30 '13 at 05:18
  • Yes, you're right, I forgot one step. While doing this kind of things, I've often had difficulties comparing file paths, due to the various existing ways to reference the same file on the file system. One way to avoid this is to canonicalize all paths before comparing them. Please see my edit for an example (hopefully complete, this time!) – François Févotte Sep 30 '13 at 06:56
  • this part: if (strcmp(clang_getCString(fileName), "/canonical/path/to/your/source/file") != 0) { return CXChildVisit_Continue; } does not work... it does not reach the method declarartions, without it everything works fine(but slow) – mc_plectrum Sep 30 '13 at 08:49
  • Yes, yet another mistake on my part. I edited the code to base the paths comparison on `canonicalPath` (which was the whole point of using `realpath`. – François Févotte Sep 30 '13 at 09:07
  • And? Have you tried debugging it? What does not work? Which file(s) does it visit? How are you testing it? – François Févotte Oct 02 '13 at 06:31