mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
311 lines
10 KiB
C++
311 lines
10 KiB
C++
//===--- JSON.cpp - Symbol Graph JSON Helpers -----------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// Adds Symbol Graph JSON serialization to other types.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "JSON.h"
|
|
#include "Symbol.h"
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/FileUnit.h"
|
|
#include "swift/AST/GenericParamList.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/AST/Type.h"
|
|
#include "swift/AST/USRGeneration.h"
|
|
#include "swift/ClangImporter/ClangModule.h"
|
|
#include "swift/Serialization/SerializedModuleLoader.h"
|
|
|
|
void swift::symbolgraphgen::serialize(const llvm::VersionTuple &VT,
|
|
llvm::json::OStream &OS) {
|
|
OS.object([&](){
|
|
OS.attribute("major", VT.getMajor());
|
|
if (VT.getMinor()) {
|
|
OS.attribute("minor", *VT.getMinor());
|
|
}
|
|
if (VT.getSubminor()) {
|
|
OS.attribute("patch", *VT.getSubminor());
|
|
}
|
|
// Despite the name,
|
|
// this is not Semantic Versioning "build metadata"
|
|
if (VT.getBuild()) {
|
|
OS.attribute("prerelease", *VT.getBuild());
|
|
}
|
|
});
|
|
}
|
|
|
|
void swift::symbolgraphgen::serialize(const llvm::Triple &T,
|
|
llvm::json::OStream &OS) {
|
|
OS.object([&](){
|
|
OS.attribute("architecture", T.getArchName());
|
|
if (!T.getEnvironmentName().empty()) {
|
|
OS.attribute("environment", T.getEnvironmentName());
|
|
}
|
|
OS.attribute("vendor", T.getVendorName());
|
|
OS.attributeObject("operatingSystem", [&](){
|
|
OS.attribute("name", T.getOSTypeName(T.getOS()));
|
|
|
|
llvm::VersionTuple OSVersion = T.getOSVersion();
|
|
if (!OSVersion.empty()) {
|
|
OS.attributeBegin("minimumVersion");
|
|
serialize(OSVersion, OS);
|
|
OS.attributeEnd();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
void swift::symbolgraphgen::serialize(const ExtensionDecl *Extension,
|
|
llvm::json::OStream &OS) {
|
|
OS.attributeObject("swiftExtension", [&](){
|
|
if (const auto *ExtendedNominal = Extension->getExtendedNominal()) {
|
|
if (const auto *ExtendedModule = ExtendedNominal->getModuleContext()) {
|
|
OS.attribute("extendedModule", ExtendedModule->getNameStr());
|
|
}
|
|
|
|
OS.attribute("typeKind", Symbol::getKind(ExtendedNominal).first);
|
|
}
|
|
|
|
SmallVector<Requirement, 4> FilteredRequirements;
|
|
|
|
filterGenericRequirements(Extension,
|
|
FilteredRequirements);
|
|
|
|
if (!FilteredRequirements.empty()) {
|
|
OS.attributeArray("constraints", [&](){
|
|
for (const auto &Requirement : FilteredRequirements) {
|
|
serialize(Requirement, OS);
|
|
}
|
|
}); // end constraints:
|
|
}
|
|
}); // end swiftExtension:
|
|
}
|
|
|
|
void swift::symbolgraphgen::serialize(const Requirement &Req,
|
|
llvm::json::OStream &OS) {
|
|
StringRef Kind;
|
|
switch (Req.getKind()) {
|
|
case RequirementKind::SameShape:
|
|
Kind = "sameShape";
|
|
break;
|
|
case RequirementKind::Conformance:
|
|
Kind = "conformance";
|
|
break;
|
|
case RequirementKind::Superclass:
|
|
Kind = "superclass";
|
|
break;
|
|
case RequirementKind::SameType:
|
|
Kind = "sameType";
|
|
break;
|
|
case RequirementKind::Layout:
|
|
return;
|
|
}
|
|
|
|
OS.object([&](){
|
|
OS.attribute("kind", Kind);
|
|
OS.attribute("lhs", Req.getFirstType()->getString());
|
|
OS.attribute("rhs", Req.getSecondType()->getString());
|
|
|
|
// If the RHS type has a USR we can link to, add it to the output
|
|
if (auto *TyDecl = Req.getSecondType()->getAnyNominal()) {
|
|
SmallString<256> USR;
|
|
{
|
|
llvm::raw_svector_ostream SOS(USR);
|
|
ide::printDeclUSR(TyDecl, SOS);
|
|
}
|
|
OS.attribute("rhsPrecise", USR.str());
|
|
}
|
|
});
|
|
}
|
|
|
|
void swift::symbolgraphgen::serialize(const swift::GenericTypeParamType *Param,
|
|
llvm::json::OStream &OS) {
|
|
OS.object([&](){
|
|
OS.attribute("name", Param->getName().str());
|
|
OS.attribute("index", Param->getIndex());
|
|
OS.attribute("depth", Param->getDepth());
|
|
});
|
|
}
|
|
|
|
void swift::symbolgraphgen::serialize(const ModuleDecl &Module,
|
|
llvm::json::OStream &OS,
|
|
llvm::Triple Target) {
|
|
auto *MainFile = Module.getFiles().front();
|
|
switch (MainFile->getKind()) {
|
|
case FileUnitKind::Builtin:
|
|
llvm_unreachable("Unexpected module kind: Builtin");
|
|
case FileUnitKind::DWARFModule:
|
|
llvm_unreachable("Unexpected module kind: DWARFModule");
|
|
case FileUnitKind::Synthesized:
|
|
llvm_unreachable("Unexpected module kind: Synthesized");
|
|
break;
|
|
case FileUnitKind::Source:
|
|
serialize(Module.getASTContext().LangOpts.Target, OS);
|
|
break;
|
|
case FileUnitKind::SerializedAST: {
|
|
auto SerializedAST = cast<SerializedASTFile>(MainFile);
|
|
auto Target = llvm::Triple(SerializedAST->getTargetTriple());
|
|
serialize(Target, OS);
|
|
break;
|
|
}
|
|
case FileUnitKind::ClangModule: {
|
|
auto ClangModule = cast<ClangModuleUnit>(MainFile);
|
|
if (const auto *Overlay = ClangModule->getOverlayModule()) {
|
|
serialize(*Overlay, OS, Target);
|
|
} else {
|
|
serialize(Target, OS);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
swift::symbolgraphgen::filterGenericParams(
|
|
ArrayRef<GenericTypeParamType *> GenericParams,
|
|
SmallVectorImpl<const GenericTypeParamType*> &FilteredParams,
|
|
SubstitutionMap SubMap) {
|
|
|
|
for (auto Param : GenericParams) {
|
|
if (const auto *GPD = Param->getDecl()) {
|
|
|
|
// Ignore the implicit Self param
|
|
if (GPD->isImplicit()) {
|
|
if (!isa<ExtensionDecl>(GPD->getDeclContext()))
|
|
continue;
|
|
|
|
// Extension decls (and their children) refer to implicit copies of the
|
|
// explicit params of the nominal they extend. Don't filter those out.
|
|
auto *ED = cast<ExtensionDecl>(GPD->getDeclContext());
|
|
if (auto *NTD = ED->getExtendedNominal()) {
|
|
if (auto *GPL = NTD->getGenericParams()) {
|
|
auto ImplicitAndSameName = [&](GenericTypeParamDecl *NominalGPD) {
|
|
return NominalGPD->isImplicit() &&
|
|
GPD->getName() == NominalGPD->getName();
|
|
};
|
|
if (llvm::any_of(GPL->getParams(), ImplicitAndSameName))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ignore parameters that have been substituted.
|
|
if (!SubMap.empty()) {
|
|
Type SubTy = Type(Param).subst(SubMap);
|
|
if (!SubTy->hasError() && SubTy.getPointer() != Param) {
|
|
if (!SubTy->is<ArchetypeType>()) {
|
|
continue;
|
|
}
|
|
auto AT = SubTy->castTo<ArchetypeType>();
|
|
if (!AT->getInterfaceType()->isEqual(Param)) {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
FilteredParams.push_back(Param);
|
|
}
|
|
}
|
|
}
|
|
|
|
// FIXME: This is wrong. We should instead compute the new requirements of a
|
|
// member declaration by comparing against the generic signature of its
|
|
// parent, with getRequirementsNotSatisfiedBy().
|
|
static bool containsParams(swift::Type Ty, llvm::ArrayRef<const swift::GenericTypeParamType*> Others) {
|
|
return Ty.findIf([&](swift::Type T) -> bool {
|
|
if (auto AT = T->getAs<swift::ArchetypeType>()) {
|
|
T = AT->getInterfaceType();
|
|
}
|
|
|
|
for (auto *Param: Others) {
|
|
if (T->isEqual(const_cast<swift::GenericTypeParamType*>(Param)))
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
void swift::symbolgraphgen::filterGenericRequirements(
|
|
ArrayRef<Requirement> Requirements,
|
|
const ProtocolDecl *Self,
|
|
SmallVectorImpl<Requirement> &FilteredRequirements,
|
|
SubstitutionMap SubMap,
|
|
ArrayRef<const GenericTypeParamType *> FilteredParams) {
|
|
|
|
for (const auto &Req : Requirements) {
|
|
// FIXME: We're just dropping "Self: AnyObject", etc.
|
|
if (Req.getKind() == RequirementKind::Layout) {
|
|
continue;
|
|
}
|
|
// extension /* protocol */ Q {
|
|
// func foo() {}
|
|
// }
|
|
// ignore Self : Q, obvious
|
|
if (Self &&
|
|
Req.getKind() == RequirementKind::Conformance &&
|
|
Req.getProtocolDecl() == Self) {
|
|
continue;
|
|
}
|
|
|
|
// Ignore requirements that don't involve the filtered set of generic
|
|
// parameters after substitution.
|
|
if (!SubMap.empty()) {
|
|
Type SubFirst = Req.getFirstType().subst(SubMap);
|
|
if (SubFirst->hasError())
|
|
SubFirst = Req.getFirstType();
|
|
Type SubSecond = Req.getSecondType().subst(SubMap);
|
|
if (SubSecond->hasError())
|
|
SubSecond = Req.getSecondType();
|
|
|
|
if (!containsParams(SubFirst, FilteredParams) &&
|
|
!containsParams(SubSecond, FilteredParams))
|
|
continue;
|
|
|
|
// Use the same requirement kind with the substituted types.
|
|
FilteredRequirements.emplace_back(Req.getKind(), SubFirst, SubSecond);
|
|
} else {
|
|
// Use the original requirement.
|
|
FilteredRequirements.push_back(Req);
|
|
}
|
|
}
|
|
}
|
|
void
|
|
swift::symbolgraphgen::filterGenericRequirements(const ExtensionDecl *Extension,
|
|
SmallVectorImpl<Requirement> &FilteredRequirements) {
|
|
auto Sig = Extension->getGenericSignature();
|
|
if (!Sig)
|
|
return;
|
|
|
|
SmallVector<Requirement, 2> Reqs;
|
|
SmallVector<InverseRequirement, 2> InverseReqs;
|
|
Sig->getRequirementsWithInverses(Reqs, InverseReqs);
|
|
// FIXME(noncopyable_generics): Do something with InverseReqs, or just use
|
|
// getRequirements() above and update the tests.
|
|
|
|
for (const auto &Req : Reqs) {
|
|
if (Req.getKind() == RequirementKind::Layout) {
|
|
continue;
|
|
}
|
|
|
|
// extension /* protocol */ Q
|
|
// ignore Self : Q, obvious
|
|
if (auto *Proto = Extension->getExtendedProtocolDecl()) {
|
|
if (Req.getKind() == RequirementKind::Conformance &&
|
|
Req.getFirstType()->isEqual(Extension->getSelfInterfaceType()) &&
|
|
Req.getProtocolDecl() == Proto) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
FilteredRequirements.push_back(Req);
|
|
}
|
|
}
|