2424#include " swift/Frontend/FrontendOptions.h"
2525#include " swift/IDE/SourceEntityWalker.h"
2626
27- #include " clang/Basic/Module.h"
2827#include " clang/AST/DeclObjC.h"
28+ #include " clang/Basic/Module.h"
2929
3030#include " llvm/ADT/SmallPtrSet.h"
3131#include " llvm/ADT/SmallString.h"
32+ #include " llvm/Support/JSON.h"
3233#include " llvm/Support/Path.h"
3334#include " llvm/Support/YAMLTraits.h"
3435#include " llvm/Support/FileUtilities.h"
@@ -814,49 +815,56 @@ bool swift::emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
814815 return false ;
815816}
816817
817-
818- bool swift::emitObjCMessageSendTraceIfNeeded (ModuleDecl *mainModule,
819- const FrontendOptions &opts) {
820- ASTContext &ctxt = mainModule->getASTContext ();
821- assert (!ctxt.hadError () &&
822- " We should've already exited earlier if there was an error." );
823- class ObjcMethodRefereceCollector : public SourceEntityWalker {
824- std::set<const clang::ObjCMethodDecl*> results;
825- bool visitDeclReference (ValueDecl *D, CharSourceRange Range,
826- TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
827- Type T, ReferenceMetaData Data) override {
828- if (!Range.isValid ())
829- return true ;
830- if (auto *clangD = dyn_cast_or_null<clang::ObjCMethodDecl>(D->getClangDecl ())) {
831- results.insert (clangD);
832- }
818+ class ObjcMethodReferenceCollector : public SourceEntityWalker {
819+ llvm::DenseSet<const clang::ObjCMethodDecl*> results;
820+ bool visitDeclReference (ValueDecl *D, CharSourceRange Range,
821+ TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
822+ Type T, ReferenceMetaData Data) override {
823+ if (!Range.isValid ())
833824 return true ;
825+ if (auto *clangD = dyn_cast_or_null<clang::ObjCMethodDecl>(D->getClangDecl ())) {
826+ results.insert (clangD);
834827 }
835- public:
836- void dump (llvm::raw_ostream &OS) {
837- OS << " [\n " ;
828+ return true ;
829+ }
830+ public:
831+ void serializeAsJson (llvm::raw_ostream &OS) {
832+ llvm::json::OStream out (OS, /* IndentSize=*/ 4 );
833+ out.array ([&] {
838834 for (const clang::ObjCMethodDecl* clangD: results) {
839835 auto &SM = clangD->getASTContext ().getSourceManager ();
840836 clang::SourceLocation Loc = clangD->getLocation ();
841837 if (!Loc.isValid ()) {
842838 continue ;
843839 }
844- OS << " \t {\n " ;
845- OS << " \t\t\" method_name\" : \" " << clangD->getNameAsString () << " \" ,\n " ;
846- OS << " \t\t\" location\" : \" " << Loc.printToString (SM) << " \"\n " ;
847- OS << " \t }" ;
848- OS << " ,\n " ;
840+ out.object ([&] {
841+ if (auto *parent = dyn_cast_or_null<clang::NamedDecl>(clangD
842+ ->getParent ())) {
843+ auto pName = parent->getName ();
844+ if (!pName.empty ())
845+ out.attribute (" type" , pName);
846+ }
847+ out.attribute (" method" , clangD->getNameAsString ());
848+ out.attribute (" location" , Loc.printToString (SM));
849+ });
849850 }
850- OS << " {} ]\n " ;
851- }
852- };
851+ });
852+ }
853+ };
854+
855+ bool swift::emitObjCMessageSendTraceIfNeeded (ModuleDecl *mainModule,
856+ const FrontendOptions &opts) {
857+ ASTContext &ctxt = mainModule->getASTContext ();
858+ assert (!ctxt.hadError () &&
859+ " We should've already exited earlier if there was an error." );
860+
853861 opts.InputsAndOutputs .forEachInput ([&](const InputFile &input) {
854862 auto loadedModuleTracePath = input.getLoadedModuleTracePath ();
855863 if (loadedModuleTracePath.empty ())
856864 return false ;
857865 llvm::SmallString<128 > tracePath {loadedModuleTracePath};
858866 llvm::sys::path::remove_filename (tracePath);
859- llvm::sys::path::append (tracePath, " SWIFT_OBJC_MESSAGE_TRACE" );
867+ llvm::sys::path::append (tracePath, " . SWIFT_OBJC_MESSAGE_TRACE" );
860868 if (!llvm::sys::fs::exists (tracePath)) {
861869 if (llvm::sys::fs::create_directory (tracePath))
862870 return false ;
@@ -868,13 +876,13 @@ bool swift::emitObjCMessageSendTraceIfNeeded(ModuleDecl *mainModule,
868876 }
869877 // Write the contents of the buffer.
870878 llvm::raw_fd_ostream out (tmpFD, /* shouldClose=*/ true );
871- ObjcMethodRefereceCollector collector;
879+ ObjcMethodReferenceCollector collector;
872880 for (auto *FU : mainModule->getFiles ()) {
873881 if (auto *SF = dyn_cast<SourceFile>(FU)) {
874882 collector.walk (*SF);
875883 }
876884 }
877- collector.dump (out);
885+ collector.serializeAsJson (out);
878886 return true ;
879887 });
880888 return false ;
0 commit comments