Skip to content

Commit

Permalink
Merge branch '2023.2' into 2023.3
Browse files Browse the repository at this point in the history
  • Loading branch information
DenWav committed Aug 4, 2024
2 parents a3c37a4 + 40d6b84 commit 370a370
Show file tree
Hide file tree
Showing 64 changed files with 1,976 additions and 408 deletions.
8 changes: 3 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ dependencies {

implementation(libs.mixinExtras.expressions)
testLibs(libs.mixinExtras.common)
implementation("org.ow2.asm:asm-util:9.3")

// Kotlin
implementation(kotlin("stdlib-jdk8"))
Expand Down Expand Up @@ -298,10 +297,9 @@ tasks.processResources {
tasks.test {
dependsOn(tasks.jar, testLibs)
useJUnitPlatform()
doFirst {
testLibs.resolvedConfiguration.resolvedArtifacts.forEach {
systemProperty("testLibs.${it.name}", it.file.absolutePath)
}

testLibs.resolvedConfiguration.resolvedArtifacts.forEach {
systemProperty("testLibs.${it.name}", it.file.absolutePath)
}
systemProperty("NO_FS_ROOTS_ACCESS_CHECK", "true")
systemProperty("java.awt.headless", "true")
Expand Down
21 changes: 21 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Minecraft Development for IntelliJ

## [Unreleased]

### Added

- Access widener completion in fabric.mod.json
- Event listener generation for Kotlin
- `JUMP` injection point support (without source navigation)
- Inspection highlighting that `JUMP` usages are discouraged
- Inspection highlighting discouraged instruction shifts
- Inspections for when @Inject local capture is unused and for when they can be replaced with @Local
- [#2306](https://github.com/minecraft-dev/MinecraftDev/issues/2306) Use mixin icon for mixin classes

### Fixed

- [#2330](https://github.com/minecraft-dev/MinecraftDev/issues/2330) Reformat created files without keeping line breaks. Fixes the Velocity main class annotation's bad formatting.
- [#2331](https://github.com/minecraft-dev/MinecraftDev/issues/2331) Support fabric.mod.json in test resources
- MixinExtras occasional cache desync ([#2335](https://github.com/minecraft-dev/MinecraftDev/pull/2335))
- [#2163](https://github.com/minecraft-dev/MinecraftDev/issues/2163) `@ModifyVariable` method signature checking with `STORE`
- [#2282](https://github.com/minecraft-dev/MinecraftDev/issues/2282) Mixin support confusion with `$` and `.` separators in class names
- Recent NeoModDev version import errors

## [1.8.0]

This release contains two major features:
Expand Down
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ groovy = "org.codehaus.groovy:groovy-all:2.5.18"
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
asm-tree = { module = "org.ow2.asm:asm-tree", version.ref = "asm" }
asm-analysis = { module = "org.ow2.asm:asm-analysis", version.ref = "asm" }
asm-util = { module = "org.ow2.asm:asm-util", version.ref = "asm" }

fuel = { module = "com.github.kittinunf.fuel:fuel", version.ref = "fuel" }
fuel-coroutines = { module = "com.github.kittinunf.fuel:fuel-coroutines", version.ref = "fuel" }
Expand All @@ -45,5 +46,5 @@ mixinExtras-common = "io.github.llamalad7:mixinextras-common:0.5.0-beta.1"

[bundles]
coroutines = ["coroutines-swing"]
asm = ["asm", "asm-tree", "asm-analysis"]
asm = ["asm", "asm-tree", "asm-analysis", "asm-util"]
fuel = ["fuel", "fuel-coroutines"]
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Minecraft Development for IntelliJ
</tr>
</table>

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

<a href="https://discord.gg/j6UNcfr"><img src="https://i.imgur.com/JXu9C1G.png" height="48px"></img></a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package com.demonwav.mcdev.platform.mcp.gradle.tooling.neomoddev

import com.demonwav.mcdev.platform.mcp.gradle.tooling.McpModelNMD
import org.gradle.api.Project
import org.gradle.api.provider.ListProperty
import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
Expand Down Expand Up @@ -51,16 +52,26 @@ final class NeoModDevGradleModelBuilderImpl implements ModelBuilderService {
return null
}

def accessTransformers = extension.accessTransformers.get().collect { project.file(it) }
def accessTransformersRaw = extension.accessTransformers
List<File> accessTransformers
if (accessTransformersRaw instanceof ListProperty) {
accessTransformers = accessTransformersRaw.get().collect { project.file(it) }
} else {
accessTransformers = accessTransformersRaw.files.files.toList()
}

// Hacky way to guess where the mappings file is, but I could not find a proper way to find it
def neoformDir = project.buildDir.toPath().resolve("neoForm")
def mappingsFile = Files.list(neoformDir)
.map { it.resolve("config/joined.tsrg") }
.filter { Files.exists(it) }
.findFirst()
.orElse(null)
?.toFile()
File mappingsFile = null
try {
// Hacky way to guess where the mappings file is, but I could not find a proper way to find it
def neoformDir = project.buildDir.toPath().resolve("neoForm")
mappingsFile = Files.list(neoformDir)
.map { it.resolve("config/joined.tsrg") }
.filter { Files.exists(it) }
.findFirst()
.orElse(null)
?.toFile()
} catch (Exception ignore) {
}

//noinspection GroovyAssignabilityCheck
return new NeoModDevGradleModelImpl(neoforgeVersion, mappingsFile, accessTransformers)
Expand Down
7 changes: 7 additions & 0 deletions src/main/kotlin/MinecraftConfigurable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ class MinecraftConfigurable : Configurable {
}
}

group(MCDevBundle("minecraft.settings.mixin")) {
row {
checkBox(MCDevBundle("minecraft.settings.mixin.mixin_class_icon"))
.bindSelected(settings::mixinClassIcon)
}
}

group(MCDevBundle("minecraft.settings.creator")) {
row(MCDevBundle("minecraft.settings.creator.repos")) {}

Expand Down
8 changes: 8 additions & 0 deletions src/main/kotlin/MinecraftSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class MinecraftSettings : PersistentStateComponent<MinecraftSettings.State> {
var isShowChatColorUnderlines: Boolean = false,
var underlineType: UnderlineType = UnderlineType.DOTTED,

var mixinClassIcon: Boolean = true,

var creatorTemplateRepos: List<TemplateRepo> = listOf(TemplateRepo.makeBuiltinRepo()),
)

Expand Down Expand Up @@ -106,6 +108,12 @@ class MinecraftSettings : PersistentStateComponent<MinecraftSettings.State> {
state.underlineType = underlineType
}

var mixinClassIcon: Boolean
get() = state.mixinClassIcon
set(mixinClassIcon) {
state.mixinClassIcon = mixinClassIcon
}

var creatorTemplateRepos: List<TemplateRepo>
get() = state.creatorTemplateRepos.map { it.copy() }
set(creatorTemplateRepos) {
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/asset/MixinAssets.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ object MixinAssets : Assets() {

val MIXIN_CLASS_ICON = loadIcon("/assets/icons/mixin/mixin_class_gutter.png")
val MIXIN_CLASS_ICON_DARK = loadIcon("/assets/icons/mixin/mixin_class_gutter_dark.png")

val MIXIN_MARK = loadIcon("/assets/icons/mixin/mixin_mark.svg")
}
122 changes: 122 additions & 0 deletions src/main/kotlin/insight/generation/EventGenHelper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2024 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.demonwav.mcdev.insight.generation

import com.demonwav.mcdev.util.addImplements
import com.intellij.core.CoreJavaCodeStyleManager
import com.intellij.lang.LanguageExtension
import com.intellij.lang.LanguageExtensionPoint
import com.intellij.openapi.editor.RangeMarker
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.util.parentOfType
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory

interface EventGenHelper {

fun addImplements(context: PsiElement, fqn: String)

fun reformatAndShortenRefs(file: PsiFile, startOffset: Int, endOffset: Int)

companion object {

val EP_NAME = ExtensionPointName.create<LanguageExtensionPoint<EventGenHelper>>(
"com.demonwav.minecraft-dev.eventGenHelper"
)
val COLLECTOR = LanguageExtension<EventGenHelper>(EP_NAME, JvmEventGenHelper())
}
}

open class JvmEventGenHelper : EventGenHelper {

override fun addImplements(context: PsiElement, fqn: String) {}

override fun reformatAndShortenRefs(file: PsiFile, startOffset: Int, endOffset: Int) {
val project = file.project

val marker = doReformat(project, file, startOffset, endOffset) ?: return

CoreJavaCodeStyleManager.getInstance(project).shortenClassReferences(file, marker.startOffset, marker.endOffset)
}

companion object {

fun doReformat(project: Project, file: PsiFile, startOffset: Int, endOffset: Int): RangeMarker? {
val documentManager = PsiDocumentManager.getInstance(project)
val document = documentManager.getDocument(file) ?: return null

val marker = document.createRangeMarker(startOffset, endOffset).apply {
isGreedyToLeft = true
isGreedyToRight = true
}

CodeStyleManager.getInstance(project).reformatText(file, startOffset, endOffset)
documentManager.commitDocument(document)

return marker
}
}
}

class JavaEventGenHelper : JvmEventGenHelper() {

override fun addImplements(context: PsiElement, fqn: String) {
val psiClass = context.parentOfType<PsiClass>(true) ?: return
psiClass.addImplements(fqn)
}
}

class KotlinEventGenHelper : EventGenHelper {

private fun hasSuperType(ktClass: KtClassOrObject, fqn: String): Boolean {
val names = setOf(fqn, fqn.substringAfterLast('.'))
return ktClass.superTypeListEntries.any { it.text in names }
}

override fun addImplements(context: PsiElement, fqn: String) {
val ktClass = context.parentOfType<KtClassOrObject>(true) ?: return
if (hasSuperType(ktClass, fqn)) {
return
}

val factory = KtPsiFactory.contextual(context)
val entry = factory.createSuperTypeEntry(fqn)
val insertedEntry = ktClass.addSuperTypeListEntry(entry)
ShortenReferences.DEFAULT.process(insertedEntry)
}

override fun reformatAndShortenRefs(file: PsiFile, startOffset: Int, endOffset: Int) {
file as? KtFile ?: return
val project = file.project

val marker = JvmEventGenHelper.doReformat(project, file, startOffset, endOffset) ?: return

ShortenReferences.DEFAULT.process(file, marker.startOffset, marker.endOffset)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Minecraft Development for IntelliJ
*
* https://mcdev.io/
*
* Copyright (C) 2024 minecraft-dev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, version 3.0 only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.demonwav.mcdev.insight.generation

import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement

interface EventListenerGenerationSupport {

fun canGenerate(context: PsiElement, editor: Editor): Boolean

fun generateEventListener(
context: PsiElement,
listenerName: String,
eventClass: PsiClass,
data: GenerationData?,
editor: Editor
)
}
26 changes: 24 additions & 2 deletions src/main/kotlin/insight/generation/GenerateEventListenerAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,35 @@
package com.demonwav.mcdev.insight.generation

import com.demonwav.mcdev.asset.MCDevBundle
import com.intellij.codeInsight.generation.actions.BaseGenerateAction
import com.demonwav.mcdev.facet.MinecraftFacet
import com.demonwav.mcdev.util.findModule
import com.intellij.codeInsight.CodeInsightActionHandler
import com.intellij.codeInsight.actions.CodeInsightAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile

class GenerateEventListenerAction : BaseGenerateAction(GenerateEventListenerHandler()) {
class GenerateEventListenerAction : CodeInsightAction() {

private val handler = GenerateEventListenerHandler()

override fun getHandler(): CodeInsightActionHandler = handler

override fun update(e: AnActionEvent) {
super.update(e)
e.presentation.text = MCDevBundle("generate.event_listener.title")
}

override fun isValidForFile(
project: Project,
editor: Editor,
file: PsiFile
): Boolean {
val module = file.findModule() ?: return false
val minecraftFacet = MinecraftFacet.getInstance(module) ?: return false
val support = minecraftFacet.modules.firstNotNullOfOrNull { it.eventListenerGenSupport } ?: return false
val caretElement = file.findElementAt(editor.caretModel.offset) ?: return false
return support.canGenerate(caretElement, editor)
}
}
Loading

0 comments on commit 370a370

Please sign in to comment.