Search in sources :

Example 21 with Node

use of org.eclipse.ceylon.compiler.typechecker.tree.Node in project ceylon by eclipse.

the class ExpressionVisitor method warnUncheckedNulls.

private static void warnUncheckedNulls(Tree.LocalModifier local, Type type, Tree.Term term) {
    // often the LocalModifier doesn't have location info
    Node node = term == null ? local : term;
    Unit unit = local.getUnit();
    if (term instanceof Tree.InvocationExpression) {
        Tree.InvocationExpression ie = (Tree.InvocationExpression) term;
        Tree.Term p = ie.getPrimary();
        if (p instanceof Tree.StaticMemberOrTypeExpression) {
            Tree.StaticMemberOrTypeExpression bme = (Tree.StaticMemberOrTypeExpression) p;
            Declaration dec = bme.getDeclaration();
            if (dec != null) {
                String str = type.asSourceCodeString(unit);
                node.addUsageWarning(Warning.inferredNotNull, "not null type inferred from invocation of function with unchecked nulls: '" + dec.getName(unit) + "' is not known to be null-safe (explicitly specify the type '" + str + "' or '" + str + "?')");
                return;
            }
        }
    } else if (term instanceof Tree.StaticMemberOrTypeExpression) {
        Tree.StaticMemberOrTypeExpression bme = (Tree.StaticMemberOrTypeExpression) term;
        Declaration dec = bme.getDeclaration();
        if (dec != null) {
            String str = type.asSourceCodeString(unit);
            node.addUsageWarning(Warning.inferredNotNull, "not null type inferred from reference to value with unchecked nulls: '" + dec.getName(unit) + "' is not known to be null-safe (explicitly specify the type '" + str + "' or '" + str + "?')");
            return;
        }
    }
    String str = type.asSourceCodeString(unit);
    node.addUsageWarning(Warning.inferredNotNull, "not null type inferred from reference to function or value with unchecked nulls (explicitly specify the type '" + str + "' or '" + str + "?')");
}
Also used : Node(org.eclipse.ceylon.compiler.typechecker.tree.Node) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) ModelUtil.getNativeDeclaration(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getNativeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration) Unit(org.eclipse.ceylon.model.typechecker.model.Unit)

Example 22 with Node

use of org.eclipse.ceylon.compiler.typechecker.tree.Node in project ceylon by eclipse.

the class ExpressionVisitor method destructureTuple.

private void destructureTuple(Type sequenceType, Tree.TuplePattern tuplePattern) {
    List<Tree.Pattern> patterns = tuplePattern.getPatterns();
    int length = patterns.size();
    Tree.Pattern lastPattern = patterns.get(length - 1);
    boolean variadic = isVariadicPattern(lastPattern);
    List<Type> types = unit.getTupleElementTypes(sequenceType);
    boolean tupleLengthUnbounded = unit.isTupleLengthUnbounded(sequenceType);
    // boolean tupleVariantAtLeastOne =
    // unit.isTupleVariantAtLeastOne(sequenceType);
    int minimumLength = unit.getTupleMinimumLength(sequenceType);
    if (!variadic && types.size() > length) {
        tuplePattern.addError("assigned tuple has too many elements");
    }
    if (!variadic && tupleLengthUnbounded) {
        tuplePattern.addError("assigned tuple has unbounded length");
    }
    if (!variadic && minimumLength < types.size()) {
        tuplePattern.addError("assigned tuple has variadic length");
    }
    int fixedLength = variadic ? length - 1 : length;
    for (int i = 0; i < types.size() && i < fixedLength; i++) {
        Type type = types.get(i);
        Tree.Pattern pattern = patterns.get(i);
        destructure(pattern, type);
    }
    if (variadic) {
        Type tail = unit.getTailType(sequenceType, fixedLength);
        destructure(lastPattern, tail);
    }
    for (int i = types.size(); i < length; i++) {
        Tree.Pattern pattern = patterns.get(i);
        Node errNode;
        if (pattern instanceof Tree.VariablePattern) {
            Tree.VariablePattern vp = (Tree.VariablePattern) pattern;
            errNode = vp.getVariable();
        } else {
            errNode = pattern;
        }
        errNode.addError("assigned tuple has too few elements");
    }
}
Also used : ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) Node(org.eclipse.ceylon.compiler.typechecker.tree.Node) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnalyzerUtil.checkCasesDisjoint(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint) ModelUtil.argumentSatisfiesEnumeratedConstraint(org.eclipse.ceylon.model.typechecker.model.ModelUtil.argumentSatisfiesEnumeratedConstraint)

Example 23 with Node

use of org.eclipse.ceylon.compiler.typechecker.tree.Node in project ceylon by eclipse.

the class ExpressionVisitor method checkTypeArgumentAgainstDeclaration.

private boolean checkTypeArgumentAgainstDeclaration(Type receiver, Declaration dec, List<Type> typeArguments, Tree.TypeArguments tas, Node parent) {
    List<TypeParameter> params = dec.getTypeParameters();
    boolean explicit = tas instanceof Tree.TypeArgumentList;
    int min = 0;
    for (TypeParameter tp : params) {
        if (!tp.isDefaulted())
            min++;
    }
    if (receiver == null && dec.isClassOrInterfaceMember()) {
        receiver = parent.getScope().getDeclaringType(dec);
    }
    boolean enforceConstraints = modelLiteral || !(parent instanceof Tree.SimpleType) || ((Tree.SimpleType) parent).getInherited();
    int max = params.size();
    int args = typeArguments.size();
    if (args <= max && args >= min) {
        for (int i = 0; i < args; i++) {
            TypeParameter param = params.get(i);
            Type argType = typeArguments.get(i);
            boolean argTypeMeaningful = argType != null && !argType.isUnknown();
            if (argTypeMeaningful) {
                /*if (argType.isTypeConstructor() && 
                            !param.isTypeConstructor()) {
                        typeArgNode(tas, i, parent)
                            .addError("type argument must be a regular type: parameter '" + 
                                    param.getName() + 
                                    "' is a regular type parameter but '" +
                                    argType.asString(unit) + 
                                    "' is a type constructor");
                    }
                    else*/
                if (enforceConstraints && argType.isTypeParameter()) {
                    TypeParameter tp = (TypeParameter) argType.getDeclaration();
                    if (!tp.isReified() && param.isReified()) {
                        if (explicit) {
                            typeArgNode(tas, i, parent).addError("type parameter '" + param.getName() + "' of declaration '" + dec.getName(unit) + "' has argument '" + tp.getName() + "' which is not a reified type");
                        } else {
                            parent.addError("inferred type argument '" + tp.getName() + "' to type parameter '" + param.getName() + "' of declaration '" + dec.getName(unit) + "' is not a reified type");
                        }
                    }
                }
                if (!argType.isTypeConstructor() && param.isTypeConstructor()) {
                    typeArgNode(tas, i, parent).addError("type argument must be a type constructor: parameter '" + param.getName() + "' is a type constructor parameter but '" + argType.asString(unit) + "' is a regular type");
                } else if (param.isTypeConstructor()) {
                    Node argNode;
                    if (explicit) {
                        Tree.TypeArgumentList tl = (Tree.TypeArgumentList) tas;
                        argNode = tl.getTypes().get(i);
                    } else {
                        argNode = parent;
                    }
                    checkTypeConstructorParam(param, argType, argNode);
                }
            }
            List<Type> sts = param.getSatisfiedTypes();
            boolean hasConstraints = !sts.isEmpty() || param.getCaseTypes() != null;
            if (// !isCondition &&
            hasConstraints && enforceConstraints) {
                Type assignedType = argumentTypeForBoundsCheck(param, argType);
                for (Type st : sts) {
                    Type bound = st.appliedType(receiver, dec, typeArguments, null);
                    if (!assignedType.isSubtypeOf(bound)) {
                        if (argTypeMeaningful) {
                            if (explicit) {
                                typeArgNode(tas, i, parent).addError("type parameter '" + param.getName() + "' of declaration '" + dec.getName(unit) + "' has argument '" + assignedType.asString(unit) + "' which is not assignable to upper bound '" + bound.asString(unit) + "' of '" + param.getName() + "'", 2102);
                            } else {
                                parent.addError("inferred type argument '" + assignedType.asString(unit) + "' to type parameter '" + param.getName() + "' of declaration '" + dec.getName(unit) + "' is not assignable to upper bound '" + bound.asString(unit) + "' of '" + param.getName() + "'");
                            }
                        }
                        return false;
                    }
                }
                if (!argumentSatisfiesEnumeratedConstraint(receiver, dec, typeArguments, assignedType, param)) {
                    if (argTypeMeaningful) {
                        if (explicit) {
                            typeArgNode(tas, i, parent).addError("type parameter '" + param.getName() + "' of declaration '" + dec.getName(unit) + "' has argument '" + assignedType.asString(unit) + "' which is not one of the enumerated cases of '" + param.getName() + "'");
                        } else {
                            parent.addError("inferred type argument '" + assignedType.asString(unit) + "' to type parameter '" + param.getName() + "' of declaration '" + dec.getName(unit) + "' is not one of the enumerated cases of '" + param.getName() + "'");
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    } else {
        if (explicit) {
            StringBuilder paramList = typeParameterList(dec);
            String help;
            if (args < min) {
                help = " requires at least " + min + " type arguments to " + paramList;
            } else if (args > max) {
                help = " allows at most " + max + " type arguments to " + paramList;
            } else {
                help = "";
            }
            tas.addError("wrong number of type arguments: '" + dec.getName(unit) + "'" + help);
        } else {
        // Now handled in TypeArgumentVisitor
        // if (!metamodel) {
        // parent.addError("missing type arguments to generic type: '" +
        // dec.getName(unit) +
        // "' declares type parameters");
        // }
        }
        return false;
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) Node(org.eclipse.ceylon.compiler.typechecker.tree.Node) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnalyzerUtil.checkCasesDisjoint(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint) ModelUtil.argumentSatisfiesEnumeratedConstraint(org.eclipse.ceylon.model.typechecker.model.ModelUtil.argumentSatisfiesEnumeratedConstraint)

Example 24 with Node

use of org.eclipse.ceylon.compiler.typechecker.tree.Node in project ceylon by eclipse.

the class ExpressionVisitor method visit.

@Override
public void visit(Tree.MethodArgument that) {
    Tree.SpecifierExpression se = that.getSpecifierExpression();
    Function fun = that.getDeclarationModel();
    Tree.Type type = that.getType();
    if (se == null) {
        Declaration od = beginReturnDeclaration(fun);
        Tree.Type rt = beginReturnScope(type);
        super.visit(that);
        endReturnScope(rt, fun);
        endReturnDeclaration(od);
    } else {
        super.visit(that);
        Tree.Expression e = se.getExpression();
        if (e != null) {
            inferFunctionType(that, e);
            if (type != null && !(type instanceof Tree.DynamicModifier)) {
                checkFunctionType(e, type, se);
            }
            if (fun.isDeclaredVoid() && !isSatementExpression(e)) {
                se.addError("functional argument is declared void so specified expression must be a statement: '" + fun.getName() + "' is declared 'void'");
            }
        }
    }
    if (type instanceof Tree.LocalModifier) {
        if (isTypeUnknown(type.getTypeModel())) {
            if (se == null || hasError(type)) {
                Node node = type.getToken() == null ? that : type;
                node.addError("argument type could not be inferred");
            }
        }
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) Node(org.eclipse.ceylon.compiler.typechecker.tree.Node) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) ModelUtil.getNativeDeclaration(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getNativeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)

Example 25 with Node

use of org.eclipse.ceylon.compiler.typechecker.tree.Node in project ceylon by eclipse.

the class ExpressionVisitor method visit.

@Override
public void visit(Tree.Resource that) {
    super.visit(that);
    Type t = null;
    Node typedNode = null;
    Tree.Expression e = that.getExpression();
    Tree.Variable v = that.getVariable();
    if (e != null) {
        t = e.getTypeModel();
        typedNode = e;
    } else if (v != null) {
        t = v.getType().getTypeModel();
        typedNode = v.getType();
        Tree.SpecifierExpression se = v.getSpecifierExpression();
        if (se == null) {
            v.addError("missing resource specifier");
        } else {
            e = se.getExpression();
            if (typedNode instanceof Tree.ValueModifier) {
                typedNode = se.getExpression();
            }
        }
    } else {
        that.addError("missing resource expression");
    }
    if (typedNode != null) {
        if (!isTypeUnknown(t)) {
            if (e != null) {
                Type ot = unit.getObtainableType();
                Type dt = unit.getDestroyableType();
                Type act = unit.getJavaAutoCloseableType();
                if (!t.isSubtypeOf(act)) {
                    if (isInstantiationExpression(e)) {
                        if (!t.isSubtypeOf(dt) && !t.isSubtypeOf(ot)) {
                            typedNode.addError("resource must be either obtainable or destroyable: '" + t.asString(unit) + "' is neither 'Obtainable' nor 'Destroyable'");
                        }
                    } else {
                        checkAssignable(t, ot, typedNode, "resource must be obtainable");
                    }
                }
            }
        }
    }
}
Also used : ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) Node(org.eclipse.ceylon.compiler.typechecker.tree.Node) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Aggregations

Node (org.eclipse.ceylon.compiler.typechecker.tree.Node)33 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)26 Type (org.eclipse.ceylon.model.typechecker.model.Type)16 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)14 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)12 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)11 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)10 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)10 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)10 ModelUtil.genericFunctionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType)10 ModelUtil.unionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType)10 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)10 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)10 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)9 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)9 AnalyzerUtil.getTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration)7 AnalyzerUtil.getPackageTypeDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration)6 AnalyzerUtil.getPackageTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration)6 AnalyzerUtil.getTypeDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)6 AnalyzerUtil.checkCasesDisjoint (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint)5