Skip to content

Commit 3e88e0c

Browse files
committed
Add AW formatting, also identical to AT's
1 parent 85d2569 commit 3e88e0c

File tree

5 files changed

+375
-0
lines changed

5 files changed

+375
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2024 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.platform.mcp.aw.format
22+
23+
import com.demonwav.mcdev.platform.mcp.aw.gen.psi.AwTypes
24+
import com.demonwav.mcdev.util.children
25+
import com.intellij.formatting.Alignment
26+
import com.intellij.formatting.Block
27+
import com.intellij.formatting.Indent
28+
import com.intellij.formatting.Spacing
29+
import com.intellij.formatting.SpacingBuilder
30+
import com.intellij.formatting.Wrap
31+
import com.intellij.lang.ASTNode
32+
import com.intellij.psi.TokenType
33+
import com.intellij.psi.codeStyle.CodeStyleSettings
34+
import com.intellij.psi.formatter.common.AbstractBlock
35+
import com.intellij.psi.tree.IFileElementType
36+
37+
class AwBlock(
38+
node: ASTNode,
39+
wrap: Wrap?,
40+
alignment: Alignment?,
41+
val spacingBuilder: SpacingBuilder,
42+
val codeStyleSettings: CodeStyleSettings,
43+
val targetKindAlignment: Alignment? = null,
44+
val entryClassAlignment: Alignment? = null,
45+
val entryMemberAlignment: Alignment? = null,
46+
) : AbstractBlock(node, wrap, alignment) {
47+
48+
override fun buildChildren(): List<Block> {
49+
val blocks = mutableListOf<Block>()
50+
51+
var targetKindAlignment: Alignment? = targetKindAlignment
52+
var entryClassAlignment: Alignment? = entryClassAlignment
53+
var entryMemberAlignment: Alignment? = entryMemberAlignment
54+
55+
var newlineCount = 0
56+
val alignGroups = node.elementType is IFileElementType &&
57+
codeStyleSettings.getCustomSettings(AwCodeStyleSettings::class.java).ALIGN_ENTRY_CLASS_AND_MEMBER
58+
for (child in node.children()) {
59+
val childType = child.elementType
60+
if (childType == TokenType.WHITE_SPACE) {
61+
continue
62+
}
63+
64+
if (alignGroups) {
65+
if (childType == AwTypes.CRLF) {
66+
newlineCount++
67+
continue
68+
} else if (childType != AwTypes.COMMENT) {
69+
if (newlineCount >= 2) {
70+
// Align different groups separately, comments are not counted towards any group
71+
targetKindAlignment = Alignment.createAlignment(true)
72+
entryClassAlignment = Alignment.createAlignment(true)
73+
entryMemberAlignment = Alignment.createAlignment(true)
74+
}
75+
newlineCount = 0
76+
}
77+
}
78+
79+
val alignment = when (childType) {
80+
AwTypes.CLASS_ELEMENT, AwTypes.FIELD_ELEMENT, AwTypes.METHOD_ELEMENT -> targetKindAlignment
81+
AwTypes.CLASS_NAME -> entryClassAlignment
82+
AwTypes.MEMBER_NAME, AwTypes.FIELD_DESC, AwTypes.METHOD_DESC -> entryMemberAlignment
83+
else -> null
84+
}
85+
86+
blocks.add(
87+
AwBlock(
88+
child,
89+
null,
90+
alignment,
91+
spacingBuilder,
92+
codeStyleSettings,
93+
targetKindAlignment,
94+
entryClassAlignment,
95+
entryMemberAlignment
96+
)
97+
)
98+
}
99+
100+
return blocks
101+
}
102+
103+
override fun getIndent(): Indent? = Indent.getNoneIndent()
104+
105+
override fun getChildIndent(): Indent? = Indent.getNoneIndent()
106+
107+
override fun getSpacing(child1: Block?, child2: Block): Spacing? = spacingBuilder.getSpacing(this, child1, child2)
108+
109+
override fun isLeaf(): Boolean = node.firstChildNode == null
110+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2024 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.platform.mcp.aw.format
22+
23+
import com.demonwav.mcdev.platform.mcp.aw.AwLanguage
24+
import com.intellij.application.options.CodeStyleAbstractConfigurable
25+
import com.intellij.application.options.CodeStyleAbstractPanel
26+
import com.intellij.application.options.TabbedLanguageCodeStylePanel
27+
import com.intellij.lang.Language
28+
import com.intellij.openapi.util.NlsContexts
29+
import com.intellij.psi.codeStyle.CodeStyleConfigurable
30+
import com.intellij.psi.codeStyle.CodeStyleSettings
31+
import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable
32+
import com.intellij.psi.codeStyle.CodeStyleSettingsProvider
33+
import com.intellij.psi.codeStyle.CustomCodeStyleSettings
34+
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider
35+
36+
class AwCodeStyleSettings(val settings: CodeStyleSettings) : CustomCodeStyleSettings("AwCodeStyleSettings", settings) {
37+
@JvmField
38+
var SPACE_BEFORE_ENTRY_COMMENT = true
39+
40+
@JvmField
41+
var ALIGN_ENTRY_CLASS_AND_MEMBER = true
42+
}
43+
44+
class AwCodeStyleSettingsProvider : CodeStyleSettingsProvider() {
45+
override fun createCustomSettings(settings: CodeStyleSettings): CustomCodeStyleSettings =
46+
AwCodeStyleSettings(settings)
47+
48+
override fun getConfigurableDisplayName(): @NlsContexts.ConfigurableName String? = AwLanguage.displayName
49+
50+
override fun createConfigurable(
51+
settings: CodeStyleSettings,
52+
modelSettings: CodeStyleSettings
53+
): CodeStyleConfigurable {
54+
return object : CodeStyleAbstractConfigurable(settings, modelSettings, configurableDisplayName) {
55+
override fun createPanel(settings: CodeStyleSettings): CodeStyleAbstractPanel {
56+
return AwCodeStyleSettingsConfigurable(currentSettings, settings)
57+
}
58+
}
59+
}
60+
}
61+
62+
class AwCodeStyleSettingsConfigurable(currentSettings: CodeStyleSettings, settings: CodeStyleSettings) :
63+
TabbedLanguageCodeStylePanel(AwLanguage, currentSettings, settings)
64+
65+
class AwLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider() {
66+
67+
override fun getLanguage(): Language = AwLanguage
68+
69+
override fun customizeSettings(consumer: CodeStyleSettingsCustomizable, settingsType: SettingsType) {
70+
if (settingsType == SettingsType.SPACING_SETTINGS) {
71+
consumer.showCustomOption(
72+
AwCodeStyleSettings::class.java,
73+
"SPACE_BEFORE_ENTRY_COMMENT",
74+
"Space before entry comment",
75+
"Spacing and alignment"
76+
)
77+
consumer.showCustomOption(
78+
AwCodeStyleSettings::class.java,
79+
"ALIGN_ENTRY_CLASS_AND_MEMBER",
80+
"Align entry class name and member",
81+
"Spacing and alignment"
82+
)
83+
}
84+
}
85+
86+
override fun getCodeSample(settingsType: SettingsType): String? = """
87+
# Some header comment
88+
89+
accessible method net/minecraft/client/Minecraft pickBlock ()V # This is an entry comment
90+
accessible method net/minecraft/client/Minecraft userProperties ()Lcom/mojang/authlib/minecraft/UserApiService${'$'}UserProperties;
91+
92+
# Each group can be aligned independently
93+
accessible field net/minecraft/client/gui/screens/inventory/AbstractContainerScreen clickedSlot I
94+
accessible field net/minecraft/client/gui/screens/inventory/AbstractContainerScreen playerInventoryTitle Ljava/lang/String;
95+
extendable method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen findSlot (DD)Lnet/minecraft/world/inventory/Slot;
96+
""".trimIndent()
97+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2024 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.platform.mcp.aw.format
22+
23+
import com.demonwav.mcdev.platform.mcp.aw.AwLanguage
24+
import com.demonwav.mcdev.platform.mcp.aw.gen.psi.AwTypes
25+
import com.intellij.formatting.Alignment
26+
import com.intellij.formatting.FormattingContext
27+
import com.intellij.formatting.FormattingModel
28+
import com.intellij.formatting.FormattingModelBuilder
29+
import com.intellij.formatting.FormattingModelProvider
30+
import com.intellij.formatting.SpacingBuilder
31+
import com.intellij.psi.codeStyle.CodeStyleSettings
32+
import com.intellij.psi.tree.TokenSet
33+
34+
class AwFormattingModelBuilder : FormattingModelBuilder {
35+
36+
private fun createSpaceBuilder(settings: CodeStyleSettings): SpacingBuilder {
37+
val atSettings = settings.getCustomSettings(AwCodeStyleSettings::class.java)
38+
var targetKindTokens = TokenSet.create(AwTypes.CLASS_ELEMENT, AwTypes.METHOD_ELEMENT, AwTypes.FIELD_ELEMENT)
39+
var entryTokens = TokenSet.create(AwTypes.CLASS_ENTRY, AwTypes.METHOD_ENTRY, AwTypes.FIELD_ENTRY)
40+
return SpacingBuilder(settings, AwLanguage)
41+
.between(entryTokens, AwTypes.COMMENT).spaceIf(atSettings.SPACE_BEFORE_ENTRY_COMMENT)
42+
// Removes alignment spaces if it is disabled
43+
.between(AwTypes.ACCESS_ELEMENT, targetKindTokens).spaces(1)
44+
.between(targetKindTokens, AwTypes.CLASS_ELEMENT).spaces(1)
45+
.between(AwTypes.CLASS_ELEMENT, AwTypes.MEMBER_NAME).spaces(1)
46+
.between(AwTypes.MEMBER_NAME, AwTypes.FIELD_DESC).spaces(1)
47+
.between(AwTypes.MEMBER_NAME, AwTypes.METHOD_DESC).spaces(1)
48+
}
49+
50+
override fun createModel(formattingContext: FormattingContext): FormattingModel {
51+
val codeStyleSettings = formattingContext.codeStyleSettings
52+
val rootBlock = AwBlock(
53+
formattingContext.node,
54+
null,
55+
null,
56+
createSpaceBuilder(codeStyleSettings),
57+
codeStyleSettings,
58+
Alignment.createAlignment(true),
59+
Alignment.createAlignment(true),
60+
Alignment.createAlignment(true),
61+
)
62+
return FormattingModelProvider.createFormattingModelForPsiFile(
63+
formattingContext.containingFile,
64+
rootBlock,
65+
codeStyleSettings
66+
)
67+
}
68+
}

src/main/resources/META-INF/plugin.xml

+3
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,9 @@
648648
implementationClass="com.demonwav.mcdev.platform.mcp.aw.AwSyntaxHighlighterFactory"/>
649649
<colorSettingsPage implementation="com.demonwav.mcdev.platform.mcp.aw.AwColorSettingsPage"/>
650650
<lang.commenter language="Access Widener" implementationClass="com.demonwav.mcdev.platform.mcp.aw.AwCommenter"/>
651+
<codeStyleSettingsProvider implementation="com.demonwav.mcdev.platform.mcp.aw.format.AwCodeStyleSettingsProvider"/>
652+
<langCodeStyleSettingsProvider implementation="com.demonwav.mcdev.platform.mcp.aw.format.AwLanguageCodeStyleSettingsProvider"/>
653+
<lang.formatter language="Access Widener" implementationClass="com.demonwav.mcdev.platform.mcp.aw.format.AwFormattingModelBuilder"/>
651654
<annotator language="Access Widener" implementationClass="com.demonwav.mcdev.platform.mcp.aw.AwAnnotator"/>
652655
<lang.inspectionSuppressor language="Access Widener" implementationClass="com.demonwav.mcdev.platform.mcp.aw.inspections.AwInspectionSuppressor"/>
653656
<completion.contributor language="Access Widener"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2024 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.platform.mcp.aw
22+
23+
import com.demonwav.mcdev.framework.BaseMinecraftTest
24+
import com.intellij.openapi.command.WriteCommandAction
25+
import com.intellij.psi.codeStyle.CodeStyleManager
26+
import org.intellij.lang.annotations.Language
27+
import org.junit.jupiter.api.DisplayName
28+
import org.junit.jupiter.api.Test
29+
30+
@DisplayName("Access Widener Tests")
31+
class AwFormatterTest : BaseMinecraftTest() {
32+
33+
private fun doTest(
34+
@Language("Access Widener") before: String,
35+
@Language("Access Widener") after: String,
36+
) {
37+
38+
fixture.configureByText(AwFileType, before)
39+
WriteCommandAction.runWriteCommandAction(fixture.project) {
40+
CodeStyleManager.getInstance(project).reformat(fixture.file)
41+
}
42+
43+
fixture.checkResult(after)
44+
}
45+
46+
@Test
47+
@DisplayName("Entry Comment Spacing")
48+
fun entryCommentSpacing() {
49+
doTest("accessible field Test field# A comment", "accessible field Test field # A comment")
50+
}
51+
52+
@Test
53+
@DisplayName("Single Group Alignment")
54+
fun singleGroupAlignment() {
55+
doTest(
56+
"""
57+
accessible field Test field # A comment
58+
transitive-accessible method AnotherTest method ()V
59+
""".trimIndent(),
60+
"""
61+
accessible field Test field # A comment
62+
transitive-accessible method AnotherTest method ()V
63+
""".trimIndent()
64+
)
65+
}
66+
67+
@Test
68+
@DisplayName("Multiple Groups Alignments")
69+
fun multipleGroupsAlignments() {
70+
doTest(
71+
"""
72+
accessWidener v2 named
73+
74+
accessible field net/minecraft/Group1A field
75+
transitive-extendable method net/minecraft/Group1BCD method ()V
76+
77+
accessible field net/minecraft/server/Group2A anotherField
78+
extendable method net/minecraft/server/Group2BCD someMethod ()V
79+
# A comment in the middle should not join the two groups
80+
accessible field net/minecraft/world/Group3A anotherField
81+
transitive-extendable method net/minecraft/world/Group2BCD someMethod ()V
82+
""".trimIndent(),
83+
"""
84+
accessWidener v2 named
85+
86+
accessible field net/minecraft/Group1A field
87+
transitive-extendable method net/minecraft/Group1BCD method ()V
88+
89+
accessible field net/minecraft/server/Group2A anotherField
90+
extendable method net/minecraft/server/Group2BCD someMethod ()V
91+
# A comment in the middle should not join the two groups
92+
accessible field net/minecraft/world/Group3A anotherField
93+
transitive-extendable method net/minecraft/world/Group2BCD someMethod ()V
94+
""".trimIndent()
95+
)
96+
}
97+
}

0 commit comments

Comments
 (0)