Skip to content

Commit 4fc3531

Browse files
authored
Merge pull request #4518 from rintaro/cc-override-modifier
[CodeCompletion] Modifier related improvements in CompletionOverrideLookup
2 parents ec0f472 + b827298 commit 4fc3531

7 files changed

+258
-72
lines changed

lib/IDE/CodeCompletion.cpp

+83-41
Original file line numberDiff line numberDiff line change
@@ -4080,6 +4080,11 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
40804080

40814081
bool hasFuncIntroducer = false;
40824082
bool hasVarIntroducer = false;
4083+
bool hasTypealiasIntroducer = false;
4084+
bool hasInitializerModifier = false;
4085+
bool hasAccessModifier = false;
4086+
bool hasOverride = false;
4087+
bool hasOverridabilityModifier = false;
40834088

40844089
public:
40854090
CompletionOverrideLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
@@ -4088,17 +4093,41 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
40884093
: Sink(Sink), TypeResolver(createLazyResolver(Ctx)),
40894094
CurrDeclContext(CurrDeclContext), ParsedKeywords(ParsedKeywords) {
40904095
hasFuncIntroducer = isKeywordSpecified("func");
4091-
hasVarIntroducer = isKeywordSpecified("var") || isKeywordSpecified("let");
4096+
hasVarIntroducer = isKeywordSpecified("var") ||
4097+
isKeywordSpecified("let");
4098+
hasTypealiasIntroducer = isKeywordSpecified("typealias");
4099+
hasInitializerModifier = isKeywordSpecified("required") ||
4100+
isKeywordSpecified("convenience");
4101+
hasAccessModifier = isKeywordSpecified("private") ||
4102+
isKeywordSpecified("fileprivate") ||
4103+
isKeywordSpecified("internal") ||
4104+
isKeywordSpecified("public") ||
4105+
isKeywordSpecified("open");
4106+
hasOverride = isKeywordSpecified("override");
4107+
hasOverridabilityModifier = isKeywordSpecified("final") ||
4108+
isKeywordSpecified("open");
40924109
}
40934110

40944111
bool isKeywordSpecified(StringRef Word) {
40954112
return std::find(ParsedKeywords.begin(), ParsedKeywords.end(), Word)
40964113
!= ParsedKeywords.end();
40974114
}
40984115

4116+
void addAccessControl(const ValueDecl *VD,
4117+
CodeCompletionResultBuilder &Builder) {
4118+
assert(CurrDeclContext->getAsGenericTypeOrGenericTypeExtensionContext());
4119+
auto AccessibilityOfContext =
4120+
CurrDeclContext->getAsGenericTypeOrGenericTypeExtensionContext()
4121+
->getFormalAccess();
4122+
auto Access = std::min(VD->getFormalAccess(), AccessibilityOfContext);
4123+
// Only emit 'public', not needed otherwise.
4124+
if (Access >= Accessibility::Public)
4125+
Builder.addAccessControlKeyword(Access);
4126+
}
4127+
40994128
void addValueOverride(const ValueDecl *VD, DeclVisibilityKind Reason,
41004129
CodeCompletionResultBuilder &Builder,
4101-
StringRef DeclIntroducer = "") {
4130+
bool hasDeclIntroducer) {
41024131

41034132
class DeclNameOffsetLocatorPrinter : public StreamPrinter {
41044133
public:
@@ -4129,37 +4158,18 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41294158
NameOffset = Printer.NameOffset.getValue();
41304159
}
41314160

4132-
assert(CurrDeclContext->getAsGenericTypeOrGenericTypeExtensionContext());
4133-
Accessibility AccessibilityOfContext =
4134-
CurrDeclContext->getAsGenericTypeOrGenericTypeExtensionContext()
4135-
->getFormalAccess();
4136-
4137-
bool missingDeclIntroducer = !hasVarIntroducer && !hasFuncIntroducer;
4138-
bool missingAccess = !isKeywordSpecified("private") &&
4139-
!isKeywordSpecified("fileprivate") &&
4140-
!isKeywordSpecified("internal") &&
4141-
!isKeywordSpecified("public");
4142-
bool missingOverride = Reason == DeclVisibilityKind::MemberOfSuper &&
4143-
!isKeywordSpecified("override");
4144-
4145-
if (missingDeclIntroducer && missingAccess) {
4146-
auto Access = std::min(VD->getFormalAccess(), AccessibilityOfContext);
4147-
// Only emit 'public', not needed otherwise.
4148-
if (Access >= Accessibility::Public)
4149-
Builder.addAccessControlKeyword(Access);
4150-
}
4161+
if (!hasDeclIntroducer && !hasAccessModifier)
4162+
addAccessControl(VD, Builder);
41514163

41524164
// FIXME: if we're missing 'override', but have the decl introducer we
41534165
// should delete it and re-add both in the correct order.
4154-
if (missingDeclIntroducer && missingOverride)
4166+
bool missingOverride = Reason == DeclVisibilityKind::MemberOfSuper &&
4167+
!hasOverride;
4168+
if (!hasDeclIntroducer && missingOverride)
41554169
Builder.addOverrideKeyword();
41564170

4157-
if (missingDeclIntroducer) {
4158-
if (DeclIntroducer.empty())
4159-
Builder.addDeclIntroducer(DeclStr.str().substr(0, NameOffset));
4160-
else
4161-
Builder.addDeclIntroducer(DeclIntroducer);
4162-
}
4171+
if (!hasDeclIntroducer)
4172+
Builder.addDeclIntroducer(DeclStr.str().substr(0, NameOffset));
41634173

41644174
Builder.addTextChunk(DeclStr.str().substr(NameOffset));
41654175
}
@@ -4169,7 +4179,7 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41694179
Sink, CodeCompletionResult::ResultKind::Declaration,
41704180
SemanticContextKind::Super, {});
41714181
Builder.setAssociatedDecl(FD);
4172-
addValueOverride(FD, Reason, Builder);
4182+
addValueOverride(FD, Reason, Builder, hasFuncIntroducer);
41734183
Builder.addBraceStmtWithCursor();
41744184
}
41754185

@@ -4178,27 +4188,54 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
41784188
Sink, CodeCompletionResult::ResultKind::Declaration,
41794189
SemanticContextKind::Super, {});
41804190
Builder.setAssociatedDecl(VD);
4181-
addValueOverride(VD, Reason, Builder);
4191+
addValueOverride(VD, Reason, Builder, hasVarIntroducer);
41824192
}
41834193

41844194
void addTypeAlias(const AssociatedTypeDecl *ATD, DeclVisibilityKind Reason) {
41854195
CodeCompletionResultBuilder Builder(Sink,
41864196
CodeCompletionResult::ResultKind::Declaration,
41874197
SemanticContextKind::Super, {});
41884198
Builder.setAssociatedDecl(ATD);
4189-
addValueOverride(ATD, Reason, Builder, "typealias ");
4199+
if (!hasTypealiasIntroducer && !hasAccessModifier)
4200+
addAccessControl(ATD, Builder);
4201+
if (!hasTypealiasIntroducer)
4202+
Builder.addDeclIntroducer("typealias ");
4203+
Builder.addTextChunk(ATD->getName().str());
41904204
Builder.addTextChunk(" = ");
41914205
Builder.addSimpleNamedParameter("Type");
41924206
}
41934207

4194-
void addConstructor(const ConstructorDecl *CD) {
4208+
void addConstructor(const ConstructorDecl *CD, DeclVisibilityKind Reason) {
41954209
CodeCompletionResultBuilder Builder(
41964210
Sink,
41974211
CodeCompletionResult::ResultKind::Declaration,
41984212
SemanticContextKind::Super, {});
41994213
Builder.setAssociatedDecl(CD);
42004214

4215+
if (!hasAccessModifier)
4216+
addAccessControl(CD, Builder);
4217+
4218+
if (!hasOverride && Reason == DeclVisibilityKind::MemberOfSuper &&
4219+
CD->isDesignatedInit() && !CD->isRequired())
4220+
Builder.addOverrideKeyword();
4221+
4222+
// Emit 'required' if we're in class context, 'required' is not specified,
4223+
// and 1) this is a protocol conformance and the class is not final, or 2)
4224+
// this is subclass and the initializer is marked as required.
4225+
bool needRequired = false;
4226+
auto C = CurrDeclContext->getAsClassOrClassExtensionContext();
4227+
if (C && !isKeywordSpecified("required")) {
4228+
if (Reason ==
4229+
DeclVisibilityKind::MemberOfProtocolImplementedByCurrentNominal &&
4230+
!C->isFinal())
4231+
needRequired = true;
4232+
else if (Reason == DeclVisibilityKind::MemberOfSuper && CD->isRequired())
4233+
needRequired = true;
4234+
}
4235+
42014236
llvm::SmallString<256> DeclStr;
4237+
if (needRequired)
4238+
DeclStr += "required ";
42024239
{
42034240
llvm::raw_svector_ostream OS(DeclStr);
42044241
PrintOptions Options;
@@ -4232,7 +4269,9 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42324269
if (!D->hasType())
42334270
TypeResolver->resolveDeclSignature(D);
42344271

4235-
bool hasIntroducer = hasFuncIntroducer || hasVarIntroducer;
4272+
bool hasIntroducer = hasFuncIntroducer ||
4273+
hasVarIntroducer ||
4274+
hasTypealiasIntroducer;
42364275

42374276
if (auto *FD = dyn_cast<FuncDecl>(D)) {
42384277
// We cannot override operators as members.
@@ -4243,30 +4282,31 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42434282
if (FD->isAccessor())
42444283
return;
42454284

4246-
if (!hasIntroducer || hasFuncIntroducer)
4285+
if (hasFuncIntroducer || (!hasIntroducer && !hasInitializerModifier))
42474286
addMethodOverride(FD, Reason);
42484287
return;
42494288
}
42504289

42514290
if (auto *VD = dyn_cast<VarDecl>(D)) {
4252-
if (!hasIntroducer || hasVarIntroducer) {
4291+
if (hasVarIntroducer || (!hasIntroducer && !hasInitializerModifier))
42534292
addVarOverride(VD, Reason);
4254-
}
4293+
return;
42554294
}
42564295

42574296
if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
42584297
if (!isa<ProtocolDecl>(CD->getDeclContext()))
42594298
return;
4260-
if (hasIntroducer || isKeywordSpecified("override"))
4299+
if (hasIntroducer || hasOverride || hasOverridabilityModifier)
42614300
return;
42624301
if (CD->isRequired() || CD->isDesignatedInit())
4263-
addConstructor(CD);
4302+
addConstructor(CD, Reason);
42644303
return;
42654304
}
42664305
}
42674306

42684307
void addDesignatedInitializers(Type CurrTy) {
4269-
if (hasFuncIntroducer || hasVarIntroducer || isKeywordSpecified("override"))
4308+
if (hasFuncIntroducer || hasVarIntroducer || hasTypealiasIntroducer ||
4309+
hasOverridabilityModifier)
42704310
return;
42714311

42724312
assert(CurrTy);
@@ -4283,12 +4323,14 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
42834323
if (Constructor->hasStubImplementation())
42844324
continue;
42854325
if (Constructor->isDesignatedInit())
4286-
addConstructor(Constructor);
4326+
addConstructor(Constructor, DeclVisibilityKind::MemberOfSuper);
42874327
}
42884328
}
42894329

42904330
void addAssociatedTypes(Type CurrTy) {
4291-
if (hasFuncIntroducer || hasVarIntroducer || isKeywordSpecified("override"))
4331+
if (!hasTypealiasIntroducer &&
4332+
(hasFuncIntroducer || hasVarIntroducer || hasInitializerModifier ||
4333+
hasOverride || hasOverridabilityModifier))
42924334
return;
42934335

42944336
NominalTypeDecl *NTD = CurrTy->getAnyNominal();

lib/Parse/ParseDecl.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2019,6 +2019,7 @@ ParserStatus Parser::parseDecl(ParseDeclOptions Flags,
20192019
case tok::kw_typealias:
20202020
DeclResult = parseDeclTypeAlias(Flags, Attributes);
20212021
Status = DeclResult;
2022+
MayNeedOverrideCompletion = true;
20222023
break;
20232024
case tok::kw_associatedtype:
20242025
DeclResult = parseDeclAssociatedType(Flags, Attributes);
@@ -2098,6 +2099,7 @@ ParserStatus Parser::parseDecl(ParseDeclOptions Flags,
20982099
case tok::kw_func:
20992100
case tok::kw_subscript:
21002101
case tok::kw_var:
2102+
case tok::kw_typealias:
21012103
Keywords.push_back(OrigTok.getText());
21022104
break;
21032105
default:

0 commit comments

Comments
 (0)