private void refineMethod(final Method sm,
Tree.BaseMemberExpression bme,
Tree.SpecifierStatement that,
ClassOrInterface c) {
final ProducedReference rm = getRefinedMember(sm, c);
if (!sm.isFormal() && !sm.isDefault()
&& !sm.isShortcutRefinement()) { //this condition is here to squash a dupe message
that.addError("inherited method is neither formal nor default so may not be refined: " +
message(sm));
}
Method m = new Method();
m.setName(sm.getName());
List<Tree.ParameterList> tpls;
Tree.Term me = that.getBaseMemberExpression();
if (me instanceof Tree.ParameterizedExpression) {
tpls = ((Tree.ParameterizedExpression) me).getParameterLists();
}
else {
tpls = Collections.emptyList();
}
int i=0;
for (ParameterList pl: sm.getParameterLists()) {
ParameterList l = new ParameterList();
Tree.ParameterList tpl = tpls.size()<=i ?
null : tpls.get(i++);
int j=0;
for (final Parameter p: pl.getParameters()) {
//TODO: meaningful errors when parameters don't line up
// currently this is handled elsewhere, but we can
// probably do it better right here
if (tpl==null || tpl.getParameters().size()<=j) {
Parameter vp = new Parameter();
Value v = new Value();
vp.setModel(v);
v.setInitializerParameter(vp);
vp.setSequenced(p.isSequenced());
vp.setAtLeastOne(p.isAtLeastOne());
vp.setDefaulted(p.isDefaulted());
vp.setName(p.getName());
v.setName(p.getName());
vp.setDeclaration(m);
v.setContainer(m);
v.setScope(m);
l.getParameters().add(vp);
v.setType(new LazyProducedType(that.getUnit()) {
@Override
public Map<TypeParameter, ProducedType> initTypeArguments() {
return rm.getTypedParameter(p).getFullType()
.getTypeArguments();
}
@Override
public TypeDeclaration initDeclaration() {
return rm.getTypedParameter(p).getFullType()
.getDeclaration();
}
});
}
else {
Tree.Parameter tp = tpl.getParameters().get(j);
Parameter rp = tp.getParameterModel();
rp.setDefaulted(p.isDefaulted());
rp.setDeclaration(m);
l.getParameters().add(rp);
}
j++;
}
m.getParameterLists().add(l);
}
if (!sm.getTypeParameters().isEmpty()) {
bme.addError("method has type parameters: " +
message(sm));
}
m.setShared(true);
m.setActual(true);
m.getAnnotations().add(new Annotation("shared"));
m.getAnnotations().add(new Annotation("actual"));
m.setRefinedDeclaration(sm.getRefinedDeclaration()); //Note: this is not the real root, so we set it again in ExpressionVisitor
m.setUnit(that.getUnit());
m.setContainer(c);
m.setShortcutRefinement(true);
m.setDeclaredVoid(sm.isDeclaredVoid());
setVisibleScope(m);
c.addMember(m);
that.setRefinement(true);
that.setDeclaration(m);
that.setRefined(sm);
that.getUnit().addDeclaration(m);
if (that.getScope() instanceof Specification){
((Specification) that.getScope()).setDeclaration(m);
}
m.setType(new LazyProducedType(that.getUnit()) {
@Override
public Map<TypeParameter, ProducedType> initTypeArguments() {
return rm.getType().getTypeArguments();
}
@Override
public TypeDeclaration initDeclaration() {
return rm.getType().getDeclaration();
}
});
}