4

我正在使用下面的 Objective-C 类来索引一个 Objective-C 文件。我尝试使用尖括号和带引号的头文件来解析同时使用#includeand的文件。#import在任何情况下,我的ppIncludedFile回调都不会受到打击。当我获得其中定义的符号的索引回调时,Clang 显然包含了这些文件。但是关于整体结构,我得到了enteredMainFile,然后我也得到startedTranslationUnit了主文件。但我从来不知道它在寻找什么头文件。

根据文档:

/** * \brief 当文件获得#included/#imported 时调用。*/
CXIdxClientFile (*ppIncludedFile)(CXClientData client_data, const CXIdxIncludedFileInfo *);

这没有发生。这是一个错误,还是我需要做一些事情来启用这个回调?libclang我使用的版本来自 svn trunk r156259。

//
//  FZAClassParser.m
//  ObjectiveBrowser
//
//  Created by Graham Lee on 07/05/2012.
//  Copyright (c) 2012 Fuzzy Aliens Ltd.. All rights reserved.
//

#import "FZAClassParser.h"
#import "FZAClassParserDelegate.h"

int abortQuery(CXClientData client_data, void *reserved);
void diagnostic(CXClientData client_data,
                CXDiagnosticSet diagnostic_set, void *reserved);
CXIdxClientFile enteredMainFile(CXClientData client_data,
                                CXFile mainFile, void *reserved);
CXIdxClientFile ppIncludedFile(CXClientData client_data,
                               const CXIdxIncludedFileInfo *included_file);
CXIdxClientASTFile importedASTFile(CXClientData client_data,
                                   const CXIdxImportedASTFileInfo *imported_ast);
CXIdxClientContainer startedTranslationUnit(CXClientData client_data,
                                            void *reserved);
void indexDeclaration(CXClientData client_data,
                      const CXIdxDeclInfo *declaration);
void indexEntityReference(CXClientData client_data,
                          const CXIdxEntityRefInfo *entity_reference);

static IndexerCallbacks indexerCallbacks = {
    .abortQuery = abortQuery,
    .diagnostic = diagnostic,
    .enteredMainFile = enteredMainFile,
    .ppIncludedFile = ppIncludedFile,
    .importedASTFile = importedASTFile,
    .startedTranslationUnit = startedTranslationUnit,
    .indexDeclaration = indexDeclaration,
    .indexEntityReference = indexEntityReference
};

@interface FZAClassParser ()

- (void)realParse;

@end

@implementation FZAClassParser
{
    NSString *sourceFile;
    NSOperationQueue *queue;
}

@synthesize delegate;

- (id)initWithSourceFile:(NSString *)implementation {
    if ((self = [super init])) {
        if(![[NSFileManager defaultManager] fileExistsAtPath: implementation]) {
            return nil;
        }
        sourceFile = [implementation copy];
        queue = [[NSOperationQueue alloc] init];
    }
    return self;
}

- (void)parse {
    __weak id parser = self;
    [queue addOperationWithBlock: ^{ [parser realParse]; }];
}

- (void)realParse {
#pragma warning Pass errors back to the app
    @autoreleasepool {
        CXIndex index = clang_createIndex(1, 1);
        if (!index) {
            NSLog(@"fail: couldn't create translation unit");
            return;
        }
        CXTranslationUnit translationUnit = clang_parseTranslationUnit(index, [sourceFile fileSystemRepresentation], NULL, 0, NULL, 0, CXTranslationUnit_None);
        if (!translationUnit) {
            NSLog(@"fail: couldn't compile %@", sourceFile);
            return;
        }
        CXIndexAction action = clang_IndexAction_create(index);
        if ([self.delegate respondsToSelector: @selector(classParser:willBeginParsingFile:)]) {
            [self.delegate classParser: self willBeginParsingFile: sourceFile];
        }
        int indexResult = clang_indexTranslationUnit(action,
                                                     (__bridge CXClientData)self,
                                                     &indexerCallbacks,
                                                     sizeof(indexerCallbacks),
                                                     CXIndexOpt_SuppressWarnings,
                                                     translationUnit);
        if ([self.delegate respondsToSelector: @selector(classParser:didFinishParsingFile:)]) {
            [self.delegate classParser: self didFinishParsingFile: sourceFile];
        }
        clang_IndexAction_dispose(action);
        clang_disposeTranslationUnit(translationUnit);
        clang_disposeIndex(index);
        (void) indexResult;
    }
}

@end

int abortQuery(CXClientData client_data, void *reserved) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParserShouldAbort:)]) {
            return [parser.delegate classParserShouldAbort: parser];
        }
        return 0;
    }
}

void diagnostic(CXClientData client_data,
                CXDiagnosticSet diagnostic_set, void *reserved) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParser:foundDiagnostics:)]) {
            [parser.delegate classParser: parser foundDiagnostics: diagnostic_set];
        }
    }
}

CXIdxClientFile enteredMainFile(CXClientData client_data,
                                CXFile mainFile, void *reserved) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParser:enteredMainFile:)]) {
            return [parser.delegate classParser: parser enteredMainFile: mainFile];
        }
        return NULL;
    }
}

CXIdxClientFile ppIncludedFile(CXClientData client_data,
                               const CXIdxIncludedFileInfo *included_file) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParser:includedFile:)]) {
            return [parser.delegate classParser: parser includedFile: included_file];
        }
        return NULL;
    }
}

CXIdxClientASTFile importedASTFile(CXClientData client_data,
                                   const CXIdxImportedASTFileInfo *imported_ast) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParser:importedPCH:)]) {
            return [parser.delegate classParser: parser importedPCH: imported_ast];
        }
        return NULL;
    }
}

CXIdxClientContainer startedTranslationUnit(CXClientData client_data,
                                            void *reserved) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParserStartedTranslationUnit:)]) {
            return [parser.delegate classParserStartedTranslationUnit: parser];
        }
        return NULL;
    }
}

void indexDeclaration(CXClientData client_data,
                      const CXIdxDeclInfo *declaration) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParser:foundDeclaration:)]) {
            [parser.delegate classParser: parser foundDeclaration: declaration];
        }
    }
}

void indexEntityReference(CXClientData client_data,
                          const CXIdxEntityRefInfo *entity_reference) {
    @autoreleasepool {
        FZAClassParser *parser = (__bridge FZAClassParser *)client_data;
        if ([parser.delegate respondsToSelector: @selector(classParser:foundEntityReference:)]) {
            [parser.delegate classParser: parser foundEntityReference: entity_reference];
        }
    }
}
4

1 回答 1

3

可能不会记录当时的处理,#include因为那里有很多信息(一般情况下可能不需要)。如果未启用该选项,则有一个createPreporcessingRecord功能不会生成数据。

Clang 文档描述了CXTranslationUnit_DetailedPreprocessingRecord,您可以将其用作标志而不是CXTranslationUnit_None可能有帮助的标志。

于 2012-05-13T21:09:52.647 回答