use of org.eclipse.ceylon.model.typechecker.model.Type in project ceylon by eclipse.
the class ExpressionVisitor method visit.
@Override
public void visit(Tree.IsCondition that) {
// don't recurse to the Variable, since we don't
// want to check that the specifier expression is
// assignable to the declared variable type
// (nor is it possible to infer the variable type)
// isCondition=true;
Tree.Type t = that.getType();
if (t != null) {
t.visit(this);
}
// isCondition=false;
Tree.Variable v = that.getVariable();
Type type = t == null ? null : t.getTypeModel();
if (v != null) {
// if (type!=null && !that.getNot()) {
// v.getType().setTypeModel(type);
// v.getDeclarationModel().setType(type);
// }
// v.getType().visit(this);
Tree.SpecifierExpression se = v.getSpecifierExpression();
Type knownType;
if (se == null) {
knownType = null;
} else {
se.visit(this);
checkReferenceIsNonVariable(v, se);
/*checkAssignable( se.getExpression().getTypeModel(),
getOptionalType(getObjectDeclaration().getType()),
se.getExpression(),
"expression may not be of void type");*/
initOriginalDeclaration(v);
// this is a bit ugly (the parser sends us a SyntheticVariable
// instead of the real StaticType which it very well knows!)
Tree.Expression e = se.getExpression();
knownType = e == null ? null : e.getTypeModel();
// TODO: what to do here in case of !is
if (knownType != null && !isTypeUnknown(knownType)) {
// TODO: remove this if we make unknown a subtype of Anything
if (!isTypeUnknown(type)) {
checkReified(t, type, knownType, that.getAssertion());
}
Type checkType;
if (hasUncheckedNulls(e)) {
checkType = unit.getOptionalType(knownType);
// and widens to optional
if (unit.getNullType().isSubtypeOf(type)) {
knownType = checkType;
}
} else {
checkType = knownType;
}
if (that.getNot()) {
if (intersectionType(type, checkType, unit).isNothing()) {
that.addUsageWarning(Warning.redundantNarrowing, "condition does not narrow type: intersection of '" + type.asString(unit) + "' and '" + knownType.asString(unit) + "' is empty" + " (expression is already of the specified type)");
} else if (checkType.isSubtypeOf(type)) {
that.addUsageWarning(Warning.redundantNarrowing, "condition tests assignability to bottom type 'Nothing': '" + knownType.asString(unit) + "' is a subtype of '" + type.asString(unit) + "'");
}
} else {
if (checkType.isSubtypeOf(type)) {
that.addUsageWarning(Warning.redundantNarrowing, "condition does not narrow type: '" + knownType.asString(unit) + "' is a subtype of '" + type.asString(unit) + "'" + " (expression is already of the specified type)");
}
}
}
}
defaultTypeToAnything(v);
if (knownType == null) {
// or should we use unknown?
knownType = unit.getAnythingType();
}
Type it = narrow(type, knownType, that.getNot());
// check for disjointness
if (it.isNothing()) {
if (that.getNot()) {
/*that.addError("tests assignability to Nothing type: " +
knownType.asString(unit) + " is a subtype of " +
type.asString(unit));*/
} else {
that.addUsageWarning(Warning.redundantNarrowing, "condition tests assignability to bottom type 'Nothing': intersection of '" + knownType.asString(unit) + "' and '" + type.asString(unit) + "' is empty");
}
}
// do this *after* checking for disjointness!
knownType = unit.denotableType(knownType);
// now recompute the narrowed type!
it = narrow(type, knownType, that.getNot());
v.getType().setTypeModel(it);
v.getDeclarationModel().setType(it);
if (!canHaveUncheckedNulls(it)) {
v.getDeclarationModel().setUncheckedNullType(false);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Type in project ceylon by eclipse.
the class ExpressionVisitor method checkContainedType.
private void checkContainedType(Tree.Variable var, Tree.SpecifierExpression se) {
Tree.Type type = var.getType();
if (type != null && se != null) {
Tree.Expression e = se.getExpression();
if (e != null) {
Type vt = type.getTypeModel();
Type expressionType = e.getTypeModel();
if (!isTypeUnknown(vt) && !isTypeUnknown(expressionType)) {
Type it = unit.getElementType(expressionType);
checkAssignable(it, vt, var, "iterable element type must be assignable to iterator variable type");
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Type in project ceylon by eclipse.
the class ExpressionVisitor method checkPositionalArguments.
private void checkPositionalArguments(ParameterList pl, Reference pr, Tree.PositionalArgumentList pal, Tree.InvocationExpression that) {
List<Tree.PositionalArgument> args = pal.getPositionalArguments();
List<Parameter> params = pl.getParameters();
Declaration target = pr.getDeclaration();
int argCount = args.size();
int paramsSize = params.size();
for (int i = 0; i < paramsSize; i++) {
Parameter param = params.get(i);
if (i >= argCount) {
if (isRequired(param)) {
Node errorNode = that instanceof Tree.Annotation && args.isEmpty() ? that : pal;
StringBuilder message = new StringBuilder();
if (i + 1 < paramsSize && isRequired(params.get(i + 1))) {
message.append("missing arguments to required parameters '");
appendParam(pr, param, message);
int count = 1;
for (int j = i + 1; j < paramsSize; j++) {
Parameter p = params.get(j);
if (p.isDefaulted() || p.isSequenced() && !p.isAtLeastOne()) {
break;
}
message.append(", ");
appendParam(pr, p, message);
count++;
}
message.append("'").insert(20, " " + count);
} else {
message.append("missing argument to required parameter '");
appendParam(pr, param, message);
message.append("'");
}
message.append(" of '").append(target.getName(unit)).append("'");
errorNode.addError(message.toString());
break;
}
} else {
Tree.PositionalArgument arg = args.get(i);
Type pt = param.getType();
if (!dynamic && isTypeUnknown(pt)) {
arg.addError("parameter type could not be determined: " + paramdesc(param) + getTypeUnknownError(pt));
}
if (arg instanceof Tree.SpreadArgument) {
checkSpreadArgument(pr, param, arg, (Tree.SpreadArgument) arg, params.subList(i, paramsSize));
break;
} else if (arg instanceof Tree.Comprehension) {
if (param.isSequenced()) {
checkComprehensionPositionalArgument(param, pr, (Tree.Comprehension) arg, param.isAtLeastOne());
} else {
arg.addError("not a variadic parameter: parameter '" + param.getName() + "' of '" + target.getName() + "'");
}
break;
} else {
if (param.isSequenced()) {
checkSequencedPositionalArgument(param, pr, args.subList(i, argCount));
// Note: early return!
return;
} else {
checkPositionalArgument(param, pr, (Tree.ListedArgument) arg);
}
}
}
}
for (int i = paramsSize; i < argCount; i++) {
Tree.PositionalArgument arg = args.get(i);
if (arg instanceof Tree.SpreadArgument) {
if (unit.isEmptyType(arg.getTypeModel())) {
continue;
}
}
arg.addError("no matching parameter declared by '" + target.getName(unit) + "': '" + target.getName(unit) + "' has " + paramsSize + " parameters", 2000);
}
checkJavaAnnotationElements(args, params, target);
}
use of org.eclipse.ceylon.model.typechecker.model.Type 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.Type in project ceylon by eclipse.
the class ExpressionVisitor method visit.
@Override
public void visit(Tree.QualifiedType that) {
super.visit(that);
TypeDeclaration type = that.getDeclarationModel();
if (type != null) {
type = (TypeDeclaration) handleNativeHeader(type, that, true);
if (!type.isVisible(that.getScope())) {
if (type instanceof Constructor) {
that.addError("constructor is not visible: " + qualifiedDescription(that), 400);
} else {
that.addError("member type is not visible: " + qualifiedDescription(that), 400);
}
} else if (type.isPackageVisibility() && !declaredInPackage(type, unit)) {
that.addError("member type is not visible: " + qualifiedDescription(that) + " is package private");
} else // in fact this restriction is OK
if (type.isProtectedVisibility() && !declaredInPackage(type, unit)) {
that.addError("member type is not visible: " + qualifiedDescription(that) + " is protected");
}
// Note: we should remove this check if we ever
// make qualified member types like T.Member
// into a sort of virtual type
Tree.StaticType outerType = that.getOuterType();
if (outerType instanceof Tree.SimpleType) {
Tree.SimpleType st = (Tree.SimpleType) outerType;
TypeDeclaration std = st.getDeclarationModel();
if (std.isAlias()) {
Type et = std.getExtendedType();
if (et != null) {
std = et.resolveAliases().getDeclaration();
}
}
if (std instanceof TypeParameter) {
outerType.addError("type parameter should not occur as qualifying type: '" + std.getName(unit) + "' is a type parameter");
}
}
}
}
Aggregations