From 221fa3708199dc56bfb0dfd7964d6d19812294c4 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 17 Jan 2022 17:43:48 +0000 Subject: [PATCH] Fix naming of local class instances that fall within generic functions --- .../src/main/kotlin/KotlinUsesExtractor.kt | 22 +++++++++++++------ .../library-tests/generics/PrintAst.expected | 4 ++-- .../library-tests/generics/generics.expected | 8 +++---- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index 80d087b4fd0..b716f9163b4 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -145,12 +145,14 @@ open class KotlinUsesExtractor( } ?: argsIncludingOuterClasses } + fun isStaticClass(c: IrClass) = c.visibility != DescriptorVisibilities.LOCAL && !c.isInner + // Gets nested inner classes starting at `c` and proceeding outwards to the innermost enclosing static class. // For example, for (java syntax) `class A { static class B { class C { class D { } } } }`, // `nonStaticParentsWithSelf(D)` = `[D, C, B]`. fun parentsWithTypeParametersInScope(c: IrClass): List { val parentsList = c.parentsWithSelf.toList() - val firstOuterClassIdx = parentsList.indexOfFirst { it is IrClass && !it.isInner } + val firstOuterClassIdx = parentsList.indexOfFirst { it is IrClass && isStaticClass(it) } return if (firstOuterClassIdx == -1) parentsList else parentsList.subList(0, firstOuterClassIdx + 1) } @@ -158,7 +160,7 @@ open class KotlinUsesExtractor( // `class NotInScope { static class OutermostInScope { class QueryClass { } } }`, // `getTypeParametersInScope(QueryClass)` = `[C, D, A, B]`. fun getTypeParametersInScope(c: IrClass) = - parentsWithTypeParametersInScope(c).mapNotNull({ (it as? IrClass)?.typeParameters }).flatten() + parentsWithTypeParametersInScope(c).mapNotNull({ getTypeParameters(it) }).flatten() // Returns a map from `c`'s type variables in scope to type arguments `argsIncludingOuterClasses`. // Hack for the time being: the substituted types are always nullable, to prevent downstream code @@ -167,7 +169,7 @@ open class KotlinUsesExtractor( fun makeTypeGenericSubstitutionMap(c: IrClass, argsIncludingOuterClasses: List) = getTypeParametersInScope(c).map({ it.symbol }).zip(argsIncludingOuterClasses.map { it.withQuestionMark(true) }).toMap() - // The Kotlin compiler internal representation of Outer.Inner.InnerInner is InnerInner. This function returns [A, B, C, D, E, F]. + // The Kotlin compiler internal representation of Outer.Inner.InnerInner.someFunction.LocalClass is LocalClass. This function returns [A, B, C, D, E, F, G, H, I, J]. fun orderTypeArgsLeftToRight(c: IrClass, argsIncludingOuterClasses: List?): List? { if(argsIncludingOuterClasses.isNullOrEmpty()) return argsIncludingOuterClasses @@ -175,10 +177,9 @@ open class KotlinUsesExtractor( // Iterate over nested inner classes starting at `c`'s surrounding top-level or static nested class and ending at `c`, from the outermost inwards: val truncatedParents = parentsWithTypeParametersInScope(c) for(parent in truncatedParents.reversed()) { - if(parent is IrClass) { - val firstArgIdx = argsIncludingOuterClasses.size - (ret.size + parent.typeParameters.size) - ret.addAll(argsIncludingOuterClasses.subList(firstArgIdx, firstArgIdx + parent.typeParameters.size)) - } + val parentTypeParameters = getTypeParameters(parent) + val firstArgIdx = argsIncludingOuterClasses.size - (ret.size + parentTypeParameters.size) + ret.addAll(argsIncludingOuterClasses.subList(firstArgIdx, firstArgIdx + parentTypeParameters.size)) } return ret } @@ -612,6 +613,13 @@ class X { return if (f is IrConstructor) f.typeParameters else f.typeParameters.filter { it.parent == f } } + fun getTypeParameters(dp: IrDeclarationParent): List = + when(dp) { + is IrClass -> dp.typeParameters + is IrFunction -> getFunctionTypeParameters(dp) + else -> listOf() + } + fun getFunctionLabel(f: IrFunction, classTypeArguments: List? = null) : String { return getFunctionLabel(f.parent, getFunctionShortName(f), f.valueParameters, f.returnType, f.extensionReceiverParameter, getFunctionTypeParameters(f), classTypeArguments) } diff --git a/java/ql/test/kotlin/library-tests/generics/PrintAst.expected b/java/ql/test/kotlin/library-tests/generics/PrintAst.expected index 88b438f413f..b5c74b3ff72 100644 --- a/java/ql/test/kotlin/library-tests/generics/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/generics/PrintAst.expected @@ -223,8 +223,8 @@ generics.kt: # 61| 1: [ExprStmt] ; # 61| 0: [MethodAccess] fn2(...) # 61| -2: [TypeAccess] String -# 61| -1: [ClassInstanceExpr] new Local(...) -# 61| -3: [TypeAccess] Local +# 61| -1: [ClassInstanceExpr] new Local(...) +# 61| -3: [TypeAccess] Local # 61| 0: [TypeAccess] Integer # 61| 0: [VarAccess] t # 61| 1: [StringLiteral] diff --git a/java/ql/test/kotlin/library-tests/generics/generics.expected b/java/ql/test/kotlin/library-tests/generics/generics.expected index c6a3a3bf611..85bef752533 100644 --- a/java/ql/test/kotlin/library-tests/generics/generics.expected +++ b/java/ql/test/kotlin/library-tests/generics/generics.expected @@ -49,7 +49,7 @@ parameterizedType | generics.kt:56:1:63:1 | Class1 | generics.kt:56:1:63:1 | Class1 | 0 | T1 | | generics.kt:56:1:63:1 | Class1 | generics.kt:56:1:63:1 | Class1 | 0 | T2 | | generics.kt:58:9:60:9 | Local | generics.kt:58:9:60:9 | Local | 0 | T3 | -| generics.kt:58:9:60:9 | Local | generics.kt:58:9:60:9 | Local | 0 | Integer | +| generics.kt:58:9:60:9 | Local | generics.kt:58:9:60:9 | Local | 0 | Integer | function | generics.kt:3:1:5:1 | f0 | f0(int,java.lang.Object) | | generics.kt:7:1:9:1 | f1 | f1(int,java.lang.Object) | @@ -97,7 +97,7 @@ function | generics.kt:57:5:62:5 | fn1 | fn1(java.lang.Object) | | generics.kt:58:9:60:9 | | () | | generics.kt:58:9:60:9 | Local | Local() | -| generics.kt:58:9:60:9 | Local | Local() | +| generics.kt:58:9:60:9 | Local | Local() | | generics.kt:59:13:59:43 | fn2 | fn2(java.lang.Object,java.lang.Object) | | generics.kt:59:13:59:43 | fn2 | fn2(java.lang.Object,java.lang.Object) | genericFunction @@ -110,7 +110,7 @@ genericFunction | generics.kt:21:5:21:23 | f4 | generics.kt:20:1:22:1 | C2 | generics.kt:21:10:21:10 | P | 0 | | generics.kt:57:5:62:5 | fn1 | generics.kt:56:1:63:1 | Class1 | generics.kt:57:10:57:11 | T2 | 0 | | generics.kt:59:13:59:43 | fn2 | generics.kt:58:9:60:9 | Local | generics.kt:59:18:59:19 | T4 | 0 | -| generics.kt:59:13:59:43 | fn2 | generics.kt:58:9:60:9 | Local | generics.kt:59:18:59:19 | T4 | 0 | +| generics.kt:59:13:59:43 | fn2 | generics.kt:58:9:60:9 | Local | generics.kt:59:18:59:19 | T4 | 0 | genericCall | generics.kt:27:17:27:22 | f2(...) | generics.kt:15:10:15:10 | U | String | | generics.kt:30:17:30:21 | f2(...) | generics.kt:15:10:15:10 | U | Integer | @@ -128,4 +128,4 @@ genericCtor | generics.kt:45:21:45:41 | new Inner1(...) | 1 | String | | generics.kt:51:21:51:42 | new Nested1(...) | 0 | Integer | | generics.kt:51:21:51:42 | new Nested1(...) | 1 | String | -| generics.kt:61:9:61:20 | new Local(...) | 0 | Integer | +| generics.kt:61:9:61:20 | new Local(...) | 0 | Integer |