|
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