Skip to content

Commit f95c2e6

Browse files
committed
Add an option to generate summaries using custom JavaDoc tags #565
1 parent 6b7710b commit f95c2e6

File tree

9 files changed

+158
-26
lines changed

9 files changed

+158
-26
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ object UtSettings {
269269
/**
270270
* Set to true to start fuzzing if symbolic execution haven't return anything
271271
*/
272-
var useFuzzing: Boolean by getBooleanProperty(true)
272+
var useFuzzing: Boolean by getBooleanProperty(false)
273273

274274
/**
275275
* Set the total attempts to improve coverage by fuzzer.

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/visitor/CgAbstractRenderer.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,7 @@ internal abstract class CgAbstractRenderer(val context: CgContext, val printer:
309309
}
310310
override fun visit(element: CgDocPreTagStatement) {
311311
if (element.content.all { it.isEmpty() }) return
312-
313-
println("<pre>")
314312
for (stmt in element.content) stmt.accept(this)
315-
println("</pre>")
316313
}
317314
override fun visit(element: CgDocCodeStmt) {
318315
if (element.isEmpty()) return

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/javadoc/UtCustomJavaDocTagProvider.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class UtCustomJavaDocTagProvider : CustomJavadocTagProvider {
1919
UtCustomTag.ActualResult,
2020
UtCustomTag.Executes,
2121
UtCustomTag.Invokes,
22+
UtCustomTag.Iterates,
2223
UtCustomTag.ReturnsFrom,
2324
UtCustomTag.ThrowsException,
2425
)
@@ -44,6 +45,7 @@ class UtCustomJavaDocTagProvider : CustomJavadocTagProvider {
4445
object ActualResult : UtCustomTag("utbot.actualResult", "Actual result")
4546
object Executes : UtCustomTag("utbot.executes", "Executes")
4647
object Invokes : UtCustomTag("utbot.invokes", "Invokes")
48+
object Iterates : UtCustomTag("utbot.iterates", "Iterates")
4749
object ReturnsFrom : UtCustomTag("utbot.returnsFrom", "Returns from")
4850
object ThrowsException : UtCustomTag("utbot.throwsException", "Throws exception")
4951
}

utbot-summary/src/main/kotlin/org/utbot/summary/Summarization.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import org.utbot.framework.UtSettings
55
import org.utbot.framework.plugin.api.UtClusterInfo
66
import org.utbot.framework.plugin.api.UtSymbolicExecution
77
import org.utbot.framework.plugin.api.UtExecutionCluster
8+
import org.utbot.framework.plugin.api.UtExecutionCreator
89
import org.utbot.framework.plugin.api.UtMethodTestSet
910
import org.utbot.instrumentation.instrumentation.instrumenter.Instrumenter
1011
import org.utbot.summary.SummarySentenceConstants.NEW_LINE
@@ -28,6 +29,8 @@ import org.utbot.fuzzer.FuzzedValue
2829
import org.utbot.fuzzer.UtFuzzedExecution
2930
import org.utbot.summary.fuzzer.names.MethodBasedNameSuggester
3031
import org.utbot.summary.fuzzer.names.ModelBasedNameSuggester
32+
import org.utbot.summary.UtSummarySettings.USE_CUSTOM_JAVADOC_TAGS
33+
import org.utbot.summary.comment.CustomJavaDocCommentBuilder
3134
import soot.SootMethod
3235

3336
private val logger = KotlinLogging.logger {}
@@ -154,7 +157,10 @@ class Summarization(val sourceFile: File?, val invokeDescriptions: List<InvokeDe
154157
}
155158

156159
for (traceTags in clusterTraceTags.traceTags) {
157-
if (GENERATE_COMMENTS) {
160+
if (GENERATE_COMMENTS && USE_CUSTOM_JAVADOC_TAGS) {
161+
traceTags.execution.summary =
162+
CustomJavaDocCommentBuilder(traceTags, sootToAST).buildDocStatements(methodUnderTest)
163+
} else if (GENERATE_COMMENTS) {
158164
traceTags.execution.summary =
159165
SimpleCommentBuilder(traceTags, sootToAST).buildDocStmts(methodUnderTest)
160166
}

utbot-summary/src/main/kotlin/org/utbot/summary/UtSummarySettings.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ object UtSummarySettings {
1111
*/
1212
var GENERATE_CLUSTER_COMMENTS = true
1313

14+
/**
15+
* Generate summaries using plugin's custom JavaDoc tags.
16+
*/
17+
var USE_CUSTOM_JAVADOC_TAGS = true
18+
1419
/**
1520
* If True names for tests will be generated
1621
*/
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.utbot.summary.comment
2+
3+
/**
4+
* Represents a set of plugin's custom JavaDoc tags.
5+
*/
6+
data class CustomJavaDocComment(
7+
val classUnderTest: String,
8+
val methodUnderTest: String,
9+
val expectedResult: String?,
10+
val actualResult: String?,
11+
var executes: String?,
12+
var invokes: String?,
13+
var iterates: String?,
14+
var returnsFrom: String?,
15+
val throwsException: String?
16+
)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package org.utbot.summary.comment
2+
3+
import org.utbot.framework.plugin.api.DocPreTagStatement
4+
import org.utbot.framework.plugin.api.DocRegularStmt
5+
import org.utbot.framework.plugin.api.DocStatement
6+
import org.utbot.framework.plugin.api.exceptionOrNull
7+
import org.utbot.summary.ast.JimpleToASTMap
8+
import org.utbot.summary.tag.TraceTagWithoutExecution
9+
import soot.SootMethod
10+
11+
//TODO: polish code
12+
class CustomJavaDocCommentBuilder(
13+
traceTag: TraceTagWithoutExecution,
14+
sootToAST: MutableMap<SootMethod, JimpleToASTMap>
15+
) : SimpleCommentBuilder(traceTag, sootToAST, stringTemplates = StringsTemplatesPlural()) {
16+
17+
/**
18+
* Collects statements for final JavaDoc comment.
19+
*/
20+
fun buildDocStatements(method: SootMethod): List<DocStatement> {
21+
val comment: CustomJavaDocComment = buildCustomJavaDocComment(method)
22+
val docStatementList = mutableListOf<DocStatement>()
23+
24+
docStatementList += DocRegularStmt("@utbot.classUnderTest ${comment.classUnderTest}\n")
25+
docStatementList += DocRegularStmt("@utbot.methodUnderTest ${comment.methodUnderTest}\n")
26+
if (comment.expectedResult != null)
27+
docStatementList += DocRegularStmt("@utbot.expectedResult ${comment.expectedResult}\n")
28+
if (comment.actualResult != null)
29+
docStatementList += DocRegularStmt("@utbot.actualResult ${comment.actualResult}\n")
30+
if (comment.executes != null)
31+
docStatementList += DocRegularStmt("@utbot.executes ${comment.executes}\n")
32+
if (comment.invokes != null)
33+
docStatementList += DocRegularStmt("@utbot.invokes ${comment.invokes}\n")
34+
if (comment.iterates != null)
35+
docStatementList += DocRegularStmt("@utbot.iterates ${comment.iterates}\n")
36+
if (comment.returnsFrom != null)
37+
docStatementList += DocRegularStmt("@utbot.returnsFrom ${comment.returnsFrom}\n")
38+
if (comment.throwsException != null)
39+
docStatementList += DocRegularStmt("@utbot.throwsException ${comment.throwsException}")
40+
41+
return listOf<DocStatement>(DocPreTagStatement(docStatementList))
42+
}
43+
44+
private fun buildCustomJavaDocComment(currentMethod: SootMethod): CustomJavaDocComment {
45+
val methodReference =
46+
getMethodReference(currentMethod.declaringClass.name, currentMethod.name, currentMethod.parameterTypes)
47+
val classReference = getClassReference(currentMethod.declaringClass.javaStyleName)
48+
49+
val thrownException = traceTag.result.exceptionOrNull()
50+
val exceptionThrow: String? = if (thrownException == null) {
51+
traceTag.result.exceptionOrNull()?.let { it::class.qualifiedName }
52+
} else {
53+
val exceptionName = thrownException.javaClass.simpleName
54+
val reason = findExceptionReason(currentMethod, thrownException)
55+
"{@link $exceptionName} $reason"
56+
}
57+
58+
val customJavaDocComment = CustomJavaDocComment(
59+
classUnderTest = classReference,
60+
methodUnderTest = methodReference,
61+
expectedResult = null,
62+
actualResult = null,
63+
executes = null,
64+
invokes = null,
65+
iterates = null,
66+
returnsFrom = null,
67+
throwsException = exceptionThrow
68+
)
69+
70+
val rootSentenceBlock = SimpleSentenceBlock(stringTemplates = stringTemplates)
71+
72+
buildSentenceBlock(traceTag.rootStatementTag, rootSentenceBlock, currentMethod)
73+
74+
for (stmtDescription: StmtDescription in rootSentenceBlock.stmtTexts) {
75+
when (stmtDescription.stmtType.name) {
76+
"Invoke" -> {
77+
val info = stmtDescription.description
78+
customJavaDocComment.invokes = "{@code $info}"
79+
}
80+
"Return" -> {
81+
val info = stmtDescription.description
82+
customJavaDocComment.returnsFrom = "{@code $info}"
83+
}
84+
"Condition" -> {
85+
val info = stmtDescription.description
86+
customJavaDocComment.executes = "{@code $info}"
87+
}
88+
}
89+
}
90+
91+
return customJavaDocComment
92+
}
93+
}

utbot-summary/src/main/kotlin/org/utbot/summary/comment/SimpleClusterCommentBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class SimpleClusterCommentBuilder(
6363
* Builds sentence blocks as parent one,
6464
* but ignores few types of statementTag that are considered in SimpleCommentBuilder
6565
*/
66-
private fun buildSentenceBlock(
66+
override fun buildSentenceBlock(
6767
statementTag: StatementTag?,
6868
sentenceBlock: SimpleSentenceBlock,
6969
currentMethod: SootMethod
@@ -93,7 +93,7 @@ class SimpleClusterCommentBuilder(
9393
sentenceInvoke.squashStmtText()
9494
if (!sentenceInvoke.isEmpty()) {
9595
sentenceBlock.invokeSentenceBlock =
96-
Pair(invokeDescription(className, methodName, methodParameterTypes), sentenceInvoke)
96+
Pair(getMethodReference(className, methodName, methodParameterTypes), sentenceInvoke)
9797
createNextBlock = true
9898
invokeRegistered = true
9999
}

utbot-summary/src/main/kotlin/org/utbot/summary/comment/SimpleCommentBuilder.kt

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,11 @@ open class SimpleCommentBuilder(
6262
}
6363

6464
/**
65-
* Creates List<DocStatement> from SimpleSentenceBlock
65+
* Creates List<[DocStatement]> from [SimpleSentenceBlock].
6666
*/
6767
open fun buildDocStmts(currentMethod: SootMethod): List<DocStatement> {
68-
val root = SimpleSentenceBlock(stringTemplates = stringTemplates)
69-
70-
val thrownException = traceTag.result.exceptionOrNull()
71-
if (thrownException == null) {
72-
root.exceptionThrow = traceTag.result.exceptionOrNull()?.let { it::class.qualifiedName }
73-
} else {
74-
val exceptionName = thrownException.javaClass.simpleName
75-
val reason = findExceptionReason(currentMethod, thrownException)
76-
root.exceptionThrow = "$exceptionName $reason"
77-
}
78-
skippedIterations()
79-
buildSentenceBlock(traceTag.rootStatementTag, root, currentMethod)
80-
val docStmts = toDocStmts(root)
68+
val sentenceBlock = buildSentenceBlock(currentMethod)
69+
val docStmts = toDocStmts(sentenceBlock)
8170

8271
if (docStmts.isEmpty()) {
8372
return listOf(DocRegularStmt(genWarnNotification())) //TODO SAT-1310
@@ -88,6 +77,22 @@ open class SimpleCommentBuilder(
8877
return listOf<DocStatement>(DocPreTagStatement(docStmts))
8978
}
9079

80+
private fun buildSentenceBlock(currentMethod: SootMethod): SimpleSentenceBlock {
81+
val rootSentenceBlock = SimpleSentenceBlock(stringTemplates = stringTemplates)
82+
83+
val thrownException = traceTag.result.exceptionOrNull()
84+
if (thrownException == null) {
85+
rootSentenceBlock.exceptionThrow = traceTag.result.exceptionOrNull()?.let { it::class.qualifiedName }
86+
} else {
87+
val exceptionName = thrownException.javaClass.simpleName
88+
val reason = findExceptionReason(currentMethod, thrownException)
89+
rootSentenceBlock.exceptionThrow = "$exceptionName $reason"
90+
}
91+
skippedIterations()
92+
buildSentenceBlock(traceTag.rootStatementTag, rootSentenceBlock, currentMethod)
93+
return rootSentenceBlock
94+
}
95+
9196
protected fun genWarnNotification(): String = " " //why is it empty?
9297

9398
/**
@@ -114,7 +119,7 @@ open class SimpleCommentBuilder(
114119
return stmts
115120
}
116121

117-
private fun findExceptionReason(currentMethod: SootMethod, thrownException: Throwable): String {
122+
fun findExceptionReason(currentMethod: SootMethod, thrownException: Throwable): String {
118123
val path = traceTag.path
119124
if (path.isEmpty()) {
120125
if (thrownException is ConcreteExecutionFailureException) {
@@ -161,7 +166,7 @@ open class SimpleCommentBuilder(
161166
/**
162167
* Sentence blocks are built based on unique and partly unique statement tags.
163168
*/
164-
private fun buildSentenceBlock(
169+
open fun buildSentenceBlock(
165170
statementTag: StatementTag?,
166171
sentenceBlock: SimpleSentenceBlock,
167172
currentMethod: SootMethod
@@ -191,7 +196,7 @@ open class SimpleCommentBuilder(
191196
sentenceInvoke.squashStmtText()
192197
if (!sentenceInvoke.isEmpty()) {
193198
sentenceBlock.invokeSentenceBlock =
194-
Pair(invokeDescription(className, methodName, methodParameterTypes), sentenceInvoke)
199+
Pair(getMethodReference(className, methodName, methodParameterTypes), sentenceInvoke)
195200
createNextBlock = true
196201
invokeRegistered = true
197202
}
@@ -317,7 +322,7 @@ open class SimpleCommentBuilder(
317322
sentenceBlock.stmtTexts.add(
318323
StmtDescription(
319324
StmtType.Invoke,
320-
invokeDescription(className, methodName, methodParameterTypes),
325+
getMethodReference(className, methodName, methodParameterTypes),
321326
frequency
322327
)
323328
)
@@ -349,7 +354,7 @@ open class SimpleCommentBuilder(
349354
* In case when an enclosing class in nested, we need to replace '$' with '.'
350355
* to render the reference.
351356
*/
352-
fun invokeDescription(className: String, methodName: String, methodParameterTypes: List<Type>): String {
357+
protected fun getMethodReference(className: String, methodName: String, methodParameterTypes: List<Type>): String {
353358
val prettyClassName: String = className.replace("$", ".")
354359

355360
return if (methodParameterTypes.isEmpty()) {
@@ -360,6 +365,14 @@ open class SimpleCommentBuilder(
360365
}
361366
}
362367

368+
/**
369+
* Returns a reference to the class.
370+
* Replaces '$' with '.' in case a class is nested.
371+
*/
372+
fun getClassReference(fullClasName: String): String {
373+
return "{@link ${fullClasName.replace("$", ".")}}"
374+
}
375+
363376
protected fun buildIterationsBlock(
364377
iterations: List<StatementTag>,
365378
activatedStep: Step,

0 commit comments

Comments
 (0)