use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.ClassOrInterface in project ceylon by eclipse.
the class CeylonTransformer method makeDefs.
private List<JCTree> makeDefs(CompilationUnit t) {
final ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
t.visit(new SourceDeclarationVisitor() {
@Override
public void loadFromSource(Declaration decl) {
if (!checkNative(decl))
return;
Stack<Tree.Declaration> ancestors = new Stack<>();
long flags = decl instanceof Tree.AnyInterface ? Flags.INTERFACE : 0;
String name = Naming.toplevelClassName("", decl);
defs.add(makeClassDef(decl, flags, name, WantedDeclaration.Normal, defs, ancestors));
if (decl instanceof Tree.AnyInterface) {
String implName = Naming.getImplClassName(name);
defs.add(makeClassDef(decl, 0, implName, WantedDeclaration.InterfaceImpl, defs, ancestors));
}
if (Decl.isAnnotationClassNoModel(decl)) {
String annotationName = Naming.suffixName(Suffix.$annotation$, name);
defs.add(makeClassDef(decl, Flags.ANNOTATION | Flags.INTERFACE, annotationName, WantedDeclaration.Annotation, defs, ancestors));
if (Decl.isSequencedAnnotationClassNoModel((Tree.AnyClass) decl)) {
String annotationsName = Naming.suffixName(Suffix.$annotations$, name);
defs.add(makeClassDef(decl, Flags.ANNOTATION | Flags.INTERFACE, annotationsName, WantedDeclaration.AnnotationSequence, defs, ancestors));
}
}
}
private JCTree makeClassDef(Tree.Declaration decl, long flags, String name, WantedDeclaration wantedDeclaration, ListBuffer<JCTree> toplevelDeclarations, Stack<Tree.Declaration> ancestors) {
if (decl instanceof Tree.AnyInterface == false && TreeUtil.hasAnnotation(decl.getAnnotationList(), "static", null)) {
flags |= Flags.STATIC;
}
ListBuffer<JCTree.JCTypeParameter> typarams = new ListBuffer<JCTree.JCTypeParameter>();
if (decl instanceof Tree.ClassOrInterface) {
Tree.ClassOrInterface classDecl = (ClassOrInterface) decl;
if (decl instanceof Tree.AnyInterface) {
// interfaces are pulled up and catch container type params
for (Tree.Declaration ancestor : ancestors) {
if (ancestor instanceof Tree.ClassOrInterface) {
addTypeParameters(typarams, (Tree.ClassOrInterface) ancestor);
}
}
}
addTypeParameters(typarams, classDecl);
}
ancestors.push(decl);
JCTree ret = make().ClassDef(make().Modifiers(flags | Flags.PUBLIC), names().fromString(name), typarams.toList(), null, List.<JCExpression>nil(), makeClassBody(decl, wantedDeclaration, toplevelDeclarations, ancestors));
ancestors.pop();
return ret;
}
private void addTypeParameters(ListBuffer<JCTypeParameter> typarams, Tree.ClassOrInterface classDecl) {
if (classDecl.getTypeParameterList() != null) {
for (Tree.TypeParameterDeclaration typeParamDecl : classDecl.getTypeParameterList().getTypeParameterDeclarations()) {
// we don't need a valid name, just a name, and making it BOGUS helps us find it later if it turns out
// we failed to reset everything properly
typarams.add(make().TypeParameter(names().fromString("BOGUS-" + typeParamDecl.getIdentifier().getText()), List.<JCExpression>nil()));
}
}
}
private List<JCTree> makeClassBody(Declaration decl, WantedDeclaration wantedDeclaration, ListBuffer<JCTree> toplevelDeclarations, Stack<Tree.Declaration> ancestors) {
// only do it for Bootstrap where we control the annotations, because it's so dodgy ATM
if (wantedDeclaration == WantedDeclaration.Annotation) {
ListBuffer<JCTree> body = new ListBuffer<JCTree>();
for (Tree.Parameter param : ((Tree.ClassDefinition) decl).getParameterList().getParameters()) {
String name;
JCExpression type = make().TypeArray(make().Type(syms().stringType));
if (param instanceof Tree.InitializerParameter)
name = ((Tree.InitializerParameter) param).getIdentifier().getText();
else if (param instanceof Tree.ParameterDeclaration) {
Tree.TypedDeclaration typedDeclaration = ((Tree.ParameterDeclaration) param).getTypedDeclaration();
name = typedDeclaration.getIdentifier().getText();
type = getAnnotationTypeFor(typedDeclaration.getType());
} else
name = "ERROR";
JCMethodDecl method = make().MethodDef(make().Modifiers(Flags.PUBLIC), names().fromString(name), type, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
body.append(method);
}
return body.toList();
}
if (wantedDeclaration == WantedDeclaration.AnnotationSequence) {
String name = Naming.toplevelClassName("", decl);
String annotationName = Naming.suffixName(Suffix.$annotation$, name);
JCExpression type = make().TypeArray(make().Ident(names().fromString(annotationName)));
JCMethodDecl method = make().MethodDef(make().Modifiers(Flags.PUBLIC), names().fromString("value"), type, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
return List.<JCTree>of(method);
}
ListBuffer<JCTree> defs = new ListBuffer<>();
java.util.List<Statement> statements = null;
if (decl instanceof Tree.ClassDefinition)
statements = ((Tree.ClassDefinition) decl).getClassBody().getStatements();
else if (decl instanceof Tree.InterfaceDefinition) {
// only walk interface members if we're generating the impl class
if (wantedDeclaration == WantedDeclaration.InterfaceImpl)
statements = ((Tree.InterfaceDefinition) decl).getInterfaceBody().getStatements();
}
if (statements != null) {
for (Tree.Statement member : statements) {
if (member instanceof Tree.ClassOrInterface && checkNative((Tree.Declaration) member)) {
long flags = member instanceof Tree.AnyInterface ? Flags.INTERFACE : 0;
String initialName = Naming.toplevelClassName("", (Tree.Declaration) member);
String name;
if (member instanceof Tree.AnyInterface) {
// interfaces are pulled to the toplevel
StringBuffer strbuf = new StringBuffer();
for (Tree.Declaration part : ancestors) strbuf.append(part.getIdentifier().getText()).append("$");
name = strbuf.append(initialName).toString();
} else {
name = initialName;
}
JCTree def = makeClassDef((Tree.Declaration) member, flags, name, WantedDeclaration.Normal, toplevelDeclarations, ancestors);
if (member instanceof Tree.AnyInterface) {
toplevelDeclarations.add(def);
String implName = Naming.getImplClassName(initialName);
defs.add(makeClassDef((Tree.Declaration) member, 0, implName, WantedDeclaration.InterfaceImpl, defs, ancestors));
} else
defs.add(def);
// FIXME: interfaces impl?
}
}
}
return defs.toList();
}
private JCExpression getAnnotationTypeFor(Tree.Type type) {
if (type instanceof Tree.BaseType) {
String name = ((Tree.BaseType) type).getIdentifier().getText();
if (name.equals("String") || name.equals("Declaration"))
return make().Type(syms().stringType);
if (name.equals("Boolean"))
return make().Type(syms().booleanType);
if (name.equals("Integer"))
return make().Type(syms().longType);
if (name.equals("Float"))
return make().Type(syms().doubleType);
if (name.equals("Byte"))
return make().Type(syms().byteType);
if (name.equals("Character"))
return make().Type(syms().charType);
if (name.equals("Declaration") || name.equals("ClassDeclaration") || name.equals("InterfaceDeclaration") || name.equals("ClassOrInterfaceDeclaration"))
return make().Type(syms().stringType);
// probably an enum value then
return make().TypeArray(make().Type(syms().stringType));
}
if (type instanceof Tree.SequencedType) {
return make().TypeArray(getAnnotationTypeFor(((Tree.SequencedType) type).getType()));
}
if (type instanceof Tree.SequenceType) {
return make().TypeArray(getAnnotationTypeFor(((Tree.SequenceType) type).getElementType()));
}
if (type instanceof Tree.IterableType) {
return make().TypeArray(getAnnotationTypeFor(((Tree.IterableType) type).getElementType()));
}
if (type instanceof Tree.TupleType) {
// can only be one, must be a SequencedType
Tree.Type sequencedType = ((Tree.TupleType) type).getElementTypes().get(0);
return getAnnotationTypeFor(sequencedType);
}
System.err.println("Unknown Annotation type: " + type);
return make().TypeArray(make().Type(syms().stringType));
}
@Override
public void loadFromSource(ModuleDescriptor that) {
// don't think we care about these
}
@Override
public void loadFromSource(PackageDescriptor that) {
// don't think we care about these
}
});
return defs.toList();
}
Aggregations