Skip to content

Commit ceb1069

Browse files
committed
Prefer original spelling of 'static' vs. 'class'
Try to match the original spelling of static/class in diagnostics and when printing the AST. Also fixes cases with PrintOptions.PrintImplicitAttrs = false, where we would just print 'class', which was not valid code.
1 parent c934315 commit ceb1069

File tree

9 files changed

+123
-11
lines changed

9 files changed

+123
-11
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1592,7 +1592,10 @@ ERROR(attr_only_only_one_decl_kind,none,
15921592

15931593

15941594
ERROR(override_final,none,
1595-
"%0 overrides a 'final' %0", (DescriptiveDeclKind))
1595+
"%0 overrides a 'final' %1", (DescriptiveDeclKind, DescriptiveDeclKind))
1596+
1597+
ERROR(override_static,none,
1598+
"cannot override %0", (DescriptiveDeclKind))
15961599

15971600
ERROR(member_cannot_be_final,none,
15981601
"only classes and class members may be marked with 'final'",

lib/AST/ASTPrinter.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,10 +831,33 @@ class PrintAST : public ASTVisitor<PrintAST> {
831831
};
832832
} // unnamed namespace
833833

834+
static StaticSpellingKind getCorrectStaticSpelling(const Decl *D) {
835+
if (auto *VD = dyn_cast<VarDecl>(D)) {
836+
return VD->getCorrectStaticSpelling();
837+
} else if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
838+
return PBD->getCorrectStaticSpelling();
839+
} else if (auto *FD = dyn_cast<FuncDecl>(D)) {
840+
return FD->getCorrectStaticSpelling();
841+
} else {
842+
return StaticSpellingKind::None;
843+
}
844+
}
845+
834846
void PrintAST::printAttributes(const Decl *D) {
835847
if (Options.SkipAttributes)
836848
return;
849+
850+
// Don't print a redundant 'final' if we are printing a 'static' decl.
851+
unsigned originalExcludeAttrCount = Options.ExcludeAttrList.size();
852+
if (Options.PrintImplicitAttrs &&
853+
D->getDeclContext()->getAsClassOrClassExtensionContext() &&
854+
getCorrectStaticSpelling(D) == StaticSpellingKind::KeywordStatic) {
855+
Options.ExcludeAttrList.push_back(DAK_Final);
856+
}
857+
837858
D->getAttrs().print(Printer, Options);
859+
860+
Options.ExcludeAttrList.resize(originalExcludeAttrCount);
838861
}
839862

840863
void PrintAST::printTypedPattern(const TypedPattern *TP) {

lib/AST/Decl.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -952,14 +952,17 @@ SourceRange PatternBindingDecl::getSourceRange() const {
952952
}
953953

954954
static StaticSpellingKind getCorrectStaticSpellingForDecl(const Decl *D) {
955-
if (D->getDeclContext()->getAsClassOrClassExtensionContext())
956-
return StaticSpellingKind::KeywordClass;
957-
return StaticSpellingKind::KeywordStatic;
955+
if (!D->getDeclContext()->getAsClassOrClassExtensionContext())
956+
return StaticSpellingKind::KeywordStatic;
957+
958+
return StaticSpellingKind::KeywordClass;
958959
}
959960

960961
StaticSpellingKind PatternBindingDecl::getCorrectStaticSpelling() const {
961962
if (!isStatic())
962963
return StaticSpellingKind::None;
964+
if (getStaticSpelling() != StaticSpellingKind::None)
965+
return getStaticSpelling();
963966

964967
return getCorrectStaticSpellingForDecl(this);
965968
}
@@ -3351,6 +3354,10 @@ bool VarDecl::isAnonClosureParam() const {
33513354
StaticSpellingKind VarDecl::getCorrectStaticSpelling() const {
33523355
if (!isStatic())
33533356
return StaticSpellingKind::None;
3357+
if (auto *PBD = getParentPatternBinding()) {
3358+
if (PBD->getStaticSpelling() != StaticSpellingKind::None)
3359+
return PBD->getStaticSpelling();
3360+
}
33543361

33553362
return getCorrectStaticSpellingForDecl(this);
33563363
}
@@ -4079,6 +4086,8 @@ StaticSpellingKind FuncDecl::getCorrectStaticSpelling() const {
40794086
assert(getDeclContext()->isTypeContext());
40804087
if (!isStatic())
40814088
return StaticSpellingKind::None;
4089+
if (getStaticSpelling() != StaticSpellingKind::None)
4090+
return getStaticSpelling();
40824091

40834092
return getCorrectStaticSpellingForDecl(this);
40844093
}

lib/Sema/TypeCheckDecl.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5153,8 +5153,19 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
51535153
}
51545154

51555155
// FIXME: Customize message to the kind of thing.
5156-
TC.diagnose(Override, diag::override_final,
5157-
Override->getDescriptiveKind());
5156+
auto baseKind = Base->getDescriptiveKind();
5157+
switch (baseKind) {
5158+
case DescriptiveDeclKind::StaticLet:
5159+
case DescriptiveDeclKind::StaticVar:
5160+
case DescriptiveDeclKind::StaticMethod:
5161+
TC.diagnose(Override, diag::override_static, baseKind);
5162+
break;
5163+
default:
5164+
TC.diagnose(Override, diag::override_final,
5165+
Override->getDescriptiveKind(), baseKind);
5166+
break;
5167+
}
5168+
51585169
TC.diagnose(Base, diag::overridden_here);
51595170
}
51605171

test/IDE/print_ast_tc_decls.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,26 @@ class d0120_TestClassBase {
422422
return 0
423423
}
424424
// PASS_COMMON-NEXT: {{^}} subscript(i: Int) -> Int { get }{{$}}
425+
426+
class var baseClassVar1: Int { return 0 }
427+
// PASS_COMMON-NEXT: {{^}} class var baseClassVar1: Int { get }{{$}}
428+
429+
// FIXME: final class var not allowed to have storage, but static is?
430+
// final class var baseClassVar2: Int = 0
431+
432+
final class var baseClassVar3: Int { return 0 }
433+
// PASS_COMMON-NEXT: {{^}} final class var baseClassVar3: Int { get }{{$}}
434+
static var baseClassVar4: Int = 0
435+
// PASS_COMMON-NEXT: {{^}} static var baseClassVar4: Int{{$}}
436+
static var baseClassVar5: Int { return 0 }
437+
// PASS_COMMON-NEXT: {{^}} static var baseClassVar5: Int { get }{{$}}
438+
439+
class func baseClassFunc1() {}
440+
// PASS_COMMON-NEXT: {{^}} class func baseClassFunc1(){{$}}
441+
final class func baseClassFunc2() {}
442+
// PASS_COMMON-NEXT: {{^}} final class func baseClassFunc2(){{$}}
443+
static func baseClassFunc3() {}
444+
// PASS_COMMON-NEXT: {{^}} static func baseClassFunc3(){{$}}
425445
}
426446

427447
class d0121_TestClassDerived : d0120_TestClassBase {

test/Sema/availability_versions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,7 @@ class ClassForFixit {
13121312

13131313
static var fixitForReferenceInStaticPropertyType: ClassAvailableOn10_51? = nil
13141314
// expected-error@-1 {{'ClassAvailableOn10_51' is only available on OS X 10.51 or newer}}
1315-
// expected-note@-2 {{add @available attribute to enclosing class var}} {{3-3=@available(OSX 10.51, *)\n }}
1315+
// expected-note@-2 {{add @available attribute to enclosing static var}} {{3-3=@available(OSX 10.51, *)\n }}
13161316
// expected-note@-3 {{add @available attribute to enclosing class}} {{1-1=@available(OSX 10.51, *)\n}}
13171317

13181318
var fixitForReferenceInPropertyTypeMultiple: ClassAvailableOn10_51? = nil, other: Int = 7

test/SourceKit/SourceDocInfo/cursor_info.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ func refEnumElements() {
103103
let z: E3 = .C
104104
}
105105

106+
class C4 {
107+
static var v1: Int = 0
108+
final class var v2: Int = 0
109+
static func f1() {}
110+
final class func f2() {}
111+
}
112+
106113
// RUN: rm -rf %t.tmp
107114
// RUN: mkdir %t.tmp
108115
// RUN: %swiftc_driver -emit-module -o %t.tmp/FooSwiftModule.swiftmodule %S/Inputs/FooSwiftModule.swift
@@ -415,3 +422,21 @@ func refEnumElements() {
415422
// CHECK47-NEXT: T.Type
416423
// CHECK47-NEXT: <Declaration>T</Declaration>
417424
// CHECK47-NEXT: <decl.generic_type_param><decl.generic_type_param.name>T</decl.generic_type_param.name></decl.generic_type_param>
425+
426+
// RUN: %sourcekitd-test -req=cursor -pos=107:14 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | FileCheck %s -check-prefix=CHECK48
427+
// CHECK48: source.lang.swift.decl.var.static (107:14-107:16)
428+
// CHECK48: <decl.var.static><syntaxtype.keyword>static</syntaxtype.keyword> <syntaxtype.keyword>var</syntaxtype.keyword>
429+
430+
// RUN: %sourcekitd-test -req=cursor -pos=108:19 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | FileCheck %s -check-prefix=CHECK49
431+
// CHECK49: source.lang.swift.decl.var.class (108:19-108:21)
432+
// CHECK49: <decl.var.class>final <syntaxtype.keyword>class</syntaxtype.keyword> <syntaxtype.keyword>var</syntaxtype.keyword>
433+
// FIXME: missing tags on 'final'
434+
435+
// RUN: %sourcekitd-test -req=cursor -pos=109:15 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | FileCheck %s -check-prefix=CHECK50
436+
// CHECK50: source.lang.swift.decl.function.method.static (109:15-109:19)
437+
// CHECK50: <decl.function.method.static><syntaxtype.keyword>static</syntaxtype.keyword> <syntaxtype.keyword>func</syntaxtype.keyword>
438+
439+
// RUN: %sourcekitd-test -req=cursor -pos=110:20 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | FileCheck %s -check-prefix=CHECK51
440+
// CHECK51: source.lang.swift.decl.function.method.class (110:20-110:24)
441+
// CHECK51: <decl.function.method.class>final <syntaxtype.keyword>class</syntaxtype.keyword> <syntaxtype.keyword>func</syntaxtype.keyword>
442+
// FIXME: missing tags on 'final'

test/decl/func/static_func.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,13 @@ extension E {
6161
}
6262

6363
class C {
64-
static func f1() {} // expected-note {{overridden declaration is here}}
64+
static func f1() {} // expected-note 3{{overridden declaration is here}}
6565
class func f2() {}
6666
class func f3() {}
6767
class func f4() {} // expected-note {{overridden declaration is here}}
6868
class func f5() {} // expected-note {{overridden declaration is here}}
6969
static final func f6() {} // expected-error {{static declarations are already final}} {{10-16=}}
70+
final class func f7() {} // expected-note 3{{overridden declaration is here}}
7071
}
7172

7273
extension C {
@@ -78,12 +79,22 @@ extension C {
7879
}
7980

8081
class C_Derived : C {
81-
override static func f1() {} // expected-error {{class method overrides a 'final' class method}}
82+
override static func f1() {} // expected-error {{cannot override static method}}
8283
override class func f2() {}
8384
class override func f3() {}
8485

8586
override class func ef2() {} // expected-error {{declarations from extensions cannot be overridden yet}}
8687
class override func ef3() {} // expected-error {{declarations from extensions cannot be overridden yet}}
88+
override static func f7() {} // expected-error {{static method overrides a 'final' class method}}
89+
}
90+
91+
class C_Derived2 : C {
92+
override final class func f1() {} // expected-error {{cannot override static method}}
93+
override final class func f7() {} // expected-error {{class method overrides a 'final' class method}}
94+
}
95+
class C_Derived3 : C {
96+
override class func f1() {} // expected-error {{cannot override static method}}
97+
override class func f7() {} // expected-error {{class method overrides a 'final' class method}}
8798
}
8899

89100
extension C_Derived {

test/decl/var/static_var.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,26 @@ class C2 {
212212
}
213213

214214
class ClassHasVars {
215-
static var computedStatic: Int { return 0 } // expected-note {{overridden declaration is here}}
215+
static var computedStatic: Int { return 0 } // expected-note 3{{overridden declaration is here}}
216+
final class var computedFinalClass: Int { return 0 } // expected-note 3{{overridden declaration is here}}
216217
class var computedClass: Int { return 0 }
217218
var computedInstance: Int { return 0 }
218219
}
219220

220221
class ClassOverridesVars : ClassHasVars {
221-
override static var computedStatic: Int { return 1 } // expected-error {{class var overrides a 'final' class var}}
222+
override static var computedStatic: Int { return 1 } // expected-error {{cannot override static var}}
223+
override static var computedFinalClass: Int { return 1 } // expected-error {{static var overrides a 'final' class var}}
222224
override class var computedClass: Int { return 1 }
223225
override var computedInstance: Int { return 1 }
224226
}
227+
class ClassOverridesVars2 : ClassHasVars {
228+
override final class var computedStatic: Int { return 1 } // expected-error {{cannot override static var}}
229+
override final class var computedFinalClass: Int { return 1 } // expected-error {{class var overrides a 'final' class var}}
230+
}
231+
class ClassOverridesVars3 : ClassHasVars {
232+
override class var computedStatic: Int { return 1 } // expected-error {{cannot override static var}}
233+
override class var computedFinalClass: Int { return 1 } // expected-error {{class var overrides a 'final' class var}}
234+
}
225235

226236
struct S2 {
227237
var x: Int = 19

0 commit comments

Comments
 (0)