Skip to content

Commit

Permalink
Reformat a selection instead of entire file (#503)
Browse files Browse the repository at this point in the history
Closes #385
  • Loading branch information
paul-dingemans authored May 1, 2024
1 parent aeff4df commit b670dc0
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,15 @@ class KtlintActionOnSave : ActionOnSave() {
PsiManager
.getInstance(project)
.findFile(virtualFile)
?.let { psiFile -> ktlintFormat(psiFile, "KtlintActionOnSave") }
?.let { psiFile ->
ktlintFormat(psiFile, ktlintFormatRange = KtlintFileFormatRange, triggeredBy = "KtlintActionOnSave")
}
}
} else {
// Only format files which were modified
psiFiles.forEach { psiFile -> ktlintFormat(psiFile, "KtlintActionOnSave") }
psiFiles.forEach { psiFile ->
ktlintFormat(psiFile, ktlintFormatRange = KtlintFileFormatRange, triggeredBy = "KtlintActionOnSave")
}
}
}
}
Expand Down
44 changes: 28 additions & 16 deletions plugin/src/main/kotlin/com/nbadal/ktlint/KtlintConfigForm.form
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.nbadal.ktlint.KtlintConfigForm">
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="9" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="9" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="757" height="400"/>
Expand All @@ -10,7 +10,7 @@
<children>
<vspacer id="f22cd">
<constraints>
<grid row="7" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="7" column="1" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="909eb" class="javax.swing.JLabel">
Expand All @@ -24,15 +24,15 @@
</component>
<component id="c98b6" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="externalJarPaths">
<constraints>
<grid row="6" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
<grid row="6" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="6990b" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="baselinePath">
<constraints>
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
<grid row="4" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
Expand All @@ -57,7 +57,7 @@
</component>
<component id="9f881" class="javax.swing.JRadioButton" binding="distractFreeMode">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="strings" key="distractFreeModeLabel"/>
Expand All @@ -66,7 +66,7 @@
</component>
<component id="9e17" class="javax.swing.JRadioButton" binding="manualMode">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="strings" key="manualModeLabel"/>
Expand All @@ -75,13 +75,21 @@
</component>
<component id="8953f" class="javax.swing.JRadioButton" binding="disabledMode">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="2" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="strings" key="disabledMode"/>
<toolTipText resource-bundle="strings" key="disabledModeTooltip"/>
</properties>
</component>
<component id="15acd" class="javax.swing.JButton" binding="githubButton">
<constraints>
<grid row="8" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="strings" key="githubButton"/>
</properties>
</component>
<component id="30741" class="javax.swing.JLabel" binding="formatLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
Expand All @@ -100,21 +108,19 @@
</component>
<component id="e4ea7" class="javax.swing.JComboBox" binding="rulesetVersion">
<constraints>
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
<grid row="5" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<model>
<item value="default (recommended)"/>
<item value="1.2.2"/>
<item value="1.2.1"/>
<item value="1.2.0"/>
<item value="1.1.1"/>
<item value="1.0.1"/>
<item value="0.50.0"/>
</model>
</properties>
</component>
<component id="147a1" class="javax.swing.JCheckBox" binding="formatOnSave">
<component id="eff2f" class="javax.swing.JCheckBox" binding="attachToIntellijFormat">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
Expand All @@ -123,17 +129,23 @@
<hideActionText value="false"/>
<opaque value="true"/>
<selected value="true"/>
<text resource-bundle="strings" key="formatOnSaveLabel"/>
<toolTipText resource-bundle="strings" key="formatOnSaveToolTip"/>
<text resource-bundle="strings" key="attachToIntellijFormattingLabel"/>
<toolTipText resource-bundle="strings" key="attachToIntellijFormattingToolTip"/>
<visible value="true"/>
</properties>
</component>
<component id="15acd" class="javax.swing.JButton" binding="githubButton">
<component id="147a1" class="javax.swing.JCheckBox" binding="formatOnSave">
<constraints>
<grid row="8" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
<grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="strings" key="githubButton"/>
<enabled value="true"/>
<hideActionText value="false"/>
<opaque value="true"/>
<selected value="true"/>
<text resource-bundle="strings" key="formatOnSaveLabel"/>
<toolTipText resource-bundle="strings" key="formatOnSaveToolTip"/>
<visible value="true"/>
</properties>
</component>
</children>
Expand Down
9 changes: 7 additions & 2 deletions plugin/src/main/kotlin/com/nbadal/ktlint/KtlintConfigForm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class KtlintConfigForm(
private lateinit var formatLabel: JLabel
lateinit var formatOnSave: JCheckBox
private set
private lateinit var attachToIntellijFormat: JCheckBox
private lateinit var externalJarPaths: TextFieldWithBrowseButton
private lateinit var baselinePath: TextFieldWithBrowseButton
private lateinit var githubButton: JButton
Expand Down Expand Up @@ -90,6 +91,7 @@ class KtlintConfigForm(
ktlintConfigStorage.ktlintMode = ktlintMode
ktlintConfigStorage.ktlintRulesetVersion = ktlintRulesetVersion
ktlintConfigStorage.formatOnSave = formatOnSave.isSelected
ktlintConfigStorage.attachToIntellijFormat = attachToIntellijFormat.isSelected
ktlintConfigStorage.externalJarPaths =
externalJarPaths
.text
Expand All @@ -112,7 +114,7 @@ class KtlintConfigForm(
.getInstance(project)
.findFile(virtualFile)
?.let { psiFile ->
ktlintFormat(psiFile, triggeredBy = "KtlintActionOnSave")
ktlintFormat(psiFile, ktlintFormatRange = KtlintFileFormatRange, triggeredBy = "KtlintActionOnSave")
}
}
}
Expand All @@ -126,6 +128,7 @@ class KtlintConfigForm(
}
rulesetVersion.selectedItem = ktlintConfigStorage.ktlintRulesetVersion.label
formatOnSave.isSelected = ktlintConfigStorage.formatOnSave
attachToIntellijFormat.isSelected = ktlintConfigStorage.attachToIntellijFormat
baselinePath.text = ktlintConfigStorage.baselinePath.orEmpty()
externalJarPaths.text = ktlintConfigStorage.externalJarPaths.joinToString(", ")
}
Expand All @@ -148,12 +151,14 @@ class KtlintConfigForm(
Objects.equals(ktlintConfigStorage.ktlintMode, ktlintMode) &&
Objects.equals(ktlintConfigStorage.ktlintRulesetVersion, ktlintRulesetVersion) &&
Objects.equals(ktlintConfigStorage.formatOnSave, formatOnSave.isSelected) &&
Objects.equals(ktlintConfigStorage.attachToIntellijFormat, attachToIntellijFormat.isSelected) &&
Objects.equals(ktlintConfigStorage.baselinePath, baselinePath.text) &&
Objects.equals(ktlintConfigStorage.externalJarPaths, externalJarPaths.text)
)

private fun setFormatFieldsVisibility() {
formatLabel.isVisible = distractFreeMode.isSelected
formatLabel.isVisible = distractFreeMode.isSelected || manualMode.isSelected
formatOnSave.isVisible = distractFreeMode.isSelected
attachToIntellijFormat.isVisible = manualMode.isSelected
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class KtlintConfigStorage : PersistentStateComponent<KtlintConfigStorage> {
@Tag
var formatOnSave: Boolean = true

@Tag
var attachToIntellijFormat: Boolean = true

@Tag
var baselinePath: String? = null

Expand Down
22 changes: 13 additions & 9 deletions plugin/src/main/kotlin/com/nbadal/ktlint/KtlintFormat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,28 @@ internal fun ktlintLint(
psiFile: PsiFile,
triggeredBy: String,
) = if (psiFile.virtualFile.isKotlinFile()) {
executeKtlint(LINT, psiFile, triggeredBy, force = true)
executeKtlint(LINT, psiFile, KtlintFileFormatRange, triggeredBy)
} else {
KtlintResult(NOT_STARTED)
}

internal fun ktlintFormat(
psiFile: PsiFile,
ktlintFormatRange: KtlintFormatRange,
triggeredBy: String,
forceFormat: Boolean = false,
): KtlintResult {
var ktlintResult = KtlintResult(NOT_STARTED)
if (psiFile.virtualFile.isKotlinFile()) {
if (psiFile.virtualFile.isKotlinFile() &&
(psiFile.project.config().ktlintMode == DISTRACT_FREE || forceFormat)
) {
val project = psiFile.project
val document = psiFile.viewProvider.document
PsiDocumentManager
.getInstance(project)
.doPostponedOperationsAndUnblockDocument(document)
WriteCommandAction.runWriteCommandAction(project) {
ktlintResult = executeKtlint(FORMAT, psiFile, triggeredBy, forceFormat)
ktlintResult = executeKtlint(FORMAT, psiFile, ktlintFormatRange, triggeredBy)
}
FileDocumentManager.getInstance().saveDocument(document)
DaemonCodeAnalyzer.getInstance(project).restart(psiFile)
Expand All @@ -58,13 +61,10 @@ internal fun ktlintFormat(
private fun executeKtlint(
ktlintExecutionType: KtlintExecutionType,
psiFile: PsiFile,
ktlintFormatRange: KtlintFormatRange,
triggeredBy: String,
force: Boolean = false,
): KtlintResult {
val project = psiFile.project
if (project.config().ktlintMode != DISTRACT_FREE && !force) {
return KtlintResult(NOT_STARTED)
}

logger.debug { "Start ktlintFormat on file '${psiFile.virtualFile.name}' triggered by '$triggeredBy'" }

Expand Down Expand Up @@ -112,14 +112,18 @@ private fun executeKtlint(
val errorHandler = { error: LintError ->
when {
error.isIgnoredInBaseline(baselineErrors) -> Unit

else -> lintErrors.add(error)
}
}
if (ktlintExecutionType == LINT) {
ktlintRuleEngine.lint(code) { lintError -> errorHandler(lintError) }
} else {
val formattedCode = ktlintRuleEngine.format(code) { lintError, _ -> errorHandler(lintError) }
val formattedCode =
if (ktlintFormatRange == KtlintFileFormatRange) {
ktlintRuleEngine.format(code) { lintError, _ -> errorHandler(lintError) }
} else {
ktlintRuleEngine.format(code, ktlintFormatRange.intRange()) { lintError, _ -> errorHandler(lintError) }
}
if (formattedCode != code.content) {
psiFile.viewProvider.document.setText(formattedCode)
fileChangedByFormat = true
Expand Down
16 changes: 16 additions & 0 deletions plugin/src/main/kotlin/com/nbadal/ktlint/KtlintFormatRange.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.nbadal.ktlint

internal sealed interface KtlintFormatRange {
fun intRange(): IntRange
}

internal data object KtlintFileFormatRange : KtlintFormatRange {
override fun intRange(): IntRange = IntRange(0, Int.MAX_VALUE)
}

internal data class KtlintBlockFormatRange(
val startOffset: Int,
val endOffsetInclusive: Int,
) : KtlintFormatRange {
override fun intRange(): IntRange = IntRange(startOffset, endOffsetInclusive)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ class KtlintPostFormatProcessor : PostFormatProcessor {
rangeToReformat: TextRange,
settings: CodeStyleSettings,
): TextRange {
if (psiFile.project.isEnabled(KtlintFeature.POST_FORMAT_WITH_KTLINT)) {
ktlintFormat(psiFile, "KtlintPostFormatProcessor")
if (psiFile.project.isEnabled(KtlintFeature.POST_FORMAT_WITH_KTLINT) || psiFile.project.config().attachToIntellijFormat) {
ktlintFormat(
psiFile,
ktlintFormatRange = KtlintBlockFormatRange(rangeToReformat.startOffset, rangeToReformat.endOffset + 1),
triggeredBy = "KtlintPostFormatProcessor",
forceFormat = true,
)
}
return rangeToReformat
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import com.nbadal.ktlint.KtlintFeature
import com.nbadal.ktlint.KtlintFileFormatRange
import com.nbadal.ktlint.isEnabled
import com.nbadal.ktlint.ktlintFormat

Expand Down Expand Up @@ -37,6 +38,6 @@ class ForceFormatIntention :
editor: Editor?,
psiFile: PsiFile,
) {
ktlintFormat(psiFile, "ForceFormatIntention", forceFormat = true)
ktlintFormat(psiFile, ktlintFormatRange = KtlintFileFormatRange, triggeredBy = "ForceFormatIntention", forceFormat = true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiManager
import com.nbadal.ktlint.KtlintFeature.SHOW_MENU_OPTION_FORMAT_WITH_KTLINT
import com.nbadal.ktlint.KtlintFileFormatRange
import com.nbadal.ktlint.KtlintMode.DISTRACT_FREE
import com.nbadal.ktlint.KtlintNotifier.notifyInformation
import com.nbadal.ktlint.KtlintNotifier.notifyWarning
Expand Down Expand Up @@ -91,7 +92,7 @@ class FormatAction : AnAction() {
PsiManager
.getInstance(project)
.findFile(fileOrDir)
?.let { ktlintFormat(it, "FormatAction", forceFormat = true) }
?.let { ktlintFormat(it, ktlintFormatRange = KtlintFileFormatRange, triggeredBy = "FormatAction", forceFormat = true) }
// In case an error occurs, a notification has already been sent by ktlintFormat above
when (ktlintResult?.status) {
KtlintResult.Status.SUCCESS -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.nbadal.ktlint.KtlintFeature.SHOW_INTENTION_TO_SUPPRESS_VIOLATION
import com.nbadal.ktlint.KtlintFileFormatRange
import com.nbadal.ktlint.config
import com.nbadal.ktlint.isEnabled
import com.nbadal.ktlint.ktlintFormat
Expand Down Expand Up @@ -67,7 +68,7 @@ class KtlintRuleSuppressIntention(
?.let { updatedCode ->
if (updatedCode != code.content) {
document.setText(updatedCode)
ktlintFormat(psiFile, "KtlintSuppressIntention")
ktlintFormat(psiFile, ktlintFormatRange = KtlintFileFormatRange, triggeredBy = "KtlintSuppressIntention")
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions plugin/src/main/resources/strings.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
attachToIntellijFormattingLabel=&attach to Intellij IDEA formatting
attachToIntellijFormattingToolTip=Run Ktlint Formatting after Intellij IDEA formatting
baselineLabel=Baseline file:
baselineToolTip=The baseline file contains the KtLint violations which have to be ignored.
disabledMode=D&isabled
Expand Down

0 comments on commit b670dc0

Please sign in to comment.