[code-style] Fix post-processing logic and tests

GitOrigin-RevId: 99d867a00a4f0a9e285ad1836d77ee92c881fab1
This commit is contained in:
Rustam Vishniakov
2023-01-27 17:42:47 +00:00
committed by intellij-monorepo-bot
parent a1a10b4760
commit 24fe58f18d
3 changed files with 57 additions and 36 deletions
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -40,30 +41,49 @@ public final class CoreCodeStyleUtil {
private CoreCodeStyleUtil() {
}
public static PsiElement postProcessElement(@NotNull PsiFile file, @NotNull final PsiElement formatted, boolean isWhitespaceOnly) {
PsiElement result = formatted;
public static PsiElement postProcessElement(@NotNull PsiFile file, @NotNull final PsiElement element, boolean isWhitespaceOnly) {
CodeStyleSettings settingsForFile = CodeStyle.getSettings(file);
if (settingsForFile.FORMATTER_TAGS_ENABLED && formatted instanceof PsiFile) {
postProcessEnabledRanges((PsiFile)formatted, formatted.getTextRange(), settingsForFile, isWhitespaceOnly);
List<TextRange> textRanges;
if (settingsForFile.FORMATTER_TAGS_ENABLED) {
FormatterTagHandler tagHandler = new FormatterTagHandler(settingsForFile);
textRanges = tagHandler.getEnabledRanges(file.getNode(), file.getTextRange());
}
else {
boolean brokenProcFound = false;
for (PostFormatProcessor postFormatProcessor : getPostProcessors(isWhitespaceOnly)) {
try {
result = postFormatProcessor.processElement(result, settingsForFile);
if (!result.isValid() && !brokenProcFound) {
LOG.error(new RuntimeExceptionWithAttachments(String.format("PSI crash detected: processor=%s, result=%s", postFormatProcessor,
result), new Attachment("text", result.getText())));
brokenProcFound = true;
}
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
LOG.error(PluginException.createByClass(e, postFormatProcessor.getClass()));
textRanges = Collections.singletonList(element.getTextRange());
}
for (TextRange range : textRanges) {
if (range.contains(element.getTextRange())) {
PsiElement currElement = element;
for (PostFormatProcessor postFormatProcessor : getPostProcessors(isWhitespaceOnly)) {
if (currElement == null) break;
currElement = processElementOrFail(postFormatProcessor, currElement, settingsForFile);
}
return currElement;
}
else if (range.intersects(element.getTextRange())) {
postProcessRange(file, element.getTextRange().intersection(range), settingsForFile, isWhitespaceOnly);
}
}
return element;
}
private static @Nullable PsiElement processElementOrFail(@NotNull PostFormatProcessor processor,
@NotNull PsiElement element,
@NotNull CodeStyleSettings settings) {
PsiElement result = element;
try {
result = processor.processElement(result, settings);
if (!result.isValid()) {
LOG.error(new RuntimeExceptionWithAttachments(String.format("PSI crash detected: processor=%s, result=%s", processor,
result), new Attachment("text", result.getText())));
return null;
}
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
LOG.error(PluginException.createByClass(e, processor.getClass()));
}
return result;
}
@@ -98,14 +118,12 @@ public final class CoreCodeStyleUtil {
}
public static void postProcessText(@NotNull final PsiFile file, @NotNull final TextRange textRange, boolean isWhitespaceOnly) {
CodeStyleSettings settings = CodeStyle.getSettings(file);
if (!getSettings(file).FORMATTER_TAGS_ENABLED) {
TextRange currentRange = textRange;
for (final PostFormatProcessor myPostFormatProcessor : getPostProcessors(isWhitespaceOnly)) {
currentRange = myPostFormatProcessor.processText(file, currentRange, getSettings(file));
}
postProcessRange(file, textRange, settings, isWhitespaceOnly);
}
else {
postProcessEnabledRanges(file, textRange, getSettings(file), isWhitespaceOnly);
postProcessEnabledRanges(file, textRange, settings, isWhitespaceOnly);
}
}
@@ -117,13 +135,20 @@ public final class CoreCodeStyleUtil {
int delta = 0;
for (TextRange enabledRange : enabledRanges) {
enabledRange = enabledRange.shiftRight(delta);
for (PostFormatProcessor processor : getPostProcessors(isWhitespaceOnly)) {
TextRange processedRange = processor.processText(file, enabledRange, settings);
delta += processedRange.getLength() - enabledRange.getLength();
}
TextRange processedRange = postProcessRange(file, enabledRange, settings, isWhitespaceOnly);
delta += processedRange.getLength() - enabledRange.getLength();
}
}
private static TextRange postProcessRange(@NotNull PsiFile file, @NotNull TextRange textRange,
@NotNull CodeStyleSettings settings, boolean isWhitespaceOnly) {
TextRange currentRange = textRange;
for (final PostFormatProcessor myPostFormatProcessor : getPostProcessors(isWhitespaceOnly)) {
currentRange = myPostFormatProcessor.processText(file, currentRange, settings);
}
return currentRange;
}
public static class RangeFormatInfo {
private final PsiFile myFile;
private final SmartPsiElementPointer<?> startPointer;
@@ -15,6 +15,7 @@ import org.jdom.Element
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.junit.jupiter.api.Assertions.assertTrue
internal class CodeStyleTest {
companion object {
@@ -191,16 +192,11 @@ internal class CodeStyleTest {
<option name="RIGHT_MARGIN" value="64" />
<option name="USE_FQ_CLASS_NAMES_IN_JAVADOC" value="false" />
</code_scheme>""".trimIndent()
val expected = """
<code_scheme name="testSchemeName" version="${CodeStyleSettings.CURR_VERSION}">
<option name="RIGHT_MARGIN" value="64" />
</code_scheme>""".trimIndent()
settings.readExternal(JDOMUtil.load(initial))
settings.resetDeprecatedFields()
val serialized = Element("code_scheme").setAttribute("name", "testSchemeName")
settings.writeExternal(serialized)
assertThat(serialized).isEqualTo(expected)
@Suppress("removal", "DEPRECATION") // Test use
assertTrue(settings.USE_FQ_CLASS_NAMES_IN_JAVADOC)
}
}
@@ -7,7 +7,7 @@
"formatter_off_tag": "@formatter:off",
"formatter_on_tag": "@formatter:on",
"formatter_tags_accept_regexp": false,
"formatter_tags_enabled": false,
"formatter_tags_enabled": true,
"indent_size": 4,
"indent_style": "space",
"max_line_length": 120,