1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package uk.co.badgersinfoil.metaas.impl;
20
21 import java.util.ArrayList;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Set;
26 import org.asdt.core.internal.antlr.AS3Parser;
27 import uk.co.badgersinfoil.metaas.dom.ASArg;
28 import uk.co.badgersinfoil.metaas.dom.ASClassType;
29 import uk.co.badgersinfoil.metaas.dom.ASInterfaceType;
30 import uk.co.badgersinfoil.metaas.dom.ASMember;
31 import uk.co.badgersinfoil.metaas.dom.ASMethod;
32 import uk.co.badgersinfoil.metaas.dom.ASPackage;
33 import uk.co.badgersinfoil.metaas.dom.ASType;
34 import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree;
35
36
37
38
39
40
41
42 public class AutoImporter {
43
44 private List visibleQNames = new ArrayList();
45
46
47
48
49
50 private Set possiblyAmbigLocalNames = new HashSet();
51
52 public void performAutoImport(ASTActionScriptProject project) {
53 loadAccessableLanguageElements(project);
54 processSources(project);
55 }
56
57 private void loadAccessableLanguageElements(ASTActionScriptProject project) {
58 final Set seenLocalNames = new HashSet();
59
60
61 ASVisitor visitor = new ASVisitor.Null() {
62 public void visit(ASPackage pkg) {
63
64
65 ASType type = pkg.getType();
66 ASQName name = new ASQName(pkg.getName(), type.getName());
67 visibleQNames.add(name);
68 if (seenLocalNames.contains(name.getLocalName())) {
69 possiblyAmbigLocalNames.add(name.getLocalName());
70 } else {
71 seenLocalNames.add(name.getLocalName());
72 }
73 }
74 };
75 new ASWalker(visitor).walk(project);
76
77
78 Iterator i = project.getResourceRoots().iterator();
79 while (i.hasNext()) {
80 ResourceRoot resourceRoot = (ResourceRoot)i.next();
81 Iterator j = resourceRoot.getDefinitionQNames().iterator();
82 while (j.hasNext()) {
83 ASQName name = (ASQName)j.next();
84 visibleQNames.add(name);
85 if (seenLocalNames.contains(name.getLocalName())) {
86 possiblyAmbigLocalNames.add(name.getLocalName());
87 } else {
88 seenLocalNames.add(name.getLocalName());
89 }
90 }
91 }
92 }
93
94
95 private void processSources(ASTActionScriptProject project) {
96 new ASWalker(new ImportSourceProcessor()).walk(project);
97 }
98
99 private class ImportSourceProcessor extends ASVisitor.Null {
100 private String currentPackageName;
101 private ASQName currentTypeName;
102 private ASPackage currentPackage;
103 private Set currentPackageImports = new HashSet();
104 private ASType currentType;
105
106
107
108
109 public void visit(ASPackage pkg) {
110 currentPackage = pkg;
111 currentPackageName = pkg.getName();
112 inspectImports(pkg);
113 }
114
115 private void inspectImports(ASPackage pkg) {
116 currentPackageImports.clear();
117 List imports = pkg.findImports();
118 for (Iterator i=imports.iterator(); i.hasNext(); ) {
119 ASQName imp = new ASQName((String)i.next());
120 if (imp.getLocalName().equals("*")) {
121
122 importNamesFromPackage(imp.getPackagePrefix());
123 } else {
124 currentPackageImports.add(imp);
125 }
126 }
127 }
128
129 private void importNamesFromPackage(String packagePrefix) {
130 for (Iterator i=visibleQNames.iterator(); i.hasNext(); ) {
131 ASQName name = (ASQName)i.next();
132 if (packagePrefix.equals(name.getPackagePrefix())) {
133 currentPackageImports.add(name);
134 }
135 }
136 }
137
138 public void visit(ASType type) {
139 currentTypeName = new ASQName(currentPackageName, type.getName());
140 currentType = type;
141 }
142
143 public void visit(ASClassType clazz) {
144 String superClassName = clazz.getSuperclass();
145 String processed = processTypeName(superClassName);
146 if (processed != null) {
147 clazz.setSuperclass(processed);
148 }
149 List interfaceNames = clazz.getImplementedInterfaces();
150 for (Iterator i=interfaceNames.iterator(); i.hasNext(); ) {
151 String interfaceName = (String)i.next();
152 processed = processTypeName(interfaceName);
153 if (processed != null) {
154 clazz.removeImplementedInterface(interfaceName);
155 clazz.addImplementedInterface(processed);
156 }
157 }
158 }
159
160 public void visit(ASInterfaceType iface) {
161 List interfaceNames = iface.getSuperInterfaces();
162 for (Iterator i=interfaceNames.iterator(); i.hasNext(); ) {
163 String interfaceName = (String)i.next();
164 String processed = processTypeName(interfaceName);
165 if (processed != null) {
166 iface.removeSuperInterface(interfaceName);
167 iface.addSuperInterface(processed);
168 }
169 }
170 }
171
172 public void visit(ASMember member) {
173 String processedName = processTypeName(member.getType());
174 if (processedName != null) {
175 member.setType(processedName);
176 }
177 }
178
179 private String processTypeName(String typeName) {
180 if (typeName != null) {
181 ASQName qname = new ASQName(typeName);
182 if (qname.isQualified()
183 && visibleQNames.contains(qname))
184 {
185 if (importRequired(qname)) {
186 addImport(qname);
187 }
188 if (!possiblyAmbigLocalNames.contains(qname.getLocalName())) {
189 return qname.getLocalName();
190 }
191 }
192 }
193 return null;
194 }
195
196 private boolean importRequired(ASQName qname) {
197 if (currentPackageName != null && currentPackageName.equals(qname.getPackagePrefix())) {
198 return false;
199 }
200 return !currentPackageImports.contains(qname);
201 }
202
203 private void addImport(ASQName qname) {
204 currentPackage.addImport(qname.toString());
205 currentPackageImports.add(qname);
206 }
207
208 public void visit(ASMethod method) {
209
210 processAllArgs(method);
211 if (currentType instanceof ASClassType) {
212
213 processBody(method);
214 }
215 }
216
217 private void processAllArgs(ASMethod method) {
218 List args = method.getArgs();
219 for (Iterator i=args.iterator(); i.hasNext(); ) {
220 processArg((ASArg)i.next());
221 }
222 }
223
224 private void processArg(ASArg arg) {
225 String processedName = processTypeName(arg.getType());
226 if (processedName != null) {
227 arg.setType(processedName);
228 }
229 }
230
231 private void processBody(ASMethod method) {
232 LinkedListTree ast = ((ASTASMethod)method).getAST();
233 LinkedListTree body = (LinkedListTree)ast.getFirstChildWithType(AS3Parser.BLOCK);
234 processTreeForImports(body);
235 }
236
237
238
239
240 private void processTreeForImports(LinkedListTree ast) {
241 if (processNodeForImports(ast)) {
242 for (int i=0; i<ast.getChildCount(); i++) {
243 LinkedListTree child = (LinkedListTree)ast.getChild(i);
244 processTreeForImports(child);
245 }
246 }
247 }
248
249 private boolean processNodeForImports(LinkedListTree ast) {
250 switch (ast.getType()) {
251 case AS3Parser.TYPE_SPEC:
252 processTypeSpecForImports(ast);
253 return false;
254 case AS3Parser.IDENTIFIER:
255 processIdentifierForImports(ast);
256 return false;
257 case AS3Parser.PROPERTY_OR_IDENTIFIER:
258 processPropertyOrIdentifierForImports(ast);
259 return false;
260 }
261 return true;
262 }
263
264 private void processTypeSpecForImports(LinkedListTree ast) {
265 String typeName = ASTUtils.typeSpecText(ast);
266 String processedName = processTypeName(typeName);
267 if (processedName != null) {
268 LinkedListTree newTypeSpec = AS3FragmentParser.parseTypeSpec(processedName);
269 ast.setChildWithTokens(0, newTypeSpec.getFirstChild());
270 }
271 }
272
273 private void processIdentifierForImports(LinkedListTree ast) {
274 System.out.println(ASTUtils.identText(ast));
275 }
276
277 private ASQName processPropertyOrIdentifierForImports(LinkedListTree ast) {
278
279 LinkedListTree target = ast.getFirstChild();
280 LinkedListTree name = ast.getLastChild();
281 if (name.getType() != AS3Parser.IDENT) {
282 return null;
283 }
284 ASQName qname = null;
285 if (target.getType() == AS3Parser.PROPERTY_OR_IDENTIFIER) {
286 ASQName tmp = processPropertyOrIdentifierForImports(target);
287 if (tmp != null) {
288 qname = new ASQName(tmp.toString(), name.getText());
289 }
290 } else if (target.getType() == AS3Parser.IDENT) {
291 qname = new ASQName(target.getText(), name.getText());
292 }
293 if (qname == null) {
294 ast.token.setType(AS3Parser.PROPERTY_ACCESS);
295 } else {
296 String processedName = processTypeName(qname.toString());
297
298 if (processedName != null) {
299
300 int myIndex = ast.getParent().getIndexOfChild(ast);
301 ast.getParent().setChildWithTokens(myIndex, ASTUtils.newAST(AS3Parser.IDENT, processedName));
302 qname = null;
303 }
304 }
305 return qname;
306 }
307 }
308 }