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:
@@ -275,6 +275,9 @@ struct PrintOptions {
|
|||||||
/// '@sil_weak', '@sil_unmanaged'.
|
/// '@sil_weak', '@sil_unmanaged'.
|
||||||
bool PrintStorageRepresentationAttrs = false;
|
bool PrintStorageRepresentationAttrs = false;
|
||||||
|
|
||||||
|
/// Whether to print 'static' or 'class' on static decls.
|
||||||
|
bool PrintStaticKeyword = true;
|
||||||
|
|
||||||
/// Whether to print 'override' keyword on overridden decls.
|
/// Whether to print 'override' keyword on overridden decls.
|
||||||
bool PrintOverrideKeyword = true;
|
bool PrintOverrideKeyword = true;
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ public:
|
|||||||
/// Complete at the beginning of member of a nominal decl member -- no tokens
|
/// Complete at the beginning of member of a nominal decl member -- no tokens
|
||||||
/// provided by user.
|
/// provided by user.
|
||||||
virtual void completeNominalMemberBeginning(
|
virtual void completeNominalMemberBeginning(
|
||||||
SmallVectorImpl<StringRef> &Keywords) {};
|
SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) {};
|
||||||
|
|
||||||
/// Complete at the beginning of accessor in a accessor block.
|
/// Complete at the beginning of accessor in a accessor block.
|
||||||
virtual void completeAccessorBeginning() {};
|
virtual void completeAccessorBeginning() {};
|
||||||
|
|||||||
@@ -2411,7 +2411,7 @@ void PrintAST::visitVarDecl(VarDecl *decl) {
|
|||||||
printAttributes(decl);
|
printAttributes(decl);
|
||||||
printAccess(decl);
|
printAccess(decl);
|
||||||
if (!Options.SkipIntroducerKeywords) {
|
if (!Options.SkipIntroducerKeywords) {
|
||||||
if (decl->isStatic())
|
if (decl->isStatic() && Options.PrintStaticKeyword)
|
||||||
printStaticKeyword(decl->getCorrectStaticSpelling());
|
printStaticKeyword(decl->getCorrectStaticSpelling());
|
||||||
if (decl->getKind() == DeclKind::Var
|
if (decl->getKind() == DeclKind::Var
|
||||||
|| Options.PrintParameterSpecifiers) {
|
|| Options.PrintParameterSpecifiers) {
|
||||||
@@ -2687,7 +2687,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
|
|||||||
printSourceRange(Range, Ctx);
|
printSourceRange(Range, Ctx);
|
||||||
} else {
|
} else {
|
||||||
if (!Options.SkipIntroducerKeywords) {
|
if (!Options.SkipIntroducerKeywords) {
|
||||||
if (decl->isStatic())
|
if (decl->isStatic() && Options.PrintStaticKeyword)
|
||||||
printStaticKeyword(decl->getCorrectStaticSpelling());
|
printStaticKeyword(decl->getCorrectStaticSpelling());
|
||||||
if (decl->isMutating() && !decl->getAttrs().hasAttribute<MutatingAttr>()) {
|
if (decl->isMutating() && !decl->getAttrs().hasAttribute<MutatingAttr>()) {
|
||||||
Printer.printKeyword("mutating", Options, " ");
|
Printer.printKeyword("mutating", Options, " ");
|
||||||
|
|||||||
@@ -1250,6 +1250,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
|
|||||||
Optional<StmtKind> ParentStmtKind;
|
Optional<StmtKind> ParentStmtKind;
|
||||||
|
|
||||||
SmallVector<StringRef, 3> ParsedKeywords;
|
SmallVector<StringRef, 3> ParsedKeywords;
|
||||||
|
SourceLoc introducerLoc;
|
||||||
|
|
||||||
std::vector<std::pair<std::string, bool>> SubModuleNameVisibilityPairs;
|
std::vector<std::pair<std::string, bool>> SubModuleNameVisibilityPairs;
|
||||||
|
|
||||||
@@ -1348,7 +1349,7 @@ public:
|
|||||||
void completeDeclAttrParam(DeclAttrKind DK, int Index) override;
|
void completeDeclAttrParam(DeclAttrKind DK, int Index) override;
|
||||||
void completeInPrecedenceGroup(SyntaxKind SK) override;
|
void completeInPrecedenceGroup(SyntaxKind SK) override;
|
||||||
void completeNominalMemberBeginning(
|
void completeNominalMemberBeginning(
|
||||||
SmallVectorImpl<StringRef> &Keywords) override;
|
SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) override;
|
||||||
void completeAccessorBeginning() override;
|
void completeAccessorBeginning() override;
|
||||||
|
|
||||||
void completePoundAvailablePlatform() override;
|
void completePoundAvailablePlatform() override;
|
||||||
@@ -3858,9 +3859,11 @@ public:
|
|||||||
|
|
||||||
class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
|
class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
|
||||||
CodeCompletionResultSink &Sink;
|
CodeCompletionResultSink &Sink;
|
||||||
|
ASTContext &Ctx;
|
||||||
const DeclContext *CurrDeclContext;
|
const DeclContext *CurrDeclContext;
|
||||||
LazyResolver *TypeResolver;
|
LazyResolver *TypeResolver;
|
||||||
SmallVectorImpl<StringRef> &ParsedKeywords;
|
SmallVectorImpl<StringRef> &ParsedKeywords;
|
||||||
|
SourceLoc introducerLoc;
|
||||||
|
|
||||||
bool hasFuncIntroducer = false;
|
bool hasFuncIntroducer = false;
|
||||||
bool hasVarIntroducer = false;
|
bool hasVarIntroducer = false;
|
||||||
@@ -3869,13 +3872,15 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
|
|||||||
bool hasAccessModifier = false;
|
bool hasAccessModifier = false;
|
||||||
bool hasOverride = false;
|
bool hasOverride = false;
|
||||||
bool hasOverridabilityModifier = false;
|
bool hasOverridabilityModifier = false;
|
||||||
|
bool hasStaticOrClass = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CompletionOverrideLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
|
CompletionOverrideLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
|
||||||
const DeclContext *CurrDeclContext,
|
const DeclContext *CurrDeclContext,
|
||||||
SmallVectorImpl<StringRef> &ParsedKeywords)
|
SmallVectorImpl<StringRef> &ParsedKeywords,
|
||||||
: Sink(Sink),
|
SourceLoc introducerLoc)
|
||||||
CurrDeclContext(CurrDeclContext), ParsedKeywords(ParsedKeywords) {
|
: Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
|
||||||
|
ParsedKeywords(ParsedKeywords), introducerLoc(introducerLoc) {
|
||||||
(void)createTypeChecker(Ctx);
|
(void)createTypeChecker(Ctx);
|
||||||
TypeResolver = Ctx.getLazyResolver();
|
TypeResolver = Ctx.getLazyResolver();
|
||||||
|
|
||||||
@@ -3893,6 +3898,8 @@ public:
|
|||||||
hasOverride = isKeywordSpecified("override");
|
hasOverride = isKeywordSpecified("override");
|
||||||
hasOverridabilityModifier = isKeywordSpecified("final") ||
|
hasOverridabilityModifier = isKeywordSpecified("final") ||
|
||||||
isKeywordSpecified("open");
|
isKeywordSpecified("open");
|
||||||
|
hasStaticOrClass = isKeywordSpecified(getTokenText(tok::kw_class)) ||
|
||||||
|
isKeywordSpecified(getTokenText(tok::kw_static));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isKeywordSpecified(StringRef Word) {
|
bool isKeywordSpecified(StringRef Word) {
|
||||||
@@ -3942,8 +3949,10 @@ public:
|
|||||||
Options.setBaseType(transformType);
|
Options.setBaseType(transformType);
|
||||||
Options.PrintImplicitAttrs = false;
|
Options.PrintImplicitAttrs = false;
|
||||||
Options.ExclusiveAttrList.push_back(TAK_escaping);
|
Options.ExclusiveAttrList.push_back(TAK_escaping);
|
||||||
|
Options.ExclusiveAttrList.push_back(TAK_autoclosure);
|
||||||
Options.PrintOverrideKeyword = false;
|
Options.PrintOverrideKeyword = false;
|
||||||
Options.PrintPropertyAccessors = false;
|
Options.PrintPropertyAccessors = false;
|
||||||
|
Options.PrintStaticKeyword = !hasStaticOrClass;
|
||||||
VD->print(Printer, Options);
|
VD->print(Printer, Options);
|
||||||
NameOffset = Printer.NameOffset.getValue();
|
NameOffset = Printer.NameOffset.getValue();
|
||||||
}
|
}
|
||||||
@@ -3951,10 +3960,17 @@ public:
|
|||||||
if (!hasDeclIntroducer && !hasAccessModifier)
|
if (!hasDeclIntroducer && !hasAccessModifier)
|
||||||
addAccessControl(VD, Builder);
|
addAccessControl(VD, Builder);
|
||||||
|
|
||||||
// FIXME: if we're missing 'override', but have the decl introducer we
|
if (missingOverride(Reason)) {
|
||||||
// should delete it and re-add both in the correct order.
|
if (!hasDeclIntroducer)
|
||||||
if (!hasDeclIntroducer && missingOverride(Reason))
|
|
||||||
Builder.addOverrideKeyword();
|
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)
|
if (!hasDeclIntroducer)
|
||||||
Builder.addDeclIntroducer(DeclStr.str().substr(0, NameOffset));
|
Builder.addDeclIntroducer(DeclStr.str().substr(0, NameOffset));
|
||||||
@@ -4050,7 +4066,9 @@ public:
|
|||||||
if (D->shouldHideFromEditor())
|
if (D->shouldHideFromEditor())
|
||||||
return;
|
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;
|
return;
|
||||||
|
|
||||||
if (!D->hasInterfaceType())
|
if (!D->hasInterfaceType())
|
||||||
@@ -4060,6 +4078,15 @@ public:
|
|||||||
hasVarIntroducer ||
|
hasVarIntroducer ||
|
||||||
hasTypealiasIntroducer;
|
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)) {
|
if (auto *FD = dyn_cast<FuncDecl>(D)) {
|
||||||
// We cannot override operators as members.
|
// We cannot override operators as members.
|
||||||
if (FD->isBinaryOperator() || FD->isUnaryOperator())
|
if (FD->isBinaryOperator() || FD->isUnaryOperator())
|
||||||
@@ -4083,7 +4110,8 @@ public:
|
|||||||
if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
|
if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
|
||||||
if (!isa<ProtocolDecl>(CD->getDeclContext()))
|
if (!isa<ProtocolDecl>(CD->getDeclContext()))
|
||||||
return;
|
return;
|
||||||
if (hasIntroducer || hasOverride || hasOverridabilityModifier)
|
if (hasIntroducer || hasOverride || hasOverridabilityModifier ||
|
||||||
|
hasStaticOrClass)
|
||||||
return;
|
return;
|
||||||
if (CD->isRequired() || CD->isDesignatedInit())
|
if (CD->isRequired() || CD->isDesignatedInit())
|
||||||
addConstructor(CD, Reason);
|
addConstructor(CD, Reason);
|
||||||
@@ -4093,7 +4121,7 @@ public:
|
|||||||
|
|
||||||
void addDesignatedInitializers(NominalTypeDecl *NTD) {
|
void addDesignatedInitializers(NominalTypeDecl *NTD) {
|
||||||
if (hasFuncIntroducer || hasVarIntroducer || hasTypealiasIntroducer ||
|
if (hasFuncIntroducer || hasVarIntroducer || hasTypealiasIntroducer ||
|
||||||
hasOverridabilityModifier)
|
hasOverridabilityModifier || hasStaticOrClass)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto *CD = dyn_cast<ClassDecl>(NTD);
|
const auto *CD = dyn_cast<ClassDecl>(NTD);
|
||||||
@@ -4116,7 +4144,7 @@ public:
|
|||||||
void addAssociatedTypes(NominalTypeDecl *NTD) {
|
void addAssociatedTypes(NominalTypeDecl *NTD) {
|
||||||
if (!hasTypealiasIntroducer &&
|
if (!hasTypealiasIntroducer &&
|
||||||
(hasFuncIntroducer || hasVarIntroducer || hasInitializerModifier ||
|
(hasFuncIntroducer || hasVarIntroducer || hasInitializerModifier ||
|
||||||
hasOverride || hasOverridabilityModifier))
|
hasOverride || hasOverridabilityModifier || hasStaticOrClass))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto Conformance : NTD->getAllConformances()) {
|
for (auto Conformance : NTD->getAllConformances()) {
|
||||||
@@ -4147,9 +4175,11 @@ public:
|
|||||||
Type CurrTy = CurrDeclContext->getSelfTypeInContext();
|
Type CurrTy = CurrDeclContext->getSelfTypeInContext();
|
||||||
auto *NTD = CurrDeclContext->getSelfNominalTypeDecl();
|
auto *NTD = CurrDeclContext->getSelfNominalTypeDecl();
|
||||||
if (CurrTy && !CurrTy->is<ErrorType>()) {
|
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,
|
TypeResolver,
|
||||||
/*includeInstanceMembers=*/false);
|
/*includeInstanceMembers=*/true);
|
||||||
addDesignatedInitializers(NTD);
|
addDesignatedInitializers(NTD);
|
||||||
addAssociatedTypes(NTD);
|
addAssociatedTypes(NTD);
|
||||||
}
|
}
|
||||||
@@ -4471,8 +4501,9 @@ void CodeCompletionCallbacksImpl::completeGenericParams(TypeLoc TL) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CodeCompletionCallbacksImpl::completeNominalMemberBeginning(
|
void CodeCompletionCallbacksImpl::completeNominalMemberBeginning(
|
||||||
SmallVectorImpl<StringRef> &Keywords) {
|
SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) {
|
||||||
assert(!InEnumElementRawValue);
|
assert(!InEnumElementRawValue);
|
||||||
|
this->introducerLoc = introducerLoc;
|
||||||
ParsedKeywords.clear();
|
ParsedKeywords.clear();
|
||||||
ParsedKeywords.append(Keywords.begin(), Keywords.end());
|
ParsedKeywords.append(Keywords.begin(), Keywords.end());
|
||||||
Kind = CompletionKind::NominalMemberBeginning;
|
Kind = CompletionKind::NominalMemberBeginning;
|
||||||
@@ -4651,10 +4682,11 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CompletionKind::NominalMemberBeginning: {
|
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)
|
return llvm::StringSwitch<bool>(kw)
|
||||||
.Case("associatedtype", true)
|
.Case("associatedtype", true)
|
||||||
.Case("class", true)
|
.Case("class", !CurDeclContext || !isa<ClassDecl>(CurDeclContext))
|
||||||
.Case("deinit", true)
|
.Case("deinit", true)
|
||||||
.Case("enum", true)
|
.Case("enum", true)
|
||||||
.Case("extension", true)
|
.Case("extension", true)
|
||||||
@@ -5027,7 +5059,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
|
|||||||
case CompletionKind::NominalMemberBeginning: {
|
case CompletionKind::NominalMemberBeginning: {
|
||||||
CompletionOverrideLookup OverrideLookup(CompletionContext.getResultSink(),
|
CompletionOverrideLookup OverrideLookup(CompletionContext.getResultSink(),
|
||||||
P.Context, CurDeclContext,
|
P.Context, CurDeclContext,
|
||||||
ParsedKeywords);
|
ParsedKeywords, introducerLoc);
|
||||||
OverrideLookup.getOverrideCompletions(SourceLoc());
|
OverrideLookup.getOverrideCompletions(SourceLoc());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2281,10 +2281,19 @@ bool Parser::parseDeclModifierList(DeclAttributes &Attributes,
|
|||||||
{
|
{
|
||||||
BacktrackingScope Scope(*this);
|
BacktrackingScope Scope(*this);
|
||||||
consumeToken(tok::kw_class);
|
consumeToken(tok::kw_class);
|
||||||
if (!isStartOfDecl())
|
// When followed by an 'override' or CC token inside a class,
|
||||||
|
// treat 'class' as a modifier; in the case of a following CC
|
||||||
|
// token, we cannot be sure there is no intention to override
|
||||||
|
// or witness something static.
|
||||||
|
if (isStartOfDecl() || (isa<ClassDecl>(CurDeclContext) &&
|
||||||
|
(Tok.is(tok::code_complete) ||
|
||||||
|
Tok.getRawText().equals("override")))) {
|
||||||
|
/* We're OK */
|
||||||
|
} else {
|
||||||
// This 'class' is a real ClassDecl introducer.
|
// This 'class' is a real ClassDecl introducer.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (StaticLoc.isValid()) {
|
if (StaticLoc.isValid()) {
|
||||||
diagnose(Tok, diag::decl_already_static,
|
diagnose(Tok, diag::decl_already_static,
|
||||||
StaticSpellingKind::KeywordClass)
|
StaticSpellingKind::KeywordClass)
|
||||||
@@ -2932,6 +2941,7 @@ Parser::parseDecl(ParseDeclOptions Flags,
|
|||||||
// specified so that we do not duplicate them in code completion
|
// specified so that we do not duplicate them in code completion
|
||||||
// strings.
|
// strings.
|
||||||
SmallVector<StringRef, 3> Keywords;
|
SmallVector<StringRef, 3> Keywords;
|
||||||
|
SourceLoc introducerLoc;
|
||||||
switch (OrigTok.getKind()) {
|
switch (OrigTok.getKind()) {
|
||||||
case tok::kw_func:
|
case tok::kw_func:
|
||||||
case tok::kw_subscript:
|
case tok::kw_subscript:
|
||||||
@@ -2939,15 +2949,22 @@ Parser::parseDecl(ParseDeclOptions Flags,
|
|||||||
case tok::kw_let:
|
case tok::kw_let:
|
||||||
case tok::kw_typealias:
|
case tok::kw_typealias:
|
||||||
Keywords.push_back(OrigTok.getText());
|
Keywords.push_back(OrigTok.getText());
|
||||||
|
introducerLoc = OrigTok.getLoc();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Other tokens are already accounted for.
|
// Other tokens are already accounted for.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (StaticSpelling == StaticSpellingKind::KeywordStatic) {
|
||||||
|
Keywords.push_back(getTokenText(tok::kw_static));
|
||||||
|
} else if (StaticSpelling == StaticSpellingKind::KeywordClass) {
|
||||||
|
Keywords.push_back(getTokenText(tok::kw_class));
|
||||||
|
}
|
||||||
for (auto attr : Attributes) {
|
for (auto attr : Attributes) {
|
||||||
Keywords.push_back(attr->getAttrName());
|
Keywords.push_back(attr->getAttrName());
|
||||||
}
|
}
|
||||||
CodeCompletion->completeNominalMemberBeginning(Keywords);
|
CodeCompletion->completeNominalMemberBeginning(Keywords,
|
||||||
|
introducerLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclResult = makeParserCodeCompletionStatus();
|
DeclResult = makeParserCodeCompletionStatus();
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class MyCls {
|
|||||||
class MySub : MyCls {
|
class MySub : MyCls {
|
||||||
func #^METHODNAME_OVERRIDE^#
|
func #^METHODNAME_OVERRIDE^#
|
||||||
// METHODNAME_OVERRIDE: Begin completions, 1 items
|
// METHODNAME_OVERRIDE: Begin completions, 1 items
|
||||||
// METHODNAME_OVERRIDE-NEXT: Decl[InstanceMethod]/Super: foo() {|}; name=foo()
|
// METHODNAME_OVERRIDE-NEXT: Decl[InstanceMethod]/Super/Erase[5]: override func foo() {|}; name=foo()
|
||||||
// METHODNAME_OVERRIDE-NEXT: End completions
|
// METHODNAME_OVERRIDE-NEXT: End completions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,9 +127,21 @@
|
|||||||
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER9 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER9
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER9 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER9
|
||||||
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER10 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER6
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER10 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER6
|
||||||
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER11 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER9
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER11 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER9
|
||||||
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER12 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER9
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER12 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER12
|
||||||
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER13 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER13
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER13 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER13
|
||||||
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER14 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER9
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER14 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER12
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER15 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER15
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER16 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER15
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER17 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER17
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER18 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER17
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER19 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER13
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER20 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER13
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER21 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER21
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER22 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER22
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER23 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER23
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER24 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER24
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER25 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER23
|
||||||
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=MODIFIER26 -code-completion-keywords=false | %FileCheck %s -check-prefix=MODIFIER24
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=PROTOINIT_NORM -code-completion-keywords=false | %FileCheck %s -check-prefix=PROTOINIT_NORM
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=PROTOINIT_NORM -code-completion-keywords=false | %FileCheck %s -check-prefix=PROTOINIT_NORM
|
||||||
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=PROTOINIT_FINAL -code-completion-keywords=false | %FileCheck %s -check-prefix=PROTOINIT_FINAL
|
// RUN: %target-swift-ide-test -enable-objc-interop -code-completion -source-filename %s -code-completion-token=PROTOINIT_FINAL -code-completion-keywords=false | %FileCheck %s -check-prefix=PROTOINIT_FINAL
|
||||||
@@ -556,20 +568,34 @@ class Deprecated2 : Deprecated1 {
|
|||||||
|
|
||||||
class EscapingBase {
|
class EscapingBase {
|
||||||
func method(_ x: @escaping (@escaping ()->()) -> (()->())) -> (@escaping (@escaping ()->() )->()) { }
|
func method(_ x: @escaping (@escaping ()->()) -> (()->())) -> (@escaping (@escaping ()->() )->()) { }
|
||||||
|
func autoclosure(arg: @autoclosure () -> Bool) {}
|
||||||
}
|
}
|
||||||
class Escaping : EscapingBase {
|
class Escaping : EscapingBase {
|
||||||
override func #^ESCAPING_1^#
|
override func #^ESCAPING_1^#
|
||||||
}
|
}
|
||||||
// ESCAPING_1: Decl[InstanceMethod]/Super: method(_ x: @escaping (@escaping () -> ()) -> (() -> ())) -> ((@escaping () -> ()) -> ()) {|};
|
// ESCAPING_1: Decl[InstanceMethod]/Super: method(_ x: @escaping (@escaping () -> ()) -> (() -> ())) -> ((@escaping () -> ()) -> ()) {|};
|
||||||
|
// ESCAPING_1: Decl[InstanceMethod]/Super: autoclosure(arg: @autoclosure () -> Bool) {|};
|
||||||
class OverrideBase {
|
class OverrideBase {
|
||||||
|
static let staticLet = 0
|
||||||
|
static var staticVar = 0
|
||||||
|
static var staticGetOnlyVar: Int { return 0 }
|
||||||
|
|
||||||
|
class let classLet = 0
|
||||||
|
class var classVar = 0
|
||||||
|
class var classGetOnlyVar: Int { return 0 }
|
||||||
|
|
||||||
|
static func staticMethod() {}
|
||||||
|
class func classMethod() {}
|
||||||
|
|
||||||
|
let letDecl = 0
|
||||||
|
var varDecl: Int = 0
|
||||||
|
|
||||||
init(x: Int) {}
|
init(x: Int) {}
|
||||||
convenience init(y: Int) { self.init(x: y) }
|
convenience init(y: Int) { self.init(x: y) }
|
||||||
required init(a: Int) {}
|
required init(a: Int) {}
|
||||||
required convenience init(b: Int) {}
|
required convenience init(b: Int) {}
|
||||||
func defaultMethod() {}
|
func defaultMethod() {}
|
||||||
final func finalMethod() {}
|
final func finalMethod() {}
|
||||||
var varDecl: Int = 0
|
|
||||||
open func openMethod() {}
|
open func openMethod() {}
|
||||||
}
|
}
|
||||||
protocol OverrideP {
|
protocol OverrideP {
|
||||||
@@ -619,7 +645,6 @@ class Override11 : OverrideBase, OverrideP {
|
|||||||
}
|
}
|
||||||
class Override12 : OverrideBase, OverrideP {
|
class Override12 : OverrideBase, OverrideP {
|
||||||
override var #^MODIFIER12^#
|
override var #^MODIFIER12^#
|
||||||
// Same as MODIFIER9.
|
|
||||||
}
|
}
|
||||||
class Override13 : OverrideBase, OverrideP {
|
class Override13 : OverrideBase, OverrideP {
|
||||||
// No completions.
|
// No completions.
|
||||||
@@ -629,11 +654,56 @@ class Override14 : OverrideBase, OverrideP {
|
|||||||
// Note: This *does* emit variables. It will result invalid decl, but a
|
// Note: This *does* emit variables. It will result invalid decl, but a
|
||||||
// diagnostic will tell the user what to do.
|
// diagnostic will tell the user what to do.
|
||||||
override let #^MODIFIER14^#
|
override let #^MODIFIER14^#
|
||||||
// Same as MODIFIER9.
|
// Same as MODIFIER12.
|
||||||
|
}
|
||||||
|
class Override15 : OverrideBase, OverrideP {
|
||||||
|
required static var #^MODIFIER15^#
|
||||||
|
}
|
||||||
|
class Override16 : OverrideBase, OverrideP {
|
||||||
|
class var #^MODIFIER16^#
|
||||||
|
// Same as MODIFIER15
|
||||||
|
}
|
||||||
|
class Override17 : OverrideBase, OverrideP {
|
||||||
|
override class var #^MODIFIER17^#
|
||||||
|
}
|
||||||
|
class Override18 : OverrideBase, OverrideP {
|
||||||
|
// Note: This *does* emit variables. See MODIFIER14
|
||||||
|
override static let #^MODIFIER18^#
|
||||||
|
// Same as MODIFIER17
|
||||||
|
}
|
||||||
|
class Override19 : OverrideBase, OverrideP {
|
||||||
|
// No completions.
|
||||||
|
class let #^MODIFIER19^#
|
||||||
|
}
|
||||||
|
class Override20 : OverrideBase, OverrideP {
|
||||||
|
// No completions.
|
||||||
|
static let #^MODIFIER20^#
|
||||||
|
}
|
||||||
|
class Override21 : OverrideBase, OverrideP {
|
||||||
|
override class func #^MODIFIER21^#
|
||||||
|
}
|
||||||
|
class Override22 : OverrideBase, OverrideP {
|
||||||
|
class func #^MODIFIER22^#
|
||||||
|
}
|
||||||
|
class Override23 : OverrideBase, OverrideP {
|
||||||
|
static #^MODIFIER23^#
|
||||||
|
}
|
||||||
|
class Override24 : OverrideBase, OverrideP {
|
||||||
|
override static #^MODIFIER24^#
|
||||||
|
}
|
||||||
|
class Override25 : OverrideBase, OverrideP {
|
||||||
|
class #^MODIFIER25^#
|
||||||
|
// Same as MODIFIER23
|
||||||
|
}
|
||||||
|
class Override26 : OverrideBase, OverrideP {
|
||||||
|
class override #^MODIFIER26^#
|
||||||
|
// Same as MODIFIER24
|
||||||
}
|
}
|
||||||
|
|
||||||
// MODIFIER1: Begin completions, 7 items
|
// MODIFIER1: Begin completions, 9 items
|
||||||
// MODIFIER1-DAG: Decl[Constructor]/Super: required init(p: Int) {|}; name=required init(p: Int)
|
// MODIFIER1-DAG: Decl[Constructor]/Super: required init(p: Int) {|}; name=required init(p: Int)
|
||||||
|
// MODIFIER1-DAG: Decl[StaticMethod]/Super: override class func classMethod() {|}; name=classMethod()
|
||||||
|
// MODIFIER1-DAG: Decl[StaticVar]/Super: override class var classGetOnlyVar: Int; name=classGetOnlyVar: Int
|
||||||
// MODIFIER1-DAG: Decl[InstanceMethod]/Super: override func defaultMethod() {|}; name=defaultMethod()
|
// MODIFIER1-DAG: Decl[InstanceMethod]/Super: override func defaultMethod() {|}; name=defaultMethod()
|
||||||
// MODIFIER1-DAG: Decl[InstanceMethod]/Super: override func openMethod() {|}; name=openMethod()
|
// MODIFIER1-DAG: Decl[InstanceMethod]/Super: override func openMethod() {|}; name=openMethod()
|
||||||
// MODIFIER1-DAG: Decl[InstanceVar]/Super: override var varDecl: Int; name=varDecl: Int
|
// MODIFIER1-DAG: Decl[InstanceVar]/Super: override var varDecl: Int; name=varDecl: Int
|
||||||
@@ -642,7 +712,9 @@ class Override14 : OverrideBase, OverrideP {
|
|||||||
// MODIFIER1-DAG: Decl[AssociatedType]/Super: typealias Assoc = {#(Type)#}; name=Assoc = Type
|
// MODIFIER1-DAG: Decl[AssociatedType]/Super: typealias Assoc = {#(Type)#}; name=Assoc = Type
|
||||||
// MODIFIER1: End completions
|
// MODIFIER1: End completions
|
||||||
|
|
||||||
// MODIFIER2: Begin completions, 3 items
|
// MODIFIER2: Begin completions, 5 items
|
||||||
|
// MODIFIER2-DAG: Decl[StaticVar]/Super: override class var classGetOnlyVar: Int; name=classGetOnlyVar: Int
|
||||||
|
// MODIFIER2-DAG: Decl[StaticMethod]/Super: override class func classMethod() {|}; name=classMethod()
|
||||||
// MODIFIER2-DAG: Decl[InstanceMethod]/Super: override func defaultMethod() {|}; name=defaultMethod()
|
// MODIFIER2-DAG: Decl[InstanceMethod]/Super: override func defaultMethod() {|}; name=defaultMethod()
|
||||||
// MODIFIER2-DAG: Decl[InstanceMethod]/Super: override func openMethod() {|}; name=openMethod()
|
// MODIFIER2-DAG: Decl[InstanceMethod]/Super: override func openMethod() {|}; name=openMethod()
|
||||||
// MODIFIER2-DAG: Decl[InstanceVar]/Super: override var varDecl: Int; name=varDecl: Int
|
// MODIFIER2-DAG: Decl[InstanceVar]/Super: override var varDecl: Int; name=varDecl: Int
|
||||||
@@ -664,7 +736,9 @@ class Override14 : OverrideBase, OverrideP {
|
|||||||
// MODIFIER6-DAG: Decl[AssociatedType]/Super: Assoc = {#(Type)#}; name=Assoc = Type
|
// MODIFIER6-DAG: Decl[AssociatedType]/Super: Assoc = {#(Type)#}; name=Assoc = Type
|
||||||
// MODIFIER6: End completions
|
// MODIFIER6: End completions
|
||||||
|
|
||||||
// MODIFIER7: Begin completions, 5 items
|
// MODIFIER7: Begin completions, 7 items
|
||||||
|
// MODIFIER7-DAG: Decl[StaticVar]/Super: class var classGetOnlyVar: Int; name=classGetOnlyVar: Int
|
||||||
|
// MODIFIER7-DAG: Decl[StaticMethod]/Super: class func classMethod() {|}; name=classMethod()
|
||||||
// MODIFIER7-DAG: Decl[InstanceMethod]/Super: func defaultMethod() {|}; name=defaultMethod()
|
// MODIFIER7-DAG: Decl[InstanceMethod]/Super: func defaultMethod() {|}; name=defaultMethod()
|
||||||
// MODIFIER7-DAG: Decl[InstanceVar]/Super: var varDecl: Int; name=varDecl: Int
|
// MODIFIER7-DAG: Decl[InstanceVar]/Super: var varDecl: Int; name=varDecl: Int
|
||||||
// MODIFIER7-DAG: Decl[InstanceMethod]/Super: func openMethod() {|}; name=openMethod()
|
// MODIFIER7-DAG: Decl[InstanceMethod]/Super: func openMethod() {|}; name=openMethod()
|
||||||
@@ -673,16 +747,46 @@ class Override14 : OverrideBase, OverrideP {
|
|||||||
// MODIFIER7: End completions
|
// MODIFIER7: End completions
|
||||||
|
|
||||||
// MODIFIER8: Begin completions, 2 items
|
// MODIFIER8: Begin completions, 2 items
|
||||||
// MODIFIER8-DAG: Decl[InstanceMethod]/Super: defaultMethod() {|}; name=defaultMethod()
|
// MODIFIER8-DAG: Decl[InstanceMethod]/Super/Erase[5]: override func defaultMethod() {|}; name=defaultMethod()
|
||||||
// MODIFIER8-DAG: Decl[InstanceMethod]/Super: openMethod() {|}; name=openMethod()
|
// MODIFIER8-DAG: Decl[InstanceMethod]/Super/Erase[5]: override func openMethod() {|}; name=openMethod()
|
||||||
// MODIFIER8: End completions
|
// MODIFIER8: End completions
|
||||||
|
|
||||||
// MODIFIER9: Begin completions, 1 items
|
// MODIFIER9: Begin completions, 1 items
|
||||||
// MODIFIER9-DAG: Decl[InstanceVar]/Super: varDecl: Int; name=varDecl: Int
|
// MODIFIER9-DAG: Decl[InstanceVar]/Super/Erase[4]: override var varDecl: Int; name=varDecl: Int
|
||||||
// MODIFIER9: End completions
|
// MODIFIER9: End completions
|
||||||
|
|
||||||
|
// MODIFIER12: Begin completions, 1 items
|
||||||
|
// MODIFIER12-DAG: Decl[InstanceVar]/Super: varDecl: Int; name=varDecl: Int
|
||||||
|
// MODIFIER12: End completions
|
||||||
|
|
||||||
// MODIFIER13-NOT: Begin completions
|
// MODIFIER13-NOT: Begin completions
|
||||||
|
|
||||||
|
// MODIFIER15: Begin completions, 1 items
|
||||||
|
// MODIFIER15-DAG: Decl[StaticVar]/Super/Erase[4]: override var classGetOnlyVar: Int; name=classGetOnlyVar: Int
|
||||||
|
// MODIFIER15: End completions
|
||||||
|
|
||||||
|
// MODIFIER17: Begin completions, 1 items
|
||||||
|
// MODIFIER17-DAG: Decl[StaticVar]/Super: classGetOnlyVar: Int; name=classGetOnlyVar: Int
|
||||||
|
// MODIFIER17: End completions
|
||||||
|
|
||||||
|
// MODIFIER21: Begin completions, 1 items
|
||||||
|
// MODIFIER21: Decl[StaticMethod]/Super: classMethod() {|}; name=classMethod()
|
||||||
|
// MODIFIER21: End completions
|
||||||
|
|
||||||
|
// MODIFIER22: Begin completions, 1 items
|
||||||
|
// MODIFIER22: Decl[StaticMethod]/Super/Erase[5]: override func classMethod() {|}; name=classMethod()
|
||||||
|
// MODIFIER22: End completions
|
||||||
|
|
||||||
|
// MODIFIER23: Begin completions, 2 items
|
||||||
|
// MODIFIER23-DAG: Decl[StaticMethod]/Super: override func classMethod() {|}; name=classMethod()
|
||||||
|
// MODIFIER23-DAG: Decl[StaticVar]/Super: override var classGetOnlyVar: Int; name=classGetOnlyVar: Int
|
||||||
|
// MODIFIER23: End completions
|
||||||
|
|
||||||
|
// MODIFIER24: Begin completions, 2 items
|
||||||
|
// MODIFIER24-DAG: Decl[StaticMethod]/Super: func classMethod() {|}; name=classMethod()
|
||||||
|
// MODIFIER24-DAG: Decl[StaticVar]/Super: var classGetOnlyVar: Int; name=classGetOnlyVar: Int
|
||||||
|
// MODIFIER24: End completions
|
||||||
|
|
||||||
protocol RequiredP {
|
protocol RequiredP {
|
||||||
init(p: Int)
|
init(p: Int)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,21 @@ class Sub : FooClassBase {
|
|||||||
#^PA^#
|
#^PA^#
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK1: Begin completions, 8 items
|
// CHECK1: Begin completions, 16 items
|
||||||
|
// CHECK1: Decl[StaticMethod]/Super: override class func fooBaseInstanceFunc0() {|}
|
||||||
// CHECK1: Decl[InstanceMethod]/Super: override func fooBaseInstanceFunc0() {|}
|
// CHECK1: Decl[InstanceMethod]/Super: override func fooBaseInstanceFunc0() {|}
|
||||||
|
// CHECK1: Decl[StaticMethod]/Super: override class func fooBaseInstanceFunc1(_ anObject: Any!) -> FooClassBase! {|}
|
||||||
// CHECK1: Decl[InstanceMethod]/Super: override func fooBaseInstanceFunc1(_ anObject: Any!) -> FooClassBase! {|}
|
// CHECK1: Decl[InstanceMethod]/Super: override func fooBaseInstanceFunc1(_ anObject: Any!) -> FooClassBase! {|}
|
||||||
|
// CHECK1: Decl[StaticMethod]/Super: override class func fooBaseInstanceFuncOverridden() {|}
|
||||||
// CHECK1: Decl[InstanceMethod]/Super: override func fooBaseInstanceFuncOverridden() {|}
|
// CHECK1: Decl[InstanceMethod]/Super: override func fooBaseInstanceFuncOverridden() {|}
|
||||||
|
// CHECK1: Decl[StaticMethod]/Super: override class func fooBaseClassFunc0() {|}
|
||||||
|
// CHECK1: Decl[StaticMethod]/Super: override class func _internalMeth3() -> Any! {|}
|
||||||
// CHECK1: Decl[InstanceMethod]/Super: override func _internalMeth3() -> Any! {|}
|
// CHECK1: Decl[InstanceMethod]/Super: override func _internalMeth3() -> Any! {|}
|
||||||
|
// CHECK1: Decl[StaticMethod]/Super: override class func _internalMeth2() -> Any! {|}
|
||||||
// CHECK1: Decl[InstanceMethod]/Super: override func _internalMeth2() -> Any! {|}
|
// CHECK1: Decl[InstanceMethod]/Super: override func _internalMeth2() -> Any! {|}
|
||||||
|
// CHECK1: Decl[StaticMethod]/Super: override class func nonInternalMeth() -> Any! {|}
|
||||||
// CHECK1: Decl[InstanceMethod]/Super: override func nonInternalMeth() -> Any! {|}
|
// CHECK1: Decl[InstanceMethod]/Super: override func nonInternalMeth() -> Any! {|}
|
||||||
|
// CHECK1: Decl[StaticMethod]/Super: override class func _internalMeth1() -> Any! {|}
|
||||||
// CHECK1: Decl[InstanceMethod]/Super: override func _internalMeth1() -> Any! {|}
|
// CHECK1: Decl[InstanceMethod]/Super: override func _internalMeth1() -> Any! {|}
|
||||||
// CHECK1: Decl[Constructor]/Super: override init!() {|}
|
// CHECK1: Decl[Constructor]/Super: override init!() {|}
|
||||||
// CHECK1: End completions
|
// CHECK1: End completions
|
||||||
@@ -25,7 +33,7 @@ class Sub : FooClassDerived {
|
|||||||
var #^PROPERTY^#
|
var #^PROPERTY^#
|
||||||
}
|
}
|
||||||
// PROPERTY: Begin completions
|
// PROPERTY: Begin completions
|
||||||
// PROPERTY-DAG: Decl[InstanceVar]/Super: fooProperty1: Int32
|
// PROPERTY-DAG: Decl[InstanceVar]/Super/Erase[4]: override var fooProperty1: Int32;
|
||||||
// PROPERTY-DAG: Decl[InstanceVar]/Super: fooProperty2: Int32
|
// PROPERTY-DAG: Decl[InstanceVar]/Super/Erase[4]: override var fooProperty2: Int32;
|
||||||
// PROPERTY-DAG: Decl[InstanceVar]/Super: fooProperty3: Int32
|
// PROPERTY-DAG: Decl[InstanceVar]/Super/Erase[4]: override var fooProperty3: Int32;
|
||||||
// PROPERTY: End completions
|
// PROPERTY: End completions
|
||||||
|
|||||||
Reference in New Issue
Block a user