@@ -38,8 +38,8 @@ object AnonymousFeedback {
38
38
val duplicateId = findDuplicateIssue(envDetails, factory)
39
39
if (duplicateId != null ) {
40
40
// This is a duplicate
41
- val commentUrl =
42
- sendCommentOnDuplicateIssue(duplicateId, factory, convertToGitHubIssueFormat(envDetails, attachments) )
41
+ val issueContent = convertToGitHubIssueFormat(envDetails, attachments)
42
+ val commentUrl = sendCommentOnDuplicateIssue(duplicateId, factory, issueContent )
43
43
return FeedbackData (commentUrl, duplicateId, true )
44
44
}
45
45
@@ -66,8 +66,10 @@ object AnonymousFeedback {
66
66
}
67
67
68
68
var stackTrace = body.remove(" error.stacktrace" )
69
- if (stackTrace.isNullOrEmpty()) {
70
- stackTrace = " no stacktrace"
69
+ stackTrace = if (stackTrace.isNullOrEmpty()) {
70
+ " no stacktrace"
71
+ } else {
72
+ linkStacktrace(stackTrace)
71
73
}
72
74
73
75
val sb = StringBuilder ()
@@ -88,7 +90,7 @@ object AnonymousFeedback {
88
90
}
89
91
sb.append(" </table></td></tr></table>\n " )
90
92
91
- sb.append(" \n ``` \n " ).append(stackTrace).append(" \n ``` \n " )
93
+ sb.append(" \n <pre> \n " ).append(stackTrace).append(" \n </pre> \n " )
92
94
sb.append(" \n ```\n " ).append(errorMessage).append(" \n ```\n " )
93
95
94
96
if (attachments.isNotEmpty()) {
@@ -138,15 +140,15 @@ object AnonymousFeedback {
138
140
return connection
139
141
}
140
142
141
- private val numberRegex = Regex (" \\ d+" )
142
- private val newLineRegex = Regex (" [\r\n ]+" )
143
-
144
143
private const val openIssueUrl = " $baseUrl ?state=open&creator=minecraft-dev-autoreporter&per_page=100"
145
144
private const val closedIssueUrl = " $baseUrl ?state=closed&creator=minecraft-dev-autoreporter&per_page=100"
146
145
147
146
private const val packagePrefix = " \t at com.demonwav.mcdev"
148
147
149
148
private fun findDuplicateIssue (envDetails : LinkedHashMap <String , String ?>, factory : HttpConnectionFactory ): Int? {
149
+ val numberRegex = Regex (" \\ d+" )
150
+ val newLineRegex = Regex (" [\r\n ]+" )
151
+
150
152
val stack = envDetails[" error.stacktrace" ]?.replace(numberRegex, " " ) ? : return null
151
153
152
154
val stackMcdevParts = stack.lineSequence()
@@ -298,6 +300,72 @@ object AnonymousFeedback {
298
300
return connection
299
301
}
300
302
303
+ private fun linkStacktrace (stacktrace : String ): String {
304
+ val versionRegex = Regex (""" (?<intellijVersion>\d{4}\.\d)-(?<pluginVersion>\d+\.\d+\.\d+)""" )
305
+
306
+ val version = PluginUtil .pluginVersion
307
+ val match = versionRegex.matchEntire(version) ? : return stacktrace
308
+
309
+ val intellijVersion = match.groups[" intellijVersion" ]?.value ? : return stacktrace
310
+ val pluginVersion = match.groups[" pluginVersion" ]?.value ? : return stacktrace
311
+
312
+ val tag = " $pluginVersion -$intellijVersion "
313
+
314
+ // v stack element text v
315
+ // at com.demonwav.mcdev.facet.MinecraftFacet.shouldShowPluginIcon(MinecraftFacet.kt:185)
316
+ // prefix ^ class path ^ ^ file name ^ ^ ^ line number
317
+ val stackElementRegex = Regex (
318
+ """ (?<prefix>\s+at\s+)""" +
319
+ """ (?<stackElementText>""" +
320
+ """ (?<className>com\.demonwav\.mcdev(?:\.\p{javaJavaIdentifierStart}\p{javaJavaIdentifierPart}*)+)""" +
321
+ """ (?:\.\p{javaJavaIdentifierStart}\p{javaJavaIdentifierPart}*|<(?:cl)?init>)""" +
322
+ """ \((?<fileName>.*\.\w+):(?<lineNumber>\d+)\)""" +
323
+ """ )\s*"""
324
+ )
325
+
326
+ val baseTagUrl = " https://github.com/minecraft-dev/MinecraftDev/blob/$tag /src/main/kotlin/"
327
+
328
+ val sb = StringBuilder (stacktrace.length * 2 )
329
+
330
+ for (line in stacktrace.lineSequence()) {
331
+ val lineMatch = stackElementRegex.matchEntire(line)
332
+ if (lineMatch == null ) {
333
+ sb.append(line).append(' \n ' )
334
+ continue
335
+ }
336
+
337
+ val prefix = lineMatch.groups[" prefix" ]?.value
338
+ val className = lineMatch.groups[" className" ]?.value
339
+ val fileName = lineMatch.groups[" fileName" ]?.value
340
+ val lineNumber = lineMatch.groups[" lineNumber" ]?.value
341
+ val stackElementText = lineMatch.groups[" stackElementText" ]?.value
342
+
343
+ if (prefix == null || className == null || fileName == null || lineNumber == null || stackElementText == null ) {
344
+ sb.append(line).append(' \n ' )
345
+ continue
346
+ }
347
+
348
+ val path = className.substringAfter(" com.demonwav.mcdev." )
349
+ .substringBeforeLast(' .' )
350
+ .replace(' .' , ' /' )
351
+ sb.apply {
352
+ append(prefix)
353
+ append(" <a href=\" " )
354
+ append(baseTagUrl)
355
+ append(path)
356
+ append(' /' )
357
+ append(fileName)
358
+ append(" #L" )
359
+ append(lineNumber)
360
+ append(" \" >" )
361
+ append(stackElementText)
362
+ append(" </a>\n " )
363
+ }
364
+ }
365
+
366
+ return sb.toString()
367
+ }
368
+
301
369
private val userAgent by lazy {
302
370
var agent = " Minecraft Development IntelliJ IDEA plugin"
303
371
0 commit comments