String paramName = getAnnotationStringValue(paramMirror, CEYLON_NAME_ANNOTATION);
// use whatever param name we find as default
if(paramName == null)
paramName = paramMirror.getName();
Parameter parameter = new Parameter();
parameter.setName(paramName);
TypeMirror typeMirror = paramMirror.getType();
Module module = Decl.getModuleContainer((Scope) decl);
ProducedType type;
if(isVariadic){
// possibly make it optional
TypeMirror variadicType = typeMirror.getComponentType();
// we pretend it's toplevel because we want to get magic string conversion for variadic methods
type = obtainType(Decl.getModuleContainer((Scope)decl), variadicType, (Scope)decl, TypeLocation.TOPLEVEL, VarianceLocation.CONTRAVARIANT);
if(!isCeylon && !variadicType.isPrimitive()){
// Java parameters are all optional unless primitives
ProducedType optionalType = getOptionalType(type, module);
optionalType.setUnderlyingType(type.getUnderlyingType());
type = optionalType;
}
// turn it into a Sequential<T>
type = typeFactory.getSequentialType(type);
}else{
type = obtainType(typeMirror, paramMirror, (Scope) decl, module, VarianceLocation.CONTRAVARIANT,
"parameter '"+paramName+"' of method '"+methodMirror.getName()+"'", (Declaration)decl);
// variadic params may technically be null in Java, but it Ceylon sequenced params may not
// so it breaks the typechecker logic for handling them, and it will always be a case of bugs
// in the java side so let's not allow this
if(!isCeylon && !typeMirror.isPrimitive()){
// Java parameters are all optional unless primitives
ProducedType optionalType = getOptionalType(type, module);
optionalType.setUnderlyingType(type.getUnderlyingType());
type = optionalType;
}
}
MethodOrValue value = null;
if (isCeylon && decl instanceof Class){
// For a functional parameter to a class, we can just lookup the member
value = (MethodOrValue)((Class)decl).getDirectMember(paramName, null, false);
}
if (value == null) {
// So either decl is not a Class,
// or the method or value member of decl is not shared
AnnotationMirror functionalParameterAnnotation = paramMirror.getAnnotation(CEYLON_FUNCTIONAL_PARAMETER_ANNOTATION);
if (functionalParameterAnnotation != null) {
// A functional parameter to a method
Method method = loadFunctionalParameter((Declaration)decl, paramName, type, (String)functionalParameterAnnotation.getValue());
value = method;
parameter.setDeclaredAnything(method.isDeclaredVoid());
} else {
// A value parameter to a method
value = new Value();
value.setType(type);
}
value.setContainer((Scope) decl);
value.setScope((Scope) decl);
DeclarationVisitor.setVisibleScope(value);
value.setUnit(((Element)decl).getUnit());
value.setName(paramName);
}
value.setInitializerParameter(parameter);
parameter.setModel(value);
if(paramMirror.getAnnotation(CEYLON_SEQUENCED_ANNOTATION) != null
|| isVariadic)
parameter.setSequenced(true);
if(paramMirror.getAnnotation(CEYLON_DEFAULTED_ANNOTATION) != null)
parameter.setDefaulted(true);
if (parameter.isSequenced() &&
// FIXME: store info in Sequenced
typeFactory.isNonemptyIterableType(parameter.getType())) {
parameter.setAtLeastOne(true);
}
// if it's variadic, consider the array element type (T[] == T...) for boxing rules
markUnboxed(value, null, isVariadic ?
paramMirror.getType().getComponentType()
: paramMirror.getType());
parameter.setDeclaration((Declaration) decl);
setAnnotations(value, paramMirror);
parameters.getParameters().add(parameter);
parameter.getDeclaration().getMembers().add(parameter.getModel());
parameterIndex++;
}
if (decl instanceof Method) {
// Multiple parameter lists