use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class RefinementVisitor method refineAttribute.
private void refineAttribute(Value assignedAttribute, Tree.BaseMemberExpression bme, Tree.SpecifierStatement that, ClassOrInterface c) {
if (!assignedAttribute.isFormal() && !assignedAttribute.isDefault() && !assignedAttribute.isShortcutRefinement()) {
// this condition is here to squash a dupe message
that.addError("inherited attribute may not be assigned in initializer and may not be refined: " + message(assignedAttribute) + " is declared neither 'formal' nor 'default'", 510);
// return;
} else if (assignedAttribute.isVariable()) {
that.addError("inherited attribute may not be assigned in initializer and may not be refined by non-variable: " + message(assignedAttribute) + " is declared 'variable'");
// return;
}
ClassOrInterface ci = (ClassOrInterface) assignedAttribute.getContainer();
String name = assignedAttribute.getName();
Declaration refined = ci.getRefinedMember(name, null, false);
Value root = refined instanceof Value ? (Value) refined : assignedAttribute;
Reference rv = getRefinedMemberReference(assignedAttribute, c);
boolean lazy = that.getSpecifierExpression() instanceof Tree.LazySpecifierExpression;
Value attribute = new Value();
attribute.setName(name);
attribute.setShared(true);
attribute.setActual(true);
attribute.getAnnotations().add(new Annotation("shared"));
attribute.getAnnotations().add(new Annotation("actual"));
attribute.setRefinedDeclaration(root);
Unit unit = that.getUnit();
attribute.setUnit(unit);
attribute.setContainer(c);
attribute.setScope(c);
attribute.setShortcutRefinement(true);
attribute.setTransient(lazy);
Declaration rvd = rv.getDeclaration();
if (rvd instanceof TypedDeclaration) {
TypedDeclaration rvtd = (TypedDeclaration) rvd;
attribute.setUncheckedNullType(rvtd.hasUncheckedNullType());
}
ModelUtil.setVisibleScope(attribute);
c.addMember(attribute);
that.setRefinement(true);
that.setDeclaration(attribute);
that.setRefined(assignedAttribute);
unit.addDeclaration(attribute);
setRefiningType(c, ci, name, null, false, root, attribute, unit, NO_SUBSTITUTIONS);
}
use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class RefinementVisitor method refineMethod.
private void refineMethod(Function assignedMethod, Tree.BaseMemberExpression bme, Tree.SpecifierStatement that, ClassOrInterface c) {
if (!assignedMethod.isFormal() && !assignedMethod.isDefault() && !assignedMethod.isShortcutRefinement()) {
// this condition is here to squash a dupe message
bme.addError("inherited method may not be refined: " + message(assignedMethod) + " is declared neither 'formal' nor 'default'", 510);
// return;
}
ClassOrInterface ci = (ClassOrInterface) assignedMethod.getContainer();
String name = assignedMethod.getName();
List<Type> signature = getSignature(assignedMethod);
boolean variadic = isVariadic(assignedMethod);
Declaration refined = ci.getRefinedMember(name, signature, variadic);
Function root = refined instanceof Function ? (Function) refined : assignedMethod;
Reference rm = getRefinedMemberReference(assignedMethod, c);
Function method = new Function();
method.setName(name);
List<Tree.ParameterList> paramLists;
List<TypeParameter> typeParams;
Tree.Term me = that.getBaseMemberExpression();
if (me instanceof Tree.ParameterizedExpression) {
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) me;
paramLists = pe.getParameterLists();
Tree.TypeParameterList typeParameterList = pe.getTypeParameterList();
if (typeParameterList != null) {
typeParams = new ArrayList<TypeParameter>();
for (Tree.TypeParameterDeclaration tpd : typeParameterList.getTypeParameterDeclarations()) {
typeParams.add(tpd.getDeclarationModel());
}
} else {
typeParams = null;
}
} else {
paramLists = emptyList();
typeParams = null;
}
Unit unit = that.getUnit();
final Map<TypeParameter, Type> subs;
if (typeParams != null) {
// the type parameters are written
// down in the shortcut refinement
method.setTypeParameters(typeParams);
// TODO: check 'em!!
// no need to check them because
// this case is actually disallowed
// elsewhere (specification statements
// may not have type parameters)
subs = NO_SUBSTITUTIONS;
} else if (assignedMethod.isParameterized()) {
if (me instanceof Tree.ParameterizedExpression) {
// we have parameters, but no type parameters
bme.addError("refined method is generic: '" + assignedMethod.getName(unit) + "' declares type parameters");
subs = NO_SUBSTITUTIONS;
} else {
// we're assigning a method reference
// so we need to magic up some "fake"
// type parameters
subs = copyTypeParametersFromRefined(assignedMethod, method, unit);
}
} else {
subs = NO_SUBSTITUTIONS;
}
int i = 0;
for (ParameterList pl : assignedMethod.getParameterLists()) {
Tree.ParameterList params = paramLists.size() <= i ? null : paramLists.get(i++);
createRefiningParameterList(rm, method, params, unit, subs, pl);
}
method.setShared(true);
method.setActual(true);
method.getAnnotations().add(new Annotation("shared"));
method.getAnnotations().add(new Annotation("actual"));
method.setRefinedDeclaration(root);
method.setUnit(unit);
method.setContainer(c);
method.setScope(c);
method.setShortcutRefinement(true);
method.setDeclaredVoid(assignedMethod.isDeclaredVoid());
Declaration rmd = rm.getDeclaration();
if (rmd instanceof TypedDeclaration) {
TypedDeclaration rmtd = (TypedDeclaration) rmd;
method.setUncheckedNullType(rmtd.hasUncheckedNullType());
}
ModelUtil.setVisibleScope(method);
c.addMember(method);
that.setRefinement(true);
that.setDeclaration(method);
that.setRefined(root);
unit.addDeclaration(method);
Scope scope = that.getScope();
if (scope instanceof Specification) {
Specification spec = (Specification) scope;
spec.setDeclaration(method);
}
setRefiningType(c, ci, name, signature, variadic, root, method, unit, subs);
inheritDefaultedArguments(method);
}
use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class TypeArgumentInference method inferFunctionRefTypeArgs.
/**
* Infer type arguments for a direct function
* ref (i.e. not a value ref with a type
* constructor type) that occurs as an argument
* to a callable parameter.
*/
private List<Type> inferFunctionRefTypeArgs(Tree.StaticMemberOrTypeExpression smte, Type receiverType, boolean secondList, Declaration reference, List<TypeParameter> typeParameters, TypedReference paramTypedRef, Declaration paramDec, Declaration parameterizedDec) {
Reference arg = appliedReference(smte);
Functional fun = (Functional) reference;
List<ParameterList> apls = fun.getParameterLists();
Functional pfun = (Functional) paramDec;
List<ParameterList> ppls = pfun.getParameterLists();
if (apls.isEmpty() || ppls.isEmpty()) {
// TODO: to give a nicer error
return null;
} else {
ParameterList aplf = apls.get(secondList ? 1 : 0);
ParameterList pplf = ppls.get(0);
List<Parameter> apl = aplf.getParameters();
List<Parameter> ppl = pplf.getParameters();
boolean[] specifiedParams = specifiedParameters(apl.size(), ppl.size());
List<Type> inferredTypes = new ArrayList<Type>(typeParameters.size());
for (TypeParameter tp : typeParameters) {
boolean findUpperBounds = isEffectivelyContravariant(tp, reference, specifiedParams, secondList);
Type it = inferFunctionRefTypeArg(smte, tp, typeParameters, paramTypedRef, parameterizedDec, arg, apl, ppl, findUpperBounds);
inferredTypes.add(it);
}
return constrainInferredTypes(typeParameters, inferredTypes, receiverType, reference);
}
}
use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class TypeHierarchyVisitor method addUnimplementedFormal.
private void addUnimplementedFormal(Class clazz, Declaration member) {
Reference unimplemented = member.appliedReference(clazz.getType(), NO_TYPE_ARGS);
List<Reference> list = clazz.getUnimplementedFormals();
if (list.isEmpty()) {
list = new ArrayList<Reference>();
clazz.setUnimplementedFormals(list);
}
list.add(unimplemented);
}
use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class ClassImpl method getDeclaredConstructor.
@Override
@TypeParameters(@TypeParameter(value = "Arguments", satisfies = "ceylon.language::Sequential<ceylon.language::Anything>"))
@TypeInfo("ceylon.language.meta.model::CallableConstructor<Type,Arguments>|ceylon.language.meta.model::ValueConstructor<Type>|ceylon.language::Null")
public <Arguments extends Sequential<? extends Object>> java.lang.Object getDeclaredConstructor(@Ignore TypeDescriptor $reified$Arguments, @Name("name") String name) {
checkInit();
final ceylon.language.meta.declaration.Declaration ctor = ((ClassDeclarationImpl) declaration).getConstructorDeclaration(name);
if (ctor == null)
return null;
if (ctor instanceof CallableConstructorDeclaration) {
if (ctor instanceof ClassWithInitializerDeclarationConstructor) {
TypeDescriptor actualReifiedArguments = Metamodel.getTypeDescriptorForArguments(declaration.declaration.getUnit(), (Functional) ((ClassWithInitializerDeclarationConstructor) ctor).declaration, this.producedType);
Metamodel.checkReifiedTypeArgument("getDeclaredConstructor", "CallableConstructor<$1,$2>", // // this line is bullshit since it's always true, but otherwise we can't substitute the error message above :(
Variance.OUT, this.producedType, $reifiedType, Variance.IN, Metamodel.getProducedType(actualReifiedArguments), $reified$Arguments);
ClassInitializerConstructor c = new ClassInitializerConstructor<>(this);
return c;
}
CallableConstructorDeclarationImpl callableCtor = (CallableConstructorDeclarationImpl) ctor;
org.eclipse.ceylon.model.typechecker.model.Type constructorType = callableCtor.constructor.appliedType(this.producedType, Collections.<org.eclipse.ceylon.model.typechecker.model.Type>emptyList());
// return new AppliedConstructor<Type,Args>(this.$reifiedType, actualReifiedArguments, this, constructorType, ctor, this.instance);
// Reference reference = ((Function)callableCtor.declaration).getReference();
Reference reference;
if (callableCtor.declaration instanceof Function) {
reference = ((Function) callableCtor.declaration).appliedTypedReference(producedType, null);
} else if (callableCtor.declaration instanceof org.eclipse.ceylon.model.typechecker.model.Class) {
reference = ((org.eclipse.ceylon.model.typechecker.model.Class) callableCtor.declaration).appliedReference(producedType, null);
} else if (callableCtor.declaration instanceof org.eclipse.ceylon.model.typechecker.model.Constructor) {
reference = ((org.eclipse.ceylon.model.typechecker.model.Constructor) callableCtor.declaration).appliedReference(producedType, null);
} else {
throw Metamodel.newModelError("Unexpect declaration " + callableCtor.declaration);
}
// anonymous classes don't have parameter lists
TypeDescriptor actualReifiedArguments = Metamodel.getTypeDescriptorForArguments(declaration.declaration.getUnit(), (Functional) callableCtor.declaration, reference);
// This is all very ugly but we're trying to make it cheaper and friendlier than just checking the full type and showing
// implementation types to the user, such as AppliedMemberClass
Metamodel.checkReifiedTypeArgument("getConstructor", "Constructor<$1,$2>", // this line is bullshit since it's always true, but otherwise we can't substitute the error message above :(
Variance.OUT, this.producedType, $reifiedType, Variance.IN, Metamodel.getProducedType(actualReifiedArguments), $reified$Arguments);
CallableConstructorImpl<Type, Sequential<? extends Object>> appliedConstructor = new CallableConstructorImpl<Type, Sequential<? extends java.lang.Object>>(this.$reifiedType, $reified$Arguments, reference, callableCtor, this, instance);
Metamodel.checkReifiedTypeArgument("apply", "CallableConstructor<$1,$2>", Variance.OUT, producedType, $reifiedType, Variance.IN, Metamodel.getProducedTypeForArguments(declaration.declaration.getUnit(), (Functional) callableCtor.declaration, reference), $reified$Arguments);
return appliedConstructor;
} else if (ctor instanceof ValueConstructorDeclaration) {
ValueConstructorDeclarationImpl callableCtor = (ValueConstructorDeclarationImpl) ctor;
org.eclipse.ceylon.model.typechecker.model.Type constructorType = callableCtor.constructor.appliedType(this.producedType, Collections.<org.eclipse.ceylon.model.typechecker.model.Type>emptyList());
TypedDeclaration val = (TypedDeclaration) callableCtor.constructor.getContainer().getDirectMember(callableCtor.constructor.getName(), null, false);
return new ValueConstructorImpl<Type>(this.$reifiedType, callableCtor, val.getTypedReference(), this, instance);
} else {
throw new AssertionError("Constructor neither CallableConstructorDeclaration nor ValueConstructorDeclaration");
}
}
Aggregations