/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2010.
*/
package x10.visit;
import java.util.ArrayList;
import java.util.List;
import polyglot.ast.ClassBody;
import polyglot.ast.ClassDecl;
import polyglot.ast.ClassMember;
import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.ast.SourceFile;
import polyglot.ast.TopLevelDecl;
import polyglot.frontend.Job;
import polyglot.types.ClassDef;
import polyglot.types.Name;
import polyglot.types.SemanticException;
import polyglot.types.TypeSystem;
import polyglot.types.Types;
import polyglot.visit.ContextVisitor;
import polyglot.visit.NodeVisitor;
/**
* This method removes static nested classes from the AST and promotes them to top-level classes, adjusting the ClassDef.
* Does not adjust references to the class, but it might work anyway if ClassType doesn't cache values from the Def.
* */
public class StaticNestedClassRemover extends ContextVisitor {
public StaticNestedClassRemover(Job job, TypeSystem ts, NodeFactory nf) {
super(job, ts, nf);
}
List<ClassDecl> orphans = new ArrayList<ClassDecl>();
@Override
protected Node leaveCall(Node parent, Node old, Node n, NodeVisitor v) throws SemanticException {
if (n instanceof ClassBody) {
ClassBody cb = (ClassBody) n;
List<ClassMember> members = new ArrayList<ClassMember>();
for (ClassMember cm : cb.members()) {
if (cm instanceof ClassDecl) {
ClassDecl cd = (ClassDecl) cm;
ClassDef def = cd.classDef();
assert def.kind() == ClassDef.MEMBER;
assert def.flags().isStatic();
Name newName = mangleName(def);
def.outer(null);
def.kind(ClassDef.TOP_LEVEL);
def.flags(def.flags().clearStatic().clearPrivate().clearProtected());
def.name(newName);
cd = cd.name(nf.Id(cd.name().position(), newName));
cd = cd.flags(cd.flags().flags(def.flags()));
orphans.add(cd);
}
else {
members.add(cm);
}
}
return cb.members(members);
}
if (n instanceof SourceFile) {
SourceFile sf = (SourceFile) n;
List<TopLevelDecl> decls = new ArrayList<TopLevelDecl>();
decls.addAll(sf.decls());
decls.addAll(orphans);
return sf.decls(decls);
}
return n;
}
public static Name mangleName(ClassDef def) {
Name newName = def.name();
for (ClassDef d = Types.get(def.outer()); d != null; d = Types.get(d.outer())) {
newName = Name.make(d.name().toString() + "$" + newName.toString());
}
return newName;
}
}