|
22 | 22 | #include "swift/AST/NameLookup.h"
|
23 | 23 | #include "swift/AST/NameLookupRequests.h"
|
24 | 24 | #include "swift/AST/ProtocolConformance.h"
|
| 25 | +#include "swift/AST/SourceFile.h" |
25 | 26 | #include "swift/Basic/TopCollection.h"
|
26 | 27 | #include <algorithm>
|
27 | 28 |
|
@@ -223,11 +224,47 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) {
|
223 | 224 | return newOptions;
|
224 | 225 | }
|
225 | 226 |
|
| 227 | +static void installPropertyWrapperMembersIfNeeded(NominalTypeDecl *target, |
| 228 | + DeclName member) { |
| 229 | + if (!target) return; |
| 230 | + |
| 231 | + auto &Context = target->getASTContext(); |
| 232 | + auto baseName = member.getBaseName(); |
| 233 | + if (!member.isSimpleName() || baseName.isSpecial()) |
| 234 | + return; |
| 235 | + |
| 236 | + if ((!baseName.getIdentifier().str().startswith("$") && |
| 237 | + !baseName.getIdentifier().str().startswith("_")) || |
| 238 | + baseName.getIdentifier().str().size() <= 1) { |
| 239 | + return; |
| 240 | + } |
| 241 | + |
| 242 | + // $- and _-prefixed variables can be generated by properties that have |
| 243 | + // attached property wrappers. |
| 244 | + auto originalPropertyName = |
| 245 | + Context.getIdentifier(baseName.getIdentifier().str().substr(1)); |
| 246 | + for (auto member : target->lookupDirect(originalPropertyName)) { |
| 247 | + if (auto var = dyn_cast<VarDecl>(member)) { |
| 248 | + if (var->hasAttachedPropertyWrapper()) { |
| 249 | + auto sourceFile = var->getDeclContext()->getParentSourceFile(); |
| 250 | + if (sourceFile && sourceFile->Kind != SourceFileKind::Interface) |
| 251 | + (void)var->getPropertyWrapperBackingProperty(); |
| 252 | + } |
| 253 | + } |
| 254 | + } |
| 255 | +} |
| 256 | + |
226 | 257 | LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclName name,
|
227 | 258 | SourceLoc loc,
|
228 | 259 | NameLookupOptions options) {
|
229 | 260 | auto ulOptions = convertToUnqualifiedLookupOptions(options);
|
230 | 261 |
|
| 262 | + // Make sure we've resolved implicit members, if we need them. |
| 263 | + if (auto *current = dc->getInnermostTypeContext()) { |
| 264 | + installPropertyWrapperMembersIfNeeded(current->getSelfNominalTypeDecl(), |
| 265 | + name); |
| 266 | + } |
| 267 | + |
231 | 268 | auto &ctx = dc->getASTContext();
|
232 | 269 | auto descriptor = UnqualifiedLookupDescriptor(name, dc, loc, ulOptions);
|
233 | 270 | auto lookup = evaluateOrDefault(ctx.evaluator,
|
@@ -311,6 +348,12 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc,
|
311 | 348 | subOptions &= ~NL_RemoveOverridden;
|
312 | 349 | subOptions &= ~NL_RemoveNonVisible;
|
313 | 350 |
|
| 351 | + // Make sure we've resolved implicit members, if we need them. |
| 352 | + if (auto *current = type->getAnyNominal()) { |
| 353 | + current->synthesizeSemanticMembersIfNeeded(name); |
| 354 | + installPropertyWrapperMembersIfNeeded(current, name); |
| 355 | + } |
| 356 | + |
314 | 357 | LookupResultBuilder builder(result, dc, options);
|
315 | 358 | SmallVector<ValueDecl *, 4> lookupResults;
|
316 | 359 | dc->lookupQualified(type, name, subOptions, lookupResults);
|
@@ -385,6 +428,12 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
|
385 | 428 | if (options.contains(NameLookupFlags::IgnoreAccessControl))
|
386 | 429 | subOptions |= NL_IgnoreAccessControl;
|
387 | 430 |
|
| 431 | + // Make sure we've resolved implicit members, if we need them. |
| 432 | + if (auto *current = type->getAnyNominal()) { |
| 433 | + current->synthesizeSemanticMembersIfNeeded(name); |
| 434 | + installPropertyWrapperMembersIfNeeded(current, name); |
| 435 | + } |
| 436 | + |
388 | 437 | if (!dc->lookupQualified(type, name, subOptions, decls))
|
389 | 438 | return result;
|
390 | 439 |
|
|
0 commit comments