mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
IDE: Use GenericSignatures and interface types (mostly)
There was a ton of complicated logic here to work around two problems: - Same-type constraints were not represented properly in RequirementReprs, requiring us to store them in strong form and parse them out when printing type interfaces. - The TypeBase::getAllGenericArgs() method did not do the right thing for members of protocols and protocol extensions, and so instead of simple calls to Type::subst(), we had an elaborate 'ArchetypeTransformer' abstraction repeated in two places. Rewrite this code to use GenericSignatures and GenericFunctionType instead of old-school GenericParamLists and PolymorphicFunctionType. This changes the code completion and AST printer output slightly. A few of the changes are actually fixes for cases where the old code didn't handle substitutions properly. A few others are subjective, for example a generic parameter list of the form <T : Proto> now prints as <T where T : Proto>. We can add heuristics to make the output whatever we want here; the important thing is that now we're using modern abstractions.
This commit is contained in:
@@ -246,34 +246,43 @@ struct SourceTextInfo {
|
||||
}
|
||||
|
||||
static void initDocGenericParams(const Decl *D, DocEntityInfo &Info) {
|
||||
GenericParamList *GenParams = nullptr;
|
||||
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
|
||||
GenParams = NTD->getGenericParams();
|
||||
} else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
|
||||
GenParams = AFD->getGenericParams();
|
||||
} else if (auto *ExtD = dyn_cast<ExtensionDecl>(D)) {
|
||||
GenParams = ExtD->getGenericParams();
|
||||
}
|
||||
|
||||
if (!GenParams)
|
||||
auto *DC = dyn_cast<DeclContext>(D);
|
||||
if (DC == nullptr || !DC->isInnermostContextGeneric())
|
||||
return;
|
||||
|
||||
for (auto *GP : GenParams->getParams()) {
|
||||
if (GP->isImplicit())
|
||||
GenericSignature *GenericSig = DC->getGenericSignatureOfContext();
|
||||
|
||||
if (!GenericSig)
|
||||
return;
|
||||
|
||||
// FIXME: Not right for extensions of nested generic types
|
||||
for (auto *GP : GenericSig->getInnermostGenericParams()) {
|
||||
if (GP->getDecl()->isImplicit())
|
||||
continue;
|
||||
DocGenericParam Param;
|
||||
Param.Name = GP->getNameStr();
|
||||
if (!GP->getInherited().empty()) {
|
||||
llvm::raw_string_ostream OS(Param.Inherits);
|
||||
GP->getInherited()[0].getType().print(OS);
|
||||
}
|
||||
|
||||
Param.Name = GP->getName().str();
|
||||
Info.GenericParams.push_back(Param);
|
||||
}
|
||||
for (auto &Req : GenParams->getRequirements()) {
|
||||
|
||||
ProtocolDecl *proto = nullptr;
|
||||
if (auto *typeDC = DC->getInnermostTypeContext())
|
||||
proto = typeDC->getAsProtocolOrProtocolExtensionContext();
|
||||
|
||||
for (auto &Req : GenericSig->getRequirements()) {
|
||||
if (Req.getKind() == RequirementKind::WitnessMarker)
|
||||
continue;
|
||||
|
||||
// Skip protocol Self requirement.
|
||||
if (proto &&
|
||||
Req.getKind() == RequirementKind::Conformance &&
|
||||
Req.getFirstType()->isEqual(proto->getSelfInterfaceType()) &&
|
||||
Req.getSecondType()->getAnyNominal() == proto)
|
||||
continue;
|
||||
|
||||
std::string ReqStr;
|
||||
PrintOptions Opts;
|
||||
llvm::raw_string_ostream OS(ReqStr);
|
||||
Req.printAsWritten(OS);
|
||||
Req.print(OS, Opts);
|
||||
OS.flush();
|
||||
Info.GenericRequirements.push_back(std::move(ReqStr));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user