-
Notifications
You must be signed in to change notification settings - Fork 380
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TOML: add initial formatter implementation
- Loading branch information
Showing
20 changed files
with
429 additions
and
9 deletions.
There are no files selected for viewing
63 changes: 63 additions & 0 deletions
63
intellij-toml/src/main/kotlin/org/toml/ide/formatter/TomlFmtBlock.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter | ||
|
||
import com.intellij.formatting.* | ||
import com.intellij.lang.ASTNode | ||
import com.intellij.openapi.util.TextRange | ||
import com.intellij.psi.formatter.FormatterUtil | ||
import org.toml.ide.formatter.impl.computeIndent | ||
import org.toml.ide.formatter.impl.computeSpacing | ||
import org.toml.ide.formatter.impl.isWhitespaceOrEmpty | ||
import org.toml.lang.psi.TomlElementTypes.ARRAY | ||
|
||
class TomlFmtBlock( | ||
private val node: ASTNode, | ||
private val alignment: Alignment?, | ||
private val indent: Indent?, | ||
private val wrap: Wrap?, | ||
private val ctx: TomlFmtContext | ||
) : ASTBlock { | ||
override fun getNode(): ASTNode = node | ||
override fun getTextRange(): TextRange = node.textRange | ||
override fun getAlignment(): Alignment? = alignment | ||
override fun getIndent(): Indent? = indent | ||
override fun getWrap(): Wrap? = wrap | ||
|
||
override fun getSubBlocks(): List<Block> = mySubBlocks | ||
private val mySubBlocks: List<Block> by lazy { buildChildren() } | ||
|
||
private fun buildChildren(): List<Block> { | ||
return node.getChildren(null) | ||
.filter { !it.isWhitespaceOrEmpty() } | ||
.map { childNode: ASTNode -> | ||
TomlFormattingModelBuilder.createBlock( | ||
node = childNode, | ||
alignment = null, | ||
indent = computeIndent(childNode), | ||
wrap = null, | ||
ctx = ctx | ||
) | ||
} | ||
} | ||
|
||
override fun getSpacing(child1: Block?, child2: Block): Spacing? = computeSpacing(child1, child2, ctx) | ||
|
||
override fun getChildAttributes(newChildIndex: Int): ChildAttributes { | ||
val indent = when (node.elementType) { | ||
ARRAY -> Indent.getNormalIndent() | ||
else -> Indent.getNoneIndent() | ||
} | ||
return ChildAttributes(indent, null) | ||
} | ||
|
||
override fun isLeaf(): Boolean = node.firstChildNode == null | ||
|
||
override fun isIncomplete(): Boolean = myIsIncomplete | ||
private val myIsIncomplete: Boolean by lazy { FormatterUtil.isIncomplete(node) } | ||
|
||
override fun toString() = "${node.text} $textRange" | ||
} |
24 changes: 24 additions & 0 deletions
24
intellij-toml/src/main/kotlin/org/toml/ide/formatter/TomlFmtContext.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter | ||
|
||
import com.intellij.formatting.SpacingBuilder | ||
import com.intellij.psi.codeStyle.CodeStyleSettings | ||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings | ||
import org.toml.ide.formatter.impl.createSpacingBuilder | ||
import org.toml.lang.TomlLanguage | ||
|
||
data class TomlFmtContext private constructor( | ||
val commonSettings: CommonCodeStyleSettings, | ||
val spacingBuilder: SpacingBuilder | ||
) { | ||
companion object { | ||
fun create(settings: CodeStyleSettings): TomlFmtContext { | ||
val commonSettings = settings.getCommonSettings(TomlLanguage) | ||
return TomlFmtContext(commonSettings, createSpacingBuilder(commonSettings)) | ||
} | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
intellij-toml/src/main/kotlin/org/toml/ide/formatter/TomlFormattingModelBuilder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter | ||
|
||
import com.intellij.formatting.* | ||
import com.intellij.lang.ASTNode | ||
import com.intellij.openapi.util.TextRange | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.PsiFile | ||
import com.intellij.psi.codeStyle.CodeStyleSettings | ||
|
||
class TomlFormattingModelBuilder : FormattingModelBuilder { | ||
override fun getRangeAffectingIndent(file: PsiFile?, offset: Int, elementAtOffset: ASTNode?): TextRange? = null | ||
|
||
override fun createModel(element: PsiElement, settings: CodeStyleSettings): FormattingModel { | ||
val ctx = TomlFmtContext.create(settings) | ||
val block = createBlock(element.node, null, Indent.getNoneIndent(), null, ctx) | ||
return FormattingModelProvider.createFormattingModelForPsiFile(element.containingFile, block, settings) | ||
} | ||
|
||
companion object { | ||
fun createBlock( | ||
node: ASTNode, | ||
alignment: Alignment?, | ||
indent: Indent?, | ||
wrap: Wrap?, | ||
ctx: TomlFmtContext | ||
): ASTBlock = TomlFmtBlock(node, alignment, indent, wrap, ctx) | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
intellij-toml/src/main/kotlin/org/toml/ide/formatter/impl/indent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter.impl | ||
|
||
import com.intellij.formatting.Indent | ||
import com.intellij.lang.ASTNode | ||
import org.toml.ide.formatter.TomlFmtBlock | ||
import org.toml.lang.psi.TomlElementTypes.ARRAY | ||
|
||
fun TomlFmtBlock.computeIndent(child: ASTNode): Indent? = when (node.elementType) { | ||
ARRAY -> getArrayIndent(child) | ||
else -> Indent.getNoneIndent() | ||
} | ||
|
||
private fun getArrayIndent(node: ASTNode): Indent = | ||
when { | ||
node.isArrayDelimiter() -> Indent.getNoneIndent() | ||
else -> Indent.getNormalIndent() | ||
} |
37 changes: 37 additions & 0 deletions
37
intellij-toml/src/main/kotlin/org/toml/ide/formatter/impl/spacing.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter.impl | ||
|
||
import com.intellij.formatting.Block | ||
import com.intellij.formatting.Spacing | ||
import com.intellij.formatting.SpacingBuilder | ||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings | ||
import org.toml.ide.formatter.TomlFmtContext | ||
import org.toml.lang.psi.TomlElementTypes.* | ||
import com.intellij.psi.tree.TokenSet.create as ts | ||
|
||
fun createSpacingBuilder(commonSettings: CommonCodeStyleSettings): SpacingBuilder { | ||
val builder = SpacingBuilder(commonSettings) | ||
// , | ||
.after(COMMA).spacing(1, 1, 0, true, 0) | ||
.before(COMMA).spaceIf(false) | ||
// = | ||
.around(EQ).spacing(1, 1, 0, true, 0) | ||
// [ ] | ||
.after(L_BRACKET).spaceIf(false) | ||
.before(R_BRACKET).spaceIf(false) | ||
// { } | ||
.after(L_CURLY).spaceIf(true) | ||
.before(R_CURLY).spaceIf(true) | ||
// . | ||
.aroundInside(DOT, ts(KEY, TABLE_HEADER)).spaceIf(false) | ||
|
||
return builder | ||
} | ||
|
||
fun Block.computeSpacing(child1: Block?, child2: Block, ctx: TomlFmtContext): Spacing? { | ||
return ctx.spacingBuilder.getSpacing(this, child1, child2) | ||
} |
17 changes: 17 additions & 0 deletions
17
intellij-toml/src/main/kotlin/org/toml/ide/formatter/impl/utils.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter.impl | ||
|
||
import com.intellij.lang.ASTNode | ||
import com.intellij.psi.TokenType | ||
import com.intellij.psi.tree.TokenSet | ||
import org.toml.lang.psi.TomlElementTypes.* | ||
|
||
val ARRAY_DELIMITERS = TokenSet.create(L_BRACKET, R_BRACKET) | ||
|
||
fun ASTNode?.isWhitespaceOrEmpty() = this == null || textLength == 0 || elementType == TokenType.WHITE_SPACE | ||
|
||
fun ASTNode.isArrayDelimiter(): Boolean = elementType in ARRAY_DELIMITERS |
12 changes: 12 additions & 0 deletions
12
intellij-toml/src/main/kotlin/org/toml/ide/formatter/settings/TomlCodeStyleSettings.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter.settings | ||
|
||
import com.intellij.psi.codeStyle.CodeStyleSettings | ||
import com.intellij.psi.codeStyle.CustomCodeStyleSettings | ||
|
||
class TomlCodeStyleSettings(container: CodeStyleSettings) : | ||
CustomCodeStyleSettings(TomlCodeStyleSettings::class.java.simpleName, container) |
34 changes: 34 additions & 0 deletions
34
...lij-toml/src/main/kotlin/org/toml/ide/formatter/settings/TomlCodeStyleSettingsProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter.settings | ||
|
||
import com.intellij.application.options.CodeStyleAbstractConfigurable | ||
import com.intellij.application.options.TabbedLanguageCodeStylePanel | ||
import com.intellij.openapi.options.Configurable | ||
import com.intellij.psi.codeStyle.CodeStyleSettings | ||
import com.intellij.psi.codeStyle.CodeStyleSettingsProvider | ||
import com.intellij.psi.codeStyle.CustomCodeStyleSettings | ||
import org.toml.lang.TomlLanguage | ||
|
||
class TomlCodeStyleSettingsProvider : CodeStyleSettingsProvider() { | ||
override fun createCustomSettings(settings: CodeStyleSettings): CustomCodeStyleSettings = TomlCodeStyleSettings(settings) | ||
|
||
override fun getConfigurableDisplayName(): String = TomlLanguage.displayName | ||
|
||
override fun createSettingsPage(settings: CodeStyleSettings, originalSettings: CodeStyleSettings): Configurable = | ||
object : CodeStyleAbstractConfigurable(settings, originalSettings, configurableDisplayName) { | ||
override fun createPanel(settings: CodeStyleSettings) = TomlCodeStyleMainPanel(currentSettings, settings) | ||
override fun getHelpTopic() = null | ||
} | ||
|
||
private class TomlCodeStyleMainPanel(currentSettings: CodeStyleSettings, settings: CodeStyleSettings) : | ||
TabbedLanguageCodeStylePanel(TomlLanguage, currentSettings, settings) { | ||
|
||
override fun initTabs(settings: CodeStyleSettings) { | ||
addIndentOptionsTab(settings) | ||
} | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
.../src/main/kotlin/org/toml/ide/formatter/settings/TomlLanguageCodeStyleSettingsProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter.settings | ||
|
||
import com.intellij.application.options.IndentOptionsEditor | ||
import com.intellij.application.options.SmartIndentOptionsEditor | ||
import com.intellij.lang.Language | ||
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider | ||
import org.toml.lang.TomlLanguage | ||
|
||
class TomlLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider() { | ||
override fun getLanguage(): Language = TomlLanguage | ||
override fun getCodeSample(settingsType: SettingsType): String = | ||
when (settingsType) { | ||
SettingsType.INDENT_SETTINGS -> INDENT_SAMPLE | ||
else -> "" | ||
} | ||
|
||
override fun getIndentOptionsEditor(): IndentOptionsEditor? = SmartIndentOptionsEditor() | ||
} | ||
|
||
private fun sample(@org.intellij.lang.annotations.Language("TOML") code: String) = code.trim() | ||
|
||
private val INDENT_SAMPLE = sample(""" | ||
[config] | ||
items = [ | ||
"foo", | ||
"bar" | ||
] | ||
""") |
12 changes: 12 additions & 0 deletions
12
intellij-toml/src/main/kotlin/org/toml/ide/formatter/utils.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter | ||
|
||
import com.intellij.psi.codeStyle.CodeStyleSettings | ||
import org.toml.ide.formatter.settings.TomlCodeStyleSettings | ||
|
||
val CodeStyleSettings.toml: TomlCodeStyleSettings | ||
get() = getCustomSettings(TomlCodeStyleSettings::class.java) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml | ||
|
||
import com.intellij.testFramework.fixtures.BasePlatformTestCase | ||
import org.intellij.lang.annotations.Language | ||
|
||
abstract class TomlTestBase : BasePlatformTestCase() { | ||
@Suppress("TestFunctionName") | ||
protected fun InlineFile(@Language("TOML") text: String, name: String = "example.toml") { | ||
myFixture.configureByText(name, text) | ||
} | ||
|
||
protected fun checkByText( | ||
@Language("TOML") before: String, | ||
@Language("TOML") after: String, | ||
action: () -> Unit | ||
) { | ||
InlineFile(before) | ||
action() | ||
myFixture.checkResult(after) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
intellij-toml/src/test/kotlin/org/toml/ide/formatter/TomlAutoIndentTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
* Use of this source code is governed by the MIT license that can be | ||
* found in the LICENSE file. | ||
*/ | ||
|
||
package org.toml.ide.formatter | ||
|
||
import org.toml.ide.typing.TomlTypingTestBase | ||
|
||
class TomlAutoIndentTest : TomlTypingTestBase() { | ||
fun `test new array element`() = doTestByText(""" | ||
[key] | ||
foo = [ | ||
"text",<caret> | ||
] | ||
""", """ | ||
[key] | ||
foo = [ | ||
"text", | ||
<caret> | ||
] | ||
""") | ||
} |
Oops, something went wrong.