Skip to content

Commit 6af6048

Browse files
committed
AST printing: take more care to only escape 'Self' when needed.
Cleans up AST printing somewhat as well as providing slightly better type-to-declaration mappings for annotated AST printing and indexing. Swift SVN r32420
1 parent 9809dbc commit 6af6048

15 files changed

+91
-22
lines changed

include/swift/AST/ASTPrinter.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ namespace swift {
2323
class ModuleEntity;
2424
class TypeDecl;
2525

26+
/// Describes the context in which a name is being printed, which
27+
/// affects the keywords that need to be escaped.
28+
enum class PrintNameContext {
29+
// Normal context
30+
Normal,
31+
// Generic parameter context, where 'Self' is not escaped.
32+
GenericParameter,
33+
};
34+
2635
/// An abstract class used to print an AST.
2736
class ASTPrinter {
2837
unsigned CurrentIndentation = 0;
@@ -49,9 +58,8 @@ class ASTPrinter {
4958
virtual void printDeclPost(const Decl *D) {}
5059

5160
/// Called when printing the referenced name of a type declaration.
52-
virtual void printTypeRef(const TypeDecl *TD, Identifier Name) {
53-
printName(Name);
54-
}
61+
virtual void printTypeRef(const TypeDecl *TD, Identifier Name);
62+
5563
/// Called when printing the referenced name of a module.
5664
virtual void printModuleRef(ModuleEntity Mod, Identifier Name);
5765

@@ -65,7 +73,8 @@ class ASTPrinter {
6573
ASTPrinter &operator<<(unsigned long long N);
6674
ASTPrinter &operator<<(UUID UU);
6775

68-
void printName(Identifier Name);
76+
void printName(Identifier Name,
77+
PrintNameContext Context = PrintNameContext::Normal);
6978

7079
void setIndent(unsigned NumSpaces) {
7180
CurrentIndentation = NumSpaces;

include/swift/AST/Decl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2534,6 +2534,10 @@ class GenericTypeParamDecl : public AbstractTypeParamDecl {
25342534
SourceLoc getStartLoc() const { return getNameLoc(); }
25352535
SourceRange getSourceRange() const;
25362536

2537+
/// Determine whether this is the implicit 'Self' type parameter of
2538+
/// a protocol.
2539+
bool isProtocolSelf() const;
2540+
25372541
static bool classof(const Decl *D) {
25382542
return D->getKind() == DeclKind::GenericTypeParam;
25392543
}

lib/AST/ASTPrinter.cpp

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ void ASTPrinter::printTextImpl(StringRef Text) {
105105
printText(Text);
106106
}
107107

108+
void ASTPrinter::printTypeRef(const TypeDecl *TD, Identifier Name) {
109+
PrintNameContext Context = PrintNameContext::Normal;
110+
if (auto GP = dyn_cast<GenericTypeParamDecl>(TD)) {
111+
if (GP->isProtocolSelf())
112+
Context = PrintNameContext::GenericParameter;
113+
}
114+
115+
printName(Name, Context);
116+
}
117+
108118
void ASTPrinter::printModuleRef(ModuleEntity Mod, Identifier Name) {
109119
printName(Name);
110120
}
@@ -124,7 +134,18 @@ ASTPrinter &ASTPrinter::operator<<(UUID UU) {
124134
return *this;
125135
}
126136

127-
void ASTPrinter::printName(Identifier Name) {
137+
/// Determine whether to escape the fiven keyword in the given context.
138+
static bool escapeKeywordInContext(StringRef keyword, PrintNameContext context){
139+
switch (context) {
140+
case PrintNameContext::Normal:
141+
return true;
142+
143+
case PrintNameContext::GenericParameter:
144+
return keyword != "Self";
145+
}
146+
}
147+
148+
void ASTPrinter::printName(Identifier Name, PrintNameContext Context) {
128149
if (Name.empty()) {
129150
*this << "_";
130151
return;
@@ -134,6 +155,10 @@ void ASTPrinter::printName(Identifier Name) {
134155
.Case(#KW, true)
135156
#include "swift/Parse/Tokens.def"
136157
.Default(false);
158+
159+
if (IsKeyword)
160+
IsKeyword = escapeKeywordInContext(Name.str(), Context);
161+
137162
if (IsKeyword)
138163
*this << "`";
139164
*this << Name.str();
@@ -2910,7 +2935,15 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
29102935
visit(parent);
29112936
Printer << ".";
29122937
}
2913-
Printer << T->getName().str();
2938+
2939+
if (T->getName().empty())
2940+
Printer << "<anonymous>";
2941+
else {
2942+
PrintNameContext context = PrintNameContext::Normal;
2943+
if (T->getSelfProtocol())
2944+
context = PrintNameContext::GenericParameter;
2945+
Printer.printName(T->getName(), context);
2946+
}
29142947
}
29152948
}
29162949

@@ -2938,8 +2971,13 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
29382971
auto Name = T->getName();
29392972
if (Name.empty())
29402973
Printer << "<anonymous>";
2941-
else
2942-
Printer.printName(Name);
2974+
else {
2975+
PrintNameContext context = PrintNameContext::Normal;
2976+
if (T->getDecl() && T->getDecl()->isProtocolSelf())
2977+
context = PrintNameContext::GenericParameter;
2978+
2979+
Printer.printName(Name, context);
2980+
}
29432981
}
29442982

29452983
void visitAssociatedTypeType(AssociatedTypeType *T) {

lib/AST/Decl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,6 +2049,14 @@ SourceRange GenericTypeParamDecl::getSourceRange() const {
20492049
return SourceRange(getNameLoc(), endLoc);
20502050
}
20512051

2052+
bool GenericTypeParamDecl::isProtocolSelf() const {
2053+
if (!isImplicit()) return false;
2054+
auto dc = getDeclContext();
2055+
if (!dc->isProtocolOrProtocolExtensionContext()) return false;
2056+
return dc->getProtocolSelf() == this;
2057+
}
2058+
2059+
20522060
AssociatedTypeDecl::AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc,
20532061
Identifier name, SourceLoc nameLoc,
20542062
TypeLoc defaultDefinition)

lib/AST/Type.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,16 @@ TypeDecl *TypeBase::getDirectlyReferencedTypeDecl() const {
931931
if (auto depMem = dyn_cast<DependentMemberType>(this))
932932
return depMem->getAssocType();
933933

934+
if (auto archetype = dyn_cast<ArchetypeType>(this)) {
935+
if (auto proto = archetype->getSelfProtocol())
936+
return proto->getProtocolSelf();
937+
938+
if (auto assoc = archetype->getAssocType())
939+
return assoc;
940+
941+
return nullptr;
942+
}
943+
934944
return nullptr;
935945
}
936946

lib/AST/TypeRepr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,10 @@ void ComponentIdentTypeRepr::printImpl(ASTPrinter &Printer,
314314
else
315315
Printer.printTypeRef(TD, getIdentifier());
316316
} else {
317-
Printer << getIdentifier().str();
317+
Printer.printName(getIdentifier());
318318
}
319319
} else {
320-
Printer << getIdentifier().str();
320+
Printer.printName(getIdentifier());
321321
}
322322
if (auto GenIdT = dyn_cast<GenericIdentTypeRepr>(this))
323323
printGenericArgs(Printer, Opts, GenIdT->getGenericArgs());

test/Generics/associated_types_inherit.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class D : C {
99

1010
class E { }
1111

12-
protocol P { // expected-note{{requirement specified as '`Self`.Assoc' : 'C' [with Self = X2]}}
12+
protocol P { // expected-note{{requirement specified as 'Self.Assoc' : 'C' [with Self = X2]}}
1313
typealias Assoc : C
1414
func getAssoc() -> Assoc
1515
}

test/IDE/annotation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class SubCls : MyCls, Prot {
8181
var protocolProperty2 = 0
8282
}
8383

84-
// CHECK: func <Func>genFn</Func><<GenericTypeParam>T</GenericTypeParam> : <Protocol@64:10>Prot</Protocol> where T.Blarg : Prot2>(<Param>p</Param> : T) -> <iStruct@>Int</iStruct> {}{{$}}
84+
// CHECK: func <Func>genFn</Func><<GenericTypeParam>T</GenericTypeParam> : <Protocol@64:10>Prot</Protocol> where T.<AssociatedType@65:13>Blarg</AssociatedType> : Prot2>(<Param>p</Param> : T) -> <iStruct@>Int</iStruct> {}{{$}}
8585
func genFn<T : Prot where T.Blarg : Prot2>(p : T) -> Int {}
8686

8787
func test(x: Int) {

test/IDE/complete_type.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ typealias FooTypealias = Int
435435
//===---
436436

437437
// TYPE_IN_PROTOCOL: Begin completions
438-
// TYPE_IN_PROTOCOL-DAG: Decl[GenericTypeParam]/CurrNominal: Self[#`Self`#]{{; name=.+$}}
438+
// TYPE_IN_PROTOCOL-DAG: Decl[GenericTypeParam]/CurrNominal: Self[#Self#]{{; name=.+$}}
439439
// TYPE_IN_PROTOCOL: End completions
440440

441441
protocol TestSelf1 {

test/IDE/complete_value_expr.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,7 +1699,7 @@ func testUnusableProtExt(x: PWithT) {
16991699
x.#^PROTOCOL_EXT_UNUSABLE_EXISTENTIAL^#
17001700
}
17011701
// PROTOCOL_EXT_UNUSABLE_EXISTENTIAL: Begin completions
1702-
// PROTOCOL_EXT_UNUSABLE_EXISTENTIAL: Decl[InstanceMethod]/CurrNominal: foo({#(x): `Self`.T#})[#`Self`.T#]{{; name=.+}}
1702+
// PROTOCOL_EXT_UNUSABLE_EXISTENTIAL: Decl[InstanceMethod]/CurrNominal: foo({#(x): Self.T#})[#Self.T#]{{; name=.+}}
17031703
// PROTOCOL_EXT_UNUSABLE_EXISTENTIAL: Decl[InstanceMethod]/CurrNominal: bar({#(x): T#})[#T#]{{; name=.+}}
17041704
// PROTOCOL_EXT_UNUSABLE_EXISTENTIAL: End completions
17051705
@@ -1733,8 +1733,8 @@ func testDeDuped(x: dedupS) {
17331733
func testDeDuped2(x: dedupP) {
17341734
x#^PROTOCOL_EXT_DEDUP_2^#
17351735
// PROTOCOL_EXT_DEDUP_2: Begin completions, 4 items
1736-
// PROTOCOL_EXT_DEDUP_2: Decl[InstanceMethod]/CurrNominal: .foo()[#`Self`.T#]; name=foo()
1737-
// PROTOCOL_EXT_DEDUP_2: Decl[InstanceVar]/CurrNominal: .bar[#`Self`.T#]; name=bar
1736+
// PROTOCOL_EXT_DEDUP_2: Decl[InstanceMethod]/CurrNominal: .foo()[#Self.T#]; name=foo()
1737+
// PROTOCOL_EXT_DEDUP_2: Decl[InstanceVar]/CurrNominal: .bar[#Self.T#]; name=bar
17381738
// PROTOCOL_EXT_DEDUP_2: Decl[Subscript]/CurrNominal: [{#Self.T#}][#Self.T#]; name=[Self.T]
17391739
// FIXME: duplicate subscript on protocol type rdar://problem/22086900
17401740
// PROTOCOL_EXT_DEDUP_2: Decl[Subscript]/CurrNominal: [{#Self.T#}][#Self.T#]; name=[Self.T]

test/IDE/print_ast_tc_decls.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ struct d0200_EscapedIdentifiers {
626626

627627
func `func`<`let`: `protocol`, `where` where `where` : `protocol`>(
628628
`class`: Int, `struct`: `protocol`, `foo`: `let`, `bar`: `where`) {}
629-
// PASS_COMMON-NEXT: {{^}} func `func`<`let` : `protocol`, `where` where where : `protocol`>(`class`: Int, `struct`: `protocol`, foo: let, bar: where){{$}}
629+
// PASS_COMMON-NEXT: {{^}} func `func`<`let` : `protocol`, `where` where `where` : `protocol`>(`class`: Int, `struct`: `protocol`, foo: `let`, bar: `where`){{$}}
630630

631631
var `var`: `struct` = `struct`()
632632
// PASS_COMMON-NEXT: {{^}} var `var`: {{(d0200_EscapedIdentifiers.)?}}`struct`{{$}}

test/Sema/circular_decl_checking.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ var TopLevelVar: TopLevelVar? { return nil } // expected-error 2 {{use of undecl
4444

4545

4646
protocol AProtocol {
47-
typealias e : e // expected-error {{inheritance from non-protocol, non-class type '`Self`.e'}}
47+
typealias e : e // expected-error {{inheritance from non-protocol, non-class type 'Self.e'}}
4848
}
4949

5050

test/decl/ext/protocol_as_witness.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ protocol Q1 {}
99

1010
extension P1 where Self : Q1 {
1111
// FIXME: Poor QoI
12-
func f() {} // expected-note{{candidate has non-matching type '<`Self`> () -> ()'}}
12+
func f() {} // expected-note{{candidate has non-matching type '<Self> () -> ()'}}
1313
}
1414

1515
struct X1 : P1 {} // expected-error{{type 'X1' does not conform to protocol 'P1'}}
@@ -33,7 +33,7 @@ protocol P3 {
3333
}
3434

3535
extension P3 where Self : Equatable {
36-
func f() {} // expected-note{{candidate has non-matching type '<`Self`> () -> ()'}}
36+
func f() {} // expected-note{{candidate has non-matching type '<Self> () -> ()'}}
3737
}
3838

3939
struct X3 : P3 {} // expected-error{{type 'X3' does not conform to protocol 'P3'}}

test/decl/protocol/conforms/associated_type.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
class C { }
44

5-
protocol P { // expected-note{{requirement specified as '`Self`.AssocP' : 'C' [with Self = X]}}
5+
protocol P { // expected-note{{requirement specified as 'Self.AssocP' : 'C' [with Self = X]}}
66
typealias AssocP : C
77
}
88

test/decl/protocol/req/recursion.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ protocol SomeProtocol {
44
typealias T
55
}
66

7-
extension SomeProtocol where T == Optional<T> { } // expected-error{{same-type constraint '`Self`.T' == 'Optional<`Self`.T>' is recursive}}
7+
extension SomeProtocol where T == Optional<T> { } // expected-error{{same-type constraint 'Self.T' == 'Optional<Self.T>' is recursive}}
88

99
// rdar://problem/20000145
1010
public protocol P {

0 commit comments

Comments
 (0)