Skip to content

Commit 9484252

Browse files
committed
Merge branch '2020.2' into 2020.3
2 parents 697548d + 0cdd978 commit 9484252

File tree

18 files changed

+285
-87
lines changed

18 files changed

+285
-87
lines changed

build.gradle.kts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ intellij {
115115

116116
downloadSources = downloadIdeaSources.toBoolean()
117117

118-
sandboxDirectory = project.rootDir.canonicalPath + "/.sandbox"
118+
sandboxDirectory = layout.projectDirectory.dir(".sandbox")
119119
}
120120

121121
tasks.publishPlugin {
@@ -294,6 +294,12 @@ sourceSets.main { java.srcDir(generate) }
294294
// Remove gen directory on clean
295295
tasks.clean { delete(generate) }
296296

297+
tasks.register("cleanSandbox", Delete::class) {
298+
group = "intellij"
299+
description = "Deletes the sandbox directory."
300+
delete(layout.projectDirectory.dir(".sandbox"))
301+
}
302+
297303
tasks.runIde {
298304
maxHeapSize = "2G"
299305

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ kotlin.code.style=official
1414
ideaVersion = 2020.3.2
1515
ideaVersionName = 2020.3
1616

17-
coreVersion = 1.5.9
17+
coreVersion = 1.5.10
1818
downloadIdeaSources = true
1919

2020
pluginTomlVersion = 0.2.140.3644-203

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Minecraft Development for IntelliJ
3636
</tr>
3737
</table>
3838

39-
Info and Documentation [![Current Release](https://img.shields.io/badge/release-1.5.9-orange.svg?style=flat-square)](https://plugins.jetbrains.com/plugin/8327)
39+
Info and Documentation [![Current Release](https://img.shields.io/badge/release-1.5.10-orange.svg?style=flat-square)](https://plugins.jetbrains.com/plugin/8327)
4040
----------------------
4141

4242
<a href="https://discord.gg/j6UNcfr"><img src="https://i.imgur.com/JXu9C1G.png" height="48px"></img></a>

src/main/kotlin/creator/buildsystem/gradle/gradle-steps.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import java.nio.file.StandardOpenOption.CREATE
4040
import java.nio.file.StandardOpenOption.TRUNCATE_EXISTING
4141
import java.nio.file.StandardOpenOption.WRITE
4242
import org.jetbrains.plugins.gradle.service.execution.GradleExternalTaskConfigurationType
43+
import org.jetbrains.plugins.gradle.service.project.open.canLinkAndRefreshGradleProject
4344
import org.jetbrains.plugins.gradle.service.project.open.linkAndRefreshGradleProject
4445
import org.jetbrains.plugins.gradle.util.GradleConstants
4546
import org.jetbrains.plugins.groovy.GroovyLanguage
@@ -211,9 +212,11 @@ class BasicGradleFinalizerStep(
211212
rootDirectory.virtualFileOrError.refresh(false, true)
212213

213214
invokeLater {
214-
@Suppress("UnstableApiUsage")
215-
linkAndRefreshGradleProject(rootDirectory.toAbsolutePath().toString(), project)
216-
showProgress(project)
215+
val path = rootDirectory.toAbsolutePath().toString()
216+
if (canLinkAndRefreshGradleProject(path, project, false)) {
217+
linkAndRefreshGradleProject(path, project)
218+
showProgress(project)
219+
}
217220
}
218221

219222
// Set up the run config

src/main/kotlin/errorreporter/AnonymousFeedback.kt

Lines changed: 142 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ import com.demonwav.mcdev.util.fromJson
1616
import com.google.gson.Gson
1717
import com.intellij.ide.plugins.PluginManagerCore
1818
import com.intellij.openapi.diagnostic.Attachment
19-
import com.intellij.util.io.readCharSequence
20-
import java.io.InputStreamReader
2119
import java.net.HttpURLConnection
2220
import java.nio.ByteBuffer
2321
import java.nio.charset.CodingErrorAction
@@ -29,7 +27,8 @@ object AnonymousFeedback {
2927

3028
data class FeedbackData(val url: String, val token: Int, val isDuplicate: Boolean)
3129

32-
const val url = "https://www.denwav.dev/errorReport"
30+
private const val authedUrl = "https://www.denwav.dev/errorReport"
31+
private const val baseUrl = "https://api.github.com/repos/minecraft-dev/MinecraftDev/issues"
3332

3433
fun sendFeedback(
3534
factory: HttpConnectionFactory,
@@ -39,8 +38,8 @@ object AnonymousFeedback {
3938
val duplicateId = findDuplicateIssue(envDetails, factory)
4039
if (duplicateId != null) {
4140
// This is a duplicate
42-
val commentUrl =
43-
sendCommentOnDuplicateIssue(duplicateId, factory, convertToGitHubIssueFormat(envDetails, attachments))
41+
val issueContent = convertToGitHubIssueFormat(envDetails, attachments)
42+
val commentUrl = sendCommentOnDuplicateIssue(duplicateId, factory, issueContent)
4443
return FeedbackData(commentUrl, duplicateId, true)
4544
}
4645

@@ -67,21 +66,31 @@ object AnonymousFeedback {
6766
}
6867

6968
var stackTrace = body.remove("error.stacktrace")
70-
if (stackTrace.isNullOrEmpty()) {
71-
stackTrace = "no stacktrace"
69+
stackTrace = if (stackTrace.isNullOrEmpty()) {
70+
"no stacktrace"
71+
} else {
72+
linkStacktrace(stackTrace)
7273
}
7374

7475
val sb = StringBuilder()
7576

76-
if (!errorDescription.isEmpty()) {
77+
if (errorDescription.isNotEmpty()) {
7778
sb.append(errorDescription).append("\n\n")
7879
}
7980

80-
for ((key, value) in body) {
81-
sb.append(key).append(": ").append(value).append("\n")
81+
sb.append("<table><tr><td><table>\n")
82+
for ((i, entry) in body.entries.withIndex()) {
83+
if (i == 6) {
84+
sb.append("</table></td><td><table>\n")
85+
}
86+
val (key, value) = entry
87+
sb.append("<tr><td><b>").append(key).append("</b></td><td><code>").append(value).append(
88+
"</code></td></tr>\n"
89+
)
8290
}
91+
sb.append("</table></td></tr></table>\n")
8392

84-
sb.append("\n```\n").append(stackTrace).append("\n```\n")
93+
sb.append("\n<pre>\n").append(stackTrace).append("\n</pre>\n")
8594
sb.append("\n```\n").append(errorMessage).append("\n```\n")
8695

8796
if (attachments.isNotEmpty()) {
@@ -118,7 +127,7 @@ object AnonymousFeedback {
118127
}
119128

120129
private fun sendFeedback(factory: HttpConnectionFactory, payload: ByteArray): Pair<String, Int> {
121-
val connection = getConnection(factory, url)
130+
val connection = getConnection(factory, authedUrl)
122131
connection.connect()
123132
val json = executeCall(connection, payload)
124133
return json["html_url"] as String to (json["number"] as Double).toInt()
@@ -131,17 +140,15 @@ object AnonymousFeedback {
131140
return connection
132141
}
133142

134-
private val numberRegex = Regex("\\d+")
135-
private val newLineRegex = Regex("[\r\n]+")
136-
137-
private const val openIssueUrl = "https://api.github.com/repos/minecraft-dev/MinecraftDev/issues" +
138-
"?state=open&creator=minecraft-dev-autoreporter&per_page=100"
139-
private const val closedIssueUrl = "https://api.github.com/repos/minecraft-dev/MinecraftDev/issues" +
140-
"?state=closed&creator=minecraft-dev-autoreporter&per_page=100"
143+
private const val openIssueUrl = "$baseUrl?state=open&creator=minecraft-dev-autoreporter&per_page=100"
144+
private const val closedIssueUrl = "$baseUrl?state=closed&creator=minecraft-dev-autoreporter&per_page=100"
141145

142146
private const val packagePrefix = "\tat com.demonwav.mcdev"
143147

144148
private fun findDuplicateIssue(envDetails: LinkedHashMap<String, String?>, factory: HttpConnectionFactory): Int? {
149+
val numberRegex = Regex("\\d+")
150+
val newLineRegex = Regex("[\r\n]+")
151+
145152
val stack = envDetails["error.stacktrace"]?.replace(numberRegex, "") ?: return null
146153

147154
val stackMcdevParts = stack.lineSequence()
@@ -177,55 +184,50 @@ object AnonymousFeedback {
177184
}
178185

179186
private fun getAllIssues(url: String, factory: HttpConnectionFactory): List<Map<*, *>>? {
180-
var connection = connect(factory, url)
181-
connection.requestMethod = "GET"
182-
connection.setRequestProperty("User-Agent", userAgent)
183-
184-
connection.connect()
185-
if (connection.responseCode != 200) {
186-
connection.disconnect()
187-
return null
188-
}
187+
var useAuthed = false
189188

189+
var next: String? = url
190190
val list = mutableListOf<Map<*, *>>()
191-
var data = connection.inputStream.reader().use(InputStreamReader::readCharSequence).toString()
192191

193-
var response = Gson().fromJson<List<Map<*, *>>>(data)
194-
list.addAll(response)
192+
while (next != null) {
193+
val connection: HttpURLConnection = connect(factory, next)
194+
try {
195+
connection.requestMethod = "GET"
196+
connection.setRequestProperty("User-Agent", userAgent)
195197

196-
var link = connection.getHeaderField("Link")
197-
connection.disconnect()
198+
connection.connect()
198199

199-
var next = getNextLink(link)
200-
while (next != null) {
201-
connection = connect(factory, next)
202-
connection.requestMethod = "GET"
203-
connection.setRequestProperty("User-Agent", userAgent)
200+
if (connection.responseCode == 403 && !useAuthed) {
201+
useAuthed = true
202+
next = replaceWithAuth(next)
203+
continue
204+
}
204205

205-
connection.connect()
206-
if (connection.responseCode != 200) {
207-
connection.disconnect()
208-
continue
209-
}
206+
if (connection.responseCode != 200) {
207+
return null
208+
}
209+
210+
val charset = connection.getHeaderField(HttpHeaders.CONTENT_TYPE)?.let {
211+
ContentType.parse(it).charset
212+
} ?: Charsets.UTF_8
210213

211-
val charset = connection.getHeaderField(HttpHeaders.CONTENT_TYPE)?.let {
212-
ContentType.parse(it).charset
213-
} ?: Charsets.UTF_8
214+
val data = connection.inputStream.reader(charset).readText()
214215

215-
data = connection.inputStream.reader(charset).readText()
216+
val response = Gson().fromJson<List<Map<*, *>>>(data)
217+
list.addAll(response)
216218

217-
response = Gson().fromJson(data)
218-
list.addAll(response)
219+
val link = connection.getHeaderField("Link")
219220

220-
link = connection.getHeaderField("Link")
221-
connection.disconnect()
222-
next = getNextLink(link)
221+
next = getNextLink(link, useAuthed)
222+
} finally {
223+
connection.disconnect()
224+
}
223225
}
224226

225227
return list
226228
}
227229

228-
private fun getNextLink(linkHeader: String?): String? {
230+
private fun getNextLink(linkHeader: String?, useAuthed: Boolean): String? {
229231
if (linkHeader == null) {
230232
return null
231233
}
@@ -239,14 +241,31 @@ object AnonymousFeedback {
239241
if (parts.isEmpty()) {
240242
continue
241243
}
242-
return parts[0].trim().removePrefix("<").removeSuffix(">")
244+
val nextUrl = parts[0].trim().removePrefix("<").removeSuffix(">")
245+
if (!useAuthed) {
246+
return nextUrl
247+
}
248+
249+
return replaceWithAuth(nextUrl)
243250
}
244251

245252
return null
246253
}
247254

255+
private fun replaceWithAuth(url: String): String? {
256+
// non-authed-API requests are rate limited at 60 / hour / IP
257+
// authed requests have a rate limit of 5000 / hour / account
258+
// We don't want to use the authed URL by default since all users would use the same rate limit
259+
// but it's a good fallback when the non-authed API stops working.
260+
val index = url.indexOf('?')
261+
if (index == -1) {
262+
return null
263+
}
264+
return authedUrl + url.substring(index)
265+
}
266+
248267
private fun sendCommentOnDuplicateIssue(id: Int, factory: HttpConnectionFactory, payload: ByteArray): String {
249-
val commentUrl = "$url/$id/comments"
268+
val commentUrl = "$authedUrl/$id/comments"
250269
val connection = getConnection(factory, commentUrl)
251270
val json = executeCall(connection, payload)
252271
return json["html_url"] as String
@@ -281,6 +300,74 @@ object AnonymousFeedback {
281300
return connection
282301
}
283302

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 ||
344+
lineNumber == null || stackElementText == null
345+
) {
346+
sb.append(line).append('\n')
347+
continue
348+
}
349+
350+
val path = className.substringAfter("com.demonwav.mcdev.")
351+
.substringBeforeLast('.')
352+
.replace('.', '/')
353+
sb.apply {
354+
append(prefix)
355+
append("<a href=\"")
356+
append(baseTagUrl)
357+
append(path)
358+
append('/')
359+
append(fileName)
360+
append("#L")
361+
append(lineNumber)
362+
append("\">")
363+
append(stackElementText)
364+
append("</a>\n")
365+
}
366+
}
367+
368+
return sb.toString()
369+
}
370+
284371
private val userAgent by lazy {
285372
var agent = "Minecraft Development IntelliJ IDEA plugin"
286373

src/main/kotlin/facet/MinecraftFacet.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ class MinecraftFacet(
4444
name: String,
4545
configuration: MinecraftFacetConfiguration,
4646
underlyingFacet: Facet<*>?
47-
) :
48-
Facet<MinecraftFacetConfiguration>(facetType, module, name, configuration, underlyingFacet) {
47+
) : Facet<MinecraftFacetConfiguration>(facetType, module, name, configuration, underlyingFacet) {
4948

5049
private val moduleMap = ConcurrentHashMap<AbstractModuleType<*>, AbstractModule>()
5150
private val roots: HashMultimap<SourceType, VirtualFile?> = HashMultimap.create()

src/main/kotlin/insight/generation/MinecraftClassCreateAction.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class MinecraftClassCreateAction :
5555
builder.addKind("Block", icon, MinecraftTemplates.FORGE_BLOCK_TEMPLATE)
5656
builder.addKind("Item", icon, MinecraftTemplates.FORGE_ITEM_TEMPLATE)
5757
builder.addKind("Packet", icon, MinecraftTemplates.FORGE_PACKET_TEMPLATE)
58+
builder.addKind("Enchantment", icon, MinecraftTemplates.FORGE_ENCHANTMENT_TEMPLATE)
5859
}
5960
if (isFabric) {
6061
val icon = PlatformAssets.FABRIC_ICON

src/main/kotlin/platform/forge/creator/ForgeProjectConfig.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ class ForgeProjectConfig : ProjectConfig(), GradleCreator {
5858
rootDirectory: Path,
5959
buildSystem: GradleBuildSystem
6060
) {
61-
buildSystem.gradleVersion = Fg2ProjectCreator.FG_WRAPPER_VERSION
61+
buildSystem.gradleVersion = if (isFg3(mcVersion, forgeVersion)) {
62+
Fg3ProjectCreator.FG4_WRAPPER_VERSION
63+
} else {
64+
Fg2ProjectCreator.FG_WRAPPER_VERSION
65+
}
6266
}
6367

6468
private fun isFg3(mcVersion: SemanticVersion, forgeVersion: SemanticVersion): Boolean {

src/main/kotlin/platform/forge/creator/ForgeProjectCreator.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ open class Fg3ProjectCreator(
170170

171171
return steps
172172
}
173+
174+
companion object {
175+
val FG4_WRAPPER_VERSION = SemanticVersion.release(6, 8, 1)
176+
}
173177
}
174178

175179
class Fg3Mc112ProjectCreator(

0 commit comments

Comments
 (0)