From c732e372380302efde9083e5b8cf0a121e69fd10 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 5 Jun 2020 18:43:46 +0300 Subject: [PATCH] Do not overwrite detected line separator with null if no line breaks are found in (an empty) file to fix IDEA-242677 Unable to set line separator for empty file GitOrigin-RevId: cb3fd7c2bd49bd43335a8d8adbe2fbef94a69388 --- .../openapi/fileEditor/impl/LoadTextUtil.java | 35 ++++++++++++------- .../ConvertLineSeparatorsActionTest.java | 28 ++++++++++++++- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java b/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java index 923a5b00259d..4d92c568fe8d 100644 --- a/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java +++ b/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java @@ -533,12 +533,7 @@ public final class LoadTextUtil { boolean saveDetectedSeparators, boolean saveBOM) { DetectResult info = detectInternalCharsetAndSetBOM(virtualFile, bytes, bytes.length, saveBOM, virtualFile.getFileType()); - byte[] bom = info.BOM; - ConvertResult result = convertBytes(bytes, Math.min(bom == null ? 0 : bom.length, bytes.length), bytes.length, - info.hardCodedCharset); - if (saveDetectedSeparators) { - virtualFile.setDetectedLineSeparator(result.majorLineSeparator()); - } + ConvertResult result = convertBytesAndSetSeparator(bytes, bytes.length, virtualFile, saveDetectedSeparators, info, info.hardCodedCharset); return result.text; } @@ -574,17 +569,33 @@ public final class LoadTextUtil { toProcess = null; } else { - byte[] bom = info.BOM; - int BOMEndOffset = Math.min(length, bom == null ? 0 : bom.length); - ConvertResult result = convertBytes(bytes, BOMEndOffset, length, internalCharset); - if (saveDetectedSeparators) { - virtualFile.setDetectedLineSeparator(result.majorLineSeparator()); - } + ConvertResult result = + convertBytesAndSetSeparator(bytes, length, virtualFile, saveDetectedSeparators, info, internalCharset); toProcess = result.text; } return fileTextProcessor.fun(toProcess); } + @NotNull + private static ConvertResult convertBytesAndSetSeparator(byte @NotNull [] bytes, + int length, + @NotNull VirtualFile virtualFile, + boolean saveDetectedSeparators, + @NotNull DetectResult info, + @NotNull Charset internalCharset) { + byte[] bom = info.BOM; + int BOMEndOffset = Math.min(length, bom == null ? 0 : bom.length); + ConvertResult result = convertBytes(bytes, BOMEndOffset, length, internalCharset); + if (saveDetectedSeparators) { + String separator = result.majorLineSeparator(); + // when in doubt, leave old separator + if (separator != null) { + virtualFile.setDetectedLineSeparator(separator); + } + } + return result; + } + /** * Get detected line separator, if the file never been loaded, is loaded if checkFile parameter is specified. * diff --git a/platform/platform-tests/testSrc/com/intellij/codeStyle/ConvertLineSeparatorsActionTest.java b/platform/platform-tests/testSrc/com/intellij/codeStyle/ConvertLineSeparatorsActionTest.java index 478ee680633a..341a1f182782 100644 --- a/platform/platform-tests/testSrc/com/intellij/codeStyle/ConvertLineSeparatorsActionTest.java +++ b/platform/platform-tests/testSrc/com/intellij/codeStyle/ConvertLineSeparatorsActionTest.java @@ -5,13 +5,20 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.impl.SimpleDataContext; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.impl.LoadTextUtil; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.HeavyPlatformTestCase; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; public class ConvertLineSeparatorsActionTest extends HeavyPlatformTestCase { public void testLF2CRLF() throws IOException { @@ -27,12 +34,31 @@ public class ConvertLineSeparatorsActionTest extends HeavyPlatformTestCase { checkConvert("a\r\nb", new ConvertToMacLineSeparatorsAction(), "a\rb"); } - private void checkConvert(String oldContent, AbstractConvertLineSeparatorsAction action, String expectedContent) throws IOException { + @NotNull + private VirtualFile checkConvert(@NotNull String oldContent, @NotNull AbstractConvertLineSeparatorsAction action, @NotNull String expectedContent) throws IOException { VirtualFile vf = createTempFile("txt", null, oldContent, CharsetToolkit.UTF8_CHARSET); DataContext context = SimpleDataContext .getSimpleContext(CommonDataKeys.VIRTUAL_FILE_ARRAY.getName(), new VirtualFile[]{vf}, SimpleDataContext.getProjectContext(getProject())); action.actionPerformed(AnActionEvent.createFromDataContext("", null, context)); String newContent = FileUtil.loadFile(new File(vf.getPath())); assertEquals(expectedContent, newContent); + return vf; + } + + public void testChangeLineSeparatorOnEmptyFileShouldPersist() throws IOException { + VirtualFile vf = createTempFile("txt", null, "", CharsetToolkit.UTF8_CHARSET); + String separator = FileDocumentManager.getInstance().getLineSeparator(vf, getProject()); + AbstractConvertLineSeparatorsAction action = separator.equals("\n") ? new ConvertToWindowsLineSeparatorsAction() : new ConvertToUnixLineSeparatorsAction(); + + VirtualFile file = checkConvert("", action, ""); + String newSeparator = FileDocumentManager.getInstance().getLineSeparator(file, getProject()); + String expectedSeparator = separator.equals("\n") ? "\r\n" : "\n"; + assertEquals(expectedSeparator, newSeparator); + Document document = FileDocumentManager.getInstance().getDocument(file); + + WriteAction.run(() -> document.setText("a\nb")); + FileDocumentManager.getInstance().saveAllDocuments(); + assertEquals("a\nb", LoadTextUtil.loadText(file).toString()); + assertEquals(StringUtil.toHexString(("a" + expectedSeparator + "b").getBytes(StandardCharsets.UTF_8)), StringUtil.toHexString(file.contentsToByteArray())); } }