Skip to content

Commit

Permalink
Stop using the Save Actions plugin (broken in IntelliJ 2023.1) and us…
Browse files Browse the repository at this point in the history
…e native format on save (#862)

Stop using the Save Actions plugin (broken in IntelliJ 2023.1) and use native format on save (requires IntelliJ >=2021.2)
  • Loading branch information
CRogers authored Apr 6, 2023
1 parent a8b1268 commit 7697268
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 4 deletions.
6 changes: 6 additions & 0 deletions changelog/@unreleased/pr-862.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type: fix
fix:
description: Stop using the Save Actions plugin (broken in IntelliJ 2023.1) and
use native format on save (requires IntelliJ >=2021.2)
links:
- https://github.com/palantir/palantir-java-format/pull/862
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,47 @@ class ConfigureJavaFormatterXml {
matchOrCreateChild(externalDependencies, 'plugin', [id: 'palantir-java-format'])
}

static void configureFormatOnSave(Node rootNode) {
def formatOnSaveOptions = matchOrCreateChild(rootNode, 'component', [name: 'FormatOnSaveOptions'])


def myRunOnSave = matchOrCreateChild(formatOnSaveOptions, 'option', [name: 'myRunOnSave'])

def myRunOnSaveAlreadySet = Optional.ofNullable(myRunOnSave.attribute('value'))
.map(Boolean::parseBoolean)
.orElse(false)

myRunOnSave.attributes().put('value', 'true')

def myAllFileTypesSelectedAlreadySet = matchChild(formatOnSaveOptions, 'option', [name: 'myAllFileTypesSelected'])
.map { Boolean.parseBoolean(it.attribute('value')) }
.orElse(true)

if (myRunOnSaveAlreadySet && myAllFileTypesSelectedAlreadySet) {
// If the user has already configured IntelliJ to format all file types and turned on formatting on save,
// we leave the configuration as is as it will format java code, and we don't want to disable formatting
// for other file types
return
}

// Otherwise we setup intellij to not format all files...
matchOrCreateChild(formatOnSaveOptions, 'option', [name: 'myAllFileTypesSelected']).attributes().put('value', 'false')

// ...but ensure java is formatted
def mySelectedFileTypes = matchOrCreateChild(formatOnSaveOptions, 'option', [name: 'mySelectedFileTypes'])
def set = matchOrCreateChild(mySelectedFileTypes, 'set')
matchOrCreateChild(set, 'option', [value: 'JAVA'])
}

private static Node matchOrCreateChild(Node base, String name, Map attributes = [:], Map defaults = [:]) {
def child = base[name].find { it.attributes().entrySet().containsAll(attributes.entrySet()) }
if (child) {
return child
matchChild(base, name, attributes).orElseGet {
base.appendNode(name, attributes + defaults)
}
}

private static Optional<Node> matchChild(Node base, String name, Map attributes = [:]) {
def child = base[name].find { it.attributes().entrySet().containsAll(attributes.entrySet()) }

return base.appendNode(name, attributes + defaults)
return Optional.ofNullable(child)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ private static void configureLegacyIdea(Project project, Configuration implConfi
ConfigureJavaFormatterXml.configureJavaFormat(xmlProvider.asNode(), uris);
ConfigureJavaFormatterXml.configureExternalDependencies(xmlProvider.asNode());
});

ideaModel.getWorkspace().getIws().withXml(xmlProvider -> {
ConfigureJavaFormatterXml.configureFormatOnSave(xmlProvider.asNode());
});
}

private static void configureIntelliJImport(Project project, Configuration implConfiguration) {
Expand All @@ -86,10 +90,17 @@ private static void configureIntelliJImport(Project project, Configuration implC
createOrUpdateIdeaXmlFile(
project.file(".idea/externalDependencies.xml"),
node -> ConfigureJavaFormatterXml.configureExternalDependencies(node));
createOrUpdateIdeaXmlFile(
project.file(".idea/workspace.xml"), node -> ConfigureJavaFormatterXml.configureFormatOnSave(node));

// Still configure legacy idea if using intellij import
updateIdeaXmlFileIfExists(project.file(project.getName() + ".ipr"), node -> {
ConfigureJavaFormatterXml.configureJavaFormat(node, uris);
ConfigureJavaFormatterXml.configureExternalDependencies(node);
});
updateIdeaXmlFileIfExists(project.file(project.getName() + ".iws"), node -> {
ConfigureJavaFormatterXml.configureFormatOnSave(node);
});
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,104 @@ class ConfigureJavaFormatterXmlTest extends Specification {
xmlToString(node) == EXPECTED
}

void 'adds FormatOnSave block where none exists'() {
// language=xml
def node = new XmlParser().parseText '''
<root>
</root>
'''.stripIndent(true)

when:
ConfigureJavaFormatterXml.configureFormatOnSave(node)
def newXml = xmlToString(node).strip()

then:
// language=xml
def expected = '''
<root>
<component name="FormatOnSaveOptions">
<option name="myRunOnSave" value="true"/>
<option name="myAllFileTypesSelected" value="false"/>
<option name="mySelectedFileTypes">
<set>
<option value="JAVA"/>
</set>
</option>
</component>
</root>
'''.stripIndent(true).strip()

newXml == expected
}

void 'adds Java to existing FormatOnSave block'() {
// language=xml
def node = new XmlParser().parseText '''
<root>
<component name="FormatOnSaveOptions">
<option name="myRunOnSave" value="true"/>
<option name="myAllFileTypesSelected" value="false"/>
<option name="mySelectedFileTypes">
<set>
<option value="Go"/>
</set>
</option>
</component>
</root>
'''.stripIndent(true)

when:
ConfigureJavaFormatterXml.configureFormatOnSave(node)
def newXml = xmlToString(node).strip()

then:
// language=xml
def expected = '''
<root>
<component name="FormatOnSaveOptions">
<option name="myRunOnSave" value="true"/>
<option name="myAllFileTypesSelected" value="false"/>
<option name="mySelectedFileTypes">
<set>
<option value="Go"/>
<option value="JAVA"/>
</set>
</option>
</component>
</root>
'''.stripIndent(true).strip()

newXml == expected
}

void 'if all file types are already formatted on save, dont change anything'() {
// language=xml
def node = new XmlParser().parseText '''
<root>
<component name="FormatOnSaveOptions">
<option name="myRunOnSave" value="true"/>
<!-- if myAllFileTypesSelected does not exist, it defaults to true -->
</component>
</root>
'''.stripIndent(true)

when:
ConfigureJavaFormatterXml.configureFormatOnSave(node)
def newXml = xmlToString(node).strip()

then:
// language=xml
def expected = '''
<root>
<component name="FormatOnSaveOptions">
<option name="myRunOnSave" value="true"/>
</component>
</root>
'''.stripIndent(true).strip()

newXml == expected
}

static String xmlToString(Node node) {
StringWriter sw = new StringWriter();
XmlNodePrinter nodePrinter = new XmlNodePrinter(new PrintWriter(sw));
Expand Down

0 comments on commit 7697268

Please sign in to comment.