use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class ExpressionVisitor method getBaseReceivingType.
protected Type getBaseReceivingType(Tree.InvocationExpression that, Declaration dec) {
Scope scope = that.getScope();
if (dec.isClassOrInterfaceMember() && !dec.isStatic() && !dec.isDefinedInScope(scope)) {
ClassOrInterface ci = (ClassOrInterface) dec.getContainer();
Type qualifyingType = scope.getDeclaringType(dec);
List<Type> inferredArgs = new TypeArgumentInference(unit).getInferredTypeArgsForReference(that, dec, ci, qualifyingType);
return ci.appliedType(null, inferredArgs);
} else {
return null;
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class ExpressionVisitor method visitIndirectInvocation.
/**
* Typecheck an indirect invocation.
*/
private void visitIndirectInvocation(Tree.InvocationExpression that) {
Tree.Term primary = unwrapExpressionUntilTerm(that.getPrimary());
if (primary == null) {
return;
}
Type pt = primary.getTypeModel();
if (!isTypeUnknown(pt)) {
if (that.getNamedArgumentList() != null) {
that.addError("named arguments not supported for indirect invocations");
return;
}
Tree.PositionalArgumentList pal = that.getPositionalArgumentList();
if (pal == null) {
return;
}
if (pt.isNothing()) {
that.setTypeModel(unit.getNothingType());
} else if (checkCallable(pt, primary, "invoked expression must be callable")) {
Interface cd = unit.getCallableDeclaration();
Type ct = pt.getSupertype(cd);
if (ct == null) {
primary.addError("invoked expression must be callable: type '" + pt.asString(unit) + "' involves a type function");
return;
}
List<Type> typeArgs = ct.getTypeArgumentList();
if (!typeArgs.isEmpty()) {
that.setTypeModel(typeArgs.get(0));
}
// typecheck arguments using the type args of Callable
if (typeArgs.size() >= 2) {
Type paramTypesAsTuple = typeArgs.get(1);
if (paramTypesAsTuple != null) {
TypeDeclaration pttd = paramTypesAsTuple.getDeclaration();
if (pttd instanceof ClassOrInterface && (pttd.isEmpty() || pttd.isTuple() || pttd.isSequence() || pttd.isSequential())) {
// we have a plain tuple type so we can check the
// arguments individually
checkIndirectInvocationArguments(that, paramTypesAsTuple, unit.getTupleElementTypes(paramTypesAsTuple), unit.isTupleLengthUnbounded(paramTypesAsTuple), unit.isTupleVariantAtLeastOne(paramTypesAsTuple), unit.getTupleMinimumLength(paramTypesAsTuple));
} else {
// we have something exotic, a union of tuple types
// or whatever, so just check the whole argument tuple
Type tt = getTupleType(pal.getPositionalArguments(), unit, false);
checkAssignable(tt, paramTypesAsTuple, pal, "argument list type must be assignable to parameter list type");
}
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class ExpressionVisitor method refineMethod.
private void refineMethod(Tree.SpecifierStatement that) {
Function refinedMethod = (Function) that.getRefined();
Function method = (Function) that.getDeclaration();
ClassOrInterface ci = (ClassOrInterface) method.getContainer();
Declaration root = method.getRefinedDeclaration();
TypeDeclaration td = (TypeDeclaration) root.getContainer();
List<Declaration> interveningRefinements = getInterveningRefinements(method, root, ci, td);
if (interveningRefinements.isEmpty()) {
that.getBaseMemberExpression().addError("shortcut refinement does not exactly refine any overloaded inherited member");
} else {
Reference refinedProducedReference = accountForIntermediateRefinements(that, refinedMethod, method, ci, interveningRefinements);
List<Tree.ParameterList> parameterLists;
Tree.Term me = that.getBaseMemberExpression();
if (me instanceof Tree.ParameterizedExpression) {
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) me;
parameterLists = pe.getParameterLists();
} else {
parameterLists = emptyList();
}
List<ParameterList> refinedParamLists = refinedMethod.getParameterLists();
List<ParameterList> methodParamLists = method.getParameterLists();
Map<TypeParameter, Type> subs = substitutions(refinedMethod, method);
for (int i = 0; i < refinedParamLists.size() && i < methodParamLists.size(); i++) {
ParameterList refinedParameters = refinedParamLists.get(i);
ParameterList parameters = methodParamLists.get(i);
Tree.ParameterList parameterList = parameterLists.size() <= i ? null : parameterLists.get(i);
List<Parameter> rps = refinedParameters.getParameters();
for (int j = 0; j < rps.size(); j++) {
Parameter refinedParameter = rps.get(j);
Type refinedParameterType = refinedProducedReference.getTypedParameter(refinedParameter).getFullType().substitute(subs, null);
Parameter parameter;
if (parameterList == null || parameterList.getParameters().size() <= j) {
parameter = parameters.getParameters().get(j);
parameter.getModel().setType(refinedParameterType);
parameter.setSequenced(refinedParameter.isSequenced());
} else {
Tree.Parameter param = parameterList.getParameters().get(j);
parameter = param.getParameterModel();
Type parameterType = parameter.getModel().getTypedReference().getFullType();
Node typeNode = param;
if (param instanceof Tree.ParameterDeclaration) {
Tree.ParameterDeclaration pd = (Tree.ParameterDeclaration) param;
Tree.Type type = pd.getTypedDeclaration().getType();
if (type != null) {
typeNode = type;
}
}
checkIsExactlyIgnoringNull(refinedParameters.isNamedParametersSupported(), parameterType, refinedParameterType, typeNode, "type of parameter '" + parameter.getName() + "' of '" + method.getName() + "' declared by '" + ci.getName() + "' is different to type of corresponding parameter " + message(refinedMethod, refinedParameter), 9200);
if (refinedParameter.isSequenced() && !parameter.isSequenced()) {
param.addError("parameter must be variadic: parameter " + message(refinedMethod, refinedParameter) + " is variadic");
}
if (!refinedParameter.isSequenced() && parameter.isSequenced()) {
param.addError("parameter may not be variadic: parameter " + message(refinedMethod, refinedParameter) + " is not variadic");
}
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class AnnotationVisitor method checkServiceImplementation.
private void checkServiceImplementation(Class clazz, Declaration d, Node that) {
if (d instanceof ClassOrInterface) {
ClassOrInterface service = (ClassOrInterface) d;
ParameterList pl = clazz.getParameterList();
if (pl == null) {
that.addError("service class must have a parameter list or default constructor");
} else {
List<Parameter> params = pl.getParameters();
if (!params.isEmpty() && !params.get(0).isDefaulted()) {
that.addError("service class must be instantiable with an empty argument list");
}
}
if (clazz.inherits(service)) {
ModelUtil.getModule(clazz).addService(service, clazz);
} else {
that.addError("service class does not implement service '" + service + "'");
}
} else {
that.addError("service must be an interface or class");
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class ExpressionVisitor method visit.
@Override
public void visit(Tree.Super that) {
ClassOrInterface ci = getContainingClassOrInterface(that.getScope());
if (inExtendsClause) {
// supertype of the outer class
if (ci != null) {
if (ci.isClassOrInterfaceMember()) {
ClassOrInterface cci = (ClassOrInterface) ci.getContainer();
that.setDeclarationModel(cci);
that.setTypeModel(intersectionOfSupertypes(cci));
}
}
} else {
// TODO: for consistency, move these errors to SelfReferenceVisitor
if (ci == null) {
that.addError("'super' occurs outside any type definition");
} else {
that.setDeclarationModel(ci);
that.setTypeModel(intersectionOfSupertypes(ci));
}
}
}
Aggregations