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:
Slava Pestov
2016-09-15 19:41:29 -07:00
parent 0b8beea69b
commit cfe9e6a3de
39 changed files with 1698 additions and 2226 deletions

View File

@@ -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));
}