@Nullable
  public ProblemDescriptor[] checkFile(
      @NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
    if (InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file))
      return null;
    if (ArrayUtil.find(file.getPsiRoots(), file) != 0) return null;
    if (!file.isPhysical()) return null;
    VirtualFile virtualFile = file.getVirtualFile();
    if (virtualFile == null) return null;
    if (virtualFile.getFileSystem() != LocalFileSystem.getInstance()
        // tests
        && virtualFile.getFileSystem() != TempFileSystem.getInstance()) return null;
    String text = file.getText();
    Charset charset =
        LoadTextUtil.extractCharsetFromFileContent(file.getProject(), virtualFile, text);

    // no sense in checking transparently decoded file: all characters there are already safely
    // encoded
    if (charset instanceof Native2AsciiCharset) return null;

    List<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
    checkIfCharactersWillBeLostAfterSave(file, manager, isOnTheFly, text, charset, descriptors);
    checkFileLoadedInWrongEncoding(file, manager, isOnTheFly, virtualFile, charset, descriptors);

    return descriptors.toArray(new ProblemDescriptor[descriptors.size()]);
  }
 @Override
 public void visitFile(PsiFile file) {
   super.visitFile(file);
   if (InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)
       || !file.isPhysical()) {
     return;
   }
   final VirtualFile virtualFile = file.getVirtualFile();
   final String text = file.getText();
   final Charset charset =
       LoadTextUtil.extractCharsetFromFileContent(file.getProject(), virtualFile, text);
   final CharsetEncoder encoder =
       charset.newEncoder().onUnmappableCharacter(CodingErrorAction.REPORT);
   final CharBuffer charBuffer = CharBuffer.allocate(1);
   final ByteBuffer byteBuffer = ByteBuffer.allocate(10);
   final int length = text.length();
   for (int i = 0; i < length; i++) {
     final char c = text.charAt(i);
     if (c != '\\') {
       continue;
     }
     boolean isEscape = true;
     int previousChar = i - 1;
     while (previousChar >= 0 && text.charAt(previousChar) == '\\') {
       isEscape = !isEscape;
       previousChar--;
     }
     if (!isEscape) {
       continue;
     }
     int nextChar = i;
     do {
       nextChar++;
       if (nextChar >= length) {
         break;
       }
     } while (text.charAt(nextChar) == 'u'); // \uuuu0061 is a legal unicode escape
     if (nextChar == i + 1 || nextChar + 3 >= length) {
       continue;
     }
     if (StringUtil.isHexDigit(text.charAt(nextChar))
         && StringUtil.isHexDigit(text.charAt(nextChar + 1))
         && StringUtil.isHexDigit(text.charAt(nextChar + 2))
         && StringUtil.isHexDigit(text.charAt(nextChar + 3))) {
       final int escapeEnd = nextChar + 4;
       final char d = (char) Integer.parseInt(text.substring(nextChar, escapeEnd), 16);
       if (Character.isISOControl(d)) {
         continue;
       }
       byteBuffer.clear();
       charBuffer.clear();
       charBuffer.put(d).rewind();
       final CoderResult coderResult = encoder.encode(charBuffer, byteBuffer, true);
       if (!coderResult.isUnmappable()) {
         final PsiElement element = file.findElementAt(i);
         if (element != null && isSuppressedFor(element)) {
           return;
         }
         registerErrorAtOffset(file, i, escapeEnd - i, Character.valueOf(d));
       }
     }
   }
 }