diff --git a/swift/ql/lib/codeql/swift/elements/decl/Decl.qll b/swift/ql/lib/codeql/swift/elements/decl/Decl.qll index 3b440878dae9..21aa82e2460d 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/Decl.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/Decl.qll @@ -1,4 +1,23 @@ -// generated by codegen/codegen.py, remove this comment if you wish to edit this file private import codeql.swift.generated.decl.Decl +private import codeql.swift.elements.decl.DeclWithMembers +private import codeql.swift.elements.decl.NominalTypeDecl +private import codeql.swift.elements.decl.ExtensionDecl -class Decl extends Generated::Decl { } +class Decl extends Generated::Decl { + /** + * Gets the class, struct, enum, protocol, or extension that declared + * this `Decl` as a member. + */ + cached + DeclWithMembers getDeclaringDecl() { result.getAMember() = this } + + /** + * Gets the class, struct, enum, or protocol that declared + * (or was extended with) this `Decl` as a member. + */ + NominalTypeDecl getDeclaringTypeDecl() { + result.getAMember() = this + or + result = any(ExtensionDecl e | e.getAMember() = this).getExtendedTypeDecl() + } +} diff --git a/swift/ql/lib/codeql/swift/elements/decl/DeclWithMembers.qll b/swift/ql/lib/codeql/swift/elements/decl/DeclWithMembers.qll new file mode 100644 index 000000000000..77941eba0b63 --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/decl/DeclWithMembers.qll @@ -0,0 +1,26 @@ +private import codeql.swift.elements.decl.IterableDeclContext +private import codeql.swift.elements.decl.VarDecl +private import codeql.swift.elements.decl.SubscriptDecl +private import codeql.swift.elements.decl.Decl + +class DeclWithMembers extends Decl, IterableDeclContext { + /** + * Gets the `index`th member (0-based) of this nominal type or extension `Decl`, + * including `AccessorDecl`s of immediate members. + */ + override Decl getImmediateMember(int index) { + result = + rank[1 + index](Decl member, Decl immMember, int immIndex, int accIndex | + immMember = super.getImmediateMember(immIndex) and + ( + member = immMember and accIndex = -1 + or + member = immMember.(VarDecl).getImmediateAccessorDecl(accIndex) + or + member = immMember.(SubscriptDecl).getImmediateAccessorDecl(accIndex) + ) + | + member order by immIndex, accIndex + ) + } +} diff --git a/swift/ql/lib/codeql/swift/elements/decl/MethodDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/MethodDecl.qll index 0f791dc5f6ac..1c71ac9df93e 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/MethodDecl.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/MethodDecl.qll @@ -1,26 +1,8 @@ private import swift - -private Decl getAMember(IterableDeclContext ctx) { - ctx.getAMember() = result - or - exists(VarDecl var | - ctx.getAMember() = var and - var.getAnAccessorDecl() = result - ) -} +private import codeql.swift.elements.decl.DeclWithMembers class MethodDecl extends AbstractFunctionDecl { - MethodDecl() { - this = getAMember(any(ClassDecl c)) - or - this = getAMember(any(StructDecl c)) - or - this = getAMember(any(ExtensionDecl c)) - or - this = getAMember(any(EnumDecl c)) - or - this = getAMember(any(ProtocolDecl c)) - } + MethodDecl() { this = any(DeclWithMembers decl).getAMember() } /** * Holds if this function is called `funcName` and its a member of a @@ -29,17 +11,7 @@ class MethodDecl extends AbstractFunctionDecl { cached predicate hasQualifiedName(string typeName, string funcName) { this.getName() = funcName and - ( - exists(NominalTypeDecl c | - c.getFullName() = typeName and - c.getAMember() = this - ) - or - exists(ExtensionDecl e | - e.getExtendedTypeDecl().getFullName() = typeName and - e.getAMember() = this - ) - ) + this.getDeclaringTypeDecl().getFullName() = typeName } /** diff --git a/swift/ql/lib/codeql/swift/elements/decl/VarDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/VarDecl.qll index baeb044a93d5..9e056b7c30f0 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/VarDecl.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/VarDecl.qll @@ -1,6 +1,6 @@ private import codeql.swift.generated.decl.VarDecl private import codeql.swift.elements.expr.DeclRefExpr -private import codeql.swift.elements.decl.IterableDeclContext +private import codeql.swift.elements.decl.DeclWithMembers class VarDecl extends Generated::VarDecl { override string toString() { result = this.getName() } @@ -9,5 +9,5 @@ class VarDecl extends Generated::VarDecl { } class FieldDecl extends VarDecl { - FieldDecl() { this = any(IterableDeclContext ctx).getAMember() } + FieldDecl() { this = any(DeclWithMembers ctx).getAMember() } } diff --git a/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.expected b/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.expected new file mode 100644 index 000000000000..11ad32cb3c1f --- /dev/null +++ b/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.expected @@ -0,0 +1,95 @@ +declHasMemberAtIndex +| iterabledeclcontext.swift:4:1:7:1 | Protocol1 | 0 | iterabledeclcontext.swift:5:2:5:30 | Associated | AssociatedTypeDecl | +| iterabledeclcontext.swift:4:1:7:1 | Protocol1 | 1 | iterabledeclcontext.swift:6:2:6:16 | foo() | ConcreteFuncDecl | +| iterabledeclcontext.swift:8:1:10:1 | extension | 0 | iterabledeclcontext.swift:9:2:9:45 | foo() | ConcreteFuncDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 0 | iterabledeclcontext.swift:13:2:13:10 | init() | ConstructorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 1 | iterabledeclcontext.swift:14:2:14:10 | deinit() | DestructorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 2 | iterabledeclcontext.swift:16:2:16:27 | var ... = ... | PatternBindingDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 3 | iterabledeclcontext.swift:16:6:16:6 | constantField | ConcreteVarDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 4 | iterabledeclcontext.swift:16:6:16:6 | get | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 5 | iterabledeclcontext.swift:17:2:17:27 | var ... = ... | PatternBindingDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 6 | iterabledeclcontext.swift:17:6:17:6 | mutableField | ConcreteVarDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 7 | iterabledeclcontext.swift:17:6:17:6 | get | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 8 | iterabledeclcontext.swift:17:6:17:6 | set | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 9 | iterabledeclcontext.swift:17:6:17:6 | (unnamed function decl) | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 10 | iterabledeclcontext.swift:18:2:18:40 | var ... = ... | PatternBindingDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 11 | iterabledeclcontext.swift:18:13:18:13 | staticConstantField | ConcreteVarDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 12 | iterabledeclcontext.swift:18:13:18:13 | get | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 13 | iterabledeclcontext.swift:19:2:19:40 | var ... = ... | PatternBindingDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 14 | iterabledeclcontext.swift:19:13:19:13 | staticMutableField | ConcreteVarDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 15 | iterabledeclcontext.swift:19:13:19:13 | get | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 16 | iterabledeclcontext.swift:19:13:19:13 | set | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 17 | iterabledeclcontext.swift:19:13:19:13 | (unnamed function decl) | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 18 | iterabledeclcontext.swift:21:2:23:2 | var ... = ... | PatternBindingDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 19 | iterabledeclcontext.swift:21:12:21:12 | gettableClassField | ConcreteVarDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 20 | iterabledeclcontext.swift:21:36:23:2 | get | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 21 | iterabledeclcontext.swift:24:2:27:2 | var ... = ... | PatternBindingDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 22 | iterabledeclcontext.swift:24:6:24:6 | observableField | ConcreteVarDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 23 | iterabledeclcontext.swift:25:3:25:36 | willSet | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 24 | iterabledeclcontext.swift:26:3:26:34 | didSet | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 25 | iterabledeclcontext.swift:24:6:24:6 | get | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 26 | iterabledeclcontext.swift:24:6:24:6 | set | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 27 | iterabledeclcontext.swift:24:6:24:6 | (unnamed function decl) | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 28 | iterabledeclcontext.swift:29:2:36:2 | subscript ... | SubscriptDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 29 | iterabledeclcontext.swift:30:3:32:3 | get | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 30 | iterabledeclcontext.swift:33:3:35:3 | set | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 31 | iterabledeclcontext.swift:29:2:29:2 | (unnamed function decl) | AccessorDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 32 | iterabledeclcontext.swift:38:2:38:25 | instanceMethod() | ConcreteFuncDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 33 | iterabledeclcontext.swift:39:2:39:30 | staticMethod() | ConcreteFuncDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 34 | iterabledeclcontext.swift:40:2:40:28 | classMethod() | ConcreteFuncDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 35 | iterabledeclcontext.swift:44:2:44:25 | Associated | TypeAliasDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 36 | iterabledeclcontext.swift:48:2:50:2 | NestedClass | ClassDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 37 | iterabledeclcontext.swift:51:2:53:2 | NestedStruct | StructDecl | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | 38 | iterabledeclcontext.swift:54:2:58:2 | NestedEnum | EnumDecl | +| iterabledeclcontext.swift:48:2:50:2 | NestedClass | 0 | iterabledeclcontext.swift:49:3:49:25 | foo() | ConcreteFuncDecl | +| iterabledeclcontext.swift:48:2:50:2 | NestedClass | 1 | file://:0:0:0:0 | Associated | TypeAliasDecl | +| iterabledeclcontext.swift:48:2:50:2 | NestedClass | 2 | iterabledeclcontext.swift:48:8:48:8 | deinit() | DestructorDecl | +| iterabledeclcontext.swift:48:2:50:2 | NestedClass | 3 | iterabledeclcontext.swift:48:8:48:8 | init() | ConstructorDecl | +| iterabledeclcontext.swift:51:2:53:2 | NestedStruct | 0 | iterabledeclcontext.swift:52:3:52:25 | foo() | ConcreteFuncDecl | +| iterabledeclcontext.swift:51:2:53:2 | NestedStruct | 1 | file://:0:0:0:0 | Associated | TypeAliasDecl | +| iterabledeclcontext.swift:51:2:53:2 | NestedStruct | 2 | iterabledeclcontext.swift:51:9:51:9 | init() | ConstructorDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 0 | iterabledeclcontext.swift:55:3:55:8 | case ... | EnumCaseDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 1 | iterabledeclcontext.swift:55:8:55:8 | case1 | EnumElementDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 2 | iterabledeclcontext.swift:56:3:56:8 | case ... | EnumCaseDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 3 | iterabledeclcontext.swift:56:8:56:8 | case2 | EnumElementDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 4 | iterabledeclcontext.swift:57:3:57:25 | foo() | ConcreteFuncDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 5 | file://:0:0:0:0 | __derived_enum_equals(_:_:) | ConcreteFuncDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 6 | file://:0:0:0:0 | var ... = ... | PatternBindingDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 7 | file://:0:0:0:0 | hash(into:) | ConcreteFuncDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 8 | file://:0:0:0:0 | Associated | TypeAliasDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 9 | file://:0:0:0:0 | hashValue | ConcreteVarDecl | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | 10 | file://:0:0:0:0 | get | AccessorDecl | +methodDecl +| iterabledeclcontext.swift:4:1:7:1 | Protocol1 | iterabledeclcontext.swift:6:2:6:16 | foo() | ConcreteFuncDecl | iterabledeclcontext.Protocol1.foo() | +| iterabledeclcontext.swift:8:1:10:1 | extension | iterabledeclcontext.swift:9:2:9:45 | foo() | ConcreteFuncDecl | iterabledeclcontext.Protocol1.foo() | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:13:2:13:10 | init() | ConstructorDecl | iterabledeclcontext.Class1.init() | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:14:2:14:10 | deinit() | DestructorDecl | iterabledeclcontext.Class1.deinit() | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:16:6:16:6 | get | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:17:6:17:6 | (unnamed function decl) | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:17:6:17:6 | get | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:17:6:17:6 | set | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:18:13:18:13 | get | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:19:13:19:13 | (unnamed function decl) | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:19:13:19:13 | get | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:19:13:19:13 | set | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:21:36:23:2 | get | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:24:6:24:6 | (unnamed function decl) | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:24:6:24:6 | get | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:24:6:24:6 | set | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:25:3:25:36 | willSet | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:26:3:26:34 | didSet | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:29:2:29:2 | (unnamed function decl) | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:30:3:32:3 | get | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:33:3:35:3 | set | AccessorDecl | iterabledeclcontext.Class1.(unnamed function decl) | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:38:2:38:25 | instanceMethod() | ConcreteFuncDecl | iterabledeclcontext.Class1.instanceMethod() | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:39:2:39:30 | staticMethod() | ConcreteFuncDecl | iterabledeclcontext.Class1.staticMethod() | +| iterabledeclcontext.swift:12:1:59:1 | Class1 | iterabledeclcontext.swift:40:2:40:28 | classMethod() | ConcreteFuncDecl | iterabledeclcontext.Class1.classMethod() | +| iterabledeclcontext.swift:48:2:50:2 | NestedClass | iterabledeclcontext.swift:48:8:48:8 | deinit() | DestructorDecl | iterabledeclcontext.Class1.NestedClass.deinit() | +| iterabledeclcontext.swift:48:2:50:2 | NestedClass | iterabledeclcontext.swift:48:8:48:8 | init() | ConstructorDecl | iterabledeclcontext.Class1.NestedClass.init() | +| iterabledeclcontext.swift:48:2:50:2 | NestedClass | iterabledeclcontext.swift:49:3:49:25 | foo() | ConcreteFuncDecl | iterabledeclcontext.Class1.NestedClass.foo() | +| iterabledeclcontext.swift:51:2:53:2 | NestedStruct | iterabledeclcontext.swift:51:9:51:9 | init() | ConstructorDecl | iterabledeclcontext.Class1.NestedStruct.init() | +| iterabledeclcontext.swift:51:2:53:2 | NestedStruct | iterabledeclcontext.swift:52:3:52:25 | foo() | ConcreteFuncDecl | iterabledeclcontext.Class1.NestedStruct.foo() | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | file://:0:0:0:0 | __derived_enum_equals(_:_:) | ConcreteFuncDecl | iterabledeclcontext.Class1.NestedEnum.__derived_enum_equals(_:_:) | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | file://:0:0:0:0 | get | AccessorDecl | iterabledeclcontext.Class1.NestedEnum.(unnamed function decl) | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | file://:0:0:0:0 | hash(into:) | ConcreteFuncDecl | iterabledeclcontext.Class1.NestedEnum.hash(into:) | +| iterabledeclcontext.swift:54:2:58:2 | NestedEnum | iterabledeclcontext.swift:57:3:57:25 | foo() | ConcreteFuncDecl | iterabledeclcontext.Class1.NestedEnum.foo() | diff --git a/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.ql b/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.ql new file mode 100644 index 000000000000..87e773213248 --- /dev/null +++ b/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.ql @@ -0,0 +1,24 @@ +import swift +import codeql.swift.elements.decl.DeclWithMembers + +predicate isInTestModule(Decl decl) { decl.getModule().getName() = "iterabledeclcontext" } + +query predicate declHasMemberAtIndex( + DeclWithMembers decl, int index, Decl member, string memberClass +) { + isInTestModule(decl) and + member = decl.getMember(index) and + memberClass = member.getPrimaryQlClasses() +} + +query predicate methodDecl( + DeclWithMembers decl, MethodDecl member, string memberClass, string memberQName +) { + isInTestModule(member) and + memberClass = member.getPrimaryQlClasses() and + decl.getAMember() = member and + exists(string memberModule, string memberType, string memberName | + member.hasQualifiedName(memberModule, memberType, memberName) and + memberQName = memberModule + "." + memberType + "." + memberName + ) +} diff --git a/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.swift b/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.swift new file mode 100644 index 000000000000..7bfa087e9fbb --- /dev/null +++ b/swift/ql/test/library-tests/elements/decl/iterabledeclcontext/iterabledeclcontext.swift @@ -0,0 +1,59 @@ + +func freeFunction() {} + +protocol Protocol1 { + associatedtype Associated = Int + func foo() -> Int +} +extension Protocol1 { + func foo() -> Int { return 1 /* default */ } +} + +class Class1: Protocol1 { + init() {} + deinit {} + + let constantField: Int = 42 + var mutableField: Int? = nil + static let staticConstantField: Int = 42 + static var staticMutableField: Int? = nil + + class var gettableClassField: Int { + return 42 /* get-Accessor */ + } + var observableField: Int = 1 { + willSet { /* willSet-Accessor */ } + didSet { /* didSet-Accessor */ } + } + + subscript(_ index: Int) -> Int { + get { + return mutableField ?? 0 /* get-Accessor */ + } + set(value) { + mutableField = index + value /* set-Accessor */ + } + } + + func instanceMethod() {} + static func staticMethod() {} + class func classMethod() {} + + // Type members: + + typealias Associated = Int + + // Nominal types: + + class NestedClass: Protocol1 { + func foo() -> Int { 2 } + } + struct NestedStruct: Protocol1 { + func foo() -> Int { 3 } + } + enum NestedEnum: Protocol1 { + case case1 + case case2 + func foo() -> Int { 4 } + } +}