use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class ClassTransformer method addAtMembers.
private void addAtMembers(ClassDefinitionBuilder classBuilder, ClassOrInterface model, Tree.ClassOrInterface def) {
List<JCExpression> members = List.nil();
for (Declaration member : model.getMembers()) {
if (member instanceof ClassOrInterface == false && member instanceof TypeAlias == false) {
continue;
}
TypeDeclaration innerType = (TypeDeclaration) member;
Tree.Declaration innerTypeTree = findInnerType(def, innerType.getName());
if (innerTypeTree != null) {
TransformationPlan plan = errors().hasDeclarationAndMarkBrokenness(innerTypeTree);
if (plan instanceof Drop) {
continue;
}
}
if (innerType.isAlias() && innerTypeTree != null && Decl.isAncestorLocal(innerTypeTree))
// for the same reason we do not generate aliases in transform(ClassOrInterface def) let's not list them
continue;
JCAnnotation atMember;
// interfaces are moved to toplevel so they can lose visibility of member types if they are local
if (Decl.isLocal(model) && model instanceof Interface)
atMember = makeAtMember(innerType.getName());
else
atMember = makeAtMember(innerType.getType());
members = members.prepend(atMember);
}
classBuilder.annotations(makeAtMembers(members));
}
use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class ClassTransformer method addAmbiguousMembers.
private void addAmbiguousMembers(ClassDefinitionBuilder classBuilder, Interface model) {
// only if we refine more than one interface
java.util.List<Type> satisfiedTypes = model.getSatisfiedTypes();
if (satisfiedTypes.size() <= 1)
return;
Set<Interface> satisfiedInterfaces = new HashSet<Interface>();
for (Type interfaceDecl : model.getSatisfiedTypes()) {
collectInterfaces((Interface) interfaceDecl.getDeclaration(), satisfiedInterfaces);
}
Set<Interface> ambiguousInterfaces = new HashSet<Interface>();
for (Interface satisfiedInterface : satisfiedInterfaces) {
if (isInheritedWithDifferentTypeArguments(satisfiedInterface, model.getType()) != null) {
ambiguousInterfaces.add(satisfiedInterface);
}
}
Set<String> treated = new HashSet<String>();
for (Interface ambiguousInterface : ambiguousInterfaces) {
for (Declaration member : ambiguousInterface.getMembers()) {
String name = member.getName();
// skip if already handled
if (treated.contains(name))
continue;
// skip if it's implemented directly
if (model.getDirectMember(name, null, false) != null) {
treated.add(name);
continue;
}
// find if we have different implementations in two direct interfaces
LOOKUP: for (int i = 0; i < satisfiedTypes.size(); i++) {
Type firstInterface = satisfiedTypes.get(i);
Declaration member1 = firstInterface.getDeclaration().getMember(name, null, false);
// if we can't find it in this interface, move to the next
if (member1 == null)
continue;
// try to find member in other interfaces
for (int j = i + 1; j < satisfiedTypes.size(); j++) {
Type secondInterface = satisfiedTypes.get(j);
Declaration member2 = secondInterface.getDeclaration().getMember(name, null, false);
// if we can't find it in this interface, move to the next
if (member2 == null)
continue;
// we have it in two separate interfaces
Reference typedMember1 = firstInterface.getTypedReference(member1, Collections.<Type>emptyList());
Reference typedMember2 = secondInterface.getTypedReference(member2, Collections.<Type>emptyList());
Type type1 = simplifyType(typedMember1.getType());
Type type2 = simplifyType(typedMember2.getType());
if (!type1.isExactly(type2)) {
// treat it and stop looking for other interfaces
addAmbiguousMember(classBuilder, model, name);
break LOOKUP;
}
}
}
// that member has no conflict
treated.add(name);
}
}
}
use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class ClassTransformer method addAtContainer.
private void addAtContainer(ClassDefinitionBuilder classBuilder, TypeDeclaration model) {
Scope scope = Decl.getNonSkippedContainer((Scope) model);
Scope declarationScope = Decl.getFirstDeclarationContainer((Scope) model);
boolean inlineObjectInToplevelAttr = Decl.isTopLevelObjectExpressionType(model);
if (scope == null || (scope instanceof Package && !inlineObjectInToplevelAttr) && scope == declarationScope)
return;
if (scope instanceof ClassOrInterface && scope == declarationScope && !inlineObjectInToplevelAttr && // we do not check for types inside initialiser section which are private and not captured because we treat them as members
!(model instanceof Interface && Decl.hasLocalNotInitializerAncestor(model))) {
ClassOrInterface container = (ClassOrInterface) scope;
List<JCAnnotation> atContainer = makeAtContainer(container.getType());
classBuilder.annotations(atContainer);
} else {
if (model instanceof Interface)
classBuilder.annotations(makeLocalContainerPath((Interface) model));
Declaration declarationContainer = getDeclarationContainer(model);
classBuilder.annotations(makeAtLocalDeclaration(model.getQualifier(), declarationContainer == null));
}
}
use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class ClassTransformer method transformSpecifiedMethodBody.
List<JCStatement> transformSpecifiedMethodBody(Tree.MethodDeclaration def, SpecifierExpression specifierExpression) {
final Function model = def.getDeclarationModel();
List<JCStatement> body;
Tree.MethodDeclaration methodDecl = def;
boolean isLazy = specifierExpression instanceof Tree.LazySpecifierExpression;
boolean returnNull = false;
JCExpression bodyExpr;
Tree.Term term = null;
if (specifierExpression != null && specifierExpression.getExpression() != null) {
term = Decl.unwrapExpressionsUntilTerm(specifierExpression.getExpression());
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(term);
if (error != null) {
return List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error));
}
}
if (!isLazy && term instanceof Tree.FunctionArgument) {
// Function specified with lambda: Don't bother generating a
// Callable, just transform the expr to use as the method body.
Tree.FunctionArgument fa = (Tree.FunctionArgument) term;
Type resultType = model.getType();
returnNull = isAnything(resultType) && fa.getExpression().getUnboxed();
final java.util.List<Tree.Parameter> lambdaParams = fa.getParameterLists().get(0).getParameters();
final java.util.List<Tree.Parameter> defParams = def.getParameterLists().get(0).getParameters();
List<Substitution> substitutions = List.nil();
for (int ii = 0; ii < lambdaParams.size(); ii++) {
substitutions = substitutions.append(naming.addVariableSubst((TypedDeclaration) lambdaParams.get(ii).getParameterModel().getModel(), defParams.get(ii).getParameterModel().getName()));
}
bodyExpr = gen().expressionGen().transformExpression(fa.getExpression(), returnNull ? BoxingStrategy.INDIFFERENT : CodegenUtil.getBoxingStrategy(model), resultType);
for (Substitution subs : substitutions) {
subs.close();
}
} else if (!isLazy && typeFact().isCallableType(term.getTypeModel())) {
returnNull = isAnything(term.getTypeModel()) && term.getUnboxed();
Function method = methodDecl.getDeclarationModel();
boolean lazy = specifierExpression instanceof Tree.LazySpecifierExpression;
boolean inlined = CodegenUtil.canOptimiseMethodSpecifier(term, method);
Invocation invocation;
if ((lazy || inlined) && term instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) term).getDeclaration() instanceof Functional) {
Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) term).getDeclaration();
Reference producedReference = ((Tree.MemberOrTypeExpression) term).getTarget();
invocation = new MethodReferenceSpecifierInvocation(this, (Tree.MemberOrTypeExpression) term, primaryDeclaration, producedReference, method, specifierExpression);
} else if (!lazy && !inlined) {
// must be a callable we stored
String name = naming.getMethodSpecifierAttributeName(method);
invocation = new CallableSpecifierInvocation(this, method, naming.makeUnquotedIdent(name), term, term);
} else if (isCeylonCallableSubtype(term.getTypeModel())) {
invocation = new CallableSpecifierInvocation(this, method, expressionGen().transformExpression(term), term, term);
} else {
throw new BugException(term, "unhandled primary: " + term == null ? "null" : term.getNodeType());
}
invocation.handleBoxing(true);
invocation.setErased(CodegenUtil.hasTypeErased(term) || getReturnTypeOfCallable(term.getTypeModel()).isNothing());
bodyExpr = expressionGen().transformInvocation(invocation);
} else {
bodyExpr = expressionGen().transformExpression(model, term);
// The innermost of an MPL method declared void needs to return null
returnNull = Decl.isUnboxedVoid(model) && Decl.isMpl(model);
}
if (!Decl.isUnboxedVoid(model) || Decl.isMpl(model) || Strategy.useBoxedVoid(model)) {
if (returnNull) {
body = List.<JCStatement>of(make().Exec(bodyExpr), make().Return(makeNull()));
} else {
body = List.<JCStatement>of(make().Return(bodyExpr));
}
} else {
body = List.<JCStatement>of(make().Exec(bodyExpr));
}
return body;
}
use of com.redhat.ceylon.model.typechecker.model.Declaration in project ceylon-compiler by ceylon.
the class ClassTransformer method addWriteReplace.
/**
* Adds a write replace method which replaces value constructor instances
* with a SerializationProxy
* @param model
* @param classBuilder
*/
protected void addWriteReplace(final Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, "writeReplace");
mdb.resultType(null, make().Type(syms().objectType));
mdb.modifiers(PRIVATE | FINAL);
ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
SyntheticName name = naming.synthetic(Unfix.$name$);
stmts.add(makeVar(FINAL, name, make().Type(syms().stringType), null));
if (model.hasEnumerated()) {
JCStatement tail;
if (Decl.hasOnlyValueConstructors(model)) {
tail = make().Throw(statementGen().makeNewEnumeratedTypeError("Instance not of any constructor"));
} else {
tail = make().Return(naming.makeThis());
}
for (Declaration member : model.getMembers()) {
if (Decl.isValueConstructor(member)) {
Value val = (Value) member;
tail = make().If(make().Binary(JCTree.EQ, naming.makeThis(), naming.getValueConstructorFieldName(val).makeIdent()), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(name.makeIdent(), make().Literal(Naming.getGetterName(member)))))), tail);
}
}
stmts.add(tail);
} else if (model.isAnonymous()) {
stmts.add(make().Exec(make().Assign(name.makeIdent(), make().Literal(Naming.getGetterName((Value) model.getContainer().getDirectMember(model.getName(), null, false))))));
} else {
throw new BugException("Unsupported need for writeReplace()");
}
// final String name;
// if(this == instA) {
// name = "getInstA";
// } // ... else { throw new
// return new SerializationProxy(outer, Foo.clazz, name);
List<JCExpression> args = List.<JCExpression>of(name.makeIdent());
if (model.isMember()) {
ClassOrInterface outer = (ClassOrInterface) model.getContainer();
args = args.prepend(makeClassLiteral(outer.getType()));
args = args.prepend(naming.makeQualifiedThis(naming.makeTypeDeclarationExpression(null, outer, DeclNameFlag.QUALIFIED)));
} else {
args = args.prepend(makeClassLiteral(model.getType()));
}
stmts.add(make().Return(make().NewClass(null, null, make().QualIdent(syms().ceylonSerializationProxyType.tsym), args, null)));
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
Aggregations