Skip to content

[ASTPrinter] Intorduce 'IntroducerKeyword' name kind #38521

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 1 commit into from
Jul 30, 2021
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
13 changes: 13 additions & 0 deletions include/swift/AST/ASTPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ enum class PrintNameContext {
Normal,
/// Keyword context, where no keywords are escaped.
Keyword,
/// Keyword for introducing a declarations e.g. 'func', 'struct'.
IntroducerKeyword,
/// Type member context, e.g. properties or enum cases.
TypeMember,
/// Generic parameter context, where 'Self' is not escaped.
Expand Down Expand Up @@ -217,6 +219,17 @@ class ASTPrinter {
*this << Suffix;
}

void printIntroducerKeyword(StringRef name,
const PrintOptions &Opts,
StringRef Suffix = "") {
if (Opts.SkipIntroducerKeywords)
return;
callPrintNamePre(PrintNameContext::IntroducerKeyword);
*this << name;
printNamePost(PrintNameContext::IntroducerKeyword);
*this << Suffix;
}

void printAttrName(StringRef name, bool needAt = false) {
callPrintNamePre(PrintNameContext::Attribute);
if (needAt)
Expand Down
4 changes: 4 additions & 0 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ struct PrintOptions {
/// Whether to print 'static' or 'class' on static decls.
bool PrintStaticKeyword = true;

/// Whether to print 'mutating', 'nonmutating', or '__consuming' keyword on
/// specified decls.
bool PrintSelfAccessKindKeyword = true;

/// Whether to print 'override' keyword on overridden decls.
bool PrintOverrideKeyword = true;

Expand Down
125 changes: 56 additions & 69 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ static bool escapeKeywordInContext(StringRef keyword, PrintNameContext context){
case PrintNameContext::Attribute:
return isKeyword;
case PrintNameContext::Keyword:
case PrintNameContext::IntroducerKeyword:
return false;

case PrintNameContext::ClassDynamicSelf:
Expand Down Expand Up @@ -877,7 +878,7 @@ class PrintAST : public ASTVisitor<PrintAST> {
bool shouldPrintPattern(const Pattern *P);
void printPatternType(const Pattern *P);
void printAccessors(const AbstractStorageDecl *ASD);
void printMutabilityModifiersIfNeeded(const FuncDecl *FD);
void printSelfAccessKindModifiersIfNeeded(const FuncDecl *FD);
void printMembersOfDecl(Decl * NTD, bool needComma = false,
bool openBracket = true, bool closeBracket = true);
void printMembers(ArrayRef<Decl *> members, bool needComma = false,
Expand Down Expand Up @@ -1143,6 +1144,7 @@ void PrintAST::printAttributes(const Decl *D) {
if (isa<FuncDecl>(D)) {
Options.ExcludeAttrList.push_back(DAK_Mutating);
Options.ExcludeAttrList.push_back(DAK_NonMutating);
Options.ExcludeAttrList.push_back(DAK_Consuming);
}

D->getAttrs().print(Printer, Options, D);
Expand Down Expand Up @@ -1291,10 +1293,9 @@ void PrintAST::printPattern(const Pattern *pattern) {
break;

case PatternKind::Binding:
if (!Options.SkipIntroducerKeywords)
Printer << (cast<BindingPattern>(pattern)->isLet() ? tok::kw_let
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move checking SkipIntroducerKeywords into printIntroducerKeyword? That way you cannot forget, and also we could give the method the same signature as printKeyword, which also takes options.

: tok::kw_var)
<< " ";
Printer.printIntroducerKeyword(
cast<BindingPattern>(pattern)->isLet() ? "let" : "var",
Options, " ");
printPattern(cast<BindingPattern>(pattern)->getSubPattern());
}
}
Expand Down Expand Up @@ -1901,16 +1902,27 @@ void PrintAST::printBodyIfNecessary(const AbstractFunctionDecl *decl) {
printBraceStmt(decl->getBody(), /*newlineIfEmpty*/!isa<AccessorDecl>(decl));
}

void PrintAST::printMutabilityModifiersIfNeeded(const FuncDecl *FD) {
void PrintAST::printSelfAccessKindModifiersIfNeeded(const FuncDecl *FD) {
if (!Options.PrintSelfAccessKindKeyword)
return;

const auto *AD = dyn_cast<AccessorDecl>(FD);

if (FD->isMutating()) {
if (AD == nullptr || AD->isAssumedNonMutating())
if (!Options.excludeAttrKind(DAK_Mutating))
Printer.printKeyword("mutating", Options, " ");
} else if (AD && AD->isExplicitNonMutating() &&
!Options.excludeAttrKind(DAK_Mutating)) {
Printer.printKeyword("nonmutating", Options, " ");
switch (FD->getSelfAccessKind()) {
case SelfAccessKind::Mutating:
if ((!AD || AD->isAssumedNonMutating()) &&
!Options.excludeAttrKind(DAK_Mutating))
Printer.printKeyword("mutating", Options, " ");
break;
case SelfAccessKind::NonMutating:
if (AD && AD->isExplicitNonMutating() &&
!Options.excludeAttrKind(DAK_NonMutating))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was checking DAK_Mutating before, which seems like a latent bug, but I don't think it's observable since the only place I found that adds DAK_Mutating but not DAK_NonMutating is protocol conformance diagnostics for non-accessors, but this code only prints nonmutating on accessors. Oh well, at least it's correct now 🤷

Printer.printKeyword("nonmutating", Options, " ");
break;
case SelfAccessKind::Consuming:
if (!Options.excludeAttrKind(DAK_Consuming))
Printer.printKeyword("__consuming", Options, " ");
break;
}
}

Expand Down Expand Up @@ -2037,7 +2049,7 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
return true;
if (!PrintAccessorBody) {
Printer << " ";
printMutabilityModifiersIfNeeded(Accessor);
printSelfAccessKindModifiersIfNeeded(Accessor);

Printer.printKeyword(getAccessorLabel(Accessor->getAccessorKind()), Options);

Expand Down Expand Up @@ -2271,7 +2283,7 @@ static void getModuleEntities(ImportDecl *Import,

void PrintAST::visitImportDecl(ImportDecl *decl) {
printAttributes(decl);
Printer << tok::kw_import << " ";
Printer.printIntroducerKeyword("import", Options, " ");

switch (decl->getImportKind()) {
case ImportKind::Module:
Expand Down Expand Up @@ -2391,7 +2403,7 @@ void PrintAST::printSynthesizedExtension(Type ExtendedType,
if (Options.BracketOptions.shouldOpenExtension(ExtDecl)) {
printDocumentationComment(ExtDecl);
printAttributes(ExtDecl);
Printer << tok::kw_extension << " ";
Printer.printIntroducerKeyword("extension", Options, " ");

printExtendedTypeName(TypeLoc::withoutLoc(ExtendedType));
printInherited(ExtDecl);
Expand Down Expand Up @@ -2429,7 +2441,7 @@ void PrintAST::printExtension(ExtensionDecl *decl) {
if (Options.BracketOptions.shouldOpenExtension(decl)) {
printDocumentationComment(decl);
printAttributes(decl);
Printer << "extension ";
Printer.printIntroducerKeyword("extension", Options, " ");
recordDeclLoc(decl, [&]{
// We cannot extend sugared types.
Type extendedType = decl->getExtendedType();
Expand Down Expand Up @@ -2961,8 +2973,7 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) {
printDocumentationComment(decl);
printAttributes(decl);
printAccess(decl);
if (!Options.SkipIntroducerKeywords)
Printer << tok::kw_typealias << " ";
Printer.printIntroducerKeyword("typealias", Options, " ");
printContextIfNeeded(decl);
recordDeclLoc(decl,
[&]{
Expand Down Expand Up @@ -3005,8 +3016,7 @@ void PrintAST::visitGenericTypeParamDecl(GenericTypeParamDecl *decl) {
void PrintAST::visitAssociatedTypeDecl(AssociatedTypeDecl *decl) {
printDocumentationComment(decl);
printAttributes(decl);
if (!Options.SkipIntroducerKeywords)
Printer << tok::kw_associatedtype << " ";
Printer.printIntroducerKeyword("associatedtype", Options, " ");
recordDeclLoc(decl,
[&]{
Printer.printName(decl->getName(), PrintNameContext::TypeMember);
Expand Down Expand Up @@ -3035,8 +3045,7 @@ void PrintAST::visitEnumDecl(EnumDecl *decl) {
printSourceRange(CharSourceRange(Ctx.SourceMgr, decl->getStartLoc(),
decl->getBraces().Start.getAdvancedLoc(-1)), Ctx);
} else {
if (!Options.SkipIntroducerKeywords)
Printer << tok::kw_enum << " ";
Printer.printIntroducerKeyword("enum", Options, " ");
printContextIfNeeded(decl);
recordDeclLoc(decl,
[&]{
Expand All @@ -3063,8 +3072,7 @@ void PrintAST::visitStructDecl(StructDecl *decl) {
printSourceRange(CharSourceRange(Ctx.SourceMgr, decl->getStartLoc(),
decl->getBraces().Start.getAdvancedLoc(-1)), Ctx);
} else {
if (!Options.SkipIntroducerKeywords)
Printer << tok::kw_struct << " ";
Printer.printIntroducerKeyword("struct", Options, " ");
printContextIfNeeded(decl);
recordDeclLoc(decl,
[&]{
Expand All @@ -3091,13 +3099,8 @@ void PrintAST::visitClassDecl(ClassDecl *decl) {
printSourceRange(CharSourceRange(Ctx.SourceMgr, decl->getStartLoc(),
decl->getBraces().Start.getAdvancedLoc(-1)), Ctx);
} else {
if (!Options.SkipIntroducerKeywords) {
if (decl->isExplicitActor()) {
Printer.printKeyword("actor", Options, " ");
} else {
Printer << tok::kw_class << " ";
}
}
Printer.printIntroducerKeyword(
decl->isExplicitActor() ? "actor" : "class", Options, " ");
printContextIfNeeded(decl);
recordDeclLoc(decl,
[&]{
Expand Down Expand Up @@ -3126,8 +3129,7 @@ void PrintAST::visitProtocolDecl(ProtocolDecl *decl) {
printSourceRange(CharSourceRange(Ctx.SourceMgr, decl->getStartLoc(),
decl->getBraces().Start.getAdvancedLoc(-1)), Ctx);
} else {
if (!Options.SkipIntroducerKeywords)
Printer << tok::kw_protocol << " ";
Printer.printIntroducerKeyword("protocol", Options, " ");
printContextIfNeeded(decl);
recordDeclLoc(decl,
[&]{
Expand Down Expand Up @@ -3207,20 +3209,12 @@ void PrintAST::visitVarDecl(VarDecl *decl) {
Printer << "@_hasStorage ";
printAttributes(decl);
printAccess(decl);
if (!Options.SkipIntroducerKeywords) {
if (decl->isStatic() && Options.PrintStaticKeyword)
printStaticKeyword(decl->getCorrectStaticSpelling());
if (decl->getKind() == DeclKind::Var
|| Options.PrintParameterSpecifiers) {
// Map all non-let specifiers to 'var'. This is not correct, but
// SourceKit relies on this for info about parameter decls.
if (decl->isLet())
Printer << tok::kw_let;
else
Printer << tok::kw_var;

Printer << " ";
}
if (decl->isStatic() && Options.PrintStaticKeyword)
printStaticKeyword(decl->getCorrectStaticSpelling());
if (decl->getKind() == DeclKind::Var || Options.PrintParameterSpecifiers) {
// Map all non-let specifiers to 'var'. This is not correct, but
// SourceKit relies on this for info about parameter decls.
Printer.printIntroducerKeyword(decl->isLet() ? "let" : "var", Options, " ");
}
printContextIfNeeded(decl);
recordDeclLoc(decl,
Expand Down Expand Up @@ -3431,10 +3425,8 @@ void PrintAST::visitAccessorDecl(AccessorDecl *decl) {
printDocumentationComment(decl);
printAttributes(decl);
// Explicitly print 'mutating' and 'nonmutating' if needed.
printMutabilityModifiersIfNeeded(decl);
if (decl->isConsuming()) {
Printer.printKeyword("__consuming", Options, " ");
}
printSelfAccessKindModifiersIfNeeded(decl);

switch (auto kind = decl->getAccessorKind()) {
case AccessorKind::Get:
case AccessorKind::Address:
Expand Down Expand Up @@ -3492,16 +3484,12 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
SourceRange(StartLoc, EndLoc));
printSourceRange(Range, Ctx);
} else {
if (!Options.SkipIntroducerKeywords) {
if (decl->isStatic() && Options.PrintStaticKeyword)
printStaticKeyword(decl->getCorrectStaticSpelling());
if (decl->isStatic() && Options.PrintStaticKeyword)
printStaticKeyword(decl->getCorrectStaticSpelling());

printSelfAccessKindModifiersIfNeeded(decl);
Printer.printIntroducerKeyword("func", Options, " ");

printMutabilityModifiersIfNeeded(decl);
if (decl->isConsuming() && !decl->getAttrs().hasAttribute<ConsumingAttr>()) {
Printer.printKeyword("__consuming", Options, " ");
}
Printer << tok::kw_func << " ";
}
printContextIfNeeded(decl);
recordDeclLoc(decl,
[&]{ // Name
Expand Down Expand Up @@ -3659,7 +3647,7 @@ void PrintAST::visitEnumCaseDecl(EnumCaseDecl *decl) {
printDocumentationComment(elems[0]);
printAttributes(elems[0]);
}
Printer << tok::kw_case << " ";
Printer.printIntroducerKeyword("case", Options, " ");

llvm::interleave(elems.begin(), elems.end(),
[&](EnumElementDecl *elt) {
Expand All @@ -3673,16 +3661,15 @@ void PrintAST::visitEnumElementDecl(EnumElementDecl *decl) {
// In cases where there is no parent EnumCaseDecl (such as imported or
// deserialized elements), print the element independently.
printAttributes(decl);
Printer << tok::kw_case << " ";
Printer.printIntroducerKeyword("case", Options, " ");
printEnumElement(decl);
}

void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) {
printDocumentationComment(decl);
printAttributes(decl);
printAccess(decl);
if (!Options.SkipIntroducerKeywords && decl->isStatic() &&
Options.PrintStaticKeyword)
if (decl->isStatic() && Options.PrintStaticKeyword)
printStaticKeyword(decl->getCorrectStaticSpelling());
printContextIfNeeded(decl);
recordDeclLoc(decl, [&]{
Expand Down Expand Up @@ -3782,7 +3769,7 @@ void PrintAST::visitDestructorDecl(DestructorDecl *decl) {

void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
Printer.printKeyword("infix", Options, " ");
Printer << tok::kw_operator << " ";
Printer.printIntroducerKeyword("operator", Options, " ");
recordDeclLoc(decl,
[&]{
Printer.printName(decl->getName());
Expand All @@ -3801,7 +3788,7 @@ void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
}

void PrintAST::visitPrecedenceGroupDecl(PrecedenceGroupDecl *decl) {
Printer << tok::kw_precedencegroup << " ";
Printer.printIntroducerKeyword("precedencegroup", Options, " ");
recordDeclLoc(decl,
[&]{
Printer.printName(decl->getName());
Expand Down Expand Up @@ -3861,7 +3848,7 @@ void PrintAST::visitPrecedenceGroupDecl(PrecedenceGroupDecl *decl) {

void PrintAST::visitPrefixOperatorDecl(PrefixOperatorDecl *decl) {
Printer.printKeyword("prefix", Options, " ");
Printer << tok::kw_operator << " ";
Printer.printIntroducerKeyword("operator", Options, " ");
recordDeclLoc(decl,
[&]{
Printer.printName(decl->getName());
Expand All @@ -3879,7 +3866,7 @@ void PrintAST::visitPrefixOperatorDecl(PrefixOperatorDecl *decl) {

void PrintAST::visitPostfixOperatorDecl(PostfixOperatorDecl *decl) {
Printer.printKeyword("postfix", Options, " ");
Printer << tok::kw_operator << " ";
Printer.printIntroducerKeyword("operator", Options, " ");
recordDeclLoc(decl,
[&]{
Printer.printName(decl->getName());
Expand Down
1 change: 1 addition & 0 deletions lib/SymbolGraphGen/DeclarationFragmentPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ void
DeclarationFragmentPrinter::printNamePre(PrintNameContext Context) {
switch (Context) {
case PrintNameContext::Keyword:
case PrintNameContext::IntroducerKeyword:
openFragment(FragmentKind::Keyword);
break;
case PrintNameContext::GenericParameter:
Expand Down
32 changes: 32 additions & 0 deletions test/SourceKit/CursorInfo/cursor_relatedname.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
struct S {
mutating func foo(x: Int) {}
__consuming func foo(x: String) {}
}

// RUN: %sourcekitd-test -req=cursor -pos=2:19 %s -- %s -module-name MyMod | %FileCheck -check-prefix=CHECK1 %s

// CHECK1: source.lang.swift.decl.function.method.instance (2:19-2:30)
// CHECK1: foo(x:)
// CHECK1: s:5MyMod1SV3foo1xySi_tF
// CHECK1: source.lang.swift
// CHECK1: (inout S) -> (Int) -> ()
// CHECK1: $s1xySi_tcD
// CHECK1: <Declaration>mutating func foo(x: <Type usr="s:Si">Int</Type>)</Declaration>
// CHECK1: <decl.function.method.instance><syntaxtype.keyword>mutating</syntaxtype.keyword> <syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>foo</decl.name>(<decl.var.parameter><decl.var.parameter.argument_label>x</decl.var.parameter.argument_label>: <decl.var.parameter.type><ref.struct usr="s:Si">Int</ref.struct></decl.var.parameter.type></decl.var.parameter>)</decl.function.method.instance>
// CHECK1: RELATED BEGIN
// CHECK1: <RelatedName usr="s:5MyMod1SV3foo1xySS_tF">foo(x: String)</RelatedName>
// CHECK1: RELATED END

// RUN: %sourcekitd-test -req=cursor -pos=3:22 %s -- %s -module-name MyMod | %FileCheck -check-prefix=CHECK2 %s

// CHECK2: source.lang.swift.decl.function.method.instance (3:22-3:36)
// CHECK2: foo(x:)
// CHECK2: s:5MyMod1SV3foo1xySS_tF
// CHECK2: source.lang.swift
// CHECK2: (__owned S) -> (String) -> ()
// CHECK2: $s1xySS_tcD
// CHECK2: <Declaration>func foo(x: <Type usr="s:SS">String</Type>)</Declaration>
// CHECK2: <decl.function.method.instance><syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>foo</decl.name>(<decl.var.parameter><decl.var.parameter.argument_label>x</decl.var.parameter.argument_label>: <decl.var.parameter.type><ref.struct usr="s:SS">String</ref.struct></decl.var.parameter.type></decl.var.parameter>)</decl.function.method.instance>
// CHECK2: RELATED BEGIN
// CHECK2: <RelatedName usr="s:5MyMod1SV3foo1xySi_tF">foo(x: Int)</RelatedName>
// CHECK2: RELATED END
Loading