Skip to content

Commit 555c00a

Browse files
authored
ModuleTrace: use clang API to emit information in JSON (#77422)
1 parent c0d64ba commit 555c00a

File tree

2 files changed

+16
-73
lines changed

2 files changed

+16
-73
lines changed

lib/FrontendTool/LoadedModuleTrace.cpp

Lines changed: 13 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/IDE/SourceEntityWalker.h"
2828

2929
#include "clang/AST/DeclObjC.h"
30+
#include "clang/AST/ObjCMethodReferenceInfo.h"
3031
#include "clang/Basic/Module.h"
3132

3233
#include "llvm/ADT/SmallPtrSet.h"
@@ -817,96 +818,38 @@ bool swift::emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
817818
return false;
818819
}
819820

820-
const static unsigned OBJC_METHOD_TRACE_FILE_FORMAT_VERSION = 1;
821-
822821
class ObjcMethodReferenceCollector: public SourceEntityWalker {
823-
std::string compilerVer;
824-
std::string target;
825-
std::string targetVariant;
826-
SmallVector<StringRef, 32> FilePaths;
827822
unsigned CurrentFileID;
828823
llvm::DenseMap<const clang::ObjCMethodDecl*, unsigned> results;
829824
bool visitDeclReference(ValueDecl *D, CharSourceRange Range,
830825
TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef,
831826
Type T, ReferenceMetaData Data) override {
832827
if (!Range.isValid())
833828
return true;
834-
if (auto *clangD = dyn_cast_or_null<clang::ObjCMethodDecl>(D->getClangDecl())) {
835-
results[clangD] = CurrentFileID;
836-
}
829+
if (auto *clangD = dyn_cast_or_null<clang::ObjCMethodDecl>(D->getClangDecl()))
830+
Info.References[CurrentFileID].push_back(clangD);
837831
return true;
838832
}
839-
static StringRef selectMethodKey(const clang::ObjCMethodDecl* clangD) {
840-
assert(clangD);
841-
if (clangD->isInstanceMethod())
842-
return "instance_method";
843-
else if (clangD->isClassMethod())
844-
return "class_method";
845-
else
846-
return "method";
847-
}
848-
static StringRef selectMethodOwnerKey(const clang::NamedDecl* clangD) {
849-
assert(clangD);
850-
if (isa<clang::ObjCInterfaceDecl>(clangD))
851-
return "interface_type";
852-
if (isa<clang::ObjCCategoryDecl>(clangD))
853-
return "category_type";
854-
if (isa<clang::ObjCProtocolDecl>(clangD))
855-
return "protocol_type";
856-
return "type";
857-
}
833+
834+
clang::ObjCMethodReferenceInfo Info;
835+
858836
public:
859837
ObjcMethodReferenceCollector(ModuleDecl *MD) {
860-
compilerVer =
838+
Info.ToolName = "swift-compiler-version";
839+
Info.ToolVersion =
861840
getSwiftInterfaceCompilerVersionForCurrentCompiler(MD->getASTContext());
862841
auto &Opts = MD->getASTContext().LangOpts;
863-
target = Opts.Target.str();
864-
targetVariant = Opts.TargetVariant.has_value() ?
842+
Info.Target = Opts.Target.str();
843+
Info.TargetVariant = Opts.TargetVariant.has_value() ?
865844
Opts.TargetVariant->str() : "";
866845
}
867846
void setFileBeforeVisiting(SourceFile *SF) {
868847
assert(SF && "need to visit actual source files");
869-
FilePaths.push_back(SF->getFilename());
870-
CurrentFileID = FilePaths.size();
848+
Info.FilePaths.push_back(SF->getFilename().str());
849+
CurrentFileID = Info.FilePaths.size();
871850
}
872851
void serializeAsJson(llvm::raw_ostream &OS) {
873-
llvm::json::OStream out(OS, /*IndentSize=*/4);
874-
out.object([&] {
875-
out.attribute("swift-compiler-version", compilerVer);
876-
out.attribute("format-vesion", OBJC_METHOD_TRACE_FILE_FORMAT_VERSION);
877-
out.attribute("target", target);
878-
if (!targetVariant.empty())
879-
out.attribute("target-variant", targetVariant);
880-
out.attributeArray("references", [&] {
881-
for (auto pair: results) {
882-
auto *clangD = pair.first;
883-
auto &SM = clangD->getASTContext().getSourceManager();
884-
clang::SourceLocation Loc = clangD->getLocation();
885-
if (!Loc.isValid()) {
886-
continue;
887-
}
888-
out.object([&] {
889-
if (auto *parent = dyn_cast_or_null<clang::NamedDecl>(clangD
890-
->getParent())) {
891-
auto pName = parent->getName();
892-
if (!pName.empty())
893-
out.attribute(selectMethodOwnerKey(parent), pName);
894-
}
895-
out.attribute(selectMethodKey(clangD), clangD->getNameAsString());
896-
out.attribute("declared_at", Loc.printToString(SM));
897-
out.attribute("referenced_at_file_id", pair.second);
898-
});
899-
}
900-
});
901-
out.attributeArray("fileMap", [&]{
902-
for (unsigned I = 0, N = FilePaths.size(); I != N; I ++) {
903-
out.object([&] {
904-
out.attribute("file_id", I + 1);
905-
out.attribute("file_path", FilePaths[I]);
906-
});
907-
}
908-
});
909-
});
852+
clang::serializeObjCMethodReferencesAsJson(Info, OS);
910853
}
911854
};
912855

test/IDE/objc_send_collector_1.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ public func testProperties(_ x: FooClassBase, _ y: FooProtocolBase) {
1818
y.fooProtoFunc()
1919
}
2020

21-
// CHECK-DAG: "instance_method": "fooBaseInstanceFunc0"
22-
// CHECK-DAG: "instance_method": "fooBaseInstanceFunc1:"
23-
// CHECK-DAG: "class_method": "fooBaseClassFunc0"
21+
// CHECK-DAG: "instance_method": "-[FooClassBase fooBaseInstanceFunc0]"
22+
// CHECK-DAG: "instance_method": "-[FooClassBase fooBaseInstanceFunc1:]"
23+
// CHECK-DAG: "class_method": "+[FooClassBase fooBaseClassFunc0]"
2424
// CHECK-DAG: "interface_type": "FooClassBase"
2525
// CHECK-DAG: "protocol_type": "FooProtocolBase"
2626
// CHECK-DAG: "declared_at": "SOURCE_DIR/test/IDE/Inputs/mock-sdk/Foo.framework/Headers/Foo.h

0 commit comments

Comments
 (0)