[IDE] Implement generating the Swift interface for an C/ObjC header

This translates clang arguments to swift ones, uses the bridging header
functionality to parse the provided file, and re-uses part of the module interface
printing implementation to print an interface for the header.

Part of rdar://19939192

Swift SVN r28062
This commit is contained in:
Argyrios Kyrtzidis
2015-05-02 01:17:45 +00:00
parent d72ae21e7c
commit a586753f0f
7 changed files with 323 additions and 44 deletions

View File

@@ -16,6 +16,7 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/Basic/PrimitiveParsing.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
@@ -27,6 +28,7 @@
#include "clang/Basic/Module.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include <queue>
#include <utility>
@@ -115,14 +117,7 @@ void swift::ide::printModuleInterface(Module *M,
printSubmoduleInterface(M, M->Name.str(), TraversalOptions, Printer, Options);
}
void swift::ide::printSubmoduleInterface(
Module *M,
ArrayRef<StringRef> FullModuleName,
ModuleTraversalOptions TraversalOptions,
ASTPrinter &Printer,
const PrintOptions &Options) {
auto AdjustedOptions = Options;
static void adjustPrintOptions(PrintOptions &AdjustedOptions) {
// Don't print empty curly braces while printing the module interface.
AdjustedOptions.FunctionDefinitions = false;
@@ -133,6 +128,16 @@ void swift::ide::printSubmoduleInterface(
AdjustedOptions.VarInitializers = false;
AdjustedOptions.PrintDefaultParameterPlaceholder = true;
}
void swift::ide::printSubmoduleInterface(
Module *M,
ArrayRef<StringRef> FullModuleName,
ModuleTraversalOptions TraversalOptions,
ASTPrinter &Printer,
const PrintOptions &Options) {
auto AdjustedOptions = Options;
adjustPrintOptions(AdjustedOptions);
SmallVector<Decl *, 1> Decls;
M->getDisplayDecls(Decls);
@@ -390,6 +395,81 @@ void swift::ide::printSubmoduleInterface(
}
}
namespace {
class ImportedHeaderFilter : public VisibleDeclConsumer {
ClangImporter &Importer;
llvm::function_ref<void(ValueDecl *)> Receiver;
const clang::FileEntry *File;
public:
ImportedHeaderFilter(StringRef Filename,
ClangImporter &Importer,
llvm::function_ref<void(ValueDecl *)> Receiver)
: Importer(Importer),
Receiver(Receiver) {
File = Importer.getClangPreprocessor().getFileManager().getFile(Filename);
}
private:
void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) override {
auto ClangN = VD->getClangNode();
if (ClangN.isNull())
return;
auto &SM = Importer.getClangPreprocessor().getSourceManager();
auto ClangLoc = SM.getFileLoc(ClangN.getLocation());
if (ClangLoc.isInvalid())
return;
if (SM.getFileEntryForID(SM.getFileID(ClangLoc)) == File)
Receiver(VD);
}
};
}
void swift::ide::printHeaderInterface(
StringRef Filename,
ASTContext &Ctx,
ASTPrinter &Printer,
const PrintOptions &Options) {
auto AdjustedOptions = Options;
adjustPrintOptions(AdjustedOptions);
SmallVector<ValueDecl *, 32> ClangDecls;
auto DeclReceiver = [&](ValueDecl *D) {
// If requested, skip unavailable declarations.
if (Options.SkipUnavailable && D->getAttrs().isUnavailable(Ctx))
return;
ClangDecls.push_back(D);
};
auto &Importer = static_cast<ClangImporter &>(*Ctx.getClangModuleLoader());
ImportedHeaderFilter Filter(Filename, Importer, DeclReceiver);
Importer.lookupVisibleDecls(Filter);
auto &ClangSM = Importer.getClangASTContext().getSourceManager();
// Sort imported declarations in source order.
std::sort(ClangDecls.begin(), ClangDecls.end(),
[&](ValueDecl *LHS, ValueDecl *RHS) -> bool {
return ClangSM.isBeforeInTranslationUnit(
LHS->getClangNode().getLocation(),
RHS->getClangNode().getLocation());
});
ASTPrinter *PrinterToUse = &Printer;
ClangCommentPrinter RegularCommentPrinter(Printer, Importer);
if (Options.PrintRegularClangComments)
PrinterToUse = &RegularCommentPrinter;
for (auto *D : ClangDecls) {
ASTPrinter &Printer = *PrinterToUse;
if (D->print(Printer, AdjustedOptions))
Printer << "\n";
}
}
void ClangCommentPrinter::printDeclPre(const Decl *D) {
if (auto ClangN = D->getClangNode()) {
printCommentsUntil(ClangN);