1 package club.wpia.gigi.localisation;
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.Properties;
17 import java.util.TreeSet;
19 import org.eclipse.jdt.core.compiler.CategorizedProblem;
20 import org.eclipse.jdt.internal.compiler.ASTVisitor;
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;
39 import club.wpia.gigi.database.DatabaseConnection;
40 import club.wpia.gigi.output.template.Template;
42 public class TranslationCollector {
44 static class TranslationEntry implements Comparable<TranslationEntry> {
52 public TranslationEntry(String text, String occur) {
57 public List<String> getOccur() {
59 return Arrays.asList(occur1);
64 public void add(String t) {
66 occur = new ArrayList<>(Arrays.asList(occur1));
72 public int compareTo(TranslationEntry o) {
73 int i = occur1.compareTo(o.occur1);
78 return text.compareTo(o.text);
82 private HashMap<String, TranslationEntry> translations = new HashMap<>();
84 public final File base;
86 private boolean hadErrors = false;
88 private int statements = 0;
90 public TranslationCollector(File base, File conf) {
92 taint = new LinkedList<>();
93 for (String s : new FileIterable(conf)) {
94 taint.add(TaintSource.parseTaint(s));
98 interface ASTVisitorFactory {
100 public ASTVisitor createVisitor(CompilationUnitDeclaration parsedUnit);
103 public void run(File out) throws IOException {
105 scanCode(new ASTVisitorFactory() {
108 public ASTVisitor createVisitor(CompilationUnitDeclaration parsedUnit) {
109 return new TranslationCollectingVisitor(parsedUnit, taint.toArray(new TaintSource[taint.size()]), TranslationCollector.this);
113 System.err.println("Total Translatable Strings: " + translations.size());
114 TreeSet<TranslationEntry> trs = new TreeSet<>(translations.values());
115 writePOFile(out, trs);
118 public void runSQLValidation() throws IOException {
119 scanCode(new ASTVisitorFactory() {
122 public ASTVisitor createVisitor(CompilationUnitDeclaration parsedUnit) {
123 return new SQLTestingVisitor(parsedUnit, TranslationCollector.this);
126 System.out.println("Validated: " + statements + " SQL statements.");
129 public void add(String text, String line) {
130 if (text.contains("\r") || text.contains("\n")) {
131 throw new Error("Malformed translation in " + line);
133 TranslationEntry i = translations.get(text);
135 translations.put(text, new TranslationEntry(text, line));
141 private void scanCode(ASTVisitorFactory visitor) throws Error {
142 PrintWriter out = new PrintWriter(System.err);
143 Main m = new Main(out, out, false, null, null);
144 File[] fs = recurse(new File(new File(new File(base, "src"), "club"), "wpia"), new LinkedList<File>(), ".java").toArray(new File[0]);
145 String[] t = new String[fs.length + 3];
147 t[1] = new File(base, "bin").getAbsolutePath();
149 for (int i = 0; i < fs.length; i++) {
150 t[i + 3] = fs[i].getAbsolutePath();
153 FileSystem environment = m.getLibraryAccess();
154 CompilerOptions compilerOptions = new CompilerOptions(m.options);
155 compilerOptions.performMethodsFullRecovery = false;
156 compilerOptions.performStatementsRecovery = false;
158 compilerOptions.sourceLevel = ClassFileConstants.JDK1_7;
159 compilerOptions.complianceLevel = ClassFileConstants.JDK1_7;
160 compilerOptions.originalComplianceLevel = ClassFileConstants.JDK1_7;
162 ProblemReporter pr = new ProblemReporter(m.getHandlingPolicy(), compilerOptions, m.getProblemFactory());
163 ITypeRequestor tr = new ITypeRequestor() {
166 public void accept(ISourceType[] sourceType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
167 throw new IllegalStateException("source type not implemented");
171 public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
172 le.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
176 public void accept(ICompilationUnit unit, AccessRestriction accessRestriction) {
177 throw new IllegalStateException("compilation unit not implemented");
180 le = new LookupEnvironment(tr, compilerOptions, pr, environment);
181 Parser parser = new Parser(pr, compilerOptions.parseLiteralExpressionsAsConstants);
182 CompilationUnit[] sourceUnits = m.getCompilationUnits();
183 CompilationUnitDeclaration[] parsedUnits = new CompilationUnitDeclaration[sourceUnits.length];
184 for (int i = 0; i < parsedUnits.length; i++) {
186 CompilationResult unitResult = new CompilationResult(sourceUnits[i], i, parsedUnits.length, compilerOptions.maxProblemsPerUnit);
187 CompilationUnitDeclaration parsedUnit = parser.parse(sourceUnits[i], unitResult);
188 le.buildTypeBindings(parsedUnit, null /* no access restriction */);
189 parsedUnits[i] = parsedUnit;
191 le.completeTypeBindings();
192 for (int i = 0; i < parsedUnits.length; i++) {
193 CompilationUnitDeclaration parsedUnit = parsedUnits[i];
195 parser.getMethodBodies(parsedUnit);
196 parsedUnit.scope.faultInTypes();
197 parsedUnit.scope.verifyMethods(le.methodVerifier());
198 parsedUnit.resolve();
200 for (int i = 0; i < parsedUnits.length; i++) {
201 CompilationUnitDeclaration parsedUnit = parsedUnits[i];
202 if (parsedUnit.compilationResult.problems != null) {
204 for (int c = 0; c < parsedUnit.compilationResult.problemCount; c++) {
205 CategorizedProblem problem = parsedUnit.compilationResult.problems[c];
206 if (problem.isError()) {
209 if (OUTPUT_WARNINGS || problem.isError()) {
210 System.err.println(problem);
211 StringBuilder prob = new StringBuilder();
212 prob.append(parsedUnit.compilationResult.fileName);
214 prob.append(problem.getSourceLineNumber());
215 System.err.println(prob.toString());
222 // Skip Database connection as some statements need to be run on older DB scheme version.
223 if(new String(parsedUnit.getFileName()).endsWith("/src/club/wpia/gigi/database/DatabaseConnection.java")) {
226 if (parsedUnit.types == null) {
227 System.err.println("No types");
230 ASTVisitor v = visitor.createVisitor(parsedUnit);
231 for (TypeDeclaration td : parsedUnit.types) {
232 td.traverse(v, td.scope);
235 parsedUnits[i] = parsedUnit;
239 private void scanTemplates() throws UnsupportedEncodingException, FileNotFoundException {
240 File[] ts = recurse(new File(new File(new File(base, "src"), "club"), "wpia"), new LinkedList<File>(), ".templ").toArray(new File[0]);
241 for (File file : ts) {
242 Template t = new Template(new InputStreamReader(new FileInputStream(file), "UTF-8"));
243 LinkedList<String> i = new LinkedList<String>();
244 t.addTranslations(i);
245 for (String string : i) {
246 add(string, file.getAbsolutePath().substring(base.getAbsolutePath().length() + 1) + ":1");
251 static LookupEnvironment le;
253 private static final boolean OUTPUT_WARNINGS = false;
255 private LinkedList<TaintSource> taint;
257 public static void main(String[] args) throws IOException {
258 Properties pp = new Properties();
259 pp.load(new InputStreamReader(new FileInputStream("config/test.properties"), "UTF-8"));
260 DatabaseConnection.init(pp);
261 TranslationCollector tc = new TranslationCollector(new File(args[1]), new File(args[0]));
262 if (args[2].equals("SQLValidation")) {
263 tc.runSQLValidation();
265 tc.run(new File(args[2]));
274 public static void writePOFile(File target, Collection<TranslationEntry> strings) throws IOException {
275 PrintWriter out = new PrintWriter(target);
276 for (TranslationEntry s : strings) {
278 for (String st : s.getOccur()) {
282 out.println("msgid \"" + s.text.replace("\\", "\\\\").replace("\"", "\\\"") + "\"");
283 out.println("msgstr \"\"");
289 private static List<File> recurse(File file, List<File> toAdd, String pt) {
290 if (file.isDirectory()) {
291 for (File f : file.listFiles()) {
292 recurse(f, toAdd, pt);
295 if (file.getName().endsWith(pt)) {
302 public void hadError() {
306 public void countStatement() {