blob: 66df111402addcacddfae2c3e16827ae3d49ec3d [file] [log] [blame]
//===--- AccessScopeChecker.cpp - Access calculation helpers ----- --------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/AST/AccessScopeChecker.h"
#include "swift/AST/Module.h"
#include "swift/AST/TypeRepr.h"
#include "swift/AST/Types.h"
using namespace swift;
//----------------------------------------------------------------------------//
// Access Scope Checkers
//----------------------------------------------------------------------------//
AccessScopeChecker::AccessScopeChecker(const DeclContext *useDC,
bool treatUsableFromInlineAsPublic)
: File(useDC->getParentSourceFile()),
TreatUsableFromInlineAsPublic(treatUsableFromInlineAsPublic) {}
bool
AccessScopeChecker::visitDecl(const ValueDecl *VD) {
if (isa<GenericTypeParamDecl>(VD))
return true;
auto AS = VD->getFormalAccessScope(File, TreatUsableFromInlineAsPublic);
Scope = Scope->intersectWith(AS);
return Scope.hasValue();
}
bool TypeReprIdentFinder::walkToTypeReprPost(TypeRepr *TR) {
auto CITR = dyn_cast<ComponentIdentTypeRepr>(TR);
if (!CITR || !CITR->getBoundDecl())
return true;
return Callback(CITR);
}
Optional<AccessScope>
AccessScopeChecker::getAccessScope(TypeRepr *TR, const DeclContext *useDC,
bool treatUsableFromInlineAsPublic) {
AccessScopeChecker checker(useDC, treatUsableFromInlineAsPublic);
TR->walk(TypeReprIdentFinder([&](const ComponentIdentTypeRepr *typeRepr) {
return checker.visitDecl(typeRepr->getBoundDecl());
}));
return checker.Scope;
}
TypeWalker::Action TypeDeclFinder::walkToTypePre(Type T) {
if (auto *TAT = dyn_cast<TypeAliasType>(T.getPointer()))
return visitTypeAliasType(TAT);
// FIXME: We're looking through sugar here so that we visit, e.g.,
// Swift.Array when we see `[Int]`. But that means we do redundant work when
// we see sugar that's purely structural, like `(Int)`. Fortunately, paren
// types are the only such purely structural sugar at the time this comment
// was written, and they're not so common in the first place.
if (auto *BGT = T->getAs<BoundGenericType>())
return visitBoundGenericType(BGT);
if (auto *NT = T->getAs<NominalType>())
return visitNominalType(NT);
return Action::Continue;
}
TypeWalker::Action
SimpleTypeDeclFinder::visitNominalType(const NominalType *ty) {
return Callback(ty->getDecl());
}
TypeWalker::Action
SimpleTypeDeclFinder::visitBoundGenericType(const BoundGenericType *ty) {
return Callback(ty->getDecl());
}
TypeWalker::Action
SimpleTypeDeclFinder::visitTypeAliasType(const TypeAliasType *ty) {
return Callback(ty->getDecl());
}
Optional<AccessScope>
AccessScopeChecker::getAccessScope(Type T, const DeclContext *useDC,
bool treatUsableFromInlineAsPublic) {
AccessScopeChecker checker(useDC, treatUsableFromInlineAsPublic);
T.walk(SimpleTypeDeclFinder([&](const ValueDecl *VD) {
if (checker.visitDecl(VD))
return TypeWalker::Action::Continue;
return TypeWalker::Action::Stop;
}));
return checker.Scope;
}