* @file
*
* This file defines functions for looking up symbol.
*/
#include "TypeCheckUtil.h"
#include "TypeCheckerImpl.h"
#include "cangjie/AST/ScopeManagerApi.h"
#include "cangjie/AST/Utils.h"
#include "cangjie/Modules/ModulesUtils.h"
using namespace Cangjie;
using namespace AST;
using namespace TypeCheckUtil;
namespace {
class LookUpImpl {
public:
LookUpImpl(const ASTContext& ctx, DiagnosticEngine& diag, TypeManager& manger, ImportManager& importManager)
: ctx(ctx), diag(diag), typeManager(manger), importManager(importManager)
{
}
~LookUpImpl() = default;
* Search target by namespace(like class, interface, struct, enum) and field name.
* NOTE: decl which has 'IN_REFERENCE_CYCLE' should only be intercepted during checking 'inheritedTypes'.
*/
std::vector<Ptr<Decl>> FieldLookup(Ptr<Decl> decl, const std::string& fieldName, const LookupInfo& info = {});
std::vector<Ptr<Decl>> Lookup(const std::string& name, const std::string& scopeName, const Node& node,
bool onlyLookUpTopLevel = false, bool isSetter = false);
void FieldLookupExtend(
Ty& ty, const std::string& fieldName, std::vector<Ptr<Decl>>& results, const LookupInfo& info);
private:
void AddMemberIfValidForLookup(std::vector<Ptr<Decl>>& results, Ty& baseTy, bool isSetter, Decl& decl);
* @brief Determine whether @param decl forms an override or implementation with decl in @param results.
* If decl in @param results override the @param decl, do nothing.
* If @param decl override the decl in @param results, replace the match item in @param results.
* @param results the results that have been collected.
* @param decl currently processed declaration.
* @param baseTy type of MemberAccess' baseExpr.
* @param parentTy inherited instantiated types. eg:
* 'I1<T1> <: I2<Int64>', parentTy should be 'I2<Int64>'.
* 'I1<T1> <: I2<T1>', parentTy should be 'I2<T1>'.
*/
void ResolveOverrideOrShadow(std::vector<Ptr<Decl>>& results, Decl& decl, Ptr<InterfaceTy> parentTy);
void FieldLookup(const ClassDecl& cd, const std::string& fieldName, std::vector<Ptr<Decl>>& results,
const LookupInfo& info);
void FieldLookup(
InterfaceTy& idTy, const std::string& fieldName, std::vector<Ptr<Decl>>& results, const LookupInfo& info);
std::vector<Ptr<Decl>> FieldLookup(const EnumDecl& ed, const std::string& fieldName, const LookupInfo& info);
std::vector<Ptr<Decl>> FieldLookup(const StructDecl& sd, const std::string& fieldName, const LookupInfo& info);
std::vector<Ptr<Decl>> FieldLookup(const PackageDecl& pd, const std::string& fieldName);
std::vector<Ptr<Decl>> StdLibFieldLookup(const Node& node, const std::string& fieldName);
void ProcessStructDeclBody(
const std::string& name, const std::string& scopeName, const Node& node, std::vector<Ptr<Decl>>& results);
bool LookupImpl(const std::string& name, std::string scopeName, const Node& node, bool onlyLookUpTopLevel,
bool isSetter, std::vector<Ptr<Decl>>& results);
bool FindRealResult(const Node& node, bool isSetter, std::vector<Ptr<Decl>>& results,
std::multimap<Position, Ptr<Decl>>& resultsMap, bool isInDeclBody);
std::vector<std::pair<Ptr<Decl>, Ptr<InterfaceTy>>> resultsWithInstTyV;
void InsertResultsWithInstTy(size_t idx, Ptr<Decl> d, Ptr<InterfaceTy> interfaceTy)
{
if (idx >= resultsWithInstTyV.size()) {
resultsWithInstTyV.resize(idx + 1);
}
resultsWithInstTyV[idx] = std::make_pair(d, interfaceTy);
}
void SwapResultsWithInstTy(size_t oldIdx, size_t newIdx, Ptr<Decl> d, Ptr<InterfaceTy> interfaceTy)
{
resultsWithInstTyV.erase(resultsWithInstTyV.begin() + static_cast<long>(oldIdx));
InsertResultsWithInstTy(newIdx, d, interfaceTy);
}
bool IsTargetMemberVisibleToNode(const Decl& target, const Node& node);
const ASTContext& ctx;
DiagnosticEngine& diag;
TypeManager& typeManager;
ImportManager& importManager;
};
bool IgnoredMember(const Decl& decl)
{
if (decl.TestAttr(Attribute::TOOL_ADD)) {
return false;
}
return decl.TestAnyAttr(Attribute::CONSTRUCTOR, Attribute::MAIN_ENTRY) ||
decl.astKind == ASTKind::PRIMARY_CTOR_DECL;
}
void UpdatePropOverriddenCache(
TypeManager& typeManager, const PropDecl& src, std::vector<Ptr<Decl>>& results, Ptr<Ty> baseTy)
{
for (auto it = results.begin(); it != results.end(); ++it) {
if (auto fd2 = DynamicCast<PropDecl*>(*it)) {
IsOverrideOrShadow(typeManager, *fd2, src, baseTy);
}
}
}
template <typename T>
inline Ptr<T> GetSpecificDecl(Ptr<Decl> decl)
{
CJC_ASSERT(decl);
return StaticCast<T*>(decl->specificImplementation == nullptr ? decl : decl->specificImplementation);
}
}
void LookUpImpl::AddMemberIfValidForLookup(std::vector<Ptr<Decl>>& results, Ty& baseTy, bool isSetter, Decl& decl)
{
bool covered{false};
if (auto pd = DynamicCast<PropDecl*>(&decl); pd) {
if (!isSetter) {
if (pd->getters.empty()) {
return;
}
} else {
if (pd->isVar && pd->setters.empty()) {
return;
}
}
}
if (decl.astKind != ASTKind::FUNC_DECL) {
if (auto prop = DynamicCast<PropDecl>(&decl)) {
UpdatePropOverriddenCache(typeManager, *prop, results, &baseTy);
}
results.push_back(&decl);
return;
}
for (auto it = results.begin(); it != results.end();) {
if (auto fd2 = DynamicCast<FuncDecl*>(*it);
fd2 && IsOverrideOrShadow(typeManager, *fd2, static_cast<FuncDecl&>(decl), &baseTy)) {
if (fd2->TestAttr(Attribute::ABSTRACT) && !decl.TestAttr(Attribute::ABSTRACT)) {
it = results.erase(it);
results.push_back(&decl);
}
covered = true;
break;
} else {
++it;
}
}
if (!covered) {
results.push_back(&decl);
}
}
void LookUpImpl::FieldLookupExtend(
Ty& ty, const std::string& fieldName, std::vector<Ptr<Decl>>& results, const LookupInfo& info)
{
CJC_NULLPTR_CHECK(info.file);
OrderedDeclSet extendFuncs;
auto extends = typeManager.GetAllExtendsByTy(ty);
std::set<Ptr<ExtendDecl>, CmpNodeByPos> orderExtends(extends.begin(), extends.end());
for (auto& extend : orderExtends) {
CJC_NULLPTR_CHECK(extend);
if (!importManager.IsExtendAccessible(*info.file, *extend)) {
continue;
}
for (auto& it : extend->members) {
if (it->identifier == fieldName) {
extendFuncs.emplace(it.get());
}
}
}
results.insert(results.end(), extendFuncs.begin(), extendFuncs.end());
for (auto& extend : orderExtends) {
CJC_NULLPTR_CHECK(extend);
if (!importManager.IsExtendAccessible(*info.file, *extend)) {
continue;
}
for (auto& it : extend->inheritedTypes) {
if (it == nullptr) {
continue;
}
auto interfaceDecl = Ty::GetDeclPtrOfTy(it->GetTy());
if (!interfaceDecl || interfaceDecl->TestAttr(Attribute::IN_REFERENCE_CYCLE)) {
continue;
}
auto mappingExtendWithDecl = GenerateTypeMappingByTy(extend->GetTy(), &ty);
auto interfaceTy = typeManager.GetInstantiatedTy(it->GetTy(), mappingExtendWithDecl);
FieldLookup(*StaticCast<InterfaceTy>(interfaceTy), fieldName, results, info);
}
}
}
void LookUpImpl::ResolveOverrideOrShadow(std::vector<Ptr<Decl>>& results, Decl& decl, Ptr<InterfaceTy> parentTy)
{
if (decl.astKind == ASTKind::PROP_DECL) {
if (!decl.TestAttr(Attribute::ABSTRACT)) {
Utils::EraseIf(results, [](auto it) { return it->TestAttr(Attribute::ABSTRACT); });
}
}
for (size_t i = 0; i < results.size(); ++i) {
if (results[i] == nullptr ||
(results[i]->astKind != ASTKind::FUNC_DECL && results[i]->astKind != ASTKind::PROP_DECL)) {
continue;
}
auto newDecl = RawStaticCast<Decl*>(&decl);
auto inResult = RawStaticCast<Decl*>(results[i]);
Ptr<Ty> inResultOuter = inResult->outerDecl->GetTy();
if (resultsWithInstTyV.size() > i && resultsWithInstTyV[i].second) {
inResultOuter = resultsWithInstTyV[i].second;
} else if (inResult->outerDecl->astKind == ASTKind::EXTEND_DECL &&
!typeManager.IsSubtype(inResultOuter, parentTy)) {
auto extendTy = inResult->outerDecl->GetTy();
auto extendedDecl = Ty::GetDeclPtrOfTy(extendTy);
if (extendedDecl) {
auto mappingExtendWithDecl = GenerateTypeMappingByTy(extendTy, extendedDecl->GetTy());
inResultOuter = typeManager.GetInstantiatedTy(inResultOuter, mappingExtendWithDecl);
}
}
if (!typeManager.PairIsOverrideOrImpl(*inResult, *newDecl, inResultOuter, parentTy) &&
!typeManager.PairIsOverrideOrImpl(*newDecl, *inResult, parentTy, inResultOuter)) {
continue;
}
if (typeManager.IsSubtype(parentTy, inResultOuter) ||
(inResult->TestAttr(Attribute::ABSTRACT) && !newDecl->TestAttr(Attribute::ABSTRACT))) {
results.erase(results.begin() + static_cast<long>(i));
SwapResultsWithInstTy(i, results.size(), &decl, parentTy);
results.emplace_back(&decl);
} else if (typeManager.IsSubtype(inResultOuter, parentTy) ||
(newDecl->TestAttr(Attribute::ABSTRACT) && !inResult->TestAttr(Attribute::ABSTRACT))) {
} else {
continue;
}
return;
}
InsertResultsWithInstTy(results.size(), &decl, parentTy);
results.emplace_back(&decl);
}
void LookUpImpl::FieldLookup(
const ClassDecl& cd, const std::string& fieldName, std::vector<Ptr<Decl>>& results, const LookupInfo& info)
{
if (!cd.body) {
return;
}
std::vector<Ptr<Decl>> decls;
for (auto& it : cd.body->decls) {
if (!it || IgnoredMember(*it)) {
continue;
}
decls.push_back(it.get());
}
for (auto& decl : decls) {
auto notValid = decl == nullptr || decl->identifier != fieldName;
if (notValid) {
continue;
}
auto staticAndNotClassLike = !decl->IsClassLikeDecl() && decl->TestAttr(Attribute::STATIC);
auto foundTy = info.baseTy;
if (staticAndNotClassLike) {
auto genericTy = foundTy ? Ty::GetGenericTyOfInsTy(*foundTy) : nullptr;
if (genericTy) {
foundTy = genericTy;
}
}
AddMemberIfValidForLookup(results, *TypeManager::GetNonNullTy(foundTy), info.isSetter, *decl);
}
if (!info.lookupInherit) {
return;
}
for (auto& it : cd.inheritedTypes) {
auto super = it ? Ty::GetDeclPtrOfTy(it->GetTy()) : nullptr;
if (!super || super->TestAttr(Attribute::IN_REFERENCE_CYCLE)) {
continue;
}
if (auto superClass = DynamicCast<ClassDecl*>(super)) {
auto superInfo = info;
superInfo.lookupExtend = true;
FieldLookup(*superClass, fieldName, results, superInfo);
} else if (Is<InterfaceDecl*>(super)) {
FieldLookup(*StaticCast<InterfaceTy>(it->GetTy()), fieldName, results, {info.baseTy});
}
}
if (info.lookupExtend) {
FieldLookupExtend(*cd.GetTy(), fieldName, results, info);
}
}
void LookUpImpl::FieldLookup(
InterfaceTy& idTy, const std::string& fieldName, std::vector<Ptr<Decl>>& results, const LookupInfo& info)
{
auto id = GetSpecificDecl<InterfaceDecl>(idTy.declPtr);
if (!id->body) {
return;
}
for (auto& decl : id->body->decls) {
if (decl == nullptr || decl->identifier != fieldName) {
continue;
}
auto foundTy = info.baseTy;
if (!decl->IsClassLikeDecl() && decl.get()->TestAttr(Attribute::STATIC)) {
auto genericTy = foundTy ? Ty::GetGenericTyOfInsTy(*foundTy) : nullptr;
if (genericTy) {
foundTy = genericTy;
}
}
if (decl->IsFuncOrProp()) {
ResolveOverrideOrShadow(results, *decl, &idTy);
} else {
InsertResultsWithInstTy(results.size(), decl.get(), &idTy);
results.emplace_back(decl.get());
}
}
if (!info.lookupInherit) {
return;
}
for (auto& it : id->inheritedTypes) {
if (!it) {
continue;
}
if (auto interfaceTy = DynamicCast<InterfaceTy*>(it->GetTy());
interfaceTy && interfaceTy->decl && !interfaceTy->decl->TestAttr(Attribute::IN_REFERENCE_CYCLE)) {
auto promTys = Promotion(typeManager).Promote(idTy, *it->GetTy());
for (auto promTy : promTys) {
FieldLookup(*StaticCast<InterfaceTy>(promTy), fieldName, results, {info.baseTy});
}
}
}
}
std::vector<Ptr<Decl>> LookUpImpl::FieldLookup(const EnumDecl& ed, const std::string& fieldName, const LookupInfo& info)
{
std::vector<Ptr<Decl>> results;
for (auto& ctor : ed.constructors) {
if (ctor->identifier == fieldName) {
results.push_back(ctor.get());
}
}
for (auto& func : ed.members) {
if (func->identifier == fieldName) {
results.push_back(func.get());
}
}
for (auto& it : ed.inheritedTypes) {
if (auto interfaceTy = DynamicCast<InterfaceTy*>(it->GetTy());
interfaceTy && interfaceTy->decl && !interfaceTy->decl->TestAttr(Attribute::IN_REFERENCE_CYCLE)) {
FieldLookup(*interfaceTy, fieldName, results, info);
}
}
if (info.lookupExtend) {
FieldLookupExtend(*ed.GetTy(), fieldName, results, info);
}
return results;
}
std::vector<Ptr<Decl>> LookUpImpl::FieldLookup(
const StructDecl& sd, const std::string& fieldName, const LookupInfo& info)
{
std::vector<Ptr<Decl>> results;
auto bodySetter = [&fieldName, &results](auto& decl) {
if (decl != nullptr && decl->identifier == fieldName && !IgnoredMember(*decl)) {
results.push_back(decl.get());
}
};
auto inheritedTypesSetter = [&fieldName, &results, &info, this](auto& it) {
if (it == nullptr) {
return;
}
if (auto interfaceTy = DynamicCast<InterfaceTy*>(it->GetTy());
interfaceTy && interfaceTy->decl && !interfaceTy->decl->TestAttr(Attribute::IN_REFERENCE_CYCLE)) {
FieldLookup(*interfaceTy, fieldName, results, info);
}
};
std::for_each(sd.body->decls.begin(), sd.body->decls.end(), bodySetter);
std::for_each(sd.inheritedTypes.begin(), sd.inheritedTypes.end(), inheritedTypesSetter);
if (info.lookupExtend) {
FieldLookupExtend(*sd.GetTy(), fieldName, results, info);
}
return results;
}
std::vector<Ptr<Decl>> LookUpImpl::FieldLookup(const PackageDecl& pd, const std::string& fieldName)
{
CJC_ASSERT(pd.TestAttr(Attribute::IMPORTED));
auto decls = importManager.GetPackageMembersByName(*pd.srcPackage, fieldName);
Utils::EraseIf(decls, [](auto decl) { return decl->TestAttr(Attribute::MAIN_ENTRY); });
return Utils::SetToVec<Ptr<Decl>>(decls);
}
std::vector<Ptr<Decl>> LookUpImpl::FieldLookup(Ptr<Decl> decl, const std::string& fieldName, const LookupInfo& info)
{
std::vector<Ptr<Decl>> results;
if (!decl) {
return results;
}
decl = GetSpecificDecl<Decl>(decl);
if (auto cd = DynamicCast<ClassDecl*>(decl)) {
FieldLookup(*cd, fieldName, results, info);
return results;
}
if (auto id = DynamicCast<InterfaceDecl*>(decl); id && Ty::IsTyCorrect(id->GetTy())) {
CJC_ASSERT(id->TyKind() == TypeKind::TYPE_INTERFACE);
FieldLookup(*StaticCast<InterfaceTy>(id->GetTy()), fieldName, results, info);
return results;
}
if (auto ed = DynamicCast<EnumDecl*>(decl)) {
return FieldLookup(*ed, fieldName, info);
}
if (auto sd = DynamicCast<StructDecl*>(decl)) {
return FieldLookup(*sd, fieldName, info);
}
if (auto pd = DynamicCast<PackageDecl*>(decl)) {
return FieldLookup(*pd, fieldName);
}
return results;
}
std::vector<Ptr<Decl>> LookUpImpl::StdLibFieldLookup(const Node& node, const std::string& fieldName)
{
std::vector<Ptr<Decl>> results;
Ptr<Decl> target = nullptr;
if (node.TestAttr(Attribute::IN_CORE)) {
target = importManager.GetCoreDecl(fieldName);
} else if (node.TestAttr(Attribute::IN_MACRO)) {
target = importManager.GetAstDecl(fieldName);
}
if (target) {
results.emplace_back(target);
}
return results;
}
namespace {
inline bool IsDefinedAfter(const Decl& target, const Node& ref)
{
return target.begin > ref.begin;
}
bool IsNodeInVarDecl(const ASTContext& ctx, const Node& node, VarDecl& vd)
{
bool found = false;
auto& nodeToSearch = ctx.GetOuterVarDeclAbstract(vd);
Walker walker(&nodeToSearch, [&node, &found](Ptr<const Node> n) -> VisitAction {
if (n == &node) {
found = true;
return VisitAction::STOP_NOW;
}
return VisitAction::WALK_CHILDREN;
});
walker.Walk();
return found;
}
bool IsNodeInDestructed(const Node& node, VarDecl& vd)
{
if (!vd.parentPattern || !vd.parentPattern->ctxExpr) {
return false;
}
bool found = false;
Walker walker(vd.parentPattern->ctxExpr, [&node, &found](Ptr<const Node> n) -> VisitAction {
if (n == &node) {
found = true;
return VisitAction::STOP_NOW;
}
return VisitAction::WALK_CHILDREN;
});
walker.Walk();
return found;
}
bool IsNodeInTypeAliasDecl(const Node& node, const TypeAliasDecl& tad)
{
bool found = false;
Walker walker(tad.type.get(), [&node, &found](Ptr<const Node> n) -> VisitAction {
if (n == &node) {
found = true;
return VisitAction::STOP_NOW;
}
return VisitAction::WALK_CHILDREN;
});
walker.Walk();
return found;
}
bool IsTargetVisibleToNode(const Decl& target, const Node& node)
{
return !target.TestAttr(Attribute::PRIVATE) || (target.curFile && node.curFile && *target.curFile == *node.curFile);
}
}
bool LookUpImpl::IsTargetMemberVisibleToNode(const Decl& target, const Node& node)
{
if (target.curFile && node.curFile && *target.curFile == *node.curFile) {
return true;
}
Symbol* sym = ScopeManager::GetCurSymbolByKind(SymbolKind::STRUCT, ctx, node.scopeName);
return IsLegalAccess(sym, target, node, importManager, typeManager);
}
bool LookUpImpl::FindRealResult(const Node& node, bool isSetter, std::vector<Ptr<Decl>>& results,
std::multimap<Position, Ptr<Decl>>& resultsMap, bool isInDeclBody)
{
bool wasAllFunction = !results.empty() && IsAllFuncDecl(results);
if (!results.empty() && !wasAllFunction) {
return true;
}
for (auto it : std::as_const(resultsMap)) {
auto targetDecl = it.second;
bool initFuncParam = targetDecl->begin == INVALID_POSITION && node.begin == INVALID_POSITION;
bool initAssignLHS = node.begin == INVALID_POSITION && node.scopeLevel > targetDecl->scopeLevel;
if (targetDecl->astKind == ASTKind::VAR_DECL) {
auto vd = RawStaticCast<VarDecl*>(targetDecl);
initAssignLHS = initAssignLHS || vd->isResourceVar;
}
bool orderRelated = !initFuncParam && !initAssignLHS && !(targetDecl->scopeLevel == 0 || isInDeclBody);
if ((orderRelated && IsDefinedAfter(*targetDecl, node)) || IgnoredMember(*targetDecl)) {
continue;
}
if ((wasAllFunction && !targetDecl->IsFunc())) {
return true;
}
if (targetDecl->astKind == ASTKind::TYPE_ALIAS_DECL) {
auto tad = RawStaticCast<TypeAliasDecl*>(targetDecl);
if (IsNodeInTypeAliasDecl(node, *tad)) {
continue;
}
}
if (!Is<VarDecl>(targetDecl)) {
results.emplace_back(RawStaticCast<Decl*>(targetDecl));
continue;
}
auto vd = RawStaticCast<VarDecl*>(targetDecl);
if (targetDecl->astKind != ASTKind::PROP_DECL &&
(IsNodeInVarDecl(ctx, node, *vd) || IsNodeInDestructed(node, *vd))) {
continue;
}
if (targetDecl->astKind == ASTKind::PROP_DECL) {
auto pd = RawStaticCast<PropDecl*>(targetDecl);
auto needContinue = (isSetter && pd->isVar && pd->setters.empty()) || (!isSetter && pd->getters.empty());
if (needContinue) {
continue;
}
}
results.emplace_back(vd);
if (auto refExpr = DynamicCast<const RefExpr*>(&node); refExpr && refExpr->callOrPattern) {
continue;
}
return true;
}
return false;
}
void LookUpImpl::ProcessStructDeclBody(
const std::string& name, const std::string& scopeName, const Node& node, std::vector<Ptr<Decl>>& results)
{
auto parentScopeName = ScopeManagerApi::GetParentScopeName(scopeName);
auto parentSopeGateName = ScopeManagerApi::GetScopeGateName(parentScopeName);
auto parentScopeGateSym = ScopeManagerApi::GetScopeGate(ctx, parentSopeGateName);
if (parentScopeGateSym == nullptr) {
return;
}
CJC_NULLPTR_CHECK(node.curFile);
auto currentDecl = StaticCast<Decl*>(parentScopeGateSym->node);
LookupInfo info{.baseTy = currentDecl->GetTy(),
.file = node.curFile,
.lookupExtend = currentDecl->astKind == ASTKind::EXTEND_DECL};
auto typeDecl = Ty::GetDeclPtrOfTy(currentDecl->GetTy());
if (!typeDecl) {
FieldLookupExtend(*currentDecl->GetTy(), name, results, info);
return;
}
auto fields = FieldLookup(typeDecl, name, info);
for (auto it : fields) {
if (auto vd = DynamicCast<VarDecl*>(it);
vd && it->astKind != ASTKind::PROP_DECL && IsNodeInVarDecl(ctx, node, *vd)) {
continue;
} else if (IsTargetMemberVisibleToNode(*it, node)) {
results.emplace_back(it);
}
}
}
bool LookUpImpl::LookupImpl(const std::string& name, std::string scopeName, const Node& node, bool onlyLookUpTopLevel,
bool isSetter, std::vector<Ptr<Decl>>& results)
{
do {
auto targetDecls = ctx.GetDeclsByName({name, scopeName});
std::multimap<Position, Ptr<Decl>> resultsMap;
for (auto decl : targetDecls) {
CJC_NULLPTR_CHECK(decl);
if (IsTargetVisibleToNode(*decl, node)) {
resultsMap.emplace(decl->begin, decl);
}
}
auto scopeGateName = ScopeManagerApi::GetScopeGateName(scopeName);
auto scopeGateSym = ScopeManagerApi::GetScopeGate(ctx, scopeGateName);
bool isInDeclBody = scopeGateSym != nullptr && scopeGateSym->node != nullptr &&
(scopeGateSym->node->IsNominalDeclBody() || scopeGateSym->node->TestAttr(Attribute::IN_EXTEND) ||
scopeGateSym->node->astKind == ASTKind::ENUM_DECL);
if (FindRealResult(node, isSetter, results, resultsMap, isInDeclBody)) {
return true;
}
if (scopeGateSym && scopeGateSym->node && scopeGateSym->node->IsNominalDeclBody() && !onlyLookUpTopLevel) {
ProcessStructDeclBody(name, scopeName, node, results);
}
scopeName = ScopeManagerApi::GetParentScopeName(scopeName);
if (!results.empty() && Is<VarDecl>(results[0])) {
return true;
}
} while (!scopeName.empty());
return false;
}
std::vector<Ptr<Decl>> LookUpImpl::Lookup(
const std::string& name, const std::string& scopeName, const Node& node, bool onlyLookUpTopLevel, bool isSetter)
{
std::vector<Ptr<Decl>> results = StdLibFieldLookup(node, name);
if (!results.empty()) {
return results;
}
if (name == INVALID_IDENTIFIER) {
return results;
}
if (scopeName.empty()) {
diag.Diagnose(node, DiagKind::sema_symbol_not_collected, name);
return results;
}
if (LookupImpl(name, scopeName, node, onlyLookUpTopLevel, isSetter, results)) {
return results;
}
if (!results.empty() && !IsAllFuncDecl(results)) {
return results;
} else {
auto importDecls = importManager.GetImportedDeclsByName(*node.curFile, name);
results.insert(results.end(), importDecls.begin(), importDecls.end());
}
for (auto it = results.begin(); it != results.end(); ++it) {
bool self = true;
for (auto i = it; i != results.end();) {
if (self) {
self = false;
} else if (*it == *i) {
i = results.erase(i);
continue;
}
++i;
}
}
return results;
}
std::vector<Ptr<Decl>> TypeChecker::TypeCheckerImpl::FieldLookup(
const ASTContext& ctx, Ptr<Decl> decl, const std::string& fieldName, const LookupInfo& info)
{
LookUpImpl lookUpImpl(ctx, diag, typeManager, importManager);
return lookUpImpl.FieldLookup(decl, fieldName, info);
}
std::vector<Ptr<Decl>> TypeChecker::TypeCheckerImpl::Lookup(
const ASTContext& ctx, const std::string& name, const std::string& scopeName, const Node& node, bool isSetter)
{
LookUpImpl lookUpImpl(ctx, diag, typeManager, importManager);
return lookUpImpl.Lookup(name, scopeName, node, false, isSetter);
}
std::vector<Ptr<Decl>> TypeChecker::TypeCheckerImpl::LookupTopLevel(
const ASTContext& ctx, const std::string& name, const std::string& scopeName, const Node& node, bool isSetter)
{
LookUpImpl lookUpImpl(ctx, diag, typeManager, importManager);
return lookUpImpl.Lookup(name, scopeName, node, true, isSetter);
}
std::vector<Ptr<Decl>> TypeChecker::TypeCheckerImpl::ExtendFieldLookup(
const ASTContext& ctx, const File& file, Ptr<Ty> ty, const std::string& fieldName)
{
LookUpImpl lookUpImpl(ctx, diag, typeManager, importManager);
std::vector<Ptr<Decl>> results = {};
if (Ty::IsTyCorrect(ty)) {
LookupInfo info{ty, &file};
lookUpImpl.FieldLookupExtend(*ty, fieldName, results, info);
}
return results;
}