|
18 | 18 | #include "swift/AST/AvailabilityScope.h" |
19 | 19 | #include "swift/AST/Decl.h" |
20 | 20 | #include "swift/AST/Module.h" |
| 21 | +#include "swift/AST/SourceFile.h" |
21 | 22 | #include "swift/Basic/Assertions.h" |
22 | 23 |
|
23 | 24 | using namespace swift; |
@@ -155,6 +156,30 @@ AvailabilityContext::forDeploymentTarget(const ASTContext &ctx) { |
155 | 156 | AvailabilityRange::forDeploymentTarget(ctx), ctx); |
156 | 157 | } |
157 | 158 |
|
| 159 | +static AvailabilityContext |
| 160 | +contextForLocationInSourceFile(SourceLoc loc, SourceFile *sf, |
| 161 | + AvailabilityContext baseAvailability, |
| 162 | + const AvailabilityScope **refinedScope) { |
| 163 | + if (!sf || loc.isInvalid()) |
| 164 | + return baseAvailability; |
| 165 | + |
| 166 | + auto &ctx = sf->getASTContext(); |
| 167 | + auto *rootScope = AvailabilityScope::getOrBuildForSourceFile(*sf); |
| 168 | + if (!rootScope) |
| 169 | + return baseAvailability; |
| 170 | + |
| 171 | + auto *scope = rootScope->findMostRefinedSubContext(loc, ctx); |
| 172 | + if (!scope) |
| 173 | + return baseAvailability; |
| 174 | + |
| 175 | + if (refinedScope) |
| 176 | + *refinedScope = scope; |
| 177 | + |
| 178 | + auto availability = scope->getAvailabilityContext(); |
| 179 | + availability.constrainWithContext(baseAvailability, ctx); |
| 180 | + return availability; |
| 181 | +} |
| 182 | + |
158 | 183 | AvailabilityContext |
159 | 184 | AvailabilityContext::forLocation(SourceLoc loc, const DeclContext *declContext, |
160 | 185 | const AvailabilityScope **refinedScope) { |
@@ -191,37 +216,25 @@ AvailabilityContext::forLocation(SourceLoc loc, const DeclContext *declContext, |
191 | 216 | declContext = decl->getDeclContext(); |
192 | 217 | } |
193 | 218 |
|
194 | | - if (!sf || loc.isInvalid()) |
195 | | - return baseAvailability; |
196 | | - |
197 | | - auto *rootScope = AvailabilityScope::getOrBuildForSourceFile(*sf); |
198 | | - if (!rootScope) |
199 | | - return baseAvailability; |
200 | | - |
201 | | - auto *scope = rootScope->findMostRefinedSubContext(loc, ctx); |
202 | | - if (!scope) |
203 | | - return baseAvailability; |
204 | | - |
205 | | - if (refinedScope) |
206 | | - *refinedScope = scope; |
207 | | - |
208 | | - auto availability = scope->getAvailabilityContext(); |
209 | | - availability.constrainWithContext(baseAvailability, ctx); |
210 | | - return availability; |
| 219 | + return contextForLocationInSourceFile(loc, sf, baseAvailability, |
| 220 | + refinedScope); |
211 | 221 | } |
212 | 222 |
|
213 | 223 | AvailabilityContext AvailabilityContext::forDeclSignature(const Decl *decl) { |
214 | | - // For decls with valid source locations, query the availability scope tree. |
| 224 | + // For decls with valid source locations in source files, we can query the |
| 225 | + // availability scope tree. |
215 | 226 | auto loc = decl->getLoc(); |
216 | | - if (loc.isValid()) |
217 | | - return forLocation(loc, decl->getInnermostDeclContext()); |
218 | | - |
219 | | - // Otherwise, walk the decl hierarchy to compute availability. This can't be |
220 | | - // delegated to `AvailabilityContext::forLocation()` since it walks up the |
221 | | - // `DeclContext` hierachy for invalid source locations and that may skip |
222 | | - // some declarations with availability attributes. |
223 | 227 | auto &ctx = decl->getASTContext(); |
224 | 228 | auto availability = forInliningTarget(ctx); |
| 229 | + |
| 230 | + if (loc.isValid()) { |
| 231 | + if (auto sf = decl->getDeclContext() |
| 232 | + ->getParentModule() |
| 233 | + ->getSourceFileContainingLocation(loc)) |
| 234 | + return contextForLocationInSourceFile(loc, sf, availability, nullptr); |
| 235 | + } |
| 236 | + |
| 237 | + // Otherwise, just walk the decl hierarchy to compute availability. |
225 | 238 | while (decl) { |
226 | 239 | availability.constrainWithDecl(decl); |
227 | 240 | decl = decl->parentDeclForAvailability(); |
|
0 commit comments