mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
skip BOM for source root detection (IDEA-77278, IDEA-98541)
This commit is contained in:
+16
-4
@@ -17,15 +17,15 @@ package com.intellij.ide.util.projectWizard.importSources.util;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.text.CharsetUtil;
|
||||
import com.intellij.util.text.StringFactory;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
|
||||
public abstract class CommonSourceRootDetectionUtil<F> {
|
||||
|
||||
@@ -98,7 +98,7 @@ public abstract class CommonSourceRootDetectionUtil<F> {
|
||||
|
||||
@Override
|
||||
protected CharSequence loadText(final File file) throws IOException {
|
||||
return StringFactory.createShared(FileUtil.loadFileText(file));
|
||||
return StringFactory.createShared(loadFileTextSkippingBom(file));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,6 +107,18 @@ public abstract class CommonSourceRootDetectionUtil<F> {
|
||||
}
|
||||
};
|
||||
|
||||
private static char[] loadFileTextSkippingBom(File file) throws IOException {
|
||||
//noinspection IOResourceOpenedButNotSafelyClosed
|
||||
InputStream stream = CharsetUtil.inputStreamSkippingBOM(new BufferedInputStream(new FileInputStream(file)));
|
||||
Reader reader = new InputStreamReader(stream);
|
||||
try {
|
||||
return FileUtilRt.loadText(reader, (int)file.length());
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static final CommonSourceRootDetectionUtil<VirtualFile> VIRTUAL_FILE = new CommonSourceRootDetectionUtil<VirtualFile>() {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com;
|
||||
|
||||
public class MyClass {
|
||||
|
||||
}
|
||||
@@ -54,6 +54,10 @@ public class JavaSourceRootDetectionTest extends PlatformTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testFileWithBom() {
|
||||
doTest("src", "");
|
||||
}
|
||||
|
||||
private void doTest(String... expected) {
|
||||
final String dirPath = JavaTestUtil.getJavaTestDataPath() + FileUtil.toSystemDependentName("/ide/sourceRootDetection/" + getTestName(true));
|
||||
final File dir = new File(dirPath);
|
||||
|
||||
@@ -546,99 +546,11 @@ public class CharsetToolkit {
|
||||
return charset;
|
||||
}
|
||||
|
||||
private static final byte FF = (byte)0xff;
|
||||
private static final byte FE = (byte)0xfe;
|
||||
private static final byte EF = (byte)0xef;
|
||||
private static final byte BB = (byte)0xbb;
|
||||
private static final byte BF = (byte)0xbf;
|
||||
/**
|
||||
* @deprecated use {@link CharsetUtil#inputStreamSkippingBOM(java.io.InputStream)} instead
|
||||
*/
|
||||
@NotNull
|
||||
public static InputStream inputStreamSkippingBOM(@NotNull InputStream stream) throws IOException {
|
||||
assert stream.markSupported() :stream;
|
||||
stream.mark(4);
|
||||
boolean mustReset = true;
|
||||
try {
|
||||
int ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b0 = (byte)ret;
|
||||
if (b0 != EF && b0 != FF && b0 != FE && b0 != 0) return stream; // no bom
|
||||
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b1 = (byte)ret;
|
||||
if (b0 == FF && b1 == FE) {
|
||||
stream.mark(2);
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // utf-16 LE
|
||||
}
|
||||
byte b2 = (byte)ret;
|
||||
if (b2 != 0) {
|
||||
return stream; // utf-16 LE
|
||||
}
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream;
|
||||
}
|
||||
byte b3 = (byte)ret;
|
||||
if (b3 != 0) {
|
||||
return stream; // utf-16 LE
|
||||
}
|
||||
|
||||
// utf-32 LE
|
||||
mustReset = false;
|
||||
return stream;
|
||||
}
|
||||
if (b0 == FE && b1 == FF) {
|
||||
mustReset = false;
|
||||
return stream; // utf-16 BE
|
||||
}
|
||||
if (b0 == EF && b1 == BB) {
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b2 = (byte)ret;
|
||||
if (b2 == BF) {
|
||||
mustReset = false;
|
||||
return stream; // utf-8 bom
|
||||
}
|
||||
|
||||
// no bom
|
||||
return stream;
|
||||
}
|
||||
|
||||
if (b0 == 0 && b1 == 0) {
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b2 = (byte)ret;
|
||||
if (b2 != FE) {
|
||||
return stream; // no bom
|
||||
}
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b3 = (byte)ret;
|
||||
if (b3 != FF) {
|
||||
return stream; // no bom
|
||||
}
|
||||
|
||||
mustReset = false;
|
||||
return stream; // UTF-32 BE
|
||||
}
|
||||
|
||||
// no bom
|
||||
return stream;
|
||||
}
|
||||
finally {
|
||||
if (mustReset) stream.reset();
|
||||
}
|
||||
return CharsetUtil.inputStreamSkippingBOM(stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.util.Function;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.DistinctRootsCollection;
|
||||
import com.intellij.util.text.CharsetUtil;
|
||||
import com.intellij.util.text.StringFactory;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -165,7 +166,7 @@ public class VfsUtilCore {
|
||||
|
||||
@NotNull
|
||||
public static InputStream inputStreamSkippingBOM(@NotNull InputStream stream, @NotNull VirtualFile file) throws IOException {
|
||||
return CharsetToolkit.inputStreamSkippingBOM(stream);
|
||||
return CharsetUtil.inputStreamSkippingBOM(stream);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -17,7 +17,10 @@ package com.intellij.util.text;
|
||||
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
@@ -26,6 +29,11 @@ import java.io.UnsupportedEncodingException;
|
||||
public class CharsetUtil {
|
||||
public static final byte[] UTF8_BOM = {0xffffffef, 0xffffffbb, 0xffffffbf};
|
||||
@NonNls public static final String UTF8 = "UTF-8";
|
||||
private static final byte FF = (byte)0xff;
|
||||
private static final byte FE = (byte)0xfe;
|
||||
private static final byte EF = (byte)0xef;
|
||||
private static final byte BB = (byte)0xbb;
|
||||
private static final byte BF = (byte)0xbf;
|
||||
|
||||
public static boolean hasUTF8Bom(byte[] bom) {
|
||||
return ArrayUtil.startsWith(bom, UTF8_BOM);
|
||||
@@ -39,4 +47,94 @@ public class CharsetUtil {
|
||||
throw new RuntimeException("UTF-8 must be supported", e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static InputStream inputStreamSkippingBOM(@NotNull InputStream stream) throws IOException {
|
||||
assert stream.markSupported() :stream;
|
||||
stream.mark(4);
|
||||
boolean mustReset = true;
|
||||
try {
|
||||
int ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b0 = (byte)ret;
|
||||
if (b0 != EF && b0 != FF && b0 != FE && b0 != 0) return stream; // no bom
|
||||
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b1 = (byte)ret;
|
||||
if (b0 == FF && b1 == FE) {
|
||||
stream.mark(2);
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // utf-16 LE
|
||||
}
|
||||
byte b2 = (byte)ret;
|
||||
if (b2 != 0) {
|
||||
return stream; // utf-16 LE
|
||||
}
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream;
|
||||
}
|
||||
byte b3 = (byte)ret;
|
||||
if (b3 != 0) {
|
||||
return stream; // utf-16 LE
|
||||
}
|
||||
|
||||
// utf-32 LE
|
||||
mustReset = false;
|
||||
return stream;
|
||||
}
|
||||
if (b0 == FE && b1 == FF) {
|
||||
mustReset = false;
|
||||
return stream; // utf-16 BE
|
||||
}
|
||||
if (b0 == EF && b1 == BB) {
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b2 = (byte)ret;
|
||||
if (b2 == BF) {
|
||||
mustReset = false;
|
||||
return stream; // utf-8 bom
|
||||
}
|
||||
|
||||
// no bom
|
||||
return stream;
|
||||
}
|
||||
|
||||
if (b0 == 0 && b1 == 0) {
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b2 = (byte)ret;
|
||||
if (b2 != FE) {
|
||||
return stream; // no bom
|
||||
}
|
||||
ret = stream.read();
|
||||
if (ret == -1) {
|
||||
return stream; // no bom
|
||||
}
|
||||
byte b3 = (byte)ret;
|
||||
if (b3 != FF) {
|
||||
return stream; // no bom
|
||||
}
|
||||
|
||||
mustReset = false;
|
||||
return stream; // UTF-32 BE
|
||||
}
|
||||
|
||||
// no bom
|
||||
return stream;
|
||||
}
|
||||
finally {
|
||||
if (mustReset) stream.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user