Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/swift/AST/ASTTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//===----------------------------------------------------------------------===//
SWIFT_TYPEID_NAMED(NominalTypeDecl *, NominalTypeDecl)
SWIFT_TYPEID_NAMED(VarDecl *, VarDecl)
SWIFT_TYPEID_NAMED(ValueDecl *, ValueDecl)
SWIFT_TYPEID_NAMED(Decl *, Decl)
SWIFT_TYPEID(Type)
SWIFT_TYPEID(PropertyWrapperBackingPropertyInfo)
Expand Down
2 changes: 2 additions & 0 deletions include/swift/IDE/IDERequestIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@
//===----------------------------------------------------------------------===//
SWIFT_TYPEID(CursorInfoRequest)
SWIFT_TYPEID(RangeInfoRequest)
SWIFT_TYPEID(ProvideDefaultImplForRequest)
SWIFT_TYPEID(CollectOverriddenDeclsRequest)
89 changes: 89 additions & 0 deletions include/swift/IDE/IDERequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,95 @@ class RangeInfoRequest:
SourceLoc getNearestLoc() const;
};

//----------------------------------------------------------------------------//
// ProvideDefaultImplForRequest
//----------------------------------------------------------------------------//
/// Collect all the protocol requirements that a given declaration can
/// provide default implementations for. Input is a declaration in extension
/// declaration. The result is an array of requirements.
class ProvideDefaultImplForRequest:
public SimpleRequest<ProvideDefaultImplForRequest,
ArrayRef<ValueDecl*>(ValueDecl*),
CacheKind::Cached>
{
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

// Evaluation.
llvm::Expected<ArrayRef<ValueDecl*>> evaluate(Evaluator &evaluator,
ValueDecl* VD) const;

public:
// Caching
bool isCached() const { return true; }
// Source location
SourceLoc getNearestLoc() const { return SourceLoc(); };
};

//----------------------------------------------------------------------------//
// CollectOverriddenDeclsRequest
//----------------------------------------------------------------------------//
struct OverridenDeclsOwner {
ValueDecl *VD;
bool IncludeProtocolRequirements;
bool Transitive;

OverridenDeclsOwner(ValueDecl *VD, bool IncludeProtocolRequirements,
bool Transitive): VD(VD),
IncludeProtocolRequirements(IncludeProtocolRequirements),
Transitive(Transitive) {}

friend llvm::hash_code hash_value(const OverridenDeclsOwner &CI) {
return hash_combine(hash_value(CI.VD),
hash_value(CI.IncludeProtocolRequirements),
hash_value(CI.Transitive));
}

friend bool operator==(const OverridenDeclsOwner &lhs,
const OverridenDeclsOwner &rhs) {
return lhs.VD == rhs.VD &&
lhs.IncludeProtocolRequirements == rhs.IncludeProtocolRequirements &&
lhs.Transitive == rhs.Transitive;
}

friend bool operator!=(const OverridenDeclsOwner &lhs,
const OverridenDeclsOwner &rhs) {
return !(lhs == rhs);
}

friend void simple_display(llvm::raw_ostream &out,
const OverridenDeclsOwner &owner) {
simple_display(out, owner.VD);
}
};

/// Get decls that the given decl overrides, protocol requirements that
/// it serves as a default implementation of, and optionally protocol
/// requirements it satisfies in a conforming class
class CollectOverriddenDeclsRequest:
public SimpleRequest<CollectOverriddenDeclsRequest,
ArrayRef<ValueDecl*>(OverridenDeclsOwner),
CacheKind::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

// Evaluation.
llvm::Expected<ArrayRef<ValueDecl*>> evaluate(Evaluator &evaluator,
OverridenDeclsOwner Owner) const;

public:
// Caching
bool isCached() const { return true; }
// Source location
SourceLoc getNearestLoc() const { return SourceLoc(); };
};

/// The zone number for the IDE.
#define SWIFT_IDE_REQUESTS_TYPEID_ZONE 137
#define SWIFT_TYPEID_ZONE SWIFT_IDE_REQUESTS_TYPEID_ZONE
Expand Down
5 changes: 2 additions & 3 deletions include/swift/Sema/IDETypeChecking.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,12 @@ namespace swift {
///
/// \returns the slice of Scratch
ArrayRef<ValueDecl*>
canDeclProvideDefaultImplementationFor(ValueDecl* VD,
llvm::SmallVectorImpl<ValueDecl*> &Scratch);
canDeclProvideDefaultImplementationFor(ValueDecl* VD);

/// Get decls that the given decl overrides, protocol requirements that
/// it serves as a default implementation of, and optionally protocol
/// requirements it satisfies in a conforming class
std::vector<ValueDecl*>
ArrayRef<ValueDecl*>
collectAllOverriddenDecls(ValueDecl *VD,
bool IncludeProtocolRequirements = true,
bool Transitive = false);
Expand Down
5 changes: 5 additions & 0 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ bool CompilerInstance::setUpASTContextIfNeeded() {
Diagnostics));
registerTypeCheckerRequestFunctions(Context->evaluator);

// Migrator and indexing need some IDE requests.
if (Invocation.getMigratorOptions().shouldRunMigrator() ||
!Invocation.getFrontendOptions().IndexStorePath.empty()) {
registerIDERequestFunctions(Context->evaluator);
}
if (setUpModuleLoaders())
return true;

Expand Down
70 changes: 70 additions & 0 deletions lib/IDE/IDERequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/Utils.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/Markup/XMLUtils.h"
#include "swift/Subsystems.h"
#include "swift/IDE/IDERequests.h"
Expand Down Expand Up @@ -1073,3 +1074,72 @@ void
swift::ide::simple_display(llvm::raw_ostream &out, const ResolvedRangeInfo &info) {
info.print(out);
}

//----------------------------------------------------------------------------//
// ProvideDefaultImplForRequest
//----------------------------------------------------------------------------//
static Type getContextFreeInterfaceType(ValueDecl *VD) {
if (auto AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
return AFD->getMethodInterfaceType();
}
return VD->getInterfaceType();
}

llvm::Expected<ArrayRef<ValueDecl*>>
ProvideDefaultImplForRequest::evaluate(Evaluator &eval, ValueDecl* VD) const {
// Skip decls that don't have valid names.
if (!VD->getFullName())
return ArrayRef<ValueDecl*>();

// Check if VD is from a protocol extension.
auto P = VD->getDeclContext()->getExtendedProtocolDecl();
if (!P)
return ArrayRef<ValueDecl*>();
SmallVector<ValueDecl*, 8> Results;
// Look up all decls in the protocol's inheritance chain for the ones with
// the same name with VD.
ResolvedMemberResult LookupResult =
resolveValueMember(*P->getInnermostDeclContext(),
P->getDeclaredInterfaceType(), VD->getFullName());

auto VDType = getContextFreeInterfaceType(VD);
for (auto Mem : LookupResult.getMemberDecls(InterestedMemberKind::All)) {
if (isa<ProtocolDecl>(Mem->getDeclContext())) {
if (Mem->isProtocolRequirement() &&
getContextFreeInterfaceType(Mem)->isEqual(VDType)) {
// We find a protocol requirement VD can provide default
// implementation for.
Results.push_back(Mem);
}
}
}
return copyToContext(VD->getASTContext(), llvm::makeArrayRef(Results));
}

//----------------------------------------------------------------------------//
// CollectOverriddenDeclsRequest
//----------------------------------------------------------------------------//
llvm::Expected<ArrayRef<ValueDecl*>>
CollectOverriddenDeclsRequest::evaluate(Evaluator &evaluator,
OverridenDeclsOwner Owner) const {
std::vector<ValueDecl*> results;
auto *VD = Owner.VD;
if (auto Overridden = VD->getOverriddenDecl()) {
results.push_back(Overridden);
while (Owner.Transitive && (Overridden = Overridden->getOverriddenDecl()))
results.push_back(Overridden);
}

for (auto Req : evaluateOrDefault(evaluator, ProvideDefaultImplForRequest(VD),
ArrayRef<ValueDecl*>())) {
results.push_back(Req);
}

if (Owner.IncludeProtocolRequirements) {
for (auto Satisfied : VD->getSatisfiedProtocolRequirements()) {
results.push_back(Satisfied);
}
}

return copyToContext(VD->getASTContext(), llvm::makeArrayRef(results));
}
70 changes: 10 additions & 60 deletions lib/IDE/IDETypeChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "swift/AST/ProtocolConformance.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/IDERequests.h"
#include "swift/Parse/Lexer.h"

using namespace swift;
Expand Down Expand Up @@ -741,68 +742,17 @@ swift::collectExpressionType(SourceFile &SF,
return Scratch;
}

static Type getContextFreeInterfaceType(ValueDecl *VD) {
if (auto AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
return AFD->getMethodInterfaceType();
}
return VD->getInterfaceType();
}

ArrayRef<ValueDecl*> swift::
canDeclProvideDefaultImplementationFor(ValueDecl* VD,
llvm::SmallVectorImpl<ValueDecl*> &Scratch) {

// Skip decls that don't have valid names.
if (!VD->getFullName())
return {};

// Check if VD is from a protocol extension.
auto P = VD->getDeclContext()->getExtendedProtocolDecl();
if (!P)
return {};

// Look up all decls in the protocol's inheritance chain for the ones with
// the same name with VD.
ResolvedMemberResult LookupResult =
resolveValueMember(*P->getInnermostDeclContext(),
P->getDeclaredInterfaceType(), VD->getFullName());

auto VDType = getContextFreeInterfaceType(VD);
for (auto Mem : LookupResult.getMemberDecls(InterestedMemberKind::All)) {
if (isa<ProtocolDecl>(Mem->getDeclContext())) {
if (Mem->isProtocolRequirement() &&
getContextFreeInterfaceType(Mem)->isEqual(VDType)) {
// We find a protocol requirement VD can provide default
// implementation for.
Scratch.push_back(Mem);
}
}
}
return Scratch;
canDeclProvideDefaultImplementationFor(ValueDecl* VD) {
return evaluateOrDefault(VD->getASTContext().evaluator,
ProvideDefaultImplForRequest(VD),
ArrayRef<ValueDecl*>());
}

std::vector<ValueDecl*> swift::
ArrayRef<ValueDecl*> swift::
collectAllOverriddenDecls(ValueDecl *VD, bool IncludeProtocolRequirements,
bool Transitive) {
std::vector<ValueDecl*> results;

if (auto Overridden = VD->getOverriddenDecl()) {
results.push_back(Overridden);
while (Transitive && (Overridden = Overridden->getOverriddenDecl()))
results.push_back(Overridden);
}

// Collect the protocol requirements this decl is a default impl for
llvm::SmallVector<ValueDecl*, 2> Buffer;
for (auto Req : canDeclProvideDefaultImplementationFor(VD, Buffer)) {
results.push_back(Req);
}

if (IncludeProtocolRequirements) {
for (auto Satisfied : VD->getSatisfiedProtocolRequirements()) {
results.push_back(Satisfied);
}
}

return results;
bool Transitive) {
return evaluateOrDefault(VD->getASTContext().evaluator,
CollectOverriddenDeclsRequest(OverridenDeclsOwner(VD,
IncludeProtocolRequirements, Transitive)), ArrayRef<ValueDecl*>());
}
5 changes: 4 additions & 1 deletion tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ void SwiftLangSupport::indexSource(StringRef InputFile,
if (IsModuleIndexing) {
if (CI.setup(Invocation))
return;
// Indexing needs IDE requests
registerIDERequestFunctions(CI.getASTContext().evaluator);
bool IsClangModule = (FileExt == ".pcm");
if (IsClangModule) {
IdxConsumer.failed("Clang module files are not supported");
Expand All @@ -292,7 +294,8 @@ void SwiftLangSupport::indexSource(StringRef InputFile,

if (CI.setup(Invocation))
return;

// Indexing needs IDE requests
registerIDERequestFunctions(CI.getASTContext().evaluator);
trace::TracedOperation TracedOp(trace::OperationKind::IndexSource);
if (TracedOp.enabled()) {
trace::SwiftInvocation SwiftArgs;
Expand Down