@@ -6,52 +6,58 @@ private import codeql.unified.internal.StaticNameBinding
66private import codeql.unified.internal.ExprPositions
77
88/**
9- * Holds if `alias` is an alias at `pathToNested` for nested type `nested` with
10- * enclosing type `parent`, where the alias itself is also enclosed by `parent`:
9+ * Holds if `alias` is an alias where the type mentioned at `pathToNested` in the
10+ * right-hand side is the nested type `nested`, and the alias is enclosed by `encl`,
11+ * which is (a sub class of) the parent class of `nested`. Furthermore, the mention
12+ * of `nested` must be "orphaned", meaning it's parent type is not mentioned explicitly:
1113 *
1214 * ```swift
13- * class Parent {
15+ * class Parent<TParent> {
1416 * class Nested {}
15- * typealias Alias = Nested // example
17+ * typealias Alias = Nested // example
18+ * typealias Alias2 = Parent<Int>.Nested // non-example (not orphaned)
1619 * class MoreNested {
17- * typealias Alias = Nested // example
20+ * typealias Alias = Nested // example
1821 * }
1922 * }
20- * typealias Alias = Parent.Nested // non-example
23+ * typealias Alias = Parent<Int>.Nested // non-example (not orphaned, not enclosed by `Parent`)
24+ * class Sub : Parent<Int> {
25+ * typealias SubAlias = Nested // example
26+ * }
2127 * ```
2228 *
2329 * The type path `pathParents` is any valid sequence of `ParentTypeParameterType`s starting
24- * from the alias declaration and not escaping `parent`, while `encl` is the enclosing
25- * class of the last element of `pathParents`.
26- *
27- * Restricted to aliases without a qualifier for `nested`.
30+ * from the alias declaration and not escaping `encl`, while `last` is the enclosing
31+ * class of the last element of `pathParents` (used to build up `pathParents` recursively).
2832 */
29- private predicate isInnerUnqualifiedAlias (
33+ private predicate isInnerAliasWithOrphanedNestedType (
3034 TypeAliasDeclaration alias , TypePath pathToNested , ClassLikeDeclaration nested ,
31- ClassLikeDeclaration parent , TypePath pathParents , ClassLikeDeclaration encl
35+ ClassLikeDeclaration encl , TypePath pathParents , ClassLikeDeclaration last
3236) {
33- nested = alias .getType ( ) .( TypeMention ) .getSimpleExpandedTypeAt ( pathToNested ) .asClass ( ) and
34- // if the alias already has a qualifier that mentions the parent type, then we assume
35- // it applies
36- not exists ( ParentTypeParameterType ptp |
37- ptp .getParent ( ) = parent and
38- exists (
39- alias
40- .getType ( )
41- .( TypeMention )
42- .getSimpleExpandedTypeAt ( pathToNested .append ( TypePath:: singleton ( ptp ) ) )
43- )
44- ) and
45- parent = nested .getEnclosingClassResolved ( ) and
46- alias .getEnclosingClassResolved + ( ) = parent and
47- pathParents = TypePath:: singleton ( TParentTypeParameterType ( alias ) ) and
48- encl = alias .getEnclosingClassResolved ( )
37+ exists ( ClassLikeDeclaration parent |
38+ parent = nested .getEnclosingClassResolved ( ) and
39+ nested = alias .getType ( ) .( TypeMention ) .getSimpleExpandedTypeAt ( pathToNested ) .asClass ( ) and
40+ // if the alias already mentions the parent type, then we assume it applies
41+ not exists ( ParentTypeParameterType ptp |
42+ ptp .getParent ( ) .getABaseClass * ( ) = parent and
43+ exists (
44+ alias
45+ .getType ( )
46+ .( TypeMention )
47+ .getSimpleExpandedTypeAt ( pathToNested .append ( TypePath:: singleton ( ptp ) ) )
48+ )
49+ ) and
50+ encl .getABaseClass * ( ) = parent and
51+ alias .getEnclosingClassResolved + ( ) = encl and
52+ pathParents = TypePath:: singleton ( TParentTypeParameterType ( alias ) ) and
53+ last = alias .getEnclosingClassResolved ( )
54+ )
4955 or
50- exists ( TypePath mid , ClassLikeDeclaration enclMid |
51- isInnerUnqualifiedAlias ( alias , pathToNested , nested , parent , mid , enclMid ) and
52- not enclMid = parent and
53- pathParents = mid .append ( TypePath:: singleton ( TParentTypeParameterType ( enclMid ) ) ) and
54- encl = enclMid .getEnclosingClassResolved ( )
56+ exists ( TypePath mid , ClassLikeDeclaration lastMid |
57+ isInnerAliasWithOrphanedNestedType ( alias , pathToNested , nested , encl , mid , lastMid ) and
58+ not lastMid = encl and
59+ pathParents = mid .append ( TypePath:: singleton ( TParentTypeParameterType ( lastMid ) ) ) and
60+ last = lastMid .getEnclosingClassResolved ( )
5561 )
5662}
5763
@@ -95,17 +101,18 @@ abstract private class TypeMentionImpl extends AstNode {
95101 not result = alias .getATypeParameter ( )
96102 or
97103 // substitute for type parameters in alias RHS
98- exists ( TypeParameter tp , TypePath mid |
104+ exists ( TypeParameter tp , TypePath pathToTp , TypePath mid |
99105 tp = alias .getATypeParameter ( ) and
100- tp = alias .getAlias ( ) .getSimpleExpandedTypeAt ( mid ) and
101- result =
102- this .getSimpleExpandedTypeAt ( prefix
103- .appendInverse ( any ( TypePath cons | cons .isCons ( tp , suffix ) ) ) ) and
104- path = prefix .append ( mid ) .append ( suffix )
106+ tp = alias .getAlias ( ) .getSimpleExpandedTypeAt ( pathToTp ) and
107+ result = this .getSimpleExpandedTypeAt ( prefix .appendInverse ( mid ) ) and
108+ mid .isCons ( tp , suffix ) and
109+ path = prefix .append ( pathToTp ) .append ( suffix )
105110 )
106111 )
107112 }
108113
114+ Type getSimpleExpandedType ( ) { result = this .getSimpleExpandedTypeAt ( TypePath:: nil ( ) ) }
115+
109116 /**
110117 * Same as `getSimpleExpandedTypeAt`, but also handles inner unqualified aliases where
111118 * the qualifier is provided at the use site:
@@ -130,22 +137,20 @@ abstract private class TypeMentionImpl extends AstNode {
130137 ClassLikeDeclaration parent , TypePath pathParents , TypePath suffix
131138 |
132139 this .getExpandedTypeAt ( prefix ) = alias and
133- isInnerUnqualifiedAlias ( alias .getTypeAliasDeclaration ( ) , pathToNested , nested , parent ,
134- pathParents , _) and
140+ isInnerAliasWithOrphanedNestedType ( alias .getTypeAliasDeclaration ( ) , pathToNested , nested ,
141+ parent , pathParents , _) and
135142 this .getExpandedTypeAt ( prefix .append ( pathParents ) ) .asClass ( ) .getABaseClass * ( ) = parent and
136143 result = this .getExpandedTypeAt ( prefix .append ( pathParents ) .appendInverse ( suffix ) ) and
137144 path =
138145 prefix .append ( pathToNested .append ( TypePath:: cons ( TParentTypeParameterType ( nested ) , suffix ) ) )
139146 )
140147 }
141148
142- private Type getExpandedType ( ) { result = this .getExpandedTypeAt ( TypePath:: nil ( ) ) }
143-
144149 /**
145150 * Gets the class-like declaration mentioned by this type mention, if any.
146151 */
147152 ClassLikeDeclaration getClassLikeDeclaration ( ) {
148- result = this .getExpandedType ( ) .( ClassLikeDeclarationType ) .getClassLikeDeclaration ( )
153+ result = this .getSimpleExpandedType ( ) .( ClassLikeDeclarationType ) .getClassLikeDeclaration ( )
149154 }
150155
151156 pragma [ nomagic]
0 commit comments