lossy encoding inspection false positive for transparently converted properties files
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInspection / LossyEncodingInspection.java
blobaa76760e298ae42ff18d9a0c95e8f417efcbb441
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Created by IntelliJ IDEA.
19 * User: cdr
20 * Date: Aug 6, 2007
21 * Time: 3:09:55 PM
23 package com.intellij.codeInspection;
25 import com.intellij.codeInsight.daemon.GroupNames;
26 import com.intellij.lang.properties.charset.Native2AsciiCharset;
27 import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
28 import com.intellij.openapi.util.TextRange;
29 import com.intellij.openapi.vfs.VirtualFile;
30 import com.intellij.psi.PsiFile;
31 import com.intellij.util.ArrayUtil;
32 import com.intellij.util.SmartList;
33 import org.jetbrains.annotations.Nls;
34 import org.jetbrains.annotations.NonNls;
35 import org.jetbrains.annotations.NotNull;
36 import org.jetbrains.annotations.Nullable;
38 import java.nio.ByteBuffer;
39 import java.nio.CharBuffer;
40 import java.nio.charset.Charset;
41 import java.util.List;
43 public class LossyEncodingInspection extends BaseJavaLocalInspectionTool {
44 @Nls
45 @NotNull
46 public String getGroupDisplayName() {
47 return GroupNames.INTERNATIONALIZATION_GROUP_NAME;
50 @Nls
51 @NotNull
52 public String getDisplayName() {
53 return InspectionsBundle.message("lossy.encoding");
56 @NonNls
57 @NotNull
58 public String getShortName() {
59 return "LossyEncoding";
62 @Nullable
63 public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
64 if (ArrayUtil.find(file.getPsiRoots(), file) != 0) return null;
65 VirtualFile virtualFile = file.getVirtualFile();
66 if (virtualFile == null) return null;
67 String text = file.getText();
68 Charset charset = LoadTextUtil.extractCharsetFromFileContent(file.getProject(), virtualFile, text);
70 // no sense in checking transparently decoded file: all characters there are already safely encoded
71 if (charset instanceof Native2AsciiCharset) return null;
73 int errorCount = 0;
74 int start = -1;
75 List<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
76 for (int i = 0; i <= text.length(); i++) {
77 char c = i == text.length() ? 0 : text.charAt(i);
78 if (i == text.length() || isRepresentable(c, charset)) {
79 if (start != -1) {
80 ProblemDescriptor descriptor = manager.createProblemDescriptor(file, new TextRange(start, i), InspectionsBundle.message(
81 "unsupported.character.for.the.charset", charset), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
82 descriptors.add(descriptor);
83 start = -1;
85 //do not report too many errors
86 if (errorCount++ > 200) break;
89 else {
90 if (start == -1) {
91 start = i;
96 return descriptors.toArray(new ProblemDescriptor[descriptors.size()]);
99 private static boolean isRepresentable(final char c, final Charset charset) {
100 String str = Character.toString(c);
101 ByteBuffer out = charset.encode(str);
102 CharBuffer buffer = charset.decode(out);
103 return str.equals(buffer.toString());