mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Frontend: when emitting loaded module trace file, also emit a JSON file tracking Objc method calls issued from the source code.
This commit is contained in:
@@ -17,12 +17,15 @@
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ModuleLoader.h"
|
||||
#include "swift/AST/PluginRegistry.h"
|
||||
#include "swift/AST/SourceFile.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
#include "swift/Basic/FileTypes.h"
|
||||
#include "swift/Basic/JSONSerialization.h"
|
||||
#include "swift/Frontend/FrontendOptions.h"
|
||||
#include "swift/IDE/SourceEntityWalker.h"
|
||||
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
@@ -810,3 +813,69 @@ bool swift::emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool swift::emitObjCMessageSendTraceIfNeeded(ModuleDecl *mainModule,
|
||||
const FrontendOptions &opts) {
|
||||
ASTContext &ctxt = mainModule->getASTContext();
|
||||
assert(!ctxt.hadError() &&
|
||||
"We should've already exited earlier if there was an error.");
|
||||
class ObjcMethodRefereceCollector: public SourceEntityWalker {
|
||||
std::set<const clang::ObjCMethodDecl*> results;
|
||||
bool visitDeclReference(ValueDecl *D, CharSourceRange Range,
|
||||
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
|
||||
Type T, ReferenceMetaData Data) override {
|
||||
if (!Range.isValid())
|
||||
return true;
|
||||
if (auto *clangD = dyn_cast_or_null<clang::ObjCMethodDecl>(D->getClangDecl())) {
|
||||
results.insert(clangD);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
void dump(llvm::raw_ostream &OS) {
|
||||
OS << "[\n";
|
||||
for (const clang::ObjCMethodDecl* clangD: results) {
|
||||
auto &SM = clangD->getASTContext().getSourceManager();
|
||||
clang::SourceLocation Loc = clangD->getLocation();
|
||||
if (!Loc.isValid()) {
|
||||
continue;
|
||||
}
|
||||
OS << "\t{\n";
|
||||
OS << "\t\t\"method_name\": \"" << clangD->getNameAsString() << "\",\n";
|
||||
OS << "\t\t\"location\": \"" << Loc.printToString(SM) << "\"\n";
|
||||
OS << "\t}";
|
||||
OS << ",\n";
|
||||
}
|
||||
OS << "{} ]\n";
|
||||
}
|
||||
};
|
||||
opts.InputsAndOutputs.forEachInput([&](const InputFile &input) {
|
||||
auto loadedModuleTracePath = input.getLoadedModuleTracePath();
|
||||
if (loadedModuleTracePath.empty())
|
||||
return false;
|
||||
llvm::SmallString<128> tracePath {loadedModuleTracePath};
|
||||
llvm::sys::path::remove_filename(tracePath);
|
||||
llvm::sys::path::append(tracePath, "SWIFT_OBJC_MESSAGE_TRACE");
|
||||
if (!llvm::sys::fs::exists(tracePath)) {
|
||||
if (llvm::sys::fs::create_directory(tracePath))
|
||||
return false;
|
||||
}
|
||||
llvm::sys::path::append(tracePath, "%%%%-%%%%-%%%%.json");
|
||||
int tmpFD;
|
||||
if (llvm::sys::fs::createUniqueFile(tracePath.str(), tmpFD, tracePath)) {
|
||||
return false;
|
||||
}
|
||||
// Write the contents of the buffer.
|
||||
llvm::raw_fd_ostream out(tmpFD, /*shouldClose=*/true);
|
||||
ObjcMethodRefereceCollector collector;
|
||||
for (auto *FU : mainModule->getFiles()) {
|
||||
if (auto *SF = dyn_cast<SourceFile>(FU)) {
|
||||
collector.walk(*SF);
|
||||
}
|
||||
}
|
||||
collector.dump(out);
|
||||
return true;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user