Esempio n. 1
0
void ModuleFile::lookupVisibleDecls(Module::AccessPathTy accessPath,
                                    VisibleDeclConsumer &consumer,
                                    NLKind lookupKind) {
  PrettyModuleFileDeserialization stackEntry(*this);
  assert(accessPath.size() <= 1 && "can only refer to top-level decls");

  if (!TopLevelDecls)
    return;

  if (!accessPath.empty()) {
    auto iter = TopLevelDecls->find(accessPath.front().first);
    if (iter == TopLevelDecls->end())
      return;

    for (auto item : *iter)
      consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)),
                         DeclVisibilityKind::VisibleAtTopLevel);
    return;
  }

  for (auto entry : TopLevelDecls->data()) {
    for (auto item : entry)
      consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)),
                         DeclVisibilityKind::VisibleAtTopLevel);
  }
}
Esempio n. 2
0
void ModuleFile::lookupClassMembers(Module::AccessPathTy accessPath,
                                    VisibleDeclConsumer &consumer) {
  PrettyModuleFileDeserialization stackEntry(*this);
  assert(accessPath.size() <= 1 && "can only refer to top-level decls");

  if (!ClassMembersByName)
    return;

  if (!accessPath.empty()) {
    for (const auto &list : ClassMembersByName->data()) {
      for (auto item : list) {
        auto vd = cast<ValueDecl>(getDecl(item.second));
        auto dc = vd->getDeclContext();
        while (!dc->getParent()->isModuleScopeContext())
          dc = dc->getParent();
        if (auto nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext())
          if (nominal->getName() == accessPath.front().first)
            consumer.foundDecl(vd, DeclVisibilityKind::DynamicLookup);
      }
    }
    return;
  }

  for (const auto &list : ClassMembersByName->data()) {
    for (auto item : list)
      consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)),
                         DeclVisibilityKind::DynamicLookup);
  }
}
Esempio n. 3
0
static void lookupDeclsFromProtocolsBeingConformedTo(
    Type BaseTy, VisibleDeclConsumer &Consumer, LookupState LS,
    const DeclContext *FromContext, DeclVisibilityKind Reason,
    LazyResolver *TypeResolver, VisitedSet &Visited) {
  NominalTypeDecl *CurrNominal = BaseTy->getAnyNominal();
  if (!CurrNominal)
    return;

  for (auto Conformance : CurrNominal->getAllConformances()) {
    auto Proto = Conformance->getProtocol();
    if (!Proto->isAccessibleFrom(FromContext))
      continue;

    DeclVisibilityKind ReasonForThisProtocol;
    if (Reason == DeclVisibilityKind::MemberOfCurrentNominal)
      ReasonForThisProtocol =
          DeclVisibilityKind::MemberOfProtocolImplementedByCurrentNominal;
    else
      ReasonForThisProtocol = getReasonForSuper(Reason);

    auto NormalConformance = Conformance->getRootNormalConformance();
    for (auto Member : Proto->getMembers()) {
      if (auto *ATD = dyn_cast<AssociatedTypeDecl>(Member)) {
        // Skip type decls if they aren't visible, or any type that has a
        // witness. This cuts down on duplicates.
        if (areTypeDeclsVisibleInLookupMode(LS) &&
            !NormalConformance->hasTypeWitness(ATD)) {
          Consumer.foundDecl(ATD, ReasonForThisProtocol);
        }
        continue;
      }
      if (auto *VD = dyn_cast<ValueDecl>(Member)) {
        if (TypeResolver) {
          TypeResolver->resolveDeclSignature(VD);
          if (!NormalConformance->hasWitness(VD) &&
              (Conformance->getDeclContext()->getParentSourceFile() !=
              FromContext->getParentSourceFile()))
            TypeResolver->resolveWitness(NormalConformance, VD);
        }
        // Skip value requirements that have corresponding witnesses. This cuts
        // down on duplicates.
        if (!NormalConformance->hasWitness(VD) ||
            !NormalConformance->getWitness(VD, nullptr) ||
            NormalConformance->getWitness(VD, nullptr).getDecl()->getFullName()
              != VD->getFullName()) {
          Consumer.foundDecl(VD, ReasonForThisProtocol);
        }
      }
    }

    // Add members from any extensions.
    SmallVector<ValueDecl *, 2> FoundDecls;
    doGlobalExtensionLookup(BaseTy, Proto->getDeclaredType(), FoundDecls,
                            FromContext, LS, ReasonForThisProtocol,
                            TypeResolver);
    for (auto *VD : FoundDecls)
      Consumer.foundDecl(VD, ReasonForThisProtocol);
  }
}
Esempio n. 4
0
/// \brief Enumerate all members in \c BaseTy (including members of extensions,
/// superclasses and implemented protocols), as seen from the context \c CurrDC.
///
/// This operation corresponds to a standard "dot" lookup operation like "a.b"
/// where 'self' is the type of 'a'.  This operation is only valid after name
/// binding.
static void lookupVisibleMemberDecls(
    Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC,
    LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver) {
  OverrideFilteringConsumer ConsumerWrapper(BaseTy, CurrDC);
  VisitedSet Visited;
  lookupVisibleMemberDeclsImpl(BaseTy, ConsumerWrapper, CurrDC, LS, Reason,
                               TypeResolver, Visited);

  // Report the declarations we found to the real consumer.
  for (const auto &DeclAndReason : ConsumerWrapper.DeclsToReport)
    Consumer.foundDecl(DeclAndReason.D, DeclAndReason.Reason);
}
Esempio n. 5
0
/// \brief Enumerate all members in \c BaseTy (including members of extensions,
/// superclasses and implemented protocols), as seen from the context \c CurrDC.
///
/// This operation corresponds to a standard "dot" lookup operation like "a.b"
/// where 'self' is the type of 'a'.  This operation is only valid after name
/// binding.
static void lookupVisibleMemberDecls(
    Type BaseTy, VisibleDeclConsumer &Consumer, const DeclContext *CurrDC,
    LookupState LS, DeclVisibilityKind Reason, LazyResolver *TypeResolver,
    GenericSignatureBuilder *GSB) {
  OverrideFilteringConsumer overrideConsumer(BaseTy, CurrDC, TypeResolver);
  RestateFilteringConsumer restateConsumer(BaseTy, CurrDC, TypeResolver);
  VisitedSet Visited;
  lookupVisibleMemberDeclsImpl(BaseTy, restateConsumer, CurrDC, LS, Reason,
                               TypeResolver, GSB, Visited);

  // Report the declarations we found to the real consumer.
  restateConsumer.feedResultsToConsumer(overrideConsumer);
  for (const auto &DeclAndReason : overrideConsumer.DeclsToReport)
    Consumer.foundDecl(DeclAndReason.D, DeclAndReason.Reason);
}
Esempio n. 6
0
/// \brief Enumerate immediate members of the type \c LookupType and its
/// extensions, as seen from the context \c CurrDC.
///
/// Don't do lookup into superclasses or implemented protocols.  Uses
/// \p BaseType as the underlying type when checking any constraints on the
/// extensions.
static void lookupTypeMembers(Type BaseType, Type LookupType,
                              VisibleDeclConsumer &Consumer,
                              const DeclContext *CurrDC, LookupState LS,
                              DeclVisibilityKind Reason,
                              LazyResolver *TypeResolver) {
  NominalTypeDecl *D = LookupType->getAnyNominal();
  assert(D && "should have a nominal type");

  bool LookupFromChildDeclContext = false;
  const DeclContext *TempDC = CurrDC;
  while (!TempDC->isModuleContext()) {
    if (TempDC == D) {
      LookupFromChildDeclContext = true;
      break;
    }
    TempDC = TempDC->getParent();
  }

  SmallVector<ValueDecl*, 2> FoundDecls;

  if (LookupFromChildDeclContext) {
    // Current decl context is contained inside 'D', so generic parameters
    // are visible.
    if (D->getGenericParams())
      for (auto Param : *D->getGenericParams())
        if (isDeclVisibleInLookupMode(Param, LS, CurrDC, TypeResolver))
          FoundDecls.push_back(Param);
  }

  for (Decl *Member : D->getMembers()) {
    if (auto *VD = dyn_cast<ValueDecl>(Member))
      if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver))
        FoundDecls.push_back(VD);
  }
  doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason,
                          TypeResolver);

  // Report the declarations we found to the consumer.
  for (auto *VD : FoundDecls)
    Consumer.foundDecl(VD, Reason);
}
Esempio n. 7
0
/// Enumerate immediate members of the type \c LookupType and its
/// extensions, as seen from the context \c CurrDC.
///
/// Don't do lookup into superclasses or implemented protocols.  Uses
/// \p BaseType as the underlying type when checking any constraints on the
/// extensions.
static void lookupTypeMembers(Type BaseType, Type LookupType,
                              VisibleDeclConsumer &Consumer,
                              const DeclContext *CurrDC, LookupState LS,
                              DeclVisibilityKind Reason,
                              LazyResolver *TypeResolver) {
  NominalTypeDecl *D = LookupType->getAnyNominal();
  assert(D && "should have a nominal type");

  SmallVector<ValueDecl*, 2> FoundDecls;

  for (Decl *Member : D->getMembers()) {
    if (auto *VD = dyn_cast<ValueDecl>(Member))
      if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver))
        FoundDecls.push_back(VD);
  }
  doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason,
                          TypeResolver);

  // Report the declarations we found to the consumer.
  for (auto *VD : FoundDecls)
    Consumer.foundDecl(VD, Reason);
}
Esempio n. 8
0
void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
                               const DeclContext *DC,
                               LazyResolver *TypeResolver,
                               bool IncludeTopLevel,
                               SourceLoc Loc) {
  const ModuleDecl &M = *DC->getParentModule();
  const SourceManager &SM = DC->getASTContext().SourceMgr;
  auto Reason = DeclVisibilityKind::MemberOfCurrentNominal;

  // If we are inside of a method, check to see if there are any ivars in scope,
  // and if so, whether this is a reference to one of them.
  while (!DC->isModuleScopeContext()) {
    const ValueDecl *BaseDecl = nullptr;
    Type ExtendedType;
    auto LS = LookupState::makeUnqualified();

    // Skip initializer contexts, we will not find any declarations there.
    if (isa<Initializer>(DC)) {
      DC = DC->getParent();
      LS = LS.withOnMetatype();
    }

    GenericParamList *GenericParams = DC->getGenericParamsOfContext();

    if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
      // Look for local variables; normally, the parser resolves these
      // for us, but it can't do the right thing inside local types.
      // FIXME: when we can parse and typecheck the function body partially for
      // code completion, AFD->getBody() check can be removed.
      if (Loc.isValid() && AFD->getBody()) {
        namelookup::FindLocalVal(SM, Loc, Consumer).visit(AFD->getBody());
      }

      for (auto *P : AFD->getParameterLists())
        namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList(P);

      // Constructors and destructors don't have 'self' in parameter patterns.
      if (isa<ConstructorDecl>(AFD) || isa<DestructorDecl>(AFD))
        if (auto *selfParam = AFD->getImplicitSelfDecl())
          Consumer.foundDecl(const_cast<ParamDecl*>(selfParam),
                             DeclVisibilityKind::FunctionParameter);

      if (AFD->getDeclContext()->isTypeContext()) {
        ExtendedType = AFD->getDeclContext()->getSelfTypeInContext();
        BaseDecl = AFD->getImplicitSelfDecl();
        DC = DC->getParent();

        if (auto *FD = dyn_cast<FuncDecl>(AFD))
          if (FD->isStatic())
            ExtendedType = MetatypeType::get(ExtendedType);
      }
    } else if (auto CE = dyn_cast<ClosureExpr>(DC)) {
      if (Loc.isValid()) {
        namelookup::FindLocalVal(SM, Loc, Consumer).visit(CE->getBody());
        if (auto P = CE->getParameters()) {
          namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList(P);
        }
      }
    } else if (auto ED = dyn_cast<ExtensionDecl>(DC)) {
      ExtendedType = ED->getExtendedType();
      if (ExtendedType)
        BaseDecl = ExtendedType->getNominalOrBoundGenericNominal();
    } else if (auto ND = dyn_cast<NominalTypeDecl>(DC)) {
      ExtendedType = ND->getDeclaredTypeInContext();
      BaseDecl = ND;
    }

    if (BaseDecl && ExtendedType) {
      ::lookupVisibleMemberDecls(ExtendedType, Consumer, DC, LS, Reason,
                                 TypeResolver, nullptr);
    }

    // Check any generic parameters for something with the given name.
    namelookup::FindLocalVal(SM, Loc, Consumer)
          .checkGenericParams(GenericParams);

    DC = DC->getParent();
    Reason = DeclVisibilityKind::MemberOfOutsideNominal;
  }

  SmallVector<ModuleDecl::ImportedModule, 8> extraImports;
  if (auto SF = dyn_cast<SourceFile>(DC)) {
    if (Loc.isValid()) {
      // Look for local variables in top-level code; normally, the parser
      // resolves these for us, but it can't do the right thing for
      // local types.
      namelookup::FindLocalVal(SM, Loc, Consumer).checkSourceFile(*SF);
    }

    if (IncludeTopLevel) {
      auto &cached = SF->getCachedVisibleDecls();
      if (!cached.empty()) {
        for (auto result : cached)
          Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel);
        return;
      }

      SF->getImportedModules(extraImports, ModuleDecl::ImportFilter::Private);
    }
  }

  if (IncludeTopLevel) {
    using namespace namelookup;
    SmallVector<ValueDecl *, 0> moduleResults;
    auto &mutableM = const_cast<ModuleDecl&>(M);
    lookupVisibleDeclsInModule(&mutableM, {}, moduleResults,
                               NLKind::UnqualifiedLookup,
                               ResolutionKind::Overloadable,
                               TypeResolver, DC, extraImports);
    for (auto result : moduleResults)
      Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel);

    if (auto SF = dyn_cast<SourceFile>(DC))
      SF->cacheVisibleDecls(std::move(moduleResults));
  }
}
Esempio n. 9
0
static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
                                   const DeclContext *DC,
                                   LazyResolver *TypeResolver,
                                   bool IncludeTopLevel, SourceLoc Loc) {
  const ModuleDecl &M = *DC->getParentModule();
  const SourceManager &SM = DC->getASTContext().SourceMgr;
  auto Reason = DeclVisibilityKind::MemberOfCurrentNominal;

  // If we are inside of a method, check to see if there are any ivars in scope,
  // and if so, whether this is a reference to one of them.
  while (!DC->isModuleScopeContext()) {
    GenericParamList *GenericParams = nullptr;
    Type ExtendedType;
    auto LS = LookupState::makeUnqualified();

    // Skip initializer contexts, we will not find any declarations there.
    if (isa<Initializer>(DC)) {
      DC = DC->getParent();
      LS = LS.withOnMetatype();
    }

    // We don't look for generic parameters if we are in the context of a
    // nominal type: they will be looked up anyways via `lookupVisibleMemberDecls`.
    if (DC && !isa<NominalTypeDecl>(DC)) {
      if (auto *decl = DC->getAsDecl()) {
        if (auto GC = decl->getAsGenericContext()) {
          auto params = GC->getGenericParams();
          namelookup::FindLocalVal(SM, Loc, Consumer).checkGenericParams(params);
        }
      }
    }

    if (auto *SE = dyn_cast<SubscriptDecl>(DC)) {
      ExtendedType = SE->getDeclContext()->getSelfTypeInContext();
      DC = DC->getParent();
    } else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {

      // Look for local variables; normally, the parser resolves these
      // for us, but it can't do the right thing inside local types.
      // FIXME: when we can parse and typecheck the function body partially for
      // code completion, AFD->getBody() check can be removed.
      if (Loc.isValid() && AFD->getBody()) {
        namelookup::FindLocalVal(SM, Loc, Consumer).visit(AFD->getBody());
      }

      if (auto *P = AFD->getImplicitSelfDecl()) {
        namelookup::FindLocalVal(SM, Loc, Consumer).checkValueDecl(
          const_cast<ParamDecl *>(P), DeclVisibilityKind::FunctionParameter);
      }

      namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList(
        AFD->getParameters());

      GenericParams = AFD->getGenericParams();

      if (AFD->getDeclContext()->isTypeContext()) {
        ExtendedType = AFD->getDeclContext()->getSelfTypeInContext();
        DC = DC->getParent();

        if (auto *FD = dyn_cast<FuncDecl>(AFD))
          if (FD->isStatic())
            ExtendedType = MetatypeType::get(ExtendedType);
      }
    } else if (auto CE = dyn_cast<ClosureExpr>(DC)) {
      if (Loc.isValid()) {
        namelookup::FindLocalVal(SM, Loc, Consumer).visit(CE->getBody());
        if (auto P = CE->getParameters()) {
          namelookup::FindLocalVal(SM, Loc, Consumer).checkParameterList(P);
        }
      }
    } else if (auto ED = dyn_cast<ExtensionDecl>(DC)) {
      ExtendedType = ED->getSelfTypeInContext();
    } else if (auto ND = dyn_cast<NominalTypeDecl>(DC)) {
      ExtendedType = ND->getSelfTypeInContext();
    }

    // If we're inside a function context, we've already moved to
    // the parent DC, so we have to check the function's generic
    // parameters first.
    if (GenericParams) {
      namelookup::FindLocalVal localVal(SM, Loc, Consumer);
      localVal.checkGenericParams(GenericParams);
    }

    // Check the generic parameters of our context.
    GenericParamList *dcGenericParams = nullptr;
    if (auto nominal = dyn_cast<NominalTypeDecl>(DC))
      dcGenericParams = nominal->getGenericParams();
    else if (auto ext = dyn_cast<ExtensionDecl>(DC))
      dcGenericParams = ext->getGenericParams();
    else if (auto subscript = dyn_cast<SubscriptDecl>(DC))
      dcGenericParams = subscript->getGenericParams();

    while (dcGenericParams) {
      namelookup::FindLocalVal localVal(SM, Loc, Consumer);
      localVal.checkGenericParams(dcGenericParams);
      dcGenericParams = dcGenericParams->getOuterParameters();
    }

    if (ExtendedType)
      ::lookupVisibleMemberDecls(ExtendedType, Consumer, DC, LS, Reason,
                                 TypeResolver, nullptr);

    DC = DC->getParent();
    Reason = DeclVisibilityKind::MemberOfOutsideNominal;
  }

  SmallVector<ModuleDecl::ImportedModule, 8> extraImports;
  if (auto SF = dyn_cast<SourceFile>(DC)) {
    if (Loc.isValid()) {
      // Look for local variables in top-level code; normally, the parser
      // resolves these for us, but it can't do the right thing for
      // local types.
      namelookup::FindLocalVal(SM, Loc, Consumer).checkSourceFile(*SF);
    }

    if (IncludeTopLevel) {
      auto &cached = SF->getCachedVisibleDecls();
      if (!cached.empty()) {
        for (auto result : cached)
          Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel);
        return;
      }

      SF->getImportedModules(extraImports, ModuleDecl::ImportFilter::Private);
    }
  }

  if (IncludeTopLevel) {
    using namespace namelookup;
    SmallVector<ValueDecl *, 0> moduleResults;
    auto &mutableM = const_cast<ModuleDecl&>(M);
    lookupVisibleDeclsInModule(&mutableM, {}, moduleResults,
                               NLKind::UnqualifiedLookup,
                               ResolutionKind::Overloadable,
                               TypeResolver, DC, extraImports);
    for (auto result : moduleResults)
      Consumer.foundDecl(result, DeclVisibilityKind::VisibleAtTopLevel);

    if (auto SF = dyn_cast<SourceFile>(DC))
      SF->cacheVisibleDecls(std::move(moduleResults));
  }
}
Esempio n. 10
0
 void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) {
   if (isUsableValue(VD, Reason))
     Consumer.foundDecl(VD, Reason);
 }
Esempio n. 11
0
 void feedResultsToConsumer(VisibleDeclConsumer &Consumer) const {
   for (const auto entry: declsToReport)
     Consumer.foundDecl(entry.first, entry.second);
 }