(str);
- }
- if (myDebugDeferredProcessing && isDeferredChangeMode()) {
- String expected = myDebugArray.toString();
- checkStrings("toString()", expected, str);
- }
- return str;
- }
-
- @Override
- public final int length() {
- final int result = myCount + myDeferredShift;
- if (myDebugDeferredProcessing && isDeferredChangeMode()) {
- int expected = myDebugArray.length();
- if (expected != result) {
- dumpDebugInfo(String.format("Incorrect length() processing. Expected: '%s', actual: '%s'", expected, result));
- }
- }
- return result;
- }
-
- @Override
- public final char charAt(int i) {
- if (i < 0 || i >= length()) {
- throw new IndexOutOfBoundsException("Wrong offset: " + i + "; count:" + length());
- }
- i += myStart;
- if (myOriginalSequence != null) return myOriginalSequence.charAt(i);
- final char result;
- if (hasDeferredChanges()) {
- TextChangesStorage storage = myDeferredChangesStorage.get();
- storage.getLock().lock();
- try {
- result = storage.charAt(myArray, i);
- } finally {
- storage.getLock().unlock();
- }
- } else {
- result = myArray[i];
- }
-
- if (myDebugDeferredProcessing && isDeferredChangeMode()) {
- char expected = myDebugArray.charAt(i);
- if (expected != result) {
- dumpDebugInfo(
- String.format("Incorrect charAt() processing for index %d. Expected: '%c', actual: '%c'", i, expected, result)
- );
- }
- }
- return result;
- }
-
- @Override
- public CharSequence subSequence(final int start, final int end) {
- if (start == 0 && end == length()) return this;
- if (myOriginalSequence != null) {
- return myOriginalSequence.subSequence(start, end);
- }
- if (hasDeferredChanges()) {
- return new CharArray(myBufferSize, myDeferredChangesStorage.get(), myArray, myStart + start, myStart + end) {
- @NotNull
- @Override
- protected DocumentEvent beforeChangedUpdate(DocumentImpl subj,
- int offset,
- CharSequence oldString,
- CharSequence newString,
- boolean wholeTextReplaced) {
- return new DocumentEventImpl(subj, offset, oldString, newString, LocalTimeCounter.currentTime(), wholeTextReplaced);
- }
-
- @Override
- protected void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp) {
- }
-
- @Override
- public char[] getChars() {
- char[] chars = CharArray.this.getChars();
- char[] result = new char[end - start];
- System.arraycopy(chars, start, result, 0, result.length);
- return result;
- }
- };
- } else {
- // We don't use the same approach as with 'defer changes' mode because the former is the new experimental one and this one
- // is rather mature, hence, we just minimizes the risks that something is wrong within the new approach.
- return new CharArrayCharSequence(myArray, start, end);
- }
- }
-
- private boolean isSubSequence() {
- return myEnd >= 0;
- }
-
- @Override
- public char[] getChars() {
- if (myOriginalSequence != null) {
- if (myArray == null) {
- myArray = CharArrayUtil.fromSequence(myOriginalSequence);
- }
- }
- flushDeferredChanged(myDeferredChangesStorage.get());
- if (myDebugDeferredProcessing && isDeferredChangeMode()) {
- char[] expected = myDebugArray.getChars();
- for (int i = 0, max = length(); i < max; i++) {
- if (myArray[i] != expected[i]) {
- dumpDebugInfo(String.format("getChars(). Index: %d, expected: %c, actual: %c", i, expected[i], myArray[i]));
- break;
- }
- }
- }
- return myArray;
- }
-
- @Override
- public void getChars(final char[] dst, final int dstOffset) {
- flushDeferredChanged(myDeferredChangesStorage.get());
- if (myOriginalSequence != null) {
- CharArrayUtil.getChars(myOriginalSequence, dst, dstOffset);
- } else {
- System.arraycopy(myArray, myStart, dst, dstOffset, length());
- }
-
- if (myDebugDeferredProcessing && isDeferredChangeMode()) {
- char[] expected = new char[dst.length];
- myDebugArray.getChars(expected, dstOffset);
- for (int i = dstOffset, j = myStart; i < dst.length && j < myArray.length; i++, j++) {
- if (expected[i] != myArray[j]) {
- dumpDebugInfo(String.format("getChars(char[], int). Given array of length %d, offset %d. Found char '%c' at index %d, " +
- "expected to find '%c'", dst.length, dstOffset, myArray[j], i, expected[i]));
- break;
- }
- }
- }
- }
-
- public CharSequence substring(final int start, final int end) {
- if (start == end) return "";
- final CharSequence result;
- if (myOriginalSequence == null) {
- TextChangesStorage storage = myDeferredChangesStorage.get();
- storage.getLock().lock();
- try {
- result = storage.substring(myArray, start + myStart, end + myStart);
- } finally {
- storage.getLock().unlock();
- }
- } else {
- result = myOriginalSequence.subSequence(start, end);
- }
-
- if (myDebugDeferredProcessing && isDeferredChangeMode()) {
- String expected = myDebugArray.substring(start, end).toString();
- checkStrings(String.format("substring(%d, %d)", start, end), expected, result.toString());
- }
- return result;
- }
-
- private static char[] relocateArray(char[] array, int index) {
- if (index < array.length) {
- return array;
- }
-
- int newArraySize = array.length;
- if (newArraySize == 0) {
- newArraySize = 16;
- }
- while (newArraySize <= index) {
- newArraySize = newArraySize * 12 / 10 + 1;
- }
- char[] newArray = new char[newArraySize];
- System.arraycopy(array, 0, newArray, 0, array.length);
- return newArray;
- }
-
- private void trimToSize(DocumentImpl subj) {
- if (myBufferSize != 0 && length() > myBufferSize) {
- flushDeferredChanged(myDeferredChangesStorage.get());
- // make a copy
- remove(subj, 0, myCount - myBufferSize, getCharArray().subSequence(0, myCount - myBufferSize).toString());
- }
- }
-
- /**
- * @return true if this object is at {@link #setDeferredChangeMode(boolean) defer changes} mode;
- * false otherwise
- */
- public boolean isDeferredChangeMode() {
- return !DISABLE_DEFERRED_PROCESSING && myDeferredChangeMode;
- }
-
- public boolean hasDeferredChanges() {
- return !myDeferredChangesStorage.get().isEmpty();
- }
-
- /**
- * There is a possible case that client of this class wants to perform great number of modifications in a short amount of time
- * (e.g. end-user performs formatting of the document backed by the object of the current class). It may result in significant
- * performance degradation is the changes are performed one by one (every time the change is applied tail content is shifted to
- * the left or right). So, we may want to optimize that by avoiding actual array modification until information about
- * all target changes is provided and perform array data moves only after that.
- *
- * This method allows to define that 'defer changes' mode usages, i.e. expected usage pattern is as follows:
- *
- *
- * -
- * Client of this class enters
'defer changes' mode (calls this method with 'true' argument).
- * That means that all subsequent changes will not actually modify backed array data and will be stored separately;
- *
- * -
- * Number of target changes are applied to the current object via standard API
- * ({@link #insert(com.intellij.openapi.editor.impl.DocumentImpl, CharSequence, int) insert},
- * {@link #remove(com.intellij.openapi.editor.impl.DocumentImpl, int, int, CharSequence) remove} and
- * {@link #replace(com.intellij.openapi.editor.impl.DocumentImpl, int, int, CharSequence, CharSequence, long, boolean) replace});
- *
- * -
- * Client of this class indicates that
'massive change time' is over by calling this method with 'false'
- * argument. That flushes all deferred changes (if any) to the backed data array and makes every subsequent change to
- * be immediate flushed to the backed array;
- *
- *
- *
- *
- * Note: we can't exclude possibility that 'defer changes' mode is started but inadvertently not ended
- * (due to programming error, unexpected exception etc). Hence, this class is free to automatically end
- * 'defer changes' mode when necessary in order to avoid memory leak with infinite deferred changes storing.
- *
- * @param deferredChangeMode flag that defines if 'defer changes' mode should be used by the current object
- */
- public void setDeferredChangeMode(boolean deferredChangeMode) {
- if (deferredChangeMode && myDebugDeferredProcessing) {
- myDebugArray.setText(null, myDebugTextOnBatchUpdateStart = toString());
- myDebugDeferredChanges.clear();
- }
- myDeferredChangeMode = deferredChangeMode;
- if (!deferredChangeMode) {
- flushDeferredChanged(myDeferredChangesStorage.get());
- }
- }
-
- private void flushDeferredChanged(@NotNull TextChangesStorage storage) {
- storage.getLock().lock();
- try {
- doFlushDeferredChanged();
- } finally {
- storage.getLock().unlock();
- }
- }
-
- private void doFlushDeferredChanged() {
- TextChangesStorage storage = myDeferredChangesStorage.get();
- List changes = storage.getChanges();
- if (changes.isEmpty()) {
- return;
- }
-
- char[] beforeMerge = null;
- final boolean inPlace;
- if (myDebugDeferredProcessing) {
- beforeMerge = new char[myArray.length];
- System.arraycopy(myArray, 0, beforeMerge, 0, myArray.length);
- }
-
- BulkChangesMerger changesMerger = BulkChangesMerger.INSTANCE;
- if (myArray.length < length()) {
- myArray = changesMerger.mergeToCharArray(myArray, myCount, changes);
- inPlace = false;
- } else {
- changesMerger.mergeInPlace(myArray, myCount, changes);
- inPlace = true;
- }
-
- if (myDebugDeferredProcessing) {
- for (int i = 0, max = length(); i < max; i++) {
- if (myArray[i] != myDebugArray.myArray[i]) {
- dumpDebugInfo(String.format(
- "flushDeferredChanged(). Index %d, expected: '%c', actual '%c'. Text before merge: '%s', merge inplace: %b",
- i, myDebugArray.myArray[i], myArray[i], Arrays.toString(beforeMerge), inPlace));
- break;
- }
- }
- }
-
- myCount += myDeferredShift;
- myDeferredShift = 0;
- storage.clear();
- myDeferredChangeMode = false;
- }
-
- @NotNull
- public String dumpState() {
- return String.format(
- "deferred changes mode: %b, length: %d (data array length: %d, deferred shift: %d); view offsets: [%d; %d]; deferred changes: %s",
- isDeferredChangeMode(), length(), myCount, myDeferredShift, myStart, myEnd, myDeferredChangesStorage
- );
- }
-
- private void checkStrings(@NotNull String operation, @NotNull String expected, @NotNull String actual) {
- if (expected.equals(actual)) {
- return;
- }
- for (int i = 0, max = Math.min(expected.length(), actual.length()); i < max; i++) {
- if (actual.charAt(i) != expected.charAt(i)) {
- dumpDebugInfo(String.format(
- "Incorrect %s processing. Expected length: %d, actual length: %d. Unmatched symbol at %d - expected: '%c', " +
- "actual: '%c', expected document: '%s', actual document: '%s'",
- operation, expected.length(), actual.length(), i, expected.charAt(i), actual.charAt(i), expected, actual
- ));
- return;
- }
- }
- dumpDebugInfo(String.format(
- "Incorrect %s processing. Expected length: %d, actual length: %d, expected: '%s', actual: '%s'",
- operation, expected.length(), actual.length(), expected, actual
- ));
- }
-
- private void dumpDebugInfo(@NotNull String problem) {
- //LOG.error(String.format(
- // "/***********************************************************\n" +
- // " * Please email idea.log to Denis.Zhdanov@jetbrains.com\n" +
- // " ***********************************************************/\n" +
- // "Incorrect CharArray processing detected: '%s'. Start: %d, end: %d, text on batch update start: '%s', deferred changes history: %s, "
- // + "current deferred changes: %s",
- // problem, myStart, myEnd, myDebugTextOnBatchUpdateStart, myDebugDeferredChanges, myDeferredChangesStorage
- //));
- LOG.error(String.format(
- "Incorrect CharArray processing detected: '%s'. Start: %d, end: %d, text on batch update start: '%s', deferred changes history: %s, "
- + "current deferred changes: %s",
- problem, myStart, myEnd, myDebugTextOnBatchUpdateStart, myDebugDeferredChanges, myDeferredChangesStorage
- ));
- }
-}
diff --git a/idea_fix/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java b/idea_fix/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java
deleted file mode 100644
index 35114b8b85e..00000000000
--- a/idea_fix/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.fileEditor.impl;
-
-import com.intellij.lang.properties.charset.Native2AsciiCharset;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.fileTypes.BinaryFileDecompiler;
-import com.intellij.openapi.fileTypes.BinaryFileTypeDecompilers;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.LanguageFileType;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Trinity;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.CharsetToolkit;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.encoding.EncodingRegistry;
-import com.intellij.testFramework.LightVirtualFile;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.text.CharArrayUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.*;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.UnsupportedCharsetException;
-
-public final class LoadTextUtil {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.LoadTextUtil");
- private static final Key DETECTED_LINE_SEPARATOR_KEY = Key.create("DETECTED_LINE_SEPARATOR_KEY");
-
- private LoadTextUtil() {
- }
-
- @NotNull
- private static Pair convertLineSeparators(@NotNull CharBuffer buffer) {
- int dst = 0;
- char prev = ' ';
- int crCount = 0;
- int lfCount = 0;
- int crlfCount = 0;
-
- final int length = buffer.length();
- final char[] bufferArray = CharArrayUtil.fromSequenceWithoutCopying(buffer);
-
- for (int src = 0; src < length; src++) {
- char c = bufferArray != null ? bufferArray[src] : buffer.charAt(src);
- switch (c) {
- case '\r':
- buffer.put(dst++, '\n');
- crCount++;
- break;
- case '\n':
- if (prev == '\r') {
- crCount--;
- crlfCount++;
- } else {
- buffer.put(dst++, '\n');
- lfCount++;
- }
- break;
- default:
- buffer.put(dst++, c);
- break;
- }
- prev = c;
- }
-
- String detectedLineSeparator = null;
- if (crlfCount > crCount && crlfCount > lfCount) {
- detectedLineSeparator = "\r\n";
- } else if (crCount > lfCount) {
- detectedLineSeparator = "\r";
- } else if (lfCount > 0) {
- detectedLineSeparator = "\n";
- }
-
- CharSequence result = buffer.length() == dst ? buffer : buffer.subSequence(0, dst);
- return Pair.create(result, detectedLineSeparator);
- }
-
- private static Charset detectCharset(@NotNull VirtualFile virtualFile, @NotNull byte[] content) {
- if (virtualFile.isCharsetSet()) return virtualFile.getCharset();
-
- Charset charset = doDetectCharset(virtualFile, content);
- charset = charset == null ? EncodingRegistry.getInstance().getDefaultCharset() : charset;
- if (EncodingRegistry.getInstance().isNative2Ascii(virtualFile)) {
- charset = Native2AsciiCharset.wrap(charset);
- }
- virtualFile.setCharset(charset);
- return charset;
- }
-
- @NotNull
- public static Charset detectCharsetAndSetBOM(@NotNull VirtualFile virtualFile, @NotNull byte[] content) {
- return doDetectCharsetAndSetBOM(virtualFile, content).getFirst();
- }
-
- @NotNull
- private static Pair doDetectCharsetAndSetBOM(@NotNull VirtualFile virtualFile, @NotNull byte[] content) {
- Charset charset = detectCharset(virtualFile, content);
- Pair bomAndCharset = getBOMAndCharset(content, charset);
- final byte[] bom = bomAndCharset.second;
- if (bom.length != 0) {
- virtualFile.setBOM(bom);
- }
- return bomAndCharset;
- }
-
- private static Charset doDetectCharset(@NotNull VirtualFile virtualFile, @NotNull byte[] content) {
- Trinity guessed = guessFromContent(virtualFile, content, content.length);
- if (guessed != null && guessed.first != null) return guessed.first;
-
- FileType fileType = virtualFile.getFileType();
- String charsetName = fileType.getCharset(virtualFile, content);
-
- if (charsetName == null) {
- Charset saved = EncodingRegistry.getInstance().getEncoding(virtualFile, true);
- if (saved != null) return saved;
- }
- return CharsetToolkit.forName(charsetName);
- }
-
- @Nullable("null means no luck, otherwise it's tuple(guessed encoding, hint about content if was unable to guess, BOM)")
- public static Trinity guessFromContent(VirtualFile virtualFile, byte[] content, int length) {
- EncodingRegistry settings = EncodingRegistry.getInstance();
- boolean shouldGuess = settings != null && settings.isUseUTFGuessing(virtualFile);
- CharsetToolkit toolkit = shouldGuess ? new CharsetToolkit(content, EncodingRegistry.getInstance().getDefaultCharset()) : null;
- setCharsetWasDetectedFromBytes(virtualFile, false);
- if (shouldGuess) {
- toolkit.setEnforce8Bit(true);
- Charset charset = toolkit.guessFromBOM();
- if (charset != null) {
- setCharsetWasDetectedFromBytes(virtualFile, true);
- byte[] bom = CharsetToolkit.getBom(charset);
- if (bom == null) bom = CharsetToolkit.UTF8_BOM;
- return Trinity.create(charset, null, bom);
- }
- CharsetToolkit.GuessedEncoding guessed = toolkit.guessFromContent(length);
- if (guessed == CharsetToolkit.GuessedEncoding.VALID_UTF8) {
- setCharsetWasDetectedFromBytes(virtualFile, true);
- return Trinity.create(CharsetToolkit.UTF8_CHARSET, null, null); //UTF detected, ignore all directives
- }
- return Trinity.create(null, guessed, null);
- }
- return null;
- }
-
- @NotNull
- private static Pair getBOMAndCharset(@NotNull byte[] content, final Charset charset) {
- if (charset != null && charset.name().contains(CharsetToolkit.UTF8) && CharsetToolkit.hasUTF8Bom(content)) {
- return Pair.create(charset, CharsetToolkit.UTF8_BOM);
- }
- try {
- if (CharsetToolkit.hasUTF16LEBom(content)) {
- return Pair.create(CharsetToolkit.UTF_16LE_CHARSET, CharsetToolkit.UTF16LE_BOM);
- }
- if (CharsetToolkit.hasUTF16BEBom(content)) {
- return Pair.create(CharsetToolkit.UTF_16BE_CHARSET, CharsetToolkit.UTF16BE_BOM);
- }
- } catch (UnsupportedCharsetException ignore) {
- }
- if (charset == null) {
- return Pair.create(Charset.defaultCharset(), CharsetToolkit.UTF8_BOM);
- }
- return Pair.create(charset, ArrayUtil.EMPTY_BYTE_ARRAY);
- }
-
- /**
- * Gets the Writer for this file and sets modification stamp and time stamp to the specified values
- * after closing the Writer.
- *
- * Normally you should not use this method.
- *
- * @param project
- * @param virtualFile
- * @param requestor any object to control who called this method. Note that
- * it is considered to be an external change if requestor is null.
- * See {@link com.intellij.openapi.vfs.VirtualFileEvent#getRequestor}
- * @param text
- * @param newModificationStamp new modification stamp or -1 if no special value should be set @return Writer
- * @throws java.io.IOException if an I/O error occurs
- * @see com.intellij.openapi.vfs.VirtualFile#getModificationStamp()
- */
- @SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
- public static Writer getWriter(@Nullable Project project, @NotNull VirtualFile virtualFile, Object requestor, @NotNull String text, final long newModificationStamp)
- throws IOException {
- Charset existing = virtualFile.getCharset();
- Charset specified = extractCharsetFromFileContent(project, virtualFile, text);
- Charset charset = chooseMostlyHarmlessCharset(existing, specified, text);
- if (charset != null) {
- if (!charset.equals(existing)) {
- virtualFile.setCharset(charset);
- }
- setDetectedFromBytesFlagBack(virtualFile, charset, text);
- }
-
- // in c ase of "UTF-16", OutputStreamWriter sometimes adds BOM on it's own.
- // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6800103
- byte[] bom = virtualFile.getBOM();
- Charset fromBom = bom == null ? null : CharsetToolkit.guessFromBOM(bom);
- if (fromBom != null) charset = fromBom;
-
- OutputStream outputStream = virtualFile.getOutputStream(requestor, newModificationStamp, -1);
- OutputStreamWriter writer = charset == null ? new OutputStreamWriter(outputStream) : new OutputStreamWriter(outputStream, charset);
- // no need to buffer ByteArrayOutputStream
- return outputStream instanceof ByteArrayOutputStream ? writer : new BufferedWriter(writer);
- }
-
- private static void setDetectedFromBytesFlagBack(@NotNull VirtualFile virtualFile, @NotNull Charset charset, @NotNull String text) {
- if (virtualFile.getBOM() != null) {
- // prevent file to be reloaded in other encoding after save with BOM
- setCharsetWasDetectedFromBytes(virtualFile, true);
- return;
- }
-
- byte[] content = text.getBytes(charset);
- CharsetToolkit.GuessedEncoding guessedEncoding = new CharsetToolkit(content).guessFromContent(content.length);
- if (guessedEncoding == CharsetToolkit.GuessedEncoding.VALID_UTF8) {
- setCharsetWasDetectedFromBytes(virtualFile, true);
- }
- }
-
- private static Charset chooseMostlyHarmlessCharset(Charset existing, Charset specified, String text) {
- if (existing == null) return specified;
- if (specified == null) return existing;
- if (specified.equals(existing)) return specified;
- if (isSupported(specified, text)) return specified; //if explicitly specified encoding is safe, return it
- if (isSupported(existing, text)) return existing; //otherwise stick to the old encoding if it's ok
- return specified; //if both are bad there is no difference
- }
-
- private static boolean isSupported(@NotNull Charset charset, @NotNull String str) {
- if (!charset.canEncode()) return false;
- ByteBuffer out = charset.encode(str);
- CharBuffer buffer = charset.decode(out);
- return str.equals(buffer.toString());
- }
-
- public static Charset extractCharsetFromFileContent(@Nullable Project project, @NotNull VirtualFile virtualFile, @NotNull String text) {
- Charset charset = charsetFromContentOrNull(project, virtualFile, text);
- if (charset == null) charset = virtualFile.getCharset();
- return charset;
- }
-
- @Nullable("returns null if cannot determine from content")
- public static Charset charsetFromContentOrNull(@Nullable Project project, @NotNull VirtualFile virtualFile, @NotNull String text) {
- FileType fileType = virtualFile.getFileType();
- if (fileType instanceof LanguageFileType) {
- return ((LanguageFileType) fileType).extractCharsetFromFileContent(project, virtualFile, text);
- }
- return null;
- }
-
- public static CharSequence loadText(@NotNull VirtualFile file) {
- if (file instanceof LightVirtualFile) {
- CharSequence content = ((LightVirtualFile) file).getContent();
- if (StringUtil.indexOf(content, '\r') == -1) return content;
-
- CharBuffer buffer = CharBuffer.allocate(content.length());
- buffer.append(content);
- buffer.rewind();
- return convertLineSeparators(buffer).first;
- }
-
- assert !file.isDirectory() : "'" + file.getPresentableUrl() + "' is directory";
- final FileType fileType = file.getFileType();
-
- if (fileType.isBinary()) {
- final BinaryFileDecompiler decompiler = BinaryFileTypeDecompilers.INSTANCE.forFileType(fileType);
- if (decompiler != null) {
- CharSequence text = decompiler.decompile(file);
- StringUtil.assertValidSeparators(text);
- return text;
- }
-
- throw new IllegalArgumentException("Attempt to load text for binary file, that doesn't have decompiler plugged in: " + file.getPresentableUrl());
- }
-
- try {
- byte[] bytes = file.contentsToByteArray();
- return getTextByBinaryPresentation(bytes, file);
- } catch (IOException e) {
- return ArrayUtil.EMPTY_CHAR_SEQUENCE;
- }
- }
-
- @NotNull
- public static CharSequence getTextByBinaryPresentation(@NotNull final byte[] bytes, @NotNull VirtualFile virtualFile) {
- return getTextByBinaryPresentation(bytes, virtualFile, true);
- }
-
- @NotNull
- public static CharSequence getTextByBinaryPresentation(@NotNull byte[] bytes, @NotNull VirtualFile virtualFile, final boolean rememberDetectedSeparators) {
- Pair pair = doDetectCharsetAndSetBOM(virtualFile, bytes);
- final Charset charset = pair.getFirst();
- byte[] bom = pair.getSecond();
- int offset = bom == null ? 0 : bom.length;
-
- final Pair result = convertBytes(bytes, charset, offset);
- if (rememberDetectedSeparators) {
- virtualFile.putUserData(DETECTED_LINE_SEPARATOR_KEY, result.getSecond());
- }
- return result.getFirst();
- }
-
- /**
- * Get detected line separator, if the file never been loaded, is loaded if checkFile parameter is specified.
- *
- * @param file the file to check
- * @param checkFile if the line separator was not detected before, try to detect it
- * @return the detected line separator or null
- */
- @Nullable
- public static String detectLineSeparator(@NotNull VirtualFile file, boolean checkFile) {
- String lineSeparator = getDetectedLineSeparator(file);
- if (lineSeparator == null && checkFile) {
- try {
- getTextByBinaryPresentation(file.contentsToByteArray(), file);
- lineSeparator = getDetectedLineSeparator(file);
- } catch (IOException e) {
- // null will be returned
- }
- }
- return lineSeparator;
- }
-
- static String getDetectedLineSeparator(@NotNull VirtualFile file) {
- return file.getUserData(DETECTED_LINE_SEPARATOR_KEY);
- }
-
- /**
- * Change line separator for the file to the specified value (assumes that the documents were saved)
- *
- * @param project the project instance
- * @param requestor the requestor for the operation
- * @param file the file to convert
- * @param newLineSeparator the new line separator for the file
- * @throws java.io.IOException in the case of IO problem
- */
- public static void changeLineSeparator(@Nullable Project project,
- @Nullable Object requestor,
- @NotNull VirtualFile file,
- @NotNull String newLineSeparator) throws IOException {
- String lineSeparator = getDetectedLineSeparator(file);
- if (lineSeparator != null && lineSeparator.equals(newLineSeparator)) {
- return;
- }
- CharSequence cs = getTextByBinaryPresentation(file.contentsToByteArray(), file);
- lineSeparator = getDetectedLineSeparator(file);
- if (lineSeparator == null || lineSeparator.equals(newLineSeparator)) {
- return;
- }
- if (!newLineSeparator.equals("\n")) {
- cs = StringUtil.convertLineSeparators(cs.toString(), newLineSeparator);
- }
- String text = cs.toString();
- file.putUserData(DETECTED_LINE_SEPARATOR_KEY, newLineSeparator);
- Writer w = getWriter(project, file, requestor, text, System.currentTimeMillis());
- try {
- w.write(text);
- } finally {
- w.close();
- }
- }
-
- @NotNull
- public static CharSequence getTextByBinaryPresentation(@NotNull byte[] bytes, Charset charset) {
- Pair pair = getBOMAndCharset(bytes, charset);
- byte[] bom = pair.getSecond();
- int offset = bom == null ? 0 : bom.length;
-
- final Pair result = convertBytes(bytes, charset, offset);
- return result.getFirst();
- }
-
- // do not need to think about BOM here. it is processed outside
- @NotNull
- private static Pair convertBytes(@NotNull byte[] bytes, Charset charset, final int startOffset) {
- ByteBuffer byteBuffer = ByteBuffer.wrap(bytes, startOffset, bytes.length - startOffset);
-
- if (charset == null) {
- charset = CharsetToolkit.getDefaultSystemCharset();
- }
- if (charset == null) {
- //noinspection HardCodedStringLiteral
- charset = Charset.forName("ISO-8859-1");
- }
- CharBuffer charBuffer = charset.decode(byteBuffer);
- return convertLineSeparators(charBuffer);
- }
-
- private static final Key CHARSET_WAS_DETECTED_FROM_BYTES = new Key("CHARSET_WAS_DETECTED_FROM_BYTES");
-
- public static boolean wasCharsetDetectedFromBytes(@NotNull VirtualFile virtualFile) {
- return virtualFile.getUserData(CHARSET_WAS_DETECTED_FROM_BYTES) != null;
- }
-
- public static void setCharsetWasDetectedFromBytes(@NotNull VirtualFile virtualFile, boolean flag) {
- virtualFile.putUserData(CHARSET_WAS_DETECTED_FROM_BYTES, flag ? Boolean.TRUE : null);
- }
-}
diff --git a/idea_fix/src/com/intellij/openapi/util/IconLoader.java b/idea_fix/src/com/intellij/openapi/util/IconLoader.java
deleted file mode 100644
index 70c739fed80..00000000000
--- a/idea_fix/src/com/intellij/openapi/util/IconLoader.java
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright 2000-2011 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.util;
-
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.reference.SoftReference;
-import com.intellij.util.ImageLoader;
-import com.intellij.util.containers.ConcurrentHashMap;
-import com.intellij.util.containers.WeakHashMap;
-import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.lang.ref.Reference;
-import java.net.URL;
-import java.util.Map;
-
-//import sun.reflect.Reflection;
-
-public final class IconLoader {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.IconLoader");
-
- @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
- private static final ConcurrentHashMap ourIconsCache = new ConcurrentHashMap(100, 0.9f, 2);
-
- /**
- * This cache contains mapping between icons and disabled icons.
- */
- private static final Map ourIcon2DisabledIcon = new WeakHashMap(200);
-
- private static final ImageIcon EMPTY_ICON = new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR)) {
- @NonNls
- public String toString() {
- return "Empty icon " + super.toString();
- }
- };
-
- private static boolean ourIsActivated = false;
-
- private IconLoader() {
- }
-
- @Deprecated
- public static Icon getIcon(@NotNull final Image image) {
- return new MyImageIcon(image);
- }
-
- @NotNull
- public static Icon getIcon(@NonNls final String path) {
- int stackFrameCount = 2;
- return IconLoader.EMPTY_ICON;
- /*Class callerClass = Reflection.getCallerClass(stackFrameCount);
- while (callerClass != null && callerClass.getClassLoader() == null) { // looks like a system class
- callerClass = Reflection.getCallerClass(++stackFrameCount);
- }
- if (callerClass == null) {
- callerClass = Reflection.getCallerClass(1);
- }
- return getIcon(path, callerClass);*/
- }
-
- @Nullable
- /**
- * Might return null if icon was not found.
- * Use only if you expected null return value, otherwise see {@link com.intellij.openapi.util.IconLoader#getIcon(String)}
- */
- public static Icon findIcon(@NonNls final String path) {
- int stackFrameCount = 2;
- return IconLoader.EMPTY_ICON;
- /*Class callerClass = Reflection.getCallerClass(stackFrameCount);
- while (callerClass != null && callerClass.getClassLoader() == null) { // looks like a system class
- callerClass = Reflection.getCallerClass(++stackFrameCount);
- }
- if (callerClass == null) {
- callerClass = Reflection.getCallerClass(1);
- }
- return findIcon(path, callerClass);*/
- }
-
- @NotNull
- public static Icon getIcon(@NotNull String path, @NotNull final Class aClass) {
- final Icon icon = findIcon(path, aClass);
- if (icon == null) {
- LOG.error("Icon cannot be found in '" + path + "', aClass='" + aClass + "'");
- }
- return icon;
- }
-
- public static void activate() {
- ourIsActivated = true;
- }
-
- private static boolean isLoaderDisabled() {
- return !ourIsActivated;
- }
-
- /**
- * Might return null if icon was not found.
- * Use only if you expected null return value, otherwise see {@link com.intellij.openapi.util.IconLoader#getIcon(String, Class)}
- */
- @Nullable
- public static Icon findIcon(@NotNull final String path, @NotNull final Class aClass) {
- return findIcon(path, aClass, false);
- }
-
- public static Icon findIcon(@NotNull final String path, @NotNull final Class aClass, boolean computeNow) {
- /*final ByClass icon = new ByClass(aClass, path);
-
- if (computeNow || !Registry.is("ide.lazyIconLoading", true)) {
- return icon.getOrComputeIcon();
- }
-
- return icon;*/
- return IconLoader.EMPTY_ICON;
- }
-
- @Nullable
- private static Icon findIcon(URL url) {
- if (url == null) return null;
- Icon icon = ourIconsCache.get(url);
- if (icon == null) {
- icon = new CachedImageIcon(url);
- icon = ourIconsCache.cacheOrGet(url, icon);
- }
- return icon;
- }
-
- @Nullable
- public static Icon findIcon(final String path, final ClassLoader aClassLoader) {
- if (!path.startsWith("/")) return null;
-
- final URL url = aClassLoader.getResource(path.substring(1));
- return findIcon(url);
- }
-
- @Nullable
- private static Icon checkIcon(final Image image, URL url) {
- if (image == null || image.getHeight(LabelHolder.ourFakeComponent) < 1) { // image wasn't loaded or broken
- return null;
- }
-
- final Icon icon = getIcon(image);
- if (icon != null && !isGoodSize(icon)) {
- LOG.error("Invalid icon: " + url); // # 22481
- return EMPTY_ICON;
- }
- return icon;
- }
-
- public static boolean isGoodSize(@NotNull final Icon icon) {
- return icon.getIconWidth() > 0 && icon.getIconHeight() > 0;
- }
-
- /**
- * Gets (creates if necessary) disabled icon based on the passed one.
- *
- * @param icon
- * @return ImageIcon constructed from disabled image of passed icon.
- */
- @Nullable
- public static Icon getDisabledIcon(final Icon icon) {
- if (icon == null) {
- return null;
- }
- Icon disabledIcon = ourIcon2DisabledIcon.get(icon);
- if (disabledIcon == null) {
- if (!isGoodSize(icon)) {
- LOG.error(icon); // # 22481
- return EMPTY_ICON;
- }
- final BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
- final Graphics2D graphics = image.createGraphics();
-
- graphics.setColor(UIUtil.TRANSPARENT_COLOR);
- graphics.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight());
- icon.paintIcon(LabelHolder.ourFakeComponent, graphics, 0, 0);
-
- graphics.dispose();
-
- disabledIcon = new MyImageIcon(GrayFilter.createDisabledImage(image));
- ourIcon2DisabledIcon.put(icon, disabledIcon);
- }
- return disabledIcon;
- }
-
- public static Icon getTransparentIcon(final Icon icon) {
- return getTransparentIcon(icon, 0.5f);
- }
-
- public static Icon getTransparentIcon(final Icon icon, final float alpha) {
- return new Icon() {
- public int getIconHeight() {
- return icon.getIconHeight();
- }
-
- public int getIconWidth() {
- return icon.getIconWidth();
- }
-
- public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
- final Graphics2D g2 = (Graphics2D) g;
- final Composite saveComposite = g2.getComposite();
- g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
- icon.paintIcon(c, g2, x, y);
- g2.setComposite(saveComposite);
- }
- };
- }
-
- private static final class CachedImageIcon implements Icon {
- private Object myRealIcon;
- private final URL myUrl;
-
- public CachedImageIcon(URL url) {
- myUrl = url;
- }
-
- private synchronized Icon getRealIcon() {
- if (isLoaderDisabled()) return EMPTY_ICON;
-
- if (myRealIcon instanceof Icon) return (Icon) myRealIcon;
-
- Icon icon;
- if (myRealIcon instanceof Reference) {
- icon = ((Reference) myRealIcon).get();
- if (icon != null) return icon;
- }
-
- Image image = ImageLoader.loadFromUrl(myUrl);
- icon = checkIcon(image, myUrl);
-
- if (icon != null) {
- if (icon.getIconWidth() < 50 && icon.getIconHeight() < 50) {
- myRealIcon = icon;
- } else {
- myRealIcon = new SoftReference(icon);
- }
- }
-
- return icon != null ? icon : EMPTY_ICON;
- }
-
- public void paintIcon(Component c, Graphics g, int x, int y) {
- getRealIcon().paintIcon(c, g, x, y);
- }
-
- public int getIconWidth() {
- return getRealIcon().getIconWidth();
- }
-
- public int getIconHeight() {
- return getRealIcon().getIconHeight();
- }
- }
-
- private static final class MyImageIcon extends ImageIcon {
- public MyImageIcon(final Image image) {
- super(image);
- }
-
- public final synchronized void paintIcon(final Component c, final Graphics g, final int x, final int y) {
- super.paintIcon(null, g, x, y);
- }
- }
-
- public abstract static class LazyIcon implements Icon {
- private boolean myWasComputed;
- private Icon myIcon;
-
- @Override
- public void paintIcon(Component c, Graphics g, int x, int y) {
- final Icon icon = getOrComputeIcon();
- if (icon != null) {
- icon.paintIcon(c, g, x, y);
- }
- }
-
- @Override
- public int getIconWidth() {
- final Icon icon = getOrComputeIcon();
- return icon != null ? icon.getIconWidth() : 0;
- }
-
- @Override
- public int getIconHeight() {
- final Icon icon = getOrComputeIcon();
- return icon != null ? icon.getIconHeight() : 0;
- }
-
- protected synchronized final Icon getOrComputeIcon() {
- if (!myWasComputed) {
- myWasComputed = true;
- myIcon = compute();
- }
-
- return myIcon;
- }
-
- public final void load() {
- getIconWidth();
- }
-
- protected abstract Icon compute();
- }
-
- private static class ByClass extends LazyIcon {
- private final Class myCallerClass;
- private final String myPath;
-
- public ByClass(Class aClass, String path) {
- myCallerClass = aClass;
- myPath = path;
- }
-
- @Override
- protected Icon compute() {
- URL url = myCallerClass.getResource(myPath);
- return findIcon(url);
- }
-
- @Override
- public String toString() {
- return "icon path=" + myPath + " class=" + myCallerClass;
- }
- }
-
- private static class LabelHolder {
- /**
- * To get disabled icon with paint it into the image. Some icons require
- * not null component to paint.
- */
- private static final JComponent ourFakeComponent = new JLabel();
- }
-}
diff --git a/idea_fix/src/com/intellij/openapi/util/UserDataHolderBase.java b/idea_fix/src/com/intellij/openapi/util/UserDataHolderBase.java
deleted file mode 100644
index 7c7b4fa3c56..00000000000
--- a/idea_fix/src/com/intellij/openapi/util/UserDataHolderBase.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.util;
-
-
-//import com.intellij.util.concurrency.AtomicFieldUpdater;
-
-import com.intellij.util.containers.StripedLockConcurrentHashMap;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
-
-import java.util.ConcurrentModificationException;
-import java.util.Map;
-import java.util.concurrent.ConcurrentMap;
-
-public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
- private static final Key