-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Swift: Simplify the API for Decl members #11046
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm still of the opinion that there's not really a need to have a class like this as part of the public AST. Rather, I'd much rather see the importing of the I think we should delay this change until we've settled on a decision here.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And I'm not very happy with the name |
||
| /** | ||
| * 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) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure, but maybe this logic should be part of the extractor or codegen.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We generally prefer to put logic in QL when we have the choice, and there are no good reasons for putting in the extractor.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... I'd like to tell you why we prefer that. I think it has to do with QL being easier to see and easier to change. |
||
| 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 | ||
| ) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do like this, having |
||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this should be PropertyDecl, to keep it consistent with the language's preferred name. |
||
| FieldDecl() { this = any(IterableDeclContext ctx).getAMember() } | ||
| FieldDecl() { this = any(DeclWithMembers ctx).getAMember() } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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() | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a rule of thumb for when I should cache a predicate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's always a bit difficult to judge when (and how) something should be cached. Generally, if a predicate is (1) expensive to compute, and (2) used in multiple queries, then it should most likely be cached. In this case, I don't think that the predicate should be cached as I don't think
getDeclaringDeclis expensive to compute.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The simplest rule of thumb is: if in doubt, don't mark predicates
cachedwhen you write them (or usepragma[only_bind_into]and other hints). The optimizer doesn't usually need these tags to do a good job, and you can make things worse by using them. In the case ofcached, I believe it prevents the optimizer from using the context in which the predicate is called to reduce its size, which can sometimes cost more than any gains.The time to use these tools IMO is when you've identified a measurable performance problem and you're trying to fix it. I guess the other situation is when you're implementing or copying a familiar pattern where
cachedhas worked out well before.