mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #19742 from AnthonyLatsis/class-var-override-compl
[CodeCompletion][Parser] Completions for overridable static members
This commit is contained in:
@@ -1250,6 +1250,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
|
||||
Optional<StmtKind> ParentStmtKind;
|
||||
|
||||
SmallVector<StringRef, 3> ParsedKeywords;
|
||||
SourceLoc introducerLoc;
|
||||
|
||||
std::vector<std::pair<std::string, bool>> SubModuleNameVisibilityPairs;
|
||||
|
||||
@@ -1348,7 +1349,7 @@ public:
|
||||
void completeDeclAttrParam(DeclAttrKind DK, int Index) override;
|
||||
void completeInPrecedenceGroup(SyntaxKind SK) override;
|
||||
void completeNominalMemberBeginning(
|
||||
SmallVectorImpl<StringRef> &Keywords) override;
|
||||
SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) override;
|
||||
void completeAccessorBeginning() override;
|
||||
|
||||
void completePoundAvailablePlatform() override;
|
||||
@@ -3858,9 +3859,11 @@ public:
|
||||
|
||||
class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
|
||||
CodeCompletionResultSink &Sink;
|
||||
ASTContext &Ctx;
|
||||
const DeclContext *CurrDeclContext;
|
||||
LazyResolver *TypeResolver;
|
||||
SmallVectorImpl<StringRef> &ParsedKeywords;
|
||||
SourceLoc introducerLoc;
|
||||
|
||||
bool hasFuncIntroducer = false;
|
||||
bool hasVarIntroducer = false;
|
||||
@@ -3869,13 +3872,15 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
|
||||
bool hasAccessModifier = false;
|
||||
bool hasOverride = false;
|
||||
bool hasOverridabilityModifier = false;
|
||||
bool hasStaticOrClass = false;
|
||||
|
||||
public:
|
||||
CompletionOverrideLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
|
||||
const DeclContext *CurrDeclContext,
|
||||
SmallVectorImpl<StringRef> &ParsedKeywords)
|
||||
: Sink(Sink),
|
||||
CurrDeclContext(CurrDeclContext), ParsedKeywords(ParsedKeywords) {
|
||||
SmallVectorImpl<StringRef> &ParsedKeywords,
|
||||
SourceLoc introducerLoc)
|
||||
: Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
|
||||
ParsedKeywords(ParsedKeywords), introducerLoc(introducerLoc) {
|
||||
(void)createTypeChecker(Ctx);
|
||||
TypeResolver = Ctx.getLazyResolver();
|
||||
|
||||
@@ -3893,6 +3898,8 @@ public:
|
||||
hasOverride = isKeywordSpecified("override");
|
||||
hasOverridabilityModifier = isKeywordSpecified("final") ||
|
||||
isKeywordSpecified("open");
|
||||
hasStaticOrClass = isKeywordSpecified(getTokenText(tok::kw_class)) ||
|
||||
isKeywordSpecified(getTokenText(tok::kw_static));
|
||||
}
|
||||
|
||||
bool isKeywordSpecified(StringRef Word) {
|
||||
@@ -3942,8 +3949,10 @@ public:
|
||||
Options.setBaseType(transformType);
|
||||
Options.PrintImplicitAttrs = false;
|
||||
Options.ExclusiveAttrList.push_back(TAK_escaping);
|
||||
Options.ExclusiveAttrList.push_back(TAK_autoclosure);
|
||||
Options.PrintOverrideKeyword = false;
|
||||
Options.PrintPropertyAccessors = false;
|
||||
Options.PrintStaticKeyword = !hasStaticOrClass;
|
||||
VD->print(Printer, Options);
|
||||
NameOffset = Printer.NameOffset.getValue();
|
||||
}
|
||||
@@ -3951,10 +3960,17 @@ public:
|
||||
if (!hasDeclIntroducer && !hasAccessModifier)
|
||||
addAccessControl(VD, Builder);
|
||||
|
||||
// FIXME: if we're missing 'override', but have the decl introducer we
|
||||
// should delete it and re-add both in the correct order.
|
||||
if (!hasDeclIntroducer && missingOverride(Reason))
|
||||
Builder.addOverrideKeyword();
|
||||
if (missingOverride(Reason)) {
|
||||
if (!hasDeclIntroducer)
|
||||
Builder.addOverrideKeyword();
|
||||
else {
|
||||
auto dist = Ctx.SourceMgr.getByteDistance(
|
||||
introducerLoc, Ctx.SourceMgr.getCodeCompletionLoc());
|
||||
Builder.setNumBytesToErase(dist);
|
||||
Builder.addOverrideKeyword();
|
||||
Builder.addDeclIntroducer(DeclStr.str().substr(0, NameOffset));
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasDeclIntroducer)
|
||||
Builder.addDeclIntroducer(DeclStr.str().substr(0, NameOffset));
|
||||
@@ -4050,7 +4066,9 @@ public:
|
||||
if (D->shouldHideFromEditor())
|
||||
return;
|
||||
|
||||
if (D->getAttrs().hasAttribute<FinalAttr>())
|
||||
if (D->getAttrs().hasAttribute<FinalAttr>() ||
|
||||
// A 'class' member with an initial value cannot be overriden either.
|
||||
(D->isStatic() && D->getAttrs().hasAttribute<HasInitialValueAttr>()))
|
||||
return;
|
||||
|
||||
if (!D->hasInterfaceType())
|
||||
@@ -4060,6 +4078,15 @@ public:
|
||||
hasVarIntroducer ||
|
||||
hasTypealiasIntroducer;
|
||||
|
||||
if (hasStaticOrClass && !D->isStatic())
|
||||
return;
|
||||
|
||||
// As per the current convention, only instance members are
|
||||
// suggested if an introducer is not accompanied by a 'static' or
|
||||
// 'class' modifier.
|
||||
if (hasIntroducer && !hasStaticOrClass && D->isStatic())
|
||||
return;
|
||||
|
||||
if (auto *FD = dyn_cast<FuncDecl>(D)) {
|
||||
// We cannot override operators as members.
|
||||
if (FD->isBinaryOperator() || FD->isUnaryOperator())
|
||||
@@ -4083,7 +4110,8 @@ public:
|
||||
if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
|
||||
if (!isa<ProtocolDecl>(CD->getDeclContext()))
|
||||
return;
|
||||
if (hasIntroducer || hasOverride || hasOverridabilityModifier)
|
||||
if (hasIntroducer || hasOverride || hasOverridabilityModifier ||
|
||||
hasStaticOrClass)
|
||||
return;
|
||||
if (CD->isRequired() || CD->isDesignatedInit())
|
||||
addConstructor(CD, Reason);
|
||||
@@ -4093,7 +4121,7 @@ public:
|
||||
|
||||
void addDesignatedInitializers(NominalTypeDecl *NTD) {
|
||||
if (hasFuncIntroducer || hasVarIntroducer || hasTypealiasIntroducer ||
|
||||
hasOverridabilityModifier)
|
||||
hasOverridabilityModifier || hasStaticOrClass)
|
||||
return;
|
||||
|
||||
const auto *CD = dyn_cast<ClassDecl>(NTD);
|
||||
@@ -4116,7 +4144,7 @@ public:
|
||||
void addAssociatedTypes(NominalTypeDecl *NTD) {
|
||||
if (!hasTypealiasIntroducer &&
|
||||
(hasFuncIntroducer || hasVarIntroducer || hasInitializerModifier ||
|
||||
hasOverride || hasOverridabilityModifier))
|
||||
hasOverride || hasOverridabilityModifier || hasStaticOrClass))
|
||||
return;
|
||||
|
||||
for (auto Conformance : NTD->getAllConformances()) {
|
||||
@@ -4147,9 +4175,11 @@ public:
|
||||
Type CurrTy = CurrDeclContext->getSelfTypeInContext();
|
||||
auto *NTD = CurrDeclContext->getSelfNominalTypeDecl();
|
||||
if (CurrTy && !CurrTy->is<ErrorType>()) {
|
||||
lookupVisibleMemberDecls(*this, CurrTy, CurrDeclContext,
|
||||
// Look for overridable static members too.
|
||||
Type Meta = MetatypeType::get(CurrTy);
|
||||
lookupVisibleMemberDecls(*this, Meta, CurrDeclContext,
|
||||
TypeResolver,
|
||||
/*includeInstanceMembers=*/false);
|
||||
/*includeInstanceMembers=*/true);
|
||||
addDesignatedInitializers(NTD);
|
||||
addAssociatedTypes(NTD);
|
||||
}
|
||||
@@ -4471,8 +4501,9 @@ void CodeCompletionCallbacksImpl::completeGenericParams(TypeLoc TL) {
|
||||
}
|
||||
|
||||
void CodeCompletionCallbacksImpl::completeNominalMemberBeginning(
|
||||
SmallVectorImpl<StringRef> &Keywords) {
|
||||
SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) {
|
||||
assert(!InEnumElementRawValue);
|
||||
this->introducerLoc = introducerLoc;
|
||||
ParsedKeywords.clear();
|
||||
ParsedKeywords.append(Keywords.begin(), Keywords.end());
|
||||
Kind = CompletionKind::NominalMemberBeginning;
|
||||
@@ -4651,10 +4682,11 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
|
||||
break;
|
||||
|
||||
case CompletionKind::NominalMemberBeginning: {
|
||||
bool HasDeclIntroducer = llvm::find_if(ParsedKeywords, [](const StringRef kw) {
|
||||
bool HasDeclIntroducer = llvm::find_if(ParsedKeywords,
|
||||
[this](const StringRef kw) {
|
||||
return llvm::StringSwitch<bool>(kw)
|
||||
.Case("associatedtype", true)
|
||||
.Case("class", true)
|
||||
.Case("class", !CurDeclContext || !isa<ClassDecl>(CurDeclContext))
|
||||
.Case("deinit", true)
|
||||
.Case("enum", true)
|
||||
.Case("extension", true)
|
||||
@@ -5027,7 +5059,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
|
||||
case CompletionKind::NominalMemberBeginning: {
|
||||
CompletionOverrideLookup OverrideLookup(CompletionContext.getResultSink(),
|
||||
P.Context, CurDeclContext,
|
||||
ParsedKeywords);
|
||||
ParsedKeywords, introducerLoc);
|
||||
OverrideLookup.getOverrideCompletions(SourceLoc());
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user