@@ -35,6 +35,7 @@ using namespace swift::ide::api;
35
35
36
36
struct FoundResult {
37
37
SourceRange TokenRange;
38
+ bool Optional; // Range has a trailing ? or ! included
38
39
bool Suffixable; // No need to wrap parens when adding optionality
39
40
bool isValid () const { return TokenRange.isValid (); }
40
41
};
@@ -53,11 +54,12 @@ class ChildIndexFinder : public TypeReprVisitor<ChildIndexFinder, FoundResult> {
53
54
return findChild (Func->getBodyResultTypeLoc ());
54
55
if (auto Init = dyn_cast<ConstructorDecl>(Parent)) {
55
56
SourceLoc End = Init->getFailabilityLoc ();
56
- if (End.isInvalid ())
57
+ bool Optional = End.isValid ();
58
+ if (!Optional)
57
59
End = Init->getNameLoc ();
58
- return {SourceRange (Init->getNameLoc (), End), true };
60
+ return {SourceRange (Init->getNameLoc (), End), Optional, /* suffixable= */ true };
59
61
}
60
- return {SourceRange (), false };
62
+ return {SourceRange (), false , false };
61
63
}
62
64
63
65
for (auto *Params: Parent->getParameterLists ()) {
@@ -73,7 +75,7 @@ class ChildIndexFinder : public TypeReprVisitor<ChildIndexFinder, FoundResult> {
73
75
}
74
76
75
77
private:
76
- bool hasNextIndex () {
78
+ bool hasNextIndex () const {
77
79
return !ChildIndices.empty ();
78
80
}
79
81
@@ -83,44 +85,56 @@ class ChildIndexFinder : public TypeReprVisitor<ChildIndexFinder, FoundResult> {
83
85
return Next;
84
86
}
85
87
88
+ bool isUserTypeAlias (TypeRepr *T) const {
89
+ if (auto Ident = dyn_cast<ComponentIdentTypeRepr>(T)) {
90
+ if (auto Bound = Ident->getBoundDecl ()) {
91
+ return isa<TypeAliasDecl>(Bound) &&
92
+ !Bound->getModuleContext ()->isSystemModule ();
93
+ }
94
+ }
95
+ return false ;
96
+ }
97
+
86
98
FoundResult findChild (TypeLoc Loc) {
87
99
if (!Loc.hasLocation ())
88
- return {SourceRange (), false };
100
+ return {SourceRange (), false , false };
89
101
return visit (Loc.getTypeRepr ());
90
102
}
91
103
92
104
public:
93
- FoundResult handleParent (TypeRepr *Parent, TypeRepr *FirstChild,
94
- TypeRepr *SecondChild, bool Suffixable = true ) {
95
- if (!hasNextIndex ())
96
- return {Parent->getSourceRange (), Suffixable};
97
- auto NextIndex = consumeNext ();
98
- assert (NextIndex < 2 && " child index out of bounds" );
99
- return visit (NextIndex ? SecondChild : FirstChild);
100
- }
101
105
102
106
template <typename T>
103
107
FoundResult handleParent (TypeRepr *Parent, const ArrayRef<T> Children,
104
- bool Suffixable = true ) {
108
+ bool Optional = false , bool Suffixable = true ) {
105
109
if (!hasNextIndex ())
106
- return {Parent->getSourceRange (), Suffixable};
110
+ return {Parent->getSourceRange (), Optional, Suffixable};
107
111
auto NextIndex = consumeNext ();
112
+ if (isUserTypeAlias (Parent))
113
+ return {SourceRange (), false , false };
108
114
assert (NextIndex < Children.size ());
109
115
TypeRepr *Child = Children[NextIndex];
110
116
return visit (Child);
111
117
}
112
118
113
- FoundResult handleParent (TypeRepr *Parent, TypeRepr *Base,
119
+ FoundResult handleParent (TypeRepr *Parent, TypeRepr *FirstChild,
120
+ TypeRepr *SecondChild, bool Optional = false ,
114
121
bool Suffixable = true ) {
115
- return handleParent (Parent, llvm::makeArrayRef (Base), Suffixable);
122
+ TypeRepr *Children[] = {FirstChild, SecondChild};
123
+ return handleParent (Parent, llvm::makeArrayRef (Children), Optional,
124
+ Suffixable);
125
+ }
126
+
127
+ FoundResult handleParent (TypeRepr *Parent, TypeRepr *Base,
128
+ bool Optional = false , bool Suffixable = true ) {
129
+ return handleParent (Parent, llvm::makeArrayRef (Base), Optional, Suffixable);
116
130
}
117
131
118
132
FoundResult visitTypeRepr (TypeRepr *T) {
119
133
llvm_unreachable (" unexpected typerepr" );
120
134
}
121
135
122
136
FoundResult visitErrorTypeRepr (ErrorTypeRepr *T) {
123
- return {SourceRange (), false };
137
+ return {SourceRange (), false , false };
124
138
}
125
139
126
140
FoundResult visitAttributedTypeRepr (AttributedTypeRepr *T) {
@@ -149,36 +163,32 @@ class ChildIndexFinder : public TypeReprVisitor<ChildIndexFinder, FoundResult> {
149
163
150
164
FoundResult visitFunctionTypeRepr (FunctionTypeRepr *T) {
151
165
return handleParent (T, T->getResultTypeRepr (), T->getArgsTypeRepr (),
152
- /* Suffixable=*/ false );
166
+ /* Optional= */ false , /* Suffixable=*/ false );
153
167
}
154
168
155
169
FoundResult visitCompositionTypeRepr (CompositionTypeRepr *T) {
156
- return handleParent (T, T->getTypes (), /* Suffixable=*/ false );
170
+ return handleParent (T, T->getTypes (), /* Optional=*/ false ,
171
+ /* Suffixable=*/ false );
157
172
}
158
173
159
174
FoundResult visitSimpleIdentTypeRepr (SimpleIdentTypeRepr *T) {
160
- if (!hasNextIndex ())
161
- return {T->getSourceRange (), true };
162
- // This may be a typealias so report no match
163
- return {SourceRange (), false };
175
+ return handleParent (T, ArrayRef<TypeRepr*>());
164
176
}
165
177
166
178
FoundResult visitGenericIdentTypeRepr (GenericIdentTypeRepr *T) {
167
- // FIXME: This could be a generic type alias
168
179
return handleParent (T, T->getGenericArgs ());
169
180
}
170
181
171
182
FoundResult visitCompoundIdentTypeRepr (CompoundIdentTypeRepr *T) {
172
- // FIXME: this could be a nested typealias
173
- return handleParent (T, T->Components );
183
+ return visit (T->Components .back ());
174
184
}
175
185
176
186
FoundResult visitOptionalTypeRepr (OptionalTypeRepr *T) {
177
- return handleParent (T, T->getBase ());
187
+ return handleParent (T, T->getBase (), /* Optional= */ true );
178
188
}
179
189
180
190
FoundResult visitImplicitlyUnwrappedOptionalTypeRepr (ImplicitlyUnwrappedOptionalTypeRepr *T) {
181
- return handleParent (T, T->getBase ());
191
+ return handleParent (T, T->getBase (), /* Optional= */ true );
182
192
}
183
193
184
194
FoundResult visitProtocolTypeRepr (ProtocolTypeRepr *T) {
@@ -190,8 +200,7 @@ class ChildIndexFinder : public TypeReprVisitor<ChildIndexFinder, FoundResult> {
190
200
}
191
201
192
202
FoundResult visitFixedTypeRepr (FixedTypeRepr *T) {
193
- assert (!hasNextIndex ());
194
- return {T->getSourceRange (), true };
203
+ return handleParent (T, ArrayRef<TypeRepr*>());
195
204
}
196
205
};
197
206
@@ -450,10 +459,12 @@ struct SyntacticMigratorPass::Implementation : public SourceEntityWalker {
450
459
}
451
460
break ;
452
461
case ide::api::NodeAnnotation::UnwrapOptional:
453
- Editor.remove (Result.TokenRange .End );
462
+ if (Result.Optional )
463
+ Editor.remove (Result.TokenRange .End );
454
464
break ;
455
465
case ide::api::NodeAnnotation::ImplicitOptionalToOptional:
456
- Editor.replace (Result.TokenRange .End , " ?" );
466
+ if (Result.Optional )
467
+ Editor.replace (Result.TokenRange .End , " ?" );
457
468
break ;
458
469
case ide::api::NodeAnnotation::TypeRewritten:
459
470
Editor.replace (Result.TokenRange , DiffItem->RightComment );
0 commit comments