PY-32711 Reformat simple injected code fragments with the corresponding language formatter

* Add `PyFormattableInjectedBlock` entity which allows passing the code inside the injection to the formatter of the injection language (e.g., SQL)
* Add code style options to enable and disable this behavior
* Add tests

GitOrigin-RevId: b63ff37d8aab3e37d101be3d0cc9e7ff0897b5a1
This commit is contained in:
Daniil Kalinin
2025-01-21 12:29:32 +01:00
committed by intellij-monorepo-bot
parent d3720a40e6
commit 31d7aa1a6c
6 changed files with 133 additions and 4 deletions

View File

@@ -36,6 +36,9 @@ formatter.imports.panel.sort.case.insensitively=Sort case-insensitively
formatter.panel.dict.alignment.label=Dict alignment:
formatter.panel.add.trailing.line.feed=Add line feed at the end of file
formatter.panel.injected.fragments=Injected fragments:
formatter.panel.format.injected.fragments=Format injected fragments
formatter.panel.injected.fragments.use.continuation.indent=Add indent
formatter.panel.use.continuation.indent.for.title=Use continuation indent for
formatter.panel.use.continuation.indent.for.parameters=Method declaration parameters

View File

@@ -23,12 +23,14 @@
</vspacer>
</children>
</grid>
<grid id="d3271" layout-manager="GridLayoutManager" row-count="4" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="d3271" layout-manager="GridLayoutManager" row-count="5" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="10" left="10" bottom="10" right="10"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<properties>
<opaque value="true"/>
</properties>
<border type="none"/>
<children>
<component id="767d3" class="com.intellij.ui.components.JBLabel">
@@ -41,7 +43,7 @@
</component>
<component id="b4945" class="com.intellij.ui.components.JBCheckBox" binding="myAddTrailingBlankLineCheckbox" default-binding="true">
<constraints>
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="3" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/PySyntaxBundle" key="formatter.panel.add.trailing.line.feed"/>
@@ -90,6 +92,39 @@
</component>
</children>
</grid>
<grid id="967d2" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
<html.disable class="java.lang.Boolean" value="false"/>
</clientProperties>
<border type="etched" title-resource-bundle="messages/PySyntaxBundle" title-key="formatter.panel.injected.fragments">
<font/>
<title-color color="-4211011"/>
</border>
<children>
<component id="3f110" class="com.intellij.ui.components.JBCheckBox" binding="myAddIndentInsideInjections">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/PySyntaxBundle" key="formatter.panel.injected.fragments.use.continuation.indent"/>
</properties>
</component>
<component id="80ca8" class="com.intellij.ui.components.JBCheckBox" binding="myFormatInjectedFragments">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/PySyntaxBundle" key="formatter.panel.format.injected.fragments"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
<vspacer id="4e0f0">

View File

@@ -32,6 +32,8 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
private JBCheckBox myUseContinuationIndentForCollectionsAndComprehensions;
private ComboBox myDictAlignmentCombo;
private JPanel myPreviewPanel;
private JBCheckBox myFormatInjectedFragments;
private JBCheckBox myAddIndentInsideInjections;
protected PyOtherCodeStylePanel(CodeStyleSettings settings) {
super(PythonLanguage.getInstance(), null, settings);
@@ -72,6 +74,20 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
somethingChanged();
}
});
myFormatInjectedFragments.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
somethingChanged();
}
});
myAddIndentInsideInjections.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
somethingChanged();
}
});
}
@Override
@@ -107,6 +123,8 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
myUseContinuationIndentForParameters.setSelected(pySettings.USE_CONTINUATION_INDENT_FOR_PARAMETERS);
myUseContinuationIndentForArguments.setSelected(pySettings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS);
myUseContinuationIndentForCollectionsAndComprehensions.setSelected(pySettings.USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS);
myFormatInjectedFragments.setSelected(pySettings.FORMAT_INJECTED_FRAGMENTS);
myAddIndentInsideInjections.setSelected(pySettings.ADD_INDENT_INSIDE_INJECTIONS);
}
@Override
@@ -117,6 +135,8 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
customSettings.USE_CONTINUATION_INDENT_FOR_PARAMETERS = useContinuationIndentForParameters();
customSettings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS = useContinuationIndentForArguments();
customSettings.USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS = useContinuationIndentForCollectionLiterals();
customSettings.FORMAT_INJECTED_FRAGMENTS = formatInjectedFragments();
customSettings.ADD_INDENT_INSIDE_INJECTIONS = addIndentInsideInjections();
}
@Override
@@ -126,7 +146,9 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
customSettings.BLANK_LINE_AT_FILE_END != ensureTrailingBlankLine() ||
customSettings.USE_CONTINUATION_INDENT_FOR_PARAMETERS != useContinuationIndentForParameters() ||
customSettings.USE_CONTINUATION_INDENT_FOR_ARGUMENTS != useContinuationIndentForArguments() ||
customSettings.USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS != useContinuationIndentForCollectionLiterals();
customSettings.USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS != useContinuationIndentForCollectionLiterals() ||
customSettings.FORMAT_INJECTED_FRAGMENTS != formatInjectedFragments() ||
customSettings.ADD_INDENT_INSIDE_INJECTIONS != addIndentInsideInjections();
}
@Override
@@ -154,6 +176,14 @@ public class PyOtherCodeStylePanel extends CodeStyleAbstractPanel {
return myUseContinuationIndentForArguments.isSelected();
}
private boolean formatInjectedFragments() {
return myFormatInjectedFragments.isSelected();
}
private boolean addIndentInsideInjections() {
return myAddIndentInsideInjections.isSelected();
}
protected boolean useContinuationIndentForCollectionLiterals() {
return myUseContinuationIndentForCollectionsAndComprehensions.isSelected();
}