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