Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 96908d1

Browse files
smowtonigfoo
authored andcommitted
Accept and amend check for anonymous types with type parameters
1 parent c0f3988 commit 96908d1

9 files changed

Lines changed: 119 additions & 14 deletions

File tree

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,17 +1126,6 @@ open class KotlinFileExtractor(
11261126

11271127
extractNewExprForLocalFunction(ids, id, locId, enclosingCallable, enclosingStmt)
11281128
} else {
1129-
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
1130-
fun isUnspecialised(type: IrSimpleType) =
1131-
type.classifier.owner is IrClass &&
1132-
(type.classifier.owner as IrClass).typeParameters.zip(type.arguments).all { paramAndArg ->
1133-
(paramAndArg.second as? IrTypeProjection)?.let {
1134-
// Type arg refers to the class' own type parameter?
1135-
it.variance == Variance.INVARIANT &&
1136-
it.type.classifierOrNull?.owner === paramAndArg.first
1137-
} ?: false
1138-
}
1139-
11401129
val methodId =
11411130
if (drType != null && extractClassTypeArguments && drType is IrSimpleType && !isUnspecialised(drType)) {
11421131
if (isBigArityFunctionInvoke) {

java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,10 @@ open class KotlinUsesExtractor(
388388
// For non-generic types it will be zero-length list.
389389
fun useSimpleTypeClass(c: IrClass, args: List<IrTypeArgument>?, hasQuestionMark: Boolean): TypeResults {
390390
if (c.isAnonymousObject) {
391-
if (args?.isNotEmpty() == true) {
392-
logger.error("Anonymous class with unexpected type arguments")
391+
args?.let {
392+
if (it.isNotEmpty() && !isUnspecialised(c, it)) {
393+
logger.error("Unexpected specialised instance of generic anonymous class")
394+
}
393395
}
394396

395397
return useAnonymousClass(c)

java/kotlin-extractor/src/main/kotlin/utils/TypeSubstitution.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,19 @@ fun IrTypeArgument.withQuestionMark(b: Boolean): IrTypeArgument =
191191
else -> this
192192
}
193193

194-
typealias TypeSubstitution = (IrType, KotlinUsesExtractor.TypeContext, IrPluginContext) -> IrType
194+
typealias TypeSubstitution = (IrType, KotlinUsesExtractor.TypeContext, IrPluginContext) -> IrType
195+
196+
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
197+
fun isUnspecialised(classType: IrClass, args: List<IrTypeArgument>) =
198+
classType.typeParameters.zip(args).all { paramAndArg ->
199+
(paramAndArg.second as? IrTypeProjection)?.let {
200+
// Type arg refers to the class' own type parameter?
201+
it.variance == Variance.INVARIANT &&
202+
it.type.classifierOrNull?.owner === paramAndArg.first
203+
} ?: false
204+
}
205+
206+
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
207+
fun isUnspecialised(type: IrSimpleType) = (type.classifier.owner as? IrClass)?.let {
208+
isUnspecialised(it, type.arguments)
209+
} ?: false

java/ql/test/kotlin/library-tests/classes/PrintAst.expected

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,90 @@ classes.kt:
418418
# 127| 1: [ExprStmt] <Expr>;
419419
# 127| 0: [ClassInstanceExpr] new (...)
420420
# 127| -3: [TypeAccess] Object
421+
generic_anonymous.kt:
422+
# 0| [CompilationUnit] generic_anonymous
423+
# 0| 1: [Class] Generic_anonymousKt
424+
# 11| 1: [Method] stringIdentity
425+
#-----| 4: (Parameters)
426+
# 11| 0: [Parameter] s
427+
# 11| 5: [BlockStmt] { ... }
428+
# 11| 0: [ReturnStmt] return ...
429+
# 11| 0: [MethodAccess] get(...)
430+
# 11| -1: [ClassInstanceExpr] new Generic<String>(...)
431+
# 11| -3: [TypeAccess] Generic<String>
432+
# 11| 0: [TypeAccess] String
433+
# 11| 0: [VarAccess] s
434+
# 13| 2: [Method] intIdentity
435+
#-----| 4: (Parameters)
436+
# 13| 0: [Parameter] i
437+
# 13| 5: [BlockStmt] { ... }
438+
# 13| 0: [ReturnStmt] return ...
439+
# 13| 0: [MethodAccess] get(...)
440+
# 13| -1: [ClassInstanceExpr] new Generic<Integer>(...)
441+
# 13| -3: [TypeAccess] Generic<Integer>
442+
# 13| 0: [TypeAccess] Integer
443+
# 13| 0: [VarAccess] i
444+
# 1| 2: [Class,GenericType,ParameterizedType] Generic
445+
#-----| -2: (Generic Parameters)
446+
# 1| 0: [TypeVariable] T
447+
# 1| 1: [Constructor] Generic
448+
#-----| 4: (Parameters)
449+
# 1| 0: [Parameter] t
450+
# 1| 5: [BlockStmt] { ... }
451+
# 1| 0: [SuperConstructorInvocationStmt] super(...)
452+
# 1| 1: [BlockStmt] { ... }
453+
# 1| 0: [ExprStmt] <Expr>;
454+
# 1| 0: [KtInitializerAssignExpr] ...=...
455+
# 1| 0: [VarAccess] t
456+
# 3| 1: [ExprStmt] <Expr>;
457+
# 3| 0: [KtInitializerAssignExpr] ...=...
458+
# 3| 0: [VarAccess] x
459+
# 1| 2: [Method] getT
460+
# 1| 5: [BlockStmt] { ... }
461+
# 1| 0: [ReturnStmt] return ...
462+
# 1| 0: [VarAccess] this.t
463+
# 1| -1: [ThisAccess] this
464+
# 1| 2: [FieldDeclaration] T t;
465+
# 1| -1: [TypeAccess] T
466+
# 1| 0: [VarAccess] t
467+
# 3| 4: [FieldDeclaration] new Object(...) { ... } x;
468+
# 3| -1: [TypeAccess] new Object(...) { ... }
469+
# 3| 0: [TypeAccess] T
470+
# 3| 0: [StmtExpr] <Stmt>
471+
# 3| 0: [BlockStmt] { ... }
472+
# 3| 0: [LocalTypeDeclStmt] class ...
473+
# 3| 0: [AnonymousClass,LocalClass] new Object(...) { ... }
474+
# 3| 1: [Constructor]
475+
# 3| 5: [BlockStmt] { ... }
476+
# 3| 0: [SuperConstructorInvocationStmt] super(...)
477+
# 3| 1: [BlockStmt] { ... }
478+
# 4| 0: [ExprStmt] <Expr>;
479+
# 4| 0: [KtInitializerAssignExpr] ...=...
480+
# 4| 0: [VarAccess] member
481+
# 4| 2: [Method] getMember
482+
# 4| 5: [BlockStmt] { ... }
483+
# 4| 0: [ReturnStmt] return ...
484+
# 4| 0: [VarAccess] this.member
485+
# 4| -1: [ThisAccess] this
486+
# 4| 2: [FieldDeclaration] T member;
487+
# 4| -1: [TypeAccess] T
488+
# 4| 0: [MethodAccess] getT(...)
489+
# 4| -1: [ThisAccess] Generic.this
490+
# 4| 0: [TypeAccess] Generic
491+
# 3| 1: [ExprStmt] <Expr>;
492+
# 3| 0: [ClassInstanceExpr] new (...)
493+
# 3| -3: [TypeAccess] Object
494+
# 3| 5: [Method] getX
495+
# 3| 5: [BlockStmt] { ... }
496+
# 3| 0: [ReturnStmt] return ...
497+
# 3| 0: [VarAccess] this.x
498+
# 3| -1: [ThisAccess] this
499+
# 7| 6: [Method] get
500+
# 7| 5: [BlockStmt] { ... }
501+
# 7| 0: [ReturnStmt] return ...
502+
# 7| 0: [MethodAccess] getMember(...)
503+
# 7| -1: [MethodAccess] getX(...)
504+
# 7| -1: [ThisAccess] this
421505
local_anonymous.kt:
422506
# 0| [CompilationUnit] local_anonymous
423507
# 3| 1: [Class] Class1

java/ql/test/kotlin/library-tests/classes/anonymousClasses.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
| classes.kt:85:16:85:25 | new Object(...) { ... } | classes.kt:85:16:85:25 | new (...) | | classes.kt:85:16:85:25 | Object | classes.kt:85:16:85:25 | class ... |
77
| classes.kt:89:16:89:44 | new Interface3<Integer>(...) { ... } | classes.kt:89:16:89:44 | new (...) | | classes.kt:89:16:89:44 | Interface3<Integer> | classes.kt:89:16:89:44 | class ... |
88
| classes.kt:127:16:134:9 | new Object(...) { ... } | classes.kt:127:16:134:9 | new (...) | | classes.kt:127:16:134:9 | Object | classes.kt:127:16:134:9 | class ... |
9+
| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | generic_anonymous.kt:3:19:5:3 | new (...) | | generic_anonymous.kt:3:19:5:3 | Object | generic_anonymous.kt:3:19:5:3 | class ... |
910
| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | local_anonymous.kt:5:16:7:9 | new (...) | | local_anonymous.kt:5:16:7:9 | Object | local_anonymous.kt:5:16:7:9 | class ... |
1011
| local_anonymous.kt:29:31:35:5 | new Object(...) { ... } | local_anonymous.kt:29:31:35:5 | new (...) | | local_anonymous.kt:29:31:35:5 | Object | local_anonymous.kt:29:31:35:5 | class ... |

java/ql/test/kotlin/library-tests/classes/classes.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
| classes.kt:119:13:121:13 | Local2 | C1$Local2 | final, private |
3535
| classes.kt:127:16:134:9 | new Object(...) { ... } | <anonymous class> | final, private |
3636
| classes.kt:129:17:131:17 | Local3 | C1$$Local3 | final, private |
37+
| generic_anonymous.kt:0:0:0:0 | Generic_anonymousKt | Generic_anonymousKt | |
38+
| generic_anonymous.kt:1:1:9:1 | Generic | Generic | final, private |
39+
| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | <anonymous class> | final, private |
3740
| local_anonymous.kt:3:1:36:1 | Class1 | LocalAnonymous.Class1 | final, public |
3841
| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | <anonymous class> | final, private |
3942
| local_anonymous.kt:11:9:11:24 | | Class1$ | final, private |

java/ql/test/kotlin/library-tests/classes/ctorCalls.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ superCall
3434
| classes.kt:119:13:121:13 | super(...) |
3535
| classes.kt:127:16:134:9 | super(...) |
3636
| classes.kt:129:17:131:17 | super(...) |
37+
| generic_anonymous.kt:1:1:9:1 | super(...) |
38+
| generic_anonymous.kt:3:19:5:3 | super(...) |
3739
| local_anonymous.kt:3:1:36:1 | super(...) |
3840
| local_anonymous.kt:5:16:7:9 | super(...) |
3941
| local_anonymous.kt:11:9:11:24 | super(...) |

java/ql/test/kotlin/library-tests/classes/paramTypes.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
| classes.kt:119:13:121:13 | Local2<Integer> | 0 | file://<external>/Integer.class:0:0:0:0 | Integer |
55
| classes.kt:129:17:131:17 | Local3 | 0 | classes.kt:129:30:129:31 | T1 |
66
| classes.kt:129:17:131:17 | Local3<Integer> | 0 | file://<external>/Integer.class:0:0:0:0 | Integer |
7+
| generic_anonymous.kt:1:1:9:1 | Generic | 0 | generic_anonymous.kt:1:23:1:23 | T |
8+
| generic_anonymous.kt:1:1:9:1 | Generic<Integer> | 0 | file://<external>/Integer.class:0:0:0:0 | Integer |
9+
| generic_anonymous.kt:1:1:9:1 | Generic<String> | 0 | file://<external>/String.class:0:0:0:0 | String |
10+
| generic_anonymous.kt:1:1:9:1 | Generic<T> | 0 | generic_anonymous.kt:1:23:1:23 | T |
711
| superChain.kt:1:1:1:33 | SuperChain1 | 0 | superChain.kt:1:24:1:25 | T1 |
812
| superChain.kt:1:1:1:33 | SuperChain1 | 1 | superChain.kt:1:28:1:29 | T2 |
913
| superChain.kt:1:1:1:33 | SuperChain1<T3,String> | 0 | superChain.kt:2:24:2:25 | T3 |

java/ql/test/kotlin/library-tests/classes/superTypes.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
| classes.kt:127:16:134:9 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object |
4343
| classes.kt:129:17:131:17 | Local3 | file://<external>/Object.class:0:0:0:0 | Object |
4444
| classes.kt:129:17:131:17 | Local3<Integer> | file://<external>/Object.class:0:0:0:0 | Object |
45+
| generic_anonymous.kt:1:1:9:1 | Generic | file://<external>/Object.class:0:0:0:0 | Object |
46+
| generic_anonymous.kt:1:1:9:1 | Generic<Integer> | file://<external>/Object.class:0:0:0:0 | Object |
47+
| generic_anonymous.kt:1:1:9:1 | Generic<String> | file://<external>/Object.class:0:0:0:0 | Object |
48+
| generic_anonymous.kt:1:1:9:1 | Generic<T> | file://<external>/Object.class:0:0:0:0 | Object |
49+
| generic_anonymous.kt:3:19:5:3 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object |
4550
| local_anonymous.kt:3:1:36:1 | Class1 | file://<external>/Object.class:0:0:0:0 | Object |
4651
| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object |
4752
| local_anonymous.kt:11:9:11:24 | | file://<external>/Object.class:0:0:0:0 | Object |

0 commit comments

Comments
 (0)