addInnerClasses(klass, classMirror);
}
// Java classes with multiple constructors get turned into multiple Ceylon classes
// Here we get the specific constructor that was assigned to us (if any)
MethodMirror constructor = null;
if (klass instanceof LazyClass) {
constructor = ((LazyClass)klass).getConstructor();
}
// Turn a list of possibly overloaded methods into a map
// of lists that contain methods with the same name
Map<String, List<MethodMirror>> methods = new LinkedHashMap<String, List<MethodMirror>>();
collectMethods(classMirror.getDirectMethods(), methods, isCeylon, isFromJDK);
if(isCeylon && klass instanceof LazyInterface && CodegenUtil.isCompanionClassNeeded(klass)){
ClassMirror companionClass = ((LazyInterface)klass).companionClass;
if(companionClass != null)
collectMethods(companionClass.getDirectMethods(), methods, isCeylon, isFromJDK);
else
logWarning("CompanionClass missing for "+klass);
}
// Add the methods
for(List<MethodMirror> methodMirrors : methods.values()){
boolean isOverloaded = isMethodOverloaded(methodMirrors);
List<Declaration> overloads = (isOverloaded) ? new ArrayList<Declaration>(methodMirrors.size()) : null;
for (MethodMirror methodMirror : methodMirrors) {
String methodName = methodMirror.getName();
// same tests as in isMethodOverloaded()
if(methodMirror.isConstructor() || isInstantiator(methodMirror)) {
break;
} else if(isGetter(methodMirror)) {
// simple attribute
addValue(klass, methodMirror, getJavaAttributeName(methodName), isCeylon);
} else if(isSetter(methodMirror)) {
// We skip setters for now and handle them later
variables.put(methodMirror, methodMirrors);
} else if(isHashAttribute(methodMirror)) {
// ERASURE
// Un-erasing 'hash' attribute from 'hashCode' method
addValue(klass, methodMirror, "hash", isCeylon);
} else if(isStringAttribute(methodMirror)) {
// ERASURE
// Un-erasing 'string' attribute from 'toString' method
addValue(klass, methodMirror, "string", isCeylon);
} else if(!methodMirror.getName().equals("hash")
&& !methodMirror.getName().equals("string")){
// normal method
Method m = addMethod(klass, methodMirror, classMirror, isCeylon, isOverloaded);
if (isOverloaded) {
overloads.add(m);
}
}
}
if (overloads != null && !overloads.isEmpty()) {
// We create an extra "abstraction" method for overloaded methods
Method abstractionMethod = addMethod(klass, methodMirrors.get(0), classMirror, false, false);
abstractionMethod.setAbstraction(true);
abstractionMethod.setOverloads(overloads);
abstractionMethod.setType(newUnknownType());
}
}
for(FieldMirror fieldMirror : classMirror.getDirectFields()){
// We skip members marked with @Ignore
if(fieldMirror.getAnnotation(CEYLON_IGNORE_ANNOTATION) != null)
continue;
if(isCeylon && fieldMirror.isStatic())
continue;
// FIXME: temporary, because some private classes from the jdk are
// referenced in private methods but not available
if(isFromJDK && !fieldMirror.isPublic())
continue;
String name = fieldMirror.getName();
// skip the field if "we've already got one"
boolean conflicts = klass.getDirectMember(name, null, false) != null
|| "equals".equals(name)
|| "string".equals(name)
|| "hash".equals(name);
if (!conflicts) {
addValue(klass, fieldMirror.getName(), fieldMirror, isCeylon);
}
}
// Having loaded methods and values, we can now set the constructor parameters
if(constructor != null
&& (!(klass instanceof LazyClass) || !((LazyClass)klass).isAnonymous()))
setParameters((Class)klass, constructor, isCeylon, klass);
// Now marry-up attributes and parameters)
if (klass instanceof Class) {
for (Declaration m : klass.getMembers()) {
if (Decl.isValue(m)) {
Value v = (Value)m;
Parameter p = ((Class)klass).getParameter(v.getName());
if (p != null) {
p.setHidden(true);
}
}
}
}
// Now mark all Values for which Setters exist as variable
for(Entry<MethodMirror, List<MethodMirror>> setterEntry : variables.entrySet()){
MethodMirror setter = setterEntry.getKey();
String name = getJavaAttributeName(setter.getName());
// make sure we handle private postfixes
name = Util.strip(name, isCeylon, setter.isPublic());
Declaration decl = klass.getMember(name, null, false);
boolean foundGetter = false;
// skip Java fields, which we only get if there is no getter method, in that case just add the setter method
if (decl instanceof Value && decl instanceof FieldValue == false) {
Value value = (Value)decl;
VariableMirror setterParam = setter.getParameters().get(0);
ProducedType paramType = obtainType(setterParam.getType(), setterParam, klass, Decl.getModuleContainer(klass), VarianceLocation.INVARIANT,
"setter '"+setter.getName()+"'", klass);
// only add the setter if it has exactly the same type as the getter
if(paramType.isExactly(value.getType())){
foundGetter = true;
value.setVariable(true);
if(decl instanceof JavaBeanValue)
((JavaBeanValue)decl).setSetterName(setter.getName());
if(value.isTransient()){
// must be a real setter
makeSetter(value, null);
}
}else