Skip to content

Commit 0d16cbf

Browse files
authored
Merge pull request swiftlang#77253 from nkcsgexi/138776708
ModuleObjcMessageTrace: also include the source file name where an ObjcMethod is referenced
2 parents 97186b0 + 3fc9e27 commit 0d16cbf

File tree

2 files changed

+80
-24
lines changed

2 files changed

+80
-24
lines changed

lib/FrontendTool/LoadedModuleTrace.cpp

+70-19
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
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+
818821
class 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+
}
830854
public:
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
}

test/IDE/objc_send_collector.swift

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %empty-directory(%t)
22

33
// RUN: %target-swift-frontend -I %t/lib/swift -typecheck %s -module-name main -swift-version 5 -F %S/Inputs/mock-sdk -emit-loaded-module-trace-path %t/.MODULE_TRACE
4-
// RUN: cat %t/.SWIFT_OBJC_MESSAGE_TRACE/* | %FileCheck %s
4+
// RUN: cat %t/.SWIFT_FINE_DEPENDENCY_TRACE/* | %FileCheck %s
55

66
// REQUIRES: objc_interop
77

@@ -10,9 +10,14 @@ import Foo
1010
public func testProperties(_ x: FooClassBase) {
1111
_ = x.fooBaseInstanceFunc0()
1212
x.fooBaseInstanceFunc1(1.2)
13+
_ = FooClassBase.fooBaseClassFunc0()
1314
}
1415

15-
// CHECK-DAG: fooBaseInstanceFunc0
16-
// CHECK-DAG: fooBaseInstanceFunc1
17-
// CHECK-DAG: "type": "FooClassBase"
18-
// CHECK-DAG: SOURCE_DIR/test/IDE/Inputs/mock-sdk/Foo.framework/Headers/Foo.h
16+
// CHECK-DAG: "instance_method": "fooBaseInstanceFunc0"
17+
// CHECK-DAG: "instance_method": "fooBaseInstanceFunc1:"
18+
// CHECK-DAG: "class_method": "fooBaseClassFunc0"
19+
// CHECK-DAG: "interface_type": "FooClassBase"
20+
// CHECK-DAG: "declared_at": "SOURCE_DIR/test/IDE/Inputs/mock-sdk/Foo.framework/Headers/Foo.h
21+
// CHECK-DAG: "referenced_at_file_id": 1
22+
// CHECK-DAG: "file_id": 1,
23+
// CHECK-DAG: "file_path": "SOURCE_DIR/test/IDE/objc_send_collector.swift"

0 commit comments

Comments
 (0)