Skip to content

[5.1][SourceKit] SourceKit support for opaque result types #24290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/AST/ASTPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ class ASTPrinter {
/// Callers should use callPrintDeclPost().
virtual void printDeclPost(const Decl *D, Optional<BracketOptions> Bracket) {}

/// Called before printing the result type of the declaration. Printer can
/// replace \p TL to customize the input.
virtual void printDeclResultTypePre(ValueDecl *VD, TypeLoc &TL) {}

/// Called before printing a type.
virtual void printTypePre(const TypeLoc &TL) {}
/// Called after printing a type.
Expand Down
24 changes: 20 additions & 4 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ struct PrintOptions {
/// Whether to print *any* accessors on properties.
bool PrintPropertyAccessors = true;

/// Whether to print *any* accessors on subscript.
bool PrintSubscriptAccessors = true;

/// Whether to print the accessors of a property abstractly,
/// i.e. always as:
/// ```
Expand Down Expand Up @@ -260,9 +263,20 @@ struct PrintOptions {
/// Whether to skip keywords with a prefix of underscore such as __consuming.
bool SkipUnderscoredKeywords = false;

/// Whether to print declarations with opaque return types with a stable,
/// parsable internal syntax.
bool PrintStableReferencesToOpaqueReturnTypes = false;
/// How to print opaque return types.
enum class OpaqueReturnTypePrintingMode {
/// 'some P1 & P2'.
WithOpaqueKeyword,
/// 'P1 & P2'.
WithoutOpaqueKeyword,
/// Stable parsable internal syntax.
StableReference,
/// Description suitable for debugging.
Description
};

OpaqueReturnTypePrintingMode OpaqueReturnTypePrinting =
OpaqueReturnTypePrintingMode::WithOpaqueKeyword;

/// Whether to print decl attributes that are only used internally,
/// such as _silgen_name, transparent, etc.
Expand Down Expand Up @@ -521,7 +535,8 @@ struct PrintOptions {
result.PrintInSILBody = true;
result.PreferTypeRepr = false;
result.PrintIfConfig = false;
result.PrintStableReferencesToOpaqueReturnTypes = true;
result.OpaqueReturnTypePrinting =
OpaqueReturnTypePrintingMode::StableReference;
return result;
}

Expand Down Expand Up @@ -559,6 +574,7 @@ struct PrintOptions {
PO.ExplodeEnumCaseDecls = true;
PO.ShouldQualifyNestedDeclarations = QualifyNestedDeclarations::TypesOnly;
PO.PrintParameterSpecifiers = true;
PO.SkipImplicit = true;
return PO;
}
};
Expand Down
1 change: 1 addition & 0 deletions include/swift/IDE/CodeCompletion.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ enum class CompletionKind {
SuperExprDot,
KeyPathExprObjC,
KeyPathExprSwift,
TypeDeclResultBeginning,
TypeSimpleBeginning,
TypeIdentifierWithDot,
TypeIdentifierWithoutDot,
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Parse/CodeCompletionCallbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ class CodeCompletionCallbacks {
/// #keyPath argument have been parsed yet.
virtual void completeExprKeyPath(KeyPathExpr *KPE, SourceLoc DotLoc) {};

/// Complete the beginning of the type of result of func/var/let/subscript.
virtual void completeTypeDeclResultBeginning() {};

/// Complete the beginning of type-simple -- no tokens provided
/// by user.
virtual void completeTypeSimpleBeginning() {};
Expand Down
2 changes: 2 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,8 @@ class Parser {
ParserResult<PrecedenceGroupDecl>
parseDeclPrecedenceGroup(ParseDeclOptions flags, DeclAttributes &attributes);

ParserResult<TypeRepr> parseDeclResultType(Diag<> MessageID);

//===--------------------------------------------------------------------===//
// Type Parsing

Expand Down
63 changes: 53 additions & 10 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ PrintOptions PrintOptions::printParseableInterfaceFile() {
result.FunctionDefinitions = true;
result.CollapseSingleGetterProperty = false;
result.VarInitializers = true;
result.PrintStableReferencesToOpaqueReturnTypes = true;
result.OpaqueReturnTypePrinting =
OpaqueReturnTypePrintingMode::StableReference;

// We should print __consuming, __owned, etc for the module interface file.
result.SkipUnderscoredKeywords = false;
Expand Down Expand Up @@ -1712,6 +1713,8 @@ void PrintAST::printMutatingModifiersIfNeeded(const AccessorDecl *accessor) {
void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
if (isa<VarDecl>(ASD) && !Options.PrintPropertyAccessors)
return;
if (isa<SubscriptDecl>(ASD) && !Options.PrintSubscriptAccessors)
return;

auto impl = ASD->getImplInfo();

Expand Down Expand Up @@ -2532,6 +2535,7 @@ void PrintAST::visitVarDecl(VarDecl *decl) {
if (!tyLoc.getTypeRepr())
tyLoc = TypeLoc::withoutLoc(decl->getInterfaceType());

Printer.printDeclResultTypePre(decl, tyLoc);
if (decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
printTypeLocForImplicitlyUnwrappedOptional(tyLoc);
else
Expand Down Expand Up @@ -2803,6 +2807,8 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
ResultTyLoc = TypeLoc::withoutLoc(ResultTy);
}
Printer << " -> ";

Printer.printDeclResultTypePre(decl, ResultTyLoc);
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
if (decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
printTypeLocForImplicitlyUnwrappedOptional(ResultTyLoc);
Expand Down Expand Up @@ -2930,8 +2936,9 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) {
});
Printer << " -> ";

Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
TypeLoc elementTy = decl->getElementTypeLoc();
Printer.printDeclResultTypePre(decl, elementTy);
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
if (!elementTy.getTypeRepr())
elementTy = TypeLoc::withoutLoc(decl->getElementInterfaceType());
if (decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
Expand Down Expand Up @@ -3402,7 +3409,27 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
return;
}

if (T->hasSimpleTypeRepr()) {
bool isSimple = T->hasSimpleTypeRepr();
if (isSimple && T->is<OpaqueTypeArchetypeType>()) {
auto opaqueTy = T->castTo<OpaqueTypeArchetypeType>();
auto opaqueDecl = opaqueTy->getDecl();
if (!opaqueDecl->hasName()) {
switch (Options.OpaqueReturnTypePrinting) {
case PrintOptions::OpaqueReturnTypePrintingMode::StableReference:
case PrintOptions::OpaqueReturnTypePrintingMode::Description:
isSimple = true;
break;
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
isSimple = false;
break;
case PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword: {
isSimple = opaqueTy->getConformsTo().size() < 2;
}
}
}
}

if (isSimple) {
visit(T);
} else {
Printer << "(";
Expand Down Expand Up @@ -4165,7 +4192,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}

void visitNestedArchetypeType(NestedArchetypeType *T) {
visit(T->getParent());
printWithParensIfNotSimple(T->getParent());
Printer << ".";
printArchetypeCommon(T);
}
Expand All @@ -4175,16 +4202,28 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}

void visitOpaqueTypeArchetypeType(OpaqueTypeArchetypeType *T) {
// Print the type by referencing the opaque decl's synthetic name, if we
// were asked to.
OpaqueTypeDecl *decl = T->getDecl();

if (Options.PrintStableReferencesToOpaqueReturnTypes) {
switch (Options.OpaqueReturnTypePrinting) {
case PrintOptions::OpaqueReturnTypePrintingMode::WithOpaqueKeyword:
Printer << "some ";
LLVM_FALLTHROUGH;
case PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword: {
SmallVector<Type, 2> types;
for (auto proto : T->getConformsTo())
types.push_back(proto->TypeDecl::getDeclaredInterfaceType());

// Create and visit temporary ProtocolCompositionType.
auto composition =
ProtocolCompositionType::get(T->getASTContext(), types, false);
visit(composition);
return;
}
case PrintOptions::OpaqueReturnTypePrintingMode::StableReference: {
// Print the source of the opaque return type as a mangled name.
// We'll use type reconstruction while parsing the attribute to
// turn this back into a reference to the naming decl for the opaque
// type.
Printer << "@_opaqueReturnTypeOf(";
OpaqueTypeDecl *decl = T->getDecl();

Printer.printEscapedStringLiteral(
decl->getOpaqueReturnTypeIdentifier().str());
Expand All @@ -4195,7 +4234,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {

Printer << u8") \U0001F9B8";
printGenericArgs(T->getSubstitutions().getReplacementTypes());
} else {
return;
}
case PrintOptions::OpaqueReturnTypePrintingMode::Description: {
// TODO(opaque): present opaque types with user-facing syntax. we should
// probably print this as `some P` and record the fact that we printed that
// so that diagnostics can add followup notes.
Expand All @@ -4209,6 +4250,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
[&] { Printer << ", "; });
Printer << '>';
}
return;
}
}
}

Expand Down
Loading