cleanup for "fix: pootle does not like translations in line number 0"
[gigi.git] / util-testing / org / cacert / gigi / localisation / TranslationCollectingVisitor.java
1 package org.cacert.gigi.localisation;
2 import java.io.File;
3 import java.io.IOException;
4 import java.lang.reflect.Method;
5
6 import org.eclipse.jdt.internal.compiler.ASTVisitor;
7 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
8 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
9 import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
10 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
11 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
12 import org.eclipse.jdt.internal.compiler.ast.Expression;
13 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
14 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
15 import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
16 import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
17 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
18 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
19 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
20 import org.eclipse.jdt.internal.compiler.util.Util;
21
22 public final class TranslationCollectingVisitor extends ASTVisitor {
23         MethodBinding cm;
24         private CompilationUnitDeclaration unit;
25         TaintSource[] ts;
26         private TranslationCollector translationCollector;
27
28         public TranslationCollectingVisitor(CompilationUnitDeclaration unit,
29                         TaintSource[] target, TranslationCollector c) {
30                 this.unit = unit;
31                 ts = target;
32                 this.translationCollector = c;
33         }
34         @Override
35         public boolean visit(MethodDeclaration methodDeclaration,
36                         org.eclipse.jdt.internal.compiler.lookup.ClassScope scope) {
37                 cm = methodDeclaration.binding;
38                 return true;
39         }
40         @Override
41         public void endVisit(MethodDeclaration methodDeclaration,
42                         org.eclipse.jdt.internal.compiler.lookup.ClassScope scope) {
43                 cm = null;
44         }
45         @Override
46         public boolean visit(ConstructorDeclaration constructorDeclaration,
47                         ClassScope scope) {
48                 cm = constructorDeclaration.binding;
49                 return super.visit(constructorDeclaration, scope);
50         }
51         @Override
52         public void endVisit(ConstructorDeclaration constructorDeclaration,
53                         ClassScope scope) {
54                 cm = null;
55         }
56         @Override
57         public boolean visit(AllocationExpression allocationExpression,
58                         BlockScope scope) {
59                 TaintSource test = new TaintSource(allocationExpression.binding);
60                 for (TaintSource taintSource : ts) {
61                         if (taintSource.equals(test)) {
62                                 check(null, scope,
63                                                 allocationExpression.arguments[taintSource.getTgt()],
64                                                 allocationExpression.toString());
65                                 return true;
66                         }
67                 }
68                 return super.visit(allocationExpression, scope);
69         }
70         @Override
71         public boolean visit(ExplicitConstructorCall explicitConstructor,
72                         BlockScope scope) {
73
74                 TaintSource t = new TaintSource(explicitConstructor.binding);
75
76                 for (TaintSource t0 : ts) {
77                         if (t0.equals(t)) {
78                                 Expression[] ags = explicitConstructor.arguments;
79                                 if (ags == null) {
80                                         System.out.println(explicitConstructor);
81                                         return true;
82                                 }
83                                 Expression e = ags[t0.getTgt()];
84                                 check(null, scope, e, explicitConstructor.toString());
85                                 break;
86                         }
87                 }
88                 return super.visit(explicitConstructor, scope);
89         }
90
91         @Override
92         public boolean visit(
93                         org.eclipse.jdt.internal.compiler.ast.MessageSend call,
94                         org.eclipse.jdt.internal.compiler.lookup.BlockScope scope) {
95                 if (call.binding == null) {
96                         System.out.println("Unbound:" + call + " in " + call.sourceStart());
97                         return true;
98                 }
99                 //System.out.println("Message");
100                 TaintSource t = new TaintSource(call.binding);
101
102                 for (TaintSource t0 : ts) {
103                         if (t0.equals(t)) {
104                                 Expression[] ags = call.arguments;
105                                 if (ags == null) {
106                                         System.out.println(call);
107                                         return true;
108                                 }
109                                 Expression e = ags[t0.getTgt()];
110                                 check(call, scope, e, call.toString());
111                                 break;
112                         }
113                 }
114                 return true;
115         }
116         private void check(org.eclipse.jdt.internal.compiler.ast.MessageSend call,
117                         org.eclipse.jdt.internal.compiler.lookup.BlockScope scope,
118                         Expression e, String caller) {
119                 if (e instanceof StringLiteral) {
120                         int[] lineEnds = null;
121                         int lineNumber = Util.getLineNumber(
122                                         e.sourceStart,
123                                         lineEnds = unit.compilationResult
124                                                         .getLineSeparatorPositions(), 0,
125                                         lineEnds.length - 1);
126
127                         String content = new String(((StringLiteral) e).source());
128                         File f0 = new File(new String(unit.compilationResult.fileName))
129                                         .getAbsoluteFile();
130                         File f2 = translationCollector.base.getAbsoluteFile();
131                         try {
132                                 translationCollector.add(content, f0.getCanonicalPath()
133                                                 .substring(f2.getCanonicalPath().length() + 1)
134                                                 + ":"
135                                                 + lineNumber);
136                         } catch (IOException e1) {
137                                 e1.printStackTrace();
138                         }
139                         return;
140                 }
141
142                 if (e instanceof NullLiteral) {
143                         return;
144                 }
145
146                 if (e instanceof MessageSend) {
147                         MessageSend m2 = (MessageSend) e;
148                         TaintSource ts = new TaintSource(m2.binding);
149                         if (ts.equals(new TaintSource("org.cacert.gigi.pages", "Page",
150                                         "getTitle()", 0))) {
151                                 return;
152                         }
153                         if (m2.receiver.resolvedType.isCompatibleWith(scope
154                                         .getJavaLangEnum())) {
155                                 testEnum(m2.receiver, m2.binding);
156                                 System.out.println("ENUM-SRC: !" + m2.receiver);
157                         }
158                 }
159                 if (e.resolvedType.isCompatibleWith(scope.getJavaLangEnum())) {
160                         // TODO ?
161                         System.out.println("ENUM-Not-Hanled");
162                 }
163
164                 TaintSource b = cm == null ? null : new TaintSource(cm);
165                 for (TaintSource taintSource : ts) {
166                         if (taintSource.equals(b)
167                                         || (taintSource.getMaskOnly() != null && taintSource
168                                                         .getMaskOnly().equals(b))) {
169                                 return;
170                         }
171                 }
172                 if (e instanceof ConditionalExpression) {
173                         check(call, scope, ((ConditionalExpression) e).valueIfFalse, caller);
174                         check(call, scope, ((ConditionalExpression) e).valueIfTrue, caller);
175                         return;
176                 }
177
178                 System.out.println();
179
180                 System.out.println(new String(scope.enclosingClassScope()
181                                 .referenceType().compilationResult.fileName));
182                 System.out.println("Cannot Handle: " + e + " in "
183                                 + (call == null ? "constructor" : call.sourceStart) + " => "
184                                 + caller);
185                 System.out.println(e.getClass());
186                 System.out.println("To ignore: " + b.toConfLine());
187         }
188         private void testEnum(Expression e, MethodBinding binding) {
189                 if (binding.parameters.length != 0) {
190                         System.out.println("ERROR: meth");
191                         return;
192                 }
193                 System.out.println(e.resolvedType.getClass());
194                 String s2 = new String(e.resolvedType.qualifiedPackageName())
195                                 + "."
196                                 + (new String(e.resolvedType.qualifiedSourceName()).replace(
197                                                 '.', '$'));
198                 try {
199                         Class<?> c = Class.forName(s2);
200                         Enum<?>[] e1 = (Enum[]) c.getMethod("values").invoke(null);
201                         Method m = c.getMethod(new String(binding.selector));
202                         for (int j = 0; j < e1.length; j++) {
203                                 System.out.println(m.invoke(e1[j]));
204                         }
205                 } catch (ClassNotFoundException e1) {
206                         e1.printStackTrace();
207                 } catch (ReflectiveOperationException e1) {
208                         e1.printStackTrace();
209                 }
210                 System.out.println("ENUM-done: " + e + "!");
211                 return;
212         }
213 }