use of org.eclipse.ceylon.model.typechecker.model.Declaration 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.Declaration in project ceylon by eclipse.
the class AnnotationVisitor method visit.
@Override
public void visit(Tree.Annotation that) {
super.visit(that);
Tree.MemberOrTypeExpression primary = (Tree.MemberOrTypeExpression) that.getPrimary();
Declaration dec = primary.getDeclaration();
/*if (dec!=null && !dec.isToplevel()) {
that.getPrimary().addError("annotation must be a toplevel function reference");
}*/
if (dec != null) {
if (!dec.isAnnotation()) {
primary.addError("not an annotation constructor: '" + dec.getName(that.getUnit()) + "'");
} else {
String pname = dec.getUnit().getPackage().getNameAsString();
String name = dec.getName();
switch(pname) {
case "java.lang":
switch(name) {
case "deprecated":
that.addError("illegal Java annotation (use 'deprecated' in 'ceylon.language')");
break;
case "override":
that.addError("illegal Java annotation (use 'actual' in 'ceylon.language')");
break;
}
break;
case "java.lang.annotation":
switch(name) {
case "target":
case "retention":
that.addError("illegal Java annotation");
}
}
checkAnnotationArguments(null, (Tree.InvocationExpression) that);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class AnnotationVisitor method checkAnnotations.
private void checkAnnotations(Tree.AnnotationList annotationList, Type declarationType, Type modelType, Node that) {
Unit unit = annotationList.getUnit();
List<Tree.Annotation> annotations = annotationList.getAnnotations();
for (Tree.Annotation annotation : annotations) {
Type t = annotation.getTypeModel();
if (t != null) {
TypeDeclaration cad = unit.getConstrainedAnnotationDeclaration();
Type cat = t.getSupertype(cad);
if (cat != null) {
// check *Ceylon* annotation constraints
List<Type> args = cat.getTypeArgumentList();
if (args.size() > 2) {
Type constraint = args.get(2);
checkAssignable(declarationType, constraint, annotation, "annotated program element does not satisfy annotation constraint");
}
if (args.size() > 3) {
Type constraint = args.get(3);
if (!constraint.isAnything()) {
checkAssignable(modelType, constraint, annotation, "annotated program element does not satisfy annotation constraint");
}
}
}
EnumSet<AnnotationTarget> target = null;
Tree.Primary primary = annotation.getPrimary();
if (primary instanceof Tree.MemberOrTypeExpression) {
Declaration ac = ((Tree.MemberOrTypeExpression) primary).getDeclaration();
if (ac instanceof TypedDeclaration) {
target = ((TypedDeclaration) ac).getAnnotationTargets();
}
}
if (target != null) {
// check the *Java* annotation constraints
boolean ok = false;
if (that instanceof Tree.PackageDescriptor) {
if (target.contains(PACKAGE)) {
ok = true;
}
}
if (that instanceof Tree.InterfaceDefinition) {
if (target.contains(TYPE)) {
ok = true;
}
}
if (that instanceof Tree.ClassDefinition) {
Tree.ClassDefinition c = (Tree.ClassDefinition) that;
boolean initializer = c.getParameterList() != null;
if (target.contains(TYPE)) {
// it always goes on the class,
// not on the constructor
ok = true;
}
if (target.contains(CONSTRUCTOR) && initializer) {
// it goes on the constructor
ok = true;
}
if (target.contains(ANNOTATION_TYPE) && c.getDeclarationModel().isAnnotation()) {
// it goes on the annotation type
ok = true;
}
}
if (that instanceof Tree.ObjectDefinition) {
if (target.contains(FIELD)) {
ok = true;
}
}
if (that instanceof Tree.Constructor || that instanceof Tree.Enumerated) {
if (target.contains(CONSTRUCTOR)) {
ok = true;
}
}
if (that instanceof Tree.MethodDefinition || that instanceof Tree.MethodDeclaration || that instanceof Tree.AttributeGetterDefinition || that instanceof Tree.AttributeSetterDefinition) {
if (target.contains(METHOD)) {
// it goes on the method, getter,
// or setter, unambiguously
ok = true;
}
}
if (that instanceof Tree.AttributeDeclaration) {
Tree.AttributeDeclaration ad = (Tree.AttributeDeclaration) that;
Value model = ad.getDeclarationModel();
boolean parameter = model.isParameter();
boolean classMember = model.isClassMember();
boolean toplevel = model.isToplevel();
boolean local = !toplevel && !model.isClassOrInterfaceMember();
if (target.contains(PARAMETER) && parameter) {
// in this case there is a parameter,
// so the annotation *never* goes on
// the field, getter, nor setter
ok = true;
}
Tree.SpecifierOrInitializerExpression se = ad.getSpecifierOrInitializerExpression();
if (se instanceof Tree.LazySpecifierExpression || model.isFormal()) {
if (target.contains(METHOD)) {
// there is no field, so it
// goes on the getter
ok = true;
}
} else {
// if it's cannot go on the field
if (classMember || toplevel) {
if (target.contains(FIELD)) {
ok = true;
} else if (target.contains(METHOD)) {
ok = true;
}
}
if (target.contains(LOCAL_VARIABLE) && !parameter && local) {
ok = true;
}
}
}
if (!ok) {
StringBuilder message = new StringBuilder();
for (AnnotationTarget at : target) {
if (message.length() > 0) {
message.append(", ");
}
message.append(at);
}
annotation.addError("annotated program element does not satisfy annotation constraint: the annotation is declared 'target {" + message + "}'");
}
}
}
}
TypeDeclaration od = unit.getOptionalAnnotationDeclaration();
for (int i = 0; i < annotations.size(); i++) {
Tree.Annotation ann = annotations.get(i);
Type t = ann.getTypeModel();
if (t != null) {
TypeDeclaration td = t.getDeclaration();
// this implicitly excludes Java annotations but they are checked in the backend for duplicates
if (td.inherits(od)) {
for (int j = 0; j < i; j++) {
Tree.Annotation other = annotations.get(j);
Type ot = other.getTypeModel();
if (ot != null) {
TypeDeclaration otd = ot.getDeclaration();
if (otd.equals(td)) {
ann.addError("duplicate annotation: there are multiple annotations of type '" + td.getName() + "'");
break;
}
}
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class AnnotationVisitor method checkServiceAnnotations.
private void checkServiceAnnotations(Class clazz, Tree.AnnotationList annotationList) {
for (Tree.Annotation ann : annotationList.getAnnotations()) {
Tree.BaseMemberExpression p = (Tree.BaseMemberExpression) ann.getPrimary();
Declaration pd = p.getDeclaration();
if (pd != null) {
Declaration sd = ann.getUnit().getLanguageModuleDeclaration("service");
if (pd.equals(sd)) {
checkServiceImplementation(clazz, getService(ann), ann);
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Declaration in project ceylon by eclipse.
the class ExpressionVisitor method handleStaticReferenceImplicitTypeArguments.
/**
* Validate the type arguments to the qualifying type
* in a static reference when no type arguments are
* given explicitly.
*
* This is called later than usual because the type args
* might be inferrable from an invocation of the whole
* static reference.
*
* @param that the static reference
*/
private void handleStaticReferenceImplicitTypeArguments(Tree.QualifiedMemberOrTypeExpression that) {
Declaration member = that.getDeclaration();
Tree.TypeArguments tas = that.getTypeArguments();
// without type arguments to the qualifying type
if (isStaticReference(that)) {
if (member != null && !explicitTypeArguments(member, tas)) {
that.addError("type arguments could not be inferred: '" + member.getName(unit) + "' is generic");
}
// the reference to the qualifying type
Tree.StaticMemberOrTypeExpression smte = (Tree.StaticMemberOrTypeExpression) that.getPrimary();
// we have to get the type args from the tree
// here because the calling code doesn't know
// them (it is walking the qualifying reference)
Tree.TypeArguments typeArgs = smte.getTypeArguments();
TypeDeclaration type = (TypeDeclaration) smte.getDeclaration();
if (type != null && !explicitTypeArguments(type, typeArgs) && typeArgs.getTypeModels() == null) {
// nothing inferred
Declaration declaration = smte.getDeclaration();
smte.addError("missing type arguments to generic type qualifying static reference: '" + declaration.getName(unit) + "' declares type parameters " + typeParameterList(declaration));
}
}
Tree.Primary primary = that.getPrimary();
if (!that.getDirectlyInvoked() && (member.isStatic() || isConstructor(member)) && primary instanceof Tree.StaticMemberOrTypeExpression) {
Tree.StaticMemberOrTypeExpression smte = (Tree.StaticMemberOrTypeExpression) primary;
Declaration qualifyingType = smte.getDeclaration();
Tree.TypeArguments qtas = smte.getTypeArguments();
if (qualifyingType != null && qualifyingType.isParameterized() && !qualifyingType.isJava() && !explicitTypeArguments(qualifyingType, qtas)) {
if (explicitTypeArguments(member, tas)) {
Type functionType = genericFunctionType(qualifyingType, that.getScope(), member, that.getTarget(), unit);
that.setTypeModel(functionType);
checkNotJvm(that, "type functions are not supported on the JVM: '" + qualifyingType.getName(unit) + "' is generic (specify explicit type arguments)");
} else {
that.addError("missing explicit type arguments to generic qualifying type: '" + qualifyingType.getName(unit) + "' declares type parameters " + typeParameterList(qualifyingType));
}
}
}
}
Aggregations