14
14
//
15
15
// ===----------------------------------------------------------------------===//
16
16
17
+ #include " swift/AST/TypeRefinementContext.h"
18
+
17
19
#include " swift/AST/ASTContext.h"
18
20
#include " swift/AST/Decl.h"
19
- #include " swift/AST/Module.h"
20
- #include " swift/AST/Stmt.h"
21
21
#include " swift/AST/Expr.h"
22
+ #include " swift/AST/Module.h"
22
23
#include " swift/AST/SourceFile.h"
24
+ #include " swift/AST/Stmt.h"
23
25
#include " swift/AST/TypeCheckRequests.h"
24
- #include " swift/AST/TypeRefinementContext.h"
25
26
#include " swift/Basic/Assertions.h"
26
27
#include " swift/Basic/SourceManager.h"
27
28
@@ -35,7 +36,7 @@ TypeRefinementContext::TypeRefinementContext(
35
36
ExplicitAvailabilityInfo(ExplicitInfo) {
36
37
if (Parent) {
37
38
assert (SrcRange.isValid ());
38
- Parent->addChild (this );
39
+ Parent->addChild (this , Ctx );
39
40
assert (Info.isContainedIn (Parent->getAvailabilityInfo ()));
40
41
}
41
42
Ctx.addDestructorCleanup (Children);
@@ -169,6 +170,36 @@ TypeRefinementContext::createForWhileStmtBody(ASTContext &Ctx, WhileStmt *S,
169
170
Ctx, S, Parent, S->getBody ()->getSourceRange (), Info, /* ExplicitInfo */ Info);
170
171
}
171
172
173
+ void TypeRefinementContext::addChild (TypeRefinementContext *Child,
174
+ ASTContext &Ctx) {
175
+ assert (Child->getSourceRange ().isValid ());
176
+
177
+ // Handle the first child.
178
+ if (Children.empty ()) {
179
+ Children.push_back (Child);
180
+ return ;
181
+ }
182
+
183
+ // Handle a child that is ordered after the existing children (this should be
184
+ // the common case).
185
+ auto &srcMgr = Ctx.SourceMgr ;
186
+ if (srcMgr.isBefore (Children.back ()->getSourceRange ().Start ,
187
+ Child->getSourceRange ().Start )) {
188
+ Children.push_back (Child);
189
+ return ;
190
+ }
191
+
192
+ // Insert the child amongst the existing sorted children.
193
+ auto iter = std::upper_bound (
194
+ Children.begin (), Children.end (), Child,
195
+ [&srcMgr](TypeRefinementContext *lhs, TypeRefinementContext *rhs) {
196
+ return srcMgr.isBefore (lhs->getSourceRange ().Start ,
197
+ rhs->getSourceRange ().Start );
198
+ });
199
+
200
+ Children.insert (iter, Child);
201
+ }
202
+
172
203
TypeRefinementContext *
173
204
TypeRefinementContext::findMostRefinedSubContext (SourceLoc Loc,
174
205
ASTContext &Ctx) {
@@ -180,16 +211,23 @@ TypeRefinementContext::findMostRefinedSubContext(SourceLoc Loc,
180
211
auto expandedChildren = evaluateOrDefault (
181
212
Ctx.evaluator , ExpandChildTypeRefinementContextsRequest{this }, {});
182
213
183
- // For the moment, we perform a linear search here, but we can and should
184
- // do something more efficient.
185
- for (TypeRefinementContext *Child : expandedChildren) {
186
- if (auto *Found = Child->findMostRefinedSubContext (Loc, Ctx)) {
187
- return Found;
188
- }
214
+ // Do a binary search to find the first child with a source range that
215
+ // ends after the given location.
216
+ auto iter = std::lower_bound (
217
+ expandedChildren.begin (), expandedChildren.end (), Loc,
218
+ [&Ctx](TypeRefinementContext *context, SourceLoc loc) {
219
+ return Ctx.SourceMgr .isBefore (context->getSourceRange ().End , loc);
220
+ });
221
+
222
+ // Check whether the matching child or any of its descendants contain
223
+ // the given location.
224
+ if (iter != expandedChildren.end ()) {
225
+ if (auto found = (*iter)->findMostRefinedSubContext (Loc, Ctx))
226
+ return found;
189
227
}
190
228
191
- // Loc is in this context's range but not in any child's, so this context
192
- // must be the inner-most context.
229
+ // The location is in this context's range but not in any child's, so this
230
+ // context must be the innermost context.
193
231
return this ;
194
232
}
195
233
0 commit comments