]> WPIA git - gigi.git/blob - util-testing/org/cacert/gigi/localisation/TranslationCollector.java
cleanup for "fix: pootle does not like translations in line number 0"
[gigi.git] / util-testing / org / cacert / gigi / localisation / TranslationCollector.java
1 package org.cacert.gigi.localisation;
2 import java.io.File;
3 import java.io.FileInputStream;
4 import java.io.FileNotFoundException;
5 import java.io.IOException;
6 import java.io.InputStreamReader;
7 import java.io.PrintWriter;
8 import java.io.UnsupportedEncodingException;
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.Collection;
12 import java.util.HashMap;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.TreeSet;
16
17 import org.cacert.gigi.output.template.Template;
18 import org.eclipse.jdt.core.compiler.CategorizedProblem;
19 import org.eclipse.jdt.internal.compiler.CompilationResult;
20 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
21 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
22 import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
23 import org.eclipse.jdt.internal.compiler.batch.FileSystem;
24 import org.eclipse.jdt.internal.compiler.batch.Main;
25 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
26 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
27 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
28 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
29 import org.eclipse.jdt.internal.compiler.env.ISourceType;
30 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
31 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
32 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
33 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
34 import org.eclipse.jdt.internal.compiler.parser.Parser;
35 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
36
37 public class TranslationCollector {
38         static class TranslationEntry implements Comparable<TranslationEntry> {
39                 String text;
40                 String occur1;
41                 List<String> occur;
42                 public TranslationEntry(String text, String occur) {
43                         this.text = text;
44                         occur1 = occur;
45                 }
46                 public List<String> getOccur() {
47                         if (occur == null) {
48                                 return Arrays.asList(occur1);
49                         }
50                         return occur;
51                 }
52                 public void add(String t) {
53                         if (occur == null) {
54                                 occur = new ArrayList<>(Arrays.asList(occur1));
55                         }
56                         occur.add(t);
57                 }
58                 @Override
59                 public int compareTo(TranslationEntry o) {
60                         int i = occur1.compareTo(o.occur1);
61                         if (i != 0) {
62                                 return i;
63                         }
64
65                         return text.compareTo(o.text);
66                 }
67         }
68
69         private HashMap<String, TranslationEntry> translations = new HashMap<>();
70
71         public final File base;
72
73         public TranslationCollector(File base, File conf) {
74                 this.base = base;
75                 taint = new LinkedList<>();
76                 for (String s : new FileIterable(conf)) {
77                         taint.add(TaintSource.parseTaint(s));
78                 }
79         }
80         public void run(File out) throws IOException {
81                 scanTemplates();
82                 scanCode(taint);
83
84                 System.out
85                                 .println("Total Translatable Strings: " + translations.size());
86                 TreeSet<TranslationEntry> trs = new TreeSet<>(translations.values());
87                 writePOFile(out, trs);
88
89         }
90
91         public void add(String text, String line) {
92             if(text.contains("\r") || text.contains("\n")){
93                 throw new Error("Malformed translation in " + line);
94             }
95                 TranslationEntry i = translations.get(text);
96                 if (i == null) {
97                         translations.put(text, new TranslationEntry(text, line));
98                         return;
99                 }
100                 i.add(line);
101         }
102
103         private void scanCode(LinkedList<TaintSource> taint) throws Error {
104                 PrintWriter out = new PrintWriter(System.out);
105                 Main m = new Main(out, out, false, null, null);
106                 File[] fs = recurse(
107                                 new File(new File(new File(base, "src"), "org"), "cacert"),
108                                 new LinkedList<File>(), ".java").toArray(new File[0]);
109                 String[] t = new String[fs.length + 3];
110                 t[0] = "-cp";
111                 t[1] = new File(base, "bin").getAbsolutePath();
112                 t[2] = "-7";
113                 for (int i = 0; i < fs.length; i++) {
114                         t[i + 3] = fs[i].getAbsolutePath();
115                 }
116                 m.configure(t);
117                 FileSystem environment = m.getLibraryAccess();
118                 CompilerOptions compilerOptions = new CompilerOptions(m.options);//new HashMap<>());//m.options);
119                 compilerOptions.performMethodsFullRecovery = false;
120                 compilerOptions.performStatementsRecovery = false;
121                 //check
122                 compilerOptions.sourceLevel = ClassFileConstants.JDK1_7;
123                 compilerOptions.complianceLevel = ClassFileConstants.JDK1_7;
124                 compilerOptions.originalComplianceLevel = ClassFileConstants.JDK1_7;
125
126                 ProblemReporter pr = new ProblemReporter(m.getHandlingPolicy(),
127                                 compilerOptions, m.getProblemFactory());
128                 ITypeRequestor tr = new ITypeRequestor() {
129
130                         @Override
131                         public void accept(ISourceType[] sourceType,
132                                         PackageBinding packageBinding,
133                                         AccessRestriction accessRestriction) {
134                                 throw new IllegalStateException("source type not implemented");
135                         }
136
137                         @Override
138                         public void accept(IBinaryType binaryType,
139                                         PackageBinding packageBinding,
140                                         AccessRestriction accessRestriction) {
141                                 le.createBinaryTypeFrom(binaryType, packageBinding,
142                                                 accessRestriction);
143                         }
144
145                         @Override
146                         public void accept(ICompilationUnit unit,
147                                         AccessRestriction accessRestriction) {
148                                 throw new IllegalStateException(
149                                                 "compilation unit not implemented");
150                         }
151                 };
152                 le = new LookupEnvironment(tr, compilerOptions, pr, environment);
153                 Parser parser = new Parser(pr,
154                                 compilerOptions.parseLiteralExpressionsAsConstants);
155                 CompilationUnit[] sourceUnits = m.getCompilationUnits();
156                 CompilationUnitDeclaration[] parsedUnits = new CompilationUnitDeclaration[sourceUnits.length];
157                 for (int i = 0; i < parsedUnits.length; i++) {
158
159                         CompilationResult unitResult = new CompilationResult(
160                                         sourceUnits[i], i, parsedUnits.length,
161                                         compilerOptions.maxProblemsPerUnit);
162                         CompilationUnitDeclaration parsedUnit = parser.parse(
163                                         sourceUnits[i], unitResult);
164                         le.buildTypeBindings(parsedUnit, null /*no access restriction*/);
165                         parsedUnits[i] = parsedUnit;
166                 }
167                 le.completeTypeBindings();
168                 for (int i = 0; i < parsedUnits.length; i++) {
169                         CompilationUnitDeclaration parsedUnit = parsedUnits[i];
170
171                         parser.getMethodBodies(parsedUnit);
172                         parsedUnit.scope.faultInTypes();
173                         parsedUnit.scope.verifyMethods(le.methodVerifier());
174                         parsedUnit.resolve();
175                 }
176                 for (int i = 0; i < parsedUnits.length; i++) {
177                         CompilationUnitDeclaration parsedUnit = parsedUnits[i];
178                         if (parsedUnit.compilationResult.problems != null) {
179                                 int err = 0;
180                                 for (int c = 0; c < parsedUnit.compilationResult.problemCount; c++) {
181                                         CategorizedProblem problem = parsedUnit.compilationResult.problems[c];
182                                         if (problem.isError()) {
183                                                 err++;
184                                         }
185                                         if (OUTPUT_WARNINGS || problem.isError()) {
186                                                 System.out.println(problem);
187                                                 StringBuilder prob = new StringBuilder();
188                                                 prob.append(parsedUnit.compilationResult.fileName);
189                                                 prob.append(":");
190                                                 prob.append(problem.getSourceLineNumber());
191                                                 System.out.println(prob.toString());
192                                         }
193                                 }
194                                 if (err > 0) {
195                                         throw new Error();
196                                 }
197                         }
198
199                         if (parsedUnit.types == null) {
200                                 System.out.println("No types");
201
202                         } else {
203                                 TranslationCollectingVisitor v = new TranslationCollectingVisitor(
204                                                 parsedUnit,
205                                                 taint.toArray(new TaintSource[taint.size()]), this);
206                                 for (TypeDeclaration td : parsedUnit.types) {
207                                         td.traverse(v, td.scope);
208                                 }
209                         }
210                         parsedUnits[i] = parsedUnit;
211                 }
212         }
213         private void scanTemplates() throws UnsupportedEncodingException,
214                         FileNotFoundException {
215                 File[] ts = recurse(
216                                 new File(new File(new File(base, "src"), "org"), "cacert"),
217                                 new LinkedList<File>(), ".templ").toArray(new File[0]);
218                 for (File file : ts) {
219                         Template t = new Template(new InputStreamReader(
220                                         new FileInputStream(file), "UTF-8"));
221                         LinkedList<String> i = new LinkedList<String>();
222                         t.addTranslations(i);
223                         for (String string : i) {
224                                 add(string,
225                                                 file.getAbsolutePath().substring(
226                                                                 base.getAbsolutePath().length() + 1)
227                                                                 + ":1");
228                         }
229                 }
230         }
231
232         static LookupEnvironment le;
233         private static final boolean OUTPUT_WARNINGS = false;
234
235         private LinkedList<TaintSource> taint;
236         public static void main(String[] args) throws IOException {
237                 new TranslationCollector(new File(args[1]), new File(args[0]))
238                                 .run(new File(args[2]));
239         }
240
241         public static void writePOFile(File target,
242                         Collection<TranslationEntry> strings) throws IOException {
243                 PrintWriter out = new PrintWriter(target);
244                 for (TranslationEntry s : strings) {
245                         out.print("#:");
246                         for (String st : s.getOccur()) {
247                                 out.print(" " + st);
248                         }
249                         out.println();
250                         out.println("msgid \""
251                                         + s.text.replace("\\", "\\\\").replace("\"", "\\\"") + "\"");
252                         out.println("msgstr \"\"");
253                         out.println();
254                 }
255                 out.close();
256         }
257
258         private static List<File> recurse(File file, List<File> toAdd, String pt) {
259                 if (file.isDirectory()) {
260                         for (File f : file.listFiles()) {
261                                 recurse(f, toAdd, pt);
262                         }
263                 } else {
264                         if (file.getName().endsWith(pt)) {
265                                 toAdd.add(file);
266                         }
267                 }
268                 return toAdd;
269         }
270 }