1 | |
package com.sun.tools.javafx.comp; |
2 | |
|
3 | |
import com.sun.tools.javac.code.Flags; |
4 | |
import com.sun.tools.javac.code.Kinds; |
5 | |
import com.sun.tools.javac.code.Scope.Entry; |
6 | |
import com.sun.tools.javac.code.Symbol; |
7 | |
import com.sun.tools.javac.code.Symbol.ClassSymbol; |
8 | |
import com.sun.tools.javac.code.Symbol.MethodSymbol; |
9 | |
import com.sun.tools.javac.code.Symbol.VarSymbol; |
10 | |
import com.sun.tools.javac.code.Type; |
11 | |
import com.sun.tools.javac.code.Type.MethodType; |
12 | |
import com.sun.tools.javac.tree.JCTree; |
13 | |
import com.sun.tools.javac.tree.JCTree.JCExpression; |
14 | |
import com.sun.tools.javac.tree.JCTree.JCStatement; |
15 | |
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
16 | |
import com.sun.tools.javac.util.List; |
17 | |
import com.sun.tools.javac.util.ListBuffer; |
18 | |
import com.sun.tools.javac.util.Log; |
19 | |
import com.sun.tools.javac.util.Name; |
20 | |
import com.sun.tools.javac.util.Position; |
21 | |
|
22 | |
import com.sun.tools.javafx.code.JavafxFlags; |
23 | |
import com.sun.tools.javafx.code.JavafxTypes; |
24 | |
import com.sun.tools.javafx.comp.JavafxTypeMorpher.VarMorphInfo; |
25 | |
import com.sun.tools.javafx.tree.*; |
26 | |
import com.sun.tools.javafx.util.MsgSym; |
27 | |
|
28 | |
import static com.sun.tools.javafx.comp.JavafxDefs.*; |
29 | |
|
30 | |
import java.util.HashMap; |
31 | |
import java.util.HashSet; |
32 | |
import java.util.Map; |
33 | |
import java.util.Set; |
34 | |
|
35 | 6 | class JavafxAnalyzeClass { |
36 | |
|
37 | |
private final DiagnosticPosition diagPos; |
38 | |
private final ClassSymbol currentClassSym; |
39 | 612 | private final ListBuffer<AttributeInfo> attributeInfos = ListBuffer.lb(); |
40 | 612 | private final Map<String,MethodSymbol> needDispatchMethods = new HashMap<String, MethodSymbol>(); |
41 | 612 | private final Map<String, AttributeInfo> translatedAttributes = new HashMap<String, AttributeInfo>(); |
42 | 612 | private final Map<String, AttributeInfo> visitedSourceAttributes = new HashMap<String, AttributeInfo>(); |
43 | 612 | private final Map<String, AttributeInfo> visitedClassFileAttributes = new HashMap<String, AttributeInfo>(); |
44 | 612 | private final Set<Symbol> addedBaseClasses = new HashSet<Symbol>(); |
45 | |
private final List<TranslatedAttributeInfo> translatedAttrInfo; |
46 | |
private final Log log; |
47 | |
private final Name.Table names; |
48 | |
private final JavafxTypes types; |
49 | |
private final JavafxClassReader reader; |
50 | |
private final JavafxTypeMorpher typeMorpher; |
51 | |
|
52 | 2739 | static class AttributeInfo { |
53 | |
private final DiagnosticPosition diagPos; |
54 | |
private final Symbol sym; |
55 | |
private final VarMorphInfo vmi; |
56 | |
private final Name name; |
57 | |
private final JCStatement initStmt; |
58 | |
private final boolean isDirectOwner; |
59 | |
private boolean needsCloning; |
60 | |
|
61 | |
private AttributeInfo(DiagnosticPosition diagPos, Name name, Symbol attrSym, VarMorphInfo vmi, |
62 | 1099 | JCStatement initStmt, boolean isDirectOwner) { |
63 | 1099 | this.diagPos = diagPos; |
64 | 1099 | this.name = name; |
65 | 1099 | this.sym = attrSym; |
66 | 1099 | this.vmi = vmi; |
67 | 1099 | this.initStmt = initStmt; |
68 | 1099 | this.isDirectOwner = isDirectOwner; |
69 | 1099 | } |
70 | |
|
71 | |
public Symbol getSymbol() { |
72 | 252 | return sym; |
73 | |
} |
74 | |
|
75 | |
public DiagnosticPosition pos() { |
76 | 3325 | return diagPos; |
77 | |
} |
78 | |
|
79 | |
public Type getRealType() { |
80 | 286 | return vmi.getRealType(); |
81 | |
} |
82 | |
|
83 | |
public Type getVariableType() { |
84 | 2568 | return vmi.getVariableType(); |
85 | |
} |
86 | |
|
87 | |
public Type getLocationType() { |
88 | 0 | return vmi.getLocationType(); |
89 | |
} |
90 | |
|
91 | |
public Type getElementType() { |
92 | 70 | return vmi.getElementType(); |
93 | |
} |
94 | |
|
95 | |
public Name getName() { |
96 | 4751 | return name; |
97 | |
} |
98 | |
|
99 | |
public String getNameString() { |
100 | 4201 | return name.toString(); |
101 | |
} |
102 | |
|
103 | |
public long getFlags() { |
104 | 5229 | return sym.flags(); |
105 | |
} |
106 | |
|
107 | |
|
108 | |
|
109 | |
|
110 | |
|
111 | |
|
112 | |
private void setNeedsCloning(boolean needs) { |
113 | 1640 | needsCloning = needs; |
114 | 1640 | } |
115 | |
|
116 | |
public boolean needsCloning() { |
117 | 2767 | return needsCloning; |
118 | |
} |
119 | |
|
120 | |
public boolean isStatic() { |
121 | 1644 | return (getFlags() & Flags.STATIC) != 0; |
122 | |
} |
123 | |
|
124 | |
public VarMorphInfo getVMI() { |
125 | 1091 | return vmi; |
126 | |
} |
127 | |
|
128 | |
public boolean isDirectOwner() { |
129 | 76 | return isDirectOwner; |
130 | |
} |
131 | |
|
132 | |
public JCStatement getDefaultInitializtionStatement() { |
133 | 1623 | return initStmt; |
134 | |
} |
135 | |
|
136 | |
public String toString() { |
137 | 0 | return getNameString(); |
138 | |
} |
139 | |
} |
140 | |
|
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
|
147 | |
|
148 | |
|
149 | |
|
150 | |
|
151 | |
|
152 | |
|
153 | |
|
154 | |
|
155 | |
|
156 | |
|
157 | |
|
158 | |
|
159 | |
|
160 | |
|
161 | |
|
162 | 2 | static class TranslatedAttributeInfo extends AttributeInfo { |
163 | |
final JFXVar attribute; |
164 | |
private final JFXOnReplace onReplace; |
165 | |
TranslatedAttributeInfo(JFXVar attribute, VarMorphInfo vmi, |
166 | |
JCStatement initStmt, JFXOnReplace onReplace) { |
167 | 563 | super(attribute.pos(), attribute.sym.name, attribute.sym, vmi, initStmt, true); |
168 | 563 | this.attribute = attribute; |
169 | 563 | this.onReplace = onReplace; |
170 | 563 | } |
171 | |
|
172 | |
private void setNeedsCloning(boolean needs) { |
173 | 0 | assert needs; |
174 | 0 | } |
175 | |
|
176 | |
public boolean needsCloning() { |
177 | 1999 | return true; |
178 | |
} |
179 | |
|
180 | 563 | JFXOnReplace onReplace() { return onReplace; } |
181 | |
|
182 | |
} |
183 | |
|
184 | |
|
185 | |
|
186 | |
|
187 | |
static class TranslatedOverrideAttributeInfo extends AttributeInfo { |
188 | |
private final JFXOnReplace onReplace; |
189 | |
TranslatedOverrideAttributeInfo(JFXOverrideAttribute override, |
190 | |
VarMorphInfo vmi, |
191 | |
JCStatement initStmt, JFXOnReplace onReplace) { |
192 | 9 | super(override.pos(), override.sym.name, override.sym, vmi, initStmt, true); |
193 | 9 | this.onReplace = onReplace; |
194 | 9 | } |
195 | |
|
196 | 9 | JFXOnReplace onReplace() { return onReplace; } |
197 | |
} |
198 | |
|
199 | |
JavafxAnalyzeClass(DiagnosticPosition diagPos, |
200 | |
ClassSymbol currentClassSym, |
201 | |
List<TranslatedAttributeInfo> translatedAttrInfo, |
202 | |
List<TranslatedOverrideAttributeInfo> translatedOverrideAttrInfo, |
203 | |
Log log, |
204 | |
Name.Table names, |
205 | |
JavafxTypes types, |
206 | |
JavafxClassReader reader, |
207 | 612 | JavafxTypeMorpher typeMorpher) { |
208 | 612 | this.log = log; |
209 | 612 | this.names = names; |
210 | 612 | this.types = types; |
211 | 612 | this.reader = reader; |
212 | 612 | this.typeMorpher = typeMorpher; |
213 | 612 | this.diagPos = diagPos; |
214 | 612 | this.currentClassSym = currentClassSym; |
215 | |
|
216 | 612 | this.translatedAttrInfo = translatedAttrInfo; |
217 | 612 | for (TranslatedAttributeInfo tai : translatedAttrInfo) { |
218 | 556 | translatedAttributes.put(tai.getNameString(), tai); |
219 | |
} |
220 | 612 | for (TranslatedOverrideAttributeInfo tai : translatedOverrideAttrInfo) { |
221 | 9 | translatedAttributes.put(tai.getNameString(), tai); |
222 | |
} |
223 | |
|
224 | |
|
225 | 612 | process(currentClassSym, true); |
226 | 612 | types.isCompoundClass(currentClassSym); |
227 | 612 | } |
228 | |
|
229 | |
public List<AttributeInfo> instanceAttributeInfos() { |
230 | 612 | return attributeInfos.toList(); |
231 | |
} |
232 | |
|
233 | |
public List<AttributeInfo> staticAttributeInfos() { |
234 | 612 | ListBuffer<AttributeInfo> ais = ListBuffer.lb(); |
235 | 612 | for (AttributeInfo ai : translatedAttrInfo) { |
236 | 556 | if (ai.isStatic()) { |
237 | 75 | ais.append( ai ); |
238 | |
} |
239 | |
} |
240 | 612 | return ais.toList(); |
241 | |
} |
242 | |
|
243 | |
public List<MethodSymbol> needDispatch() { |
244 | 612 | ListBuffer<MethodSymbol> meths = ListBuffer.lb(); |
245 | 612 | for (MethodSymbol mSym : needDispatchMethods.values()) { |
246 | 745 | meths.append( mSym ); |
247 | |
} |
248 | 612 | return meths.toList(); |
249 | |
} |
250 | |
|
251 | |
private void process(Symbol sym, boolean cloneVisible) { |
252 | 816 | if (!addedBaseClasses.contains(sym) && types.isJFXClass(sym)) { |
253 | 781 | ClassSymbol cSym = (ClassSymbol) sym; |
254 | 781 | addedBaseClasses.add(cSym); |
255 | 781 | JFXClassDeclaration cDecl = types.getFxClass(cSym); |
256 | 781 | if (cSym != currentClassSym && (cSym.flags() & (JavafxFlags.COMPOUND_CLASS|Flags.INTERFACE)) == 0) { |
257 | |
|
258 | |
|
259 | 6 | cloneVisible = false; |
260 | |
} |
261 | |
|
262 | |
|
263 | 781 | if (cDecl == null) { |
264 | 63 | for (Type supertype : cSym.getInterfaces()) { |
265 | 36 | ClassSymbol iSym = (ClassSymbol) supertype.tsym; |
266 | 36 | process(iSym, cloneVisible); |
267 | 36 | String iName = iSym.fullname.toString(); |
268 | 36 | if (iName.endsWith(JavafxDefs.interfaceSuffix)) { |
269 | 0 | String sName = iName.substring(0, iName.length() - JavafxDefs.interfaceSuffix.length()); |
270 | 0 | ClassSymbol sSym = reader.enterClass(names.fromString(sName)); |
271 | 0 | process(sSym, cloneVisible); |
272 | |
} |
273 | 36 | } |
274 | 63 | if ((cSym.flags_field & Flags.INTERFACE) == 0 && cSym.members() != null) { |
275 | |
|
276 | |
|
277 | |
|
278 | |
|
279 | |
|
280 | |
|
281 | |
|
282 | |
|
283 | 63 | ListBuffer<MethodSymbol> reversed = ListBuffer.lb(); |
284 | 4910 | for (Entry e = cSym.members().elems; e != null && e.sym != null; e = e.sibling) { |
285 | 4847 | if (e.sym.kind == Kinds.MTH) { |
286 | 3711 | reversed.prepend((MethodSymbol) e.sym); |
287 | |
} |
288 | |
} |
289 | 63 | for (MethodSymbol meth : reversed) { |
290 | 3711 | processMethodFromClassFile(meth, cSym, cloneVisible); |
291 | |
} |
292 | |
|
293 | 63 | } |
294 | |
} else { |
295 | 718 | for (JCExpression supertype : cDecl.getSupertypes()) { |
296 | 168 | process(supertype.type.tsym, cloneVisible); |
297 | |
} |
298 | 718 | for (JCTree def : cDecl.getMembers()) { |
299 | 2083 | if (def.getTag() == JavafxTag.VAR_DEF) { |
300 | 648 | processAttributeFromSource((JFXVar) def, cDecl, cloneVisible); |
301 | 1435 | } else if (cloneVisible && def.getTag() == JavafxTag.FUNCTION_DEF) { |
302 | 1105 | processFunctionFromSource((JFXFunctionDefinition) def); |
303 | |
} |
304 | |
} |
305 | |
} |
306 | |
} |
307 | 816 | } |
308 | |
|
309 | |
private AttributeInfo addAttribute(String attrName, Symbol sym, boolean needsCloning) { |
310 | 1017 | AttributeInfo attrInfo = translatedAttributes.get(attrName); |
311 | 1017 | if (attrInfo == null) { |
312 | 527 | attrInfo = new AttributeInfo(diagPos, |
313 | |
names.fromString(attrName), |
314 | |
sym, typeMorpher.varMorphInfo(sym), null, sym.owner == currentClassSym); |
315 | |
} |
316 | 1017 | attrInfo.setNeedsCloning(needsCloning || attrInfo.isDirectOwner()); |
317 | 1017 | attributeInfos.append(attrInfo); |
318 | 1017 | return attrInfo; |
319 | |
} |
320 | |
|
321 | |
private void processMethodFromClassFile(MethodSymbol meth, ClassSymbol cSym, boolean cloneVisible) { |
322 | 3711 | String methName = meth.name.toString(); |
323 | 3711 | if (methName.startsWith(attributeGetMethodNamePrefix)) { |
324 | 1091 | String nameSig = methName.substring(attributeGetMethodNamePrefix.length()); |
325 | 1091 | if (visitedSourceAttributes.containsKey(nameSig)) { |
326 | 0 | log.error(MsgSym.MESSAGE_JAVAFX_CANNOT_OVERRIDE_DEFAULT_INITIALIZER, nameSig, cSym.className(), visitedSourceAttributes.get(nameSig)); |
327 | 1091 | } else if (visitedClassFileAttributes.containsKey(nameSig)) { |
328 | |
|
329 | 623 | AttributeInfo attrInfo = visitedClassFileAttributes.get(nameSig); |
330 | 623 | attrInfo.setNeedsCloning(cloneVisible && attrInfo.needsCloning()); |
331 | 623 | } else { |
332 | 468 | visitedClassFileAttributes.put(nameSig, addAttribute(nameSig, meth, cloneVisible) ); |
333 | |
} |
334 | 1091 | } else if (cloneVisible && methName.endsWith(JavafxDefs.implFunctionSuffix)) { |
335 | |
|
336 | 267 | methName = methName.substring(0, methName.length() - JavafxDefs.implFunctionSuffix.length()); |
337 | 267 | int cnt = 0; |
338 | 267 | ListBuffer<VarSymbol> params = ListBuffer.lb(); |
339 | 267 | ListBuffer<Type> paramTypes = ListBuffer.lb(); |
340 | 267 | for (VarSymbol param : meth.getParameters()) { |
341 | 408 | cnt++; |
342 | 408 | if (cnt > 1) { |
343 | 141 | params.append(param); |
344 | 141 | paramTypes.append(param.type); |
345 | |
} |
346 | |
} |
347 | 267 | MethodType mtype = new MethodType(paramTypes.toList(), meth.type.getReturnType(), meth.type.getThrownTypes(), meth.type.tsym); |
348 | 267 | MethodSymbol fixedMeth = new MethodSymbol(meth.flags() & ~Flags.STATIC, names.fromString(methName), mtype, meth.owner); |
349 | 267 | fixedMeth.params = params.toList(); |
350 | 267 | String nameSig = methodSignature(fixedMeth); |
351 | 267 | needDispatchMethods.put(nameSig, fixedMeth); |
352 | |
} |
353 | 3711 | } |
354 | |
|
355 | |
private void processFunctionFromSource(JFXFunctionDefinition def) { |
356 | 1105 | MethodSymbol meth = def.sym; |
357 | |
|
358 | |
|
359 | |
|
360 | 1105 | if ((meth.flags() & (Flags.SYNTHETIC | Flags.ABSTRACT | Flags.STATIC)) == 0 && |
361 | |
(meth.owner.flags() & JavafxFlags.COMPOUND_CLASS) != 0) { |
362 | 510 | assert def.pos != Position.NOPOS; |
363 | 510 | String nameSig = methodSignature(meth); |
364 | 510 | needDispatchMethods.put(nameSig, meth); |
365 | |
} |
366 | 1105 | } |
367 | |
|
368 | |
private void processAttributeFromSource(JFXVar def, JFXClassDeclaration cDecl, boolean cloneVisible) { |
369 | 648 | VarSymbol var = def.sym; |
370 | 648 | if (var.owner.kind == Kinds.TYP && (var.flags() & Flags.STATIC) == 0) { |
371 | 549 | String attrName = var.name.toString(); |
372 | 549 | String className = cDecl.getName().toString(); |
373 | 549 | if (visitedSourceAttributes.containsKey(attrName)) { |
374 | 0 | log.error(MsgSym.MESSAGE_JAVAFX_CANNOT_OVERRIDE_DEFAULT_INITIALIZER, attrName, className, visitedSourceAttributes.get(attrName)); |
375 | 549 | } else if (visitedClassFileAttributes.containsKey(attrName)) { |
376 | 0 | log.error(MsgSym.MESSAGE_JAVAFX_CANNOT_OVERRIDE_DEFAULT_INITIALIZER, attrName, className, visitedClassFileAttributes.get(attrName)); |
377 | |
} else { |
378 | 549 | visitedSourceAttributes.put(attrName, addAttribute(attrName, var, cloneVisible) ); |
379 | |
} |
380 | |
} |
381 | 648 | } |
382 | |
|
383 | |
private String methodSignature(MethodSymbol meth) { |
384 | 777 | StringBuilder nameSigBld = new StringBuilder(); |
385 | 777 | nameSigBld.append(meth.name.toString()); |
386 | 777 | nameSigBld.append(":"); |
387 | 777 | nameSigBld.append(meth.getReturnType().toString()); |
388 | 777 | nameSigBld.append(":"); |
389 | 777 | for (VarSymbol param : meth.getParameters()) { |
390 | 659 | nameSigBld.append(param.type.toString()); |
391 | 659 | nameSigBld.append(":"); |
392 | |
} |
393 | 777 | return nameSigBld.toString(); |
394 | |
} |
395 | |
} |