Merge pull request #19742 from AnthonyLatsis/class-var-override-compl

[CodeCompletion][Parser] Completions for overridable static members
This commit is contained in:
Rintaro Ishizaki
2019-02-26 09:52:37 -08:00
committed by GitHub
8 changed files with 204 additions and 40 deletions

View File

@@ -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;
}