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

Skip to content

Commit 3b09cb2

Browse files
tamasvajksmowton
authored andcommitted
WIP: Extract annotation values (tests are missing)
1 parent 7b075c2 commit 3b09cb2

6 files changed

Lines changed: 185 additions & 87 deletions

File tree

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

Lines changed: 135 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -457,53 +457,93 @@ open class KotlinFileExtractor(
457457
extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) }
458458
}
459459

460-
fun extractAnnotations(c: IrClass): Int {
461-
var count = 0
462-
for (constructorCall: IrConstructorCall in c.annotations) {
463-
464-
// todo: do not extract JvmName, what else?
460+
private fun extractAnnotations(c: IrClass) {
461+
for ((idx, constructorCall: IrConstructorCall) in c.annotations.withIndex()) {
462+
extractAnnotation(constructorCall, useClassSource(c), idx)
463+
}
464+
}
465465

466-
val t = useType(constructorCall.type)
467-
val annotated = useClassSource(c)
466+
private fun extractAnnotation(
467+
constructorCall: IrConstructorCall,
468+
parent: Label<out DbExprparent>,
469+
idx: Int
470+
): Label<out DbExpr> {
471+
val t = useType(constructorCall.type)
468472

469-
val id = tw.getLabelFor<DbDeclannotation>("@\"annotation;{$annotated};{${t.javaResult.id}}\"")
470-
tw.writeExprs_declannotation(id, t.javaResult.id, annotated, count++)
471-
tw.writeExprsKotlinType(id, t.kotlinResult.id)
473+
val id = tw.getLabelFor<DbDeclannotation>("@\"annotation;{$parent};{${t.javaResult.id}}\"")
474+
tw.writeExprs_declannotation(id, t.javaResult.id, parent, idx)
475+
tw.writeExprsKotlinType(id, t.kotlinResult.id)
472476

473-
val locId = tw.getLocation(constructorCall)
474-
tw.writeHasLocation(id, locId)
477+
val locId = tw.getLocation(constructorCall)
478+
tw.writeHasLocation(id, locId)
475479

476-
for (i in 0 until constructorCall.valueArgumentsCount) {
477-
val param = constructorCall.symbol.owner.valueParameters[i]
478-
val prop = constructorCall.symbol.owner.parentAsClass.declarations.filterIsInstance<IrProperty>().firstOrNull { it.name == param.name }
479-
if (prop == null) {
480-
continue
481-
}
480+
for (i in 0 until constructorCall.valueArgumentsCount) {
481+
val param = constructorCall.symbol.owner.valueParameters[i]
482+
val prop = constructorCall.symbol.owner.parentAsClass.declarations
483+
.filterIsInstance<IrProperty>()
484+
.first { it.name == param.name }
485+
val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression
486+
val exprId = extractAnnotationValueExpression(v, id, i)
487+
if (exprId != null) {
488+
tw.writeAnnotValue(id, useFunction(prop.getter!!), exprId)
489+
}
490+
}
491+
return id
492+
}
482493

483-
val v = constructorCall.getValueArgument(i) ?: param.defaultValue?.expression
494+
private fun extractAnnotationValueExpression(
495+
v: IrExpression?,
496+
parent: Label<out DbExprparent>,
497+
idx: Int): Label<out DbExpr>? {
484498

485-
when (v) {
486-
is IrConst<*> -> {
487-
val exprId = extractConstant(v, id, i)
488-
if (exprId != null) {
499+
return when (v) {
500+
is IrConst<*> -> {
501+
extractConstant(v, parent, idx)
502+
}
503+
is IrGetEnumValue -> {
504+
extractEnumValue(v, parent, idx, null, null)
505+
}
506+
is IrClassReference -> {
507+
extractClassReference(v, parent, idx, null, null)
508+
}
509+
is IrConstructorCall -> {
510+
extractAnnotation(v, parent, idx)
511+
}
512+
is IrVararg -> {
513+
val eId = tw.getFreshIdLabel<DbArrayinit>()
514+
val type = useType(v.type)
515+
tw.writeExprs_arrayinit(eId, type.javaResult.id, parent, idx)
516+
tw.writeExprsKotlinType(eId, type.kotlinResult.id)
517+
tw.writeHasLocation(eId, tw.getLocation(v))
489518

490-
tw.writeAnnotValue(id, useFunction<DbMethod>(prop.getter!!), exprId)
519+
v.elements.forEachIndexed { index, irVarargElement -> run {
520+
val argExpr = when(irVarargElement) {
521+
is IrExpression -> irVarargElement
522+
is IrSpreadElement -> irVarargElement.expression
523+
else -> {
524+
logger.errorElement("Unrecognised IrVarargElement: " + irVarargElement.javaClass, irVarargElement)
525+
null
491526
}
492527
}
493-
/*
494-
Integer types;
495-
Enum types;
496-
String type;
497-
Classes;
498-
Other annotation types;
499-
Arrays of any type listed above.
500-
*/
528+
extractAnnotationValueExpression(argExpr, eId, index)
529+
} }
530+
531+
eId
532+
}
533+
// is IrErrorExpression
534+
// null
535+
else -> {
536+
val eId = tw.getFreshIdLabel<DbErrorexpr>()
537+
val type = useType(v?.type ?: pluginContext.irBuiltIns.unitType)
538+
tw.writeExprs_errorexpr(eId, type.javaResult.id, parent, idx)
539+
tw.writeExprsKotlinType(eId, type.kotlinResult.id)
501540

541+
if (v != null) {
542+
tw.writeHasLocation(eId, tw.getLocation(v))
502543
}
544+
eId
503545
}
504546
}
505-
506-
return count
507547
}
508548

509549
fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label<out DbClassorinterface> {
@@ -2160,7 +2200,7 @@ open class KotlinFileExtractor(
21602200
extractValueArguments(argParent, idxOffset)
21612201
}
21622202

2163-
private fun extractStaticTypeAccessQualifierUnchecked(parent: IrDeclarationParent, parentExpr: Label<out DbExprparent>, locId: Label<DbLocation>, enclosingCallable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) {
2203+
private fun extractStaticTypeAccessQualifierUnchecked(parent: IrDeclarationParent, parentExpr: Label<out DbExprparent>, locId: Label<DbLocation>, enclosingCallable: Label<out DbCallable>?, enclosingStmt: Label<out DbStmt>?) {
21642204
if (parent is IrClass) {
21652205
extractTypeAccessRecursive(parent.toRawType(), locId, parentExpr, -1, enclosingCallable, enclosingStmt)
21662206
} else if (parent is IrFile) {
@@ -2170,7 +2210,7 @@ open class KotlinFileExtractor(
21702210
}
21712211
}
21722212

2173-
private fun extractStaticTypeAccessQualifier(target: IrDeclaration, parentExpr: Label<out DbExprparent>, locId: Label<DbLocation>, enclosingCallable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) {
2213+
private fun extractStaticTypeAccessQualifier(target: IrDeclaration, parentExpr: Label<out DbExprparent>, locId: Label<DbLocation>, enclosingCallable: Label<out DbCallable>?, enclosingStmt: Label<out DbStmt>?) {
21742214
if (target.shouldExtractAsStatic) {
21752215
extractStaticTypeAccessQualifierUnchecked(target.parent, parentExpr, locId, enclosingCallable, enclosingStmt)
21762216
}
@@ -3691,19 +3731,7 @@ open class KotlinFileExtractor(
36913731
}
36923732
is IrGetEnumValue -> {
36933733
val exprParent = parent.expr(e, callable)
3694-
val id = tw.getFreshIdLabel<DbVaraccess>()
3695-
val type = useType(e.type)
3696-
val locId = tw.getLocation(e)
3697-
tw.writeExprs_varaccess(id, type.javaResult.id, exprParent.parent, exprParent.idx)
3698-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3699-
extractExprContext(id, locId, callable, exprParent.enclosingStmt)
3700-
3701-
val owner = getBoundSymbolOwner(e.symbol, e) ?: return
3702-
3703-
val vId = useEnumEntry(owner)
3704-
tw.writeVariableBinding(id, vId)
3705-
3706-
extractStaticTypeAccessQualifier(owner, id, locId, callable, exprParent.enclosingStmt)
3734+
val id = extractEnumValue(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt)
37073735
}
37083736
is IrSetValue,
37093737
is IrSetField -> {
@@ -3947,14 +3975,7 @@ open class KotlinFileExtractor(
39473975
}
39483976
is IrClassReference -> {
39493977
val exprParent = parent.expr(e, callable)
3950-
val id = tw.getFreshIdLabel<DbTypeliteral>()
3951-
val locId = tw.getLocation(e)
3952-
val type = useType(e.type)
3953-
tw.writeExprs_typeliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx)
3954-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3955-
extractExprContext(id, locId, callable, exprParent.enclosingStmt)
3956-
3957-
extractTypeAccessRecursive(e.classType, locId, id, 0, callable, exprParent.enclosingStmt)
3978+
extractClassReference(e, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt)
39583979
}
39593980
is IrPropertyReference -> {
39603981
extractPropertyReference("property reference", e, e.getter, e.setter, e.field, parent, callable)
@@ -4153,6 +4174,53 @@ open class KotlinFileExtractor(
41534174
extractExpressionExpr(loop.condition, callable, id, 0, id)
41544175
}
41554176

4177+
private fun extractClassReference(
4178+
e: IrClassReference,
4179+
parent: Label<out DbExprparent>,
4180+
idx: Int,
4181+
enclosingCallable: Label<out DbCallable>?,
4182+
enclosingStmt: Label<out DbStmt>?
4183+
): Label<out DbExpr> {
4184+
val id = tw.getFreshIdLabel<DbTypeliteral>()
4185+
val locId = tw.getLocation(e)
4186+
val type = useType(e.type)
4187+
tw.writeExprs_typeliteral(id, type.javaResult.id, parent, idx)
4188+
tw.writeExprsKotlinType(id, type.kotlinResult.id)
4189+
tw.writeHasLocation(id, locId)
4190+
4191+
enclosingCallable?.let { tw.writeCallableEnclosingExpr(id, it) }
4192+
enclosingStmt?.let { tw.writeStatementEnclosingExpr(id, it) }
4193+
4194+
extractTypeAccessRecursive(e.classType, locId, id, 0, enclosingCallable, enclosingStmt)
4195+
return id
4196+
}
4197+
4198+
private fun extractEnumValue(
4199+
e: IrGetEnumValue,
4200+
parent: Label<out DbExprparent>,
4201+
idx: Int,
4202+
enclosingCallable: Label<out DbCallable>?,
4203+
enclosingStmt: Label<out DbStmt>?
4204+
): Label<out DbExpr> {
4205+
val id = tw.getFreshIdLabel<DbVaraccess>()
4206+
val type = useType(e.type)
4207+
val locId = tw.getLocation(e)
4208+
tw.writeExprs_varaccess(id, type.javaResult.id, parent, idx)
4209+
tw.writeExprsKotlinType(id, type.kotlinResult.id)
4210+
tw.writeHasLocation(id, locId)
4211+
4212+
enclosingCallable?.let { tw.writeCallableEnclosingExpr(id, it) }
4213+
enclosingStmt?.let { tw.writeStatementEnclosingExpr(id, it) }
4214+
4215+
val owner = getBoundSymbolOwner(e.symbol, e) ?: return id
4216+
4217+
val vId = useEnumEntry(owner)
4218+
tw.writeVariableBinding(id, vId)
4219+
4220+
extractStaticTypeAccessQualifier(owner, id, locId, enclosingCallable, enclosingStmt)
4221+
return id
4222+
}
4223+
41564224
// Render a string literal as it might occur in Kotlin source. Note this is a reasonable guess; the real source
41574225
// could use other escape sequences to describe the same String. Importantly, this is the same guess the Java
41584226
// extractor makes regarding string literals occurring within annotations, which we need to coincide with to ensure
@@ -5091,10 +5159,14 @@ open class KotlinFileExtractor(
50915159
/**
50925160
* Extracts a single type access expression with enclosing callable and statement.
50935161
*/
5094-
private fun extractTypeAccess(type: TypeResults, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, enclosingCallable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>): Label<out DbExpr> {
5162+
private fun extractTypeAccess(type: TypeResults, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, enclosingCallable: Label<out DbCallable>?, enclosingStmt: Label<out DbStmt>?): Label<out DbExpr> {
50955163
val id = extractTypeAccess(type, location, parent, idx)
5096-
tw.writeCallableEnclosingExpr(id, enclosingCallable)
5097-
tw.writeStatementEnclosingExpr(id, enclosingStmt)
5164+
if (enclosingCallable != null) {
5165+
tw.writeCallableEnclosingExpr(id, enclosingCallable)
5166+
}
5167+
if (enclosingStmt != null) {
5168+
tw.writeStatementEnclosingExpr(id, enclosingStmt)
5169+
}
50985170
return id
50995171
}
51005172

@@ -5136,7 +5208,7 @@ open class KotlinFileExtractor(
51365208
/**
51375209
* Extracts a type access expression and its child type access expressions in case of a generic type. Nested generics are also handled.
51385210
*/
5139-
private fun extractTypeAccessRecursive(t: IrType, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, enclosingCallable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>, typeContext: TypeContext = TypeContext.OTHER): Label<out DbExpr> {
5211+
private fun extractTypeAccessRecursive(t: IrType, location: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, enclosingCallable: Label<out DbCallable>?, enclosingStmt: Label<out DbStmt>?, typeContext: TypeContext = TypeContext.OTHER): Label<out DbExpr> {
51405212
// TODO: `useType` substitutes types to their java equivalent, and sometimes that also means changing the number of type arguments. The below logic doesn't take this into account.
51415213
// For example `KFunction2<Int,Double,String>` becomes `KFunction<String>` with three child type access expressions: `Int`, `Double`, `String`.
51425214
val typeAccessId = extractTypeAccess(useType(t, typeContext), location, parent, idx, enclosingCallable, enclosingStmt)
@@ -5154,8 +5226,8 @@ open class KotlinFileExtractor(
51545226
typeArgs: List<IrType>,
51555227
location: Label<DbLocation>,
51565228
parentExpr: Label<out DbExprparent>,
5157-
enclosingCallable: Label<out DbCallable>,
5158-
enclosingStmt: Label<out DbStmt>,
5229+
enclosingCallable: Label<out DbCallable>?,
5230+
enclosingStmt: Label<out DbStmt>?,
51595231
startIndex: Int = 0,
51605232
reverse: Boolean = false
51615233
) {

java/ql/consistency-queries/cfgDeadEnds.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ predicate shouldBeDeadEnd(ControlFlowNode n) {
5353
not exists(n.getFile().getRelativePath()) // TODO
5454
or
5555
n = any(ConstCase c).getValue(_) // TODO
56+
or
57+
n instanceof ErrorExpr // TODO
5658
}
5759

5860
from ControlFlowNode n, string s

java/ql/test/kotlin/library-tests/annotation_classes/CONSISTENCY/children.expected

Lines changed: 0 additions & 1 deletion
This file was deleted.

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

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@ def.kt:
1616
#-----| 1: (Annotations)
1717
# 1| 2: [Method] y
1818
# 3| 3: [Interface] ReplaceWith
19+
#-----| -3: (Annotations)
1920
# 3| 1: [Method] expression
2021
# 5| 4: [Interface] Deprecated
22+
#-----| -3: (Annotations)
2123
# 6| 1: [Method] message
2224
# 7| 2: [Method] replaceWith
2325
# 9| 5: [Class] X
2426
#-----| -3: (Annotations)
2527
# 9| 1: [Annotation] Deprecated
2628
# 0| 1: [StringLiteral] This class is deprecated
29+
# 0| 1: [Annotation] ReplaceWith
30+
# 0| 1: [StringLiteral] Y
2731
# 10| 2: [Annotation] SomeAnnotation
2832
# 0| 1: [IntegerLiteral] 5
2933
# 0| 1: [StringLiteral] a
@@ -33,29 +37,36 @@ def.kt:
3337
# 11| 1: [BlockStmt] { ... }
3438
use.java:
3539
# 0| [CompilationUnit] use
36-
# 2| 1: [Class] use
40+
# 6| 1: [Class] use
41+
#-----| -3: (Annotations)
42+
# 2| 1: [Annotation] Deprecated
43+
# 3| 1: [StringLiteral] "This class is deprecated"
44+
# 4| 2: [Annotation] ReplaceWith
45+
# 4| 1: [StringLiteral] "Y"
46+
# 5| 2: [Annotation] SomeAnnotation
47+
# 5| 2: [StringLiteral] "b"
3748
#-----| -1: (Base Types)
38-
# 2| 0: [TypeAccess] SomeAnnotation
39-
# 4| 2: [Method] abc
40-
#-----| 1: (Annotations)
41-
# 3| 1: [Annotation] Override
42-
# 4| 3: [TypeAccess] int
43-
# 4| 5: [BlockStmt] { ... }
44-
# 4| 0: [ReturnStmt] return ...
45-
# 4| 0: [IntegerLiteral] 1
46-
# 6| 3: [Method] y
49+
# 6| 0: [TypeAccess] SomeAnnotation
50+
# 8| 2: [Method] abc
4751
#-----| 1: (Annotations)
48-
# 5| 1: [Annotation] Override
49-
# 6| 3: [TypeAccess] String
50-
# 6| 5: [BlockStmt] { ... }
51-
# 6| 0: [ReturnStmt] return ...
52-
# 6| 0: [StringLiteral] ""
53-
# 9| 4: [Method] annotationType
52+
# 7| 1: [Annotation] Override
53+
# 8| 3: [TypeAccess] int
54+
# 8| 5: [BlockStmt] { ... }
55+
# 8| 0: [ReturnStmt] return ...
56+
# 8| 0: [IntegerLiteral] 1
57+
# 10| 3: [Method] y
5458
#-----| 1: (Annotations)
55-
# 8| 1: [Annotation] Override
56-
# 9| 3: [TypeAccess] Class<? extends Annotation>
57-
# 9| 0: [WildcardTypeAccess] ? ...
58-
# 9| 0: [TypeAccess] Annotation
59-
# 9| 5: [BlockStmt] { ... }
59+
# 9| 1: [Annotation] Override
60+
# 10| 3: [TypeAccess] String
61+
# 10| 5: [BlockStmt] { ... }
6062
# 10| 0: [ReturnStmt] return ...
61-
# 10| 0: [NullLiteral] null
63+
# 10| 0: [StringLiteral] ""
64+
# 13| 4: [Method] annotationType
65+
#-----| 1: (Annotations)
66+
# 12| 1: [Annotation] Override
67+
# 13| 3: [TypeAccess] Class<? extends Annotation>
68+
# 13| 0: [WildcardTypeAccess] ? ...
69+
# 13| 0: [TypeAccess] Annotation
70+
# 13| 5: [BlockStmt] { ... }
71+
# 14| 0: [ReturnStmt] return ...
72+
# 14| 0: [NullLiteral] null

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,26 @@ annotationDeclarations
55
| def.kt:5:1:7:51 | Deprecated | def.kt:6:5:6:23 | message |
66
| def.kt:5:1:7:51 | Deprecated | def.kt:7:5:7:50 | replaceWith |
77
annotations
8+
| def.kt:0:0:0:0 | ReplaceWith | def.kt:9:1:9:57 | Deprecated | def.kt:3:1:3:52 | ReplaceWith |
89
| def.kt:9:1:9:57 | Deprecated | def.kt:9:1:11:7 | X | def.kt:5:1:7:51 | Deprecated |
910
| def.kt:10:1:10:24 | SomeAnnotation | def.kt:9:1:11:7 | X | def.kt:1:1:1:87 | SomeAnnotation |
11+
| use.java:2:1:4:48 | Deprecated | use.java:6:14:6:16 | use | def.kt:5:1:7:51 | Deprecated |
12+
| use.java:4:18:4:47 | ReplaceWith | use.java:2:1:4:48 | Deprecated | def.kt:3:1:3:52 | ReplaceWith |
13+
| use.java:5:1:5:24 | SomeAnnotation | use.java:6:14:6:16 | use | def.kt:1:1:1:87 | SomeAnnotation |
1014
annotationValues
15+
| def.kt:0:0:0:0 | ReplaceWith | def.kt:0:0:0:0 | Y |
16+
| def.kt:9:1:9:57 | Deprecated | def.kt:0:0:0:0 | ReplaceWith |
1117
| def.kt:9:1:9:57 | Deprecated | def.kt:0:0:0:0 | This class is deprecated |
1218
| def.kt:10:1:10:24 | SomeAnnotation | def.kt:0:0:0:0 | 5 |
1319
| def.kt:10:1:10:24 | SomeAnnotation | def.kt:0:0:0:0 | a |
20+
| use.java:2:1:4:48 | Deprecated | use.java:3:14:3:39 | "This class is deprecated" |
21+
| use.java:2:1:4:48 | Deprecated | use.java:4:18:4:47 | ReplaceWith |
22+
| use.java:4:18:4:47 | ReplaceWith | use.java:4:44:4:46 | "Y" |
23+
| use.java:5:1:5:24 | SomeAnnotation | use.java:5:21:5:23 | "b" |
1424
#select
1525
| def.kt:0:0:0:0 | DefKt | Class |
1626
| def.kt:1:1:1:87 | SomeAnnotation | Interface |
1727
| def.kt:3:1:3:52 | ReplaceWith | Interface |
1828
| def.kt:5:1:7:51 | Deprecated | Interface |
1929
| def.kt:9:1:11:7 | X | Class |
20-
| use.java:2:14:2:16 | use | Class |
30+
| use.java:6:14:6:16 | use | Class |

0 commit comments

Comments
 (0)