2121#include " swift/Basic/Assertions.h"
2222#include " swift/Basic/FileTypes.h"
2323#include " swift/Basic/JSONSerialization.h"
24+ #include " swift/Basic/SourceManager.h"
2425#include " swift/Frontend/FrontendOptions.h"
2526#include " swift/IDE/SourceEntityWalker.h"
2627
@@ -815,7 +816,13 @@ bool swift::emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
815816 return false ;
816817}
817818
819+ const static unsigned OBJC_METHOD_TRACE_FILE_FORMAT_VERSION = 1 ;
820+
818821class ObjcMethodReferenceCollector : public SourceEntityWalker {
822+ std::string target;
823+ std::string targetVariant;
824+ SmallVector<StringRef, 32 > FilePaths;
825+ unsigned CurrentFileID;
819826 llvm::DenseSet<const clang::ObjCMethodDecl*> results;
820827 bool visitDeclReference (ValueDecl *D, CharSourceRange Range,
821828 TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
@@ -827,27 +834,70 @@ class ObjcMethodReferenceCollector: public SourceEntityWalker {
827834 }
828835 return true ;
829836 }
837+ static StringRef selectMethodKey (const clang::ObjCMethodDecl* clangD) {
838+ assert (clangD);
839+ if (clangD->isInstanceMethod ())
840+ return " instance_method" ;
841+ else if (clangD->isClassMethod ())
842+ return " class_method" ;
843+ else
844+ return " method" ;
845+ }
846+ static StringRef selectMethodOwnerKey (const clang::NamedDecl* clangD) {
847+ assert (clangD);
848+ if (isa<clang::ObjCInterfaceDecl>(clangD))
849+ return " interface_type" ;
850+ if (isa<clang::ObjCCategoryDecl>(clangD))
851+ return " category_type" ;
852+ return " type" ;
853+ }
830854public:
855+ ObjcMethodReferenceCollector (ModuleDecl *MD) {
856+ auto &Opts = MD->getASTContext ().LangOpts ;
857+ target = Opts.Target .str ();
858+ targetVariant = Opts.TargetVariant .has_value () ?
859+ Opts.TargetVariant ->str () : " " ;
860+ }
861+ void setFileBeforeVisiting (SourceFile *SF) {
862+ assert (SF && " need to visit actual source files" );
863+ FilePaths.push_back (SF->getFilename ());
864+ CurrentFileID = FilePaths.size ();
865+ }
831866 void serializeAsJson (llvm::raw_ostream &OS) {
832867 llvm::json::OStream out (OS, /* IndentSize=*/ 4 );
833- out.array ([&] {
834- for (const clang::ObjCMethodDecl* clangD: results) {
835- auto &SM = clangD->getASTContext ().getSourceManager ();
836- clang::SourceLocation Loc = clangD->getLocation ();
837- if (!Loc.isValid ()) {
838- continue ;
839- }
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);
868+ out.object ([&] {
869+ out.attribute (" format-vesion" , OBJC_METHOD_TRACE_FILE_FORMAT_VERSION);
870+ out.attribute (" target" , target);
871+ if (!targetVariant.empty ())
872+ out.attribute (" target-variant" , targetVariant);
873+ out.attributeArray (" references" , [&] {
874+ for (const clang::ObjCMethodDecl* clangD: results) {
875+ auto &SM = clangD->getASTContext ().getSourceManager ();
876+ clang::SourceLocation Loc = clangD->getLocation ();
877+ if (!Loc.isValid ()) {
878+ continue ;
846879 }
847- out.attribute (" method" , clangD->getNameAsString ());
848- out.attribute (" location" , Loc.printToString (SM));
849- });
850- }
880+ out.object ([&] {
881+ if (auto *parent = dyn_cast_or_null<clang::NamedDecl>(clangD
882+ ->getParent ())) {
883+ auto pName = parent->getName ();
884+ if (!pName.empty ())
885+ out.attribute (selectMethodOwnerKey (parent), pName);
886+ }
887+ out.attribute (selectMethodKey (clangD), clangD->getNameAsString ());
888+ out.attribute (" declared_at" , Loc.printToString (SM));
889+ out.attribute (" referenced_at_file_id" , CurrentFileID);
890+ });
891+ }
892+ });
893+ out.attributeArray (" fileMap" , [&]{
894+ for (unsigned I = 0 , N = FilePaths.size (); I != N; I ++) {
895+ out.object ([&] {
896+ out.attribute (" file_id" , I + 1 );
897+ out.attribute (" file_path" , FilePaths[I]);
898+ });
899+ }
900+ });
851901 });
852902 }
853903};
@@ -864,7 +914,7 @@ bool swift::emitObjCMessageSendTraceIfNeeded(ModuleDecl *mainModule,
864914 return false ;
865915 llvm::SmallString<128 > tracePath {loadedModuleTracePath};
866916 llvm::sys::path::remove_filename (tracePath);
867- llvm::sys::path::append (tracePath, " .SWIFT_OBJC_MESSAGE_TRACE " );
917+ llvm::sys::path::append (tracePath, " .SWIFT_FINE_DEPENDENCY_TRACE " );
868918 if (!llvm::sys::fs::exists (tracePath)) {
869919 if (llvm::sys::fs::create_directory (tracePath))
870920 return false ;
@@ -876,9 +926,10 @@ bool swift::emitObjCMessageSendTraceIfNeeded(ModuleDecl *mainModule,
876926 }
877927 // Write the contents of the buffer.
878928 llvm::raw_fd_ostream out (tmpFD, /* shouldClose=*/ true );
879- ObjcMethodReferenceCollector collector;
929+ ObjcMethodReferenceCollector collector (mainModule) ;
880930 for (auto *FU : mainModule->getFiles ()) {
881931 if (auto *SF = dyn_cast<SourceFile>(FU)) {
932+ collector.setFileBeforeVisiting (SF);
882933 collector.walk (*SF);
883934 }
884935 }
0 commit comments