package org.jruby.internal.runtime.methods;
import org.jruby.anno.MethodDescriptor;
import java.util.Arrays;
import java.util.List;
public class DescriptorInfo {
private int min;
private int max;
private boolean frame;
private boolean rest;
private boolean block;
private String parameterDesc;
public static final char ANONREQ_CHAR = 'n';
public static final char ANONOPT_CHAR = 'O';
public static final char ANONREST_CHAR = 'R';
private static final boolean RICH_NATIVE_METHOD_PARAMETERS = false;
public DescriptorInfo(MethodDescriptor... descs) {
this(Arrays.asList(descs));
}
public DescriptorInfo(List<? extends MethodDescriptor> descs) {
min = Integer.MAX_VALUE;
max = 0;
frame = false;
rest = false;
block = false;
boolean first = true;
boolean lastBlock = false;
for (MethodDescriptor desc : descs) {
if (first) {
first = false;
} else {
if (lastBlock != desc.hasBlock) {
throw new RuntimeException("Mismatched block parameters for method " + desc.declaringClassName + "." + desc.name);
}
}
lastBlock = desc.hasBlock;
int specificArity = -1;
if (desc.hasVarArgs) {
if (desc.optional == 0 && !desc.rest && desc.required == 0) {
throw new RuntimeException("IRubyObject[] args but neither of optional or rest specified for method " + desc.declaringClassName + "." + desc.name);
}
rest = true;
if (descs.size() == 1) {
min = -1;
}
} else {
if (desc.optional == 0 && !desc.rest) {
if (desc.required == 0) {
if (desc.actualRequired <= 3) {
specificArity = desc.actualRequired;
} else {
throw new RuntimeException("Invalid specific-arity number of arguments (" + desc.actualRequired + ") on method " + desc.declaringClassName + "." + desc.name);
}
} else if (desc.required >= 0 && desc.required <= 3) {
if (desc.actualRequired != desc.required) {
throw new RuntimeException("Specified required args does not match actual on method " + desc.declaringClassName + "." + desc.name);
}
specificArity = desc.required;
}
}
if (specificArity < min) {
min = specificArity;
}
if (specificArity > max) {
max = specificArity;
}
}
if (frame && !desc.anno.frame())
throw new RuntimeException("Unbalanced frame property on method " + desc.declaringClassName + '.' + desc.name);
frame |= desc.anno.frame();
block |= desc.hasBlock;
}
StringBuilder descBuilder = new StringBuilder();
if (RICH_NATIVE_METHOD_PARAMETERS) {
int i = 0;
for (; i < min; i++) {
if (i > 0) descBuilder.append(';');
descBuilder.append(ANONREQ_CHAR);
}
for (; i < max; i++) {
if (i > 0) descBuilder.append(';');
descBuilder.append(ANONOPT_CHAR);
}
if (rest) {
if (i > 0) descBuilder.append(';');
descBuilder.append(ANONOPT_CHAR);
}
} else {
if (rest || min != max) {
descBuilder.append(ANONREST_CHAR);
} else {
int i = 0;
for (; i < min; i++) {
if (i > 0) descBuilder.append(';');
descBuilder.append(ANONREQ_CHAR);
}
}
}
parameterDesc = descBuilder.toString();
}
@Deprecated
public boolean isBacktrace() {
return false;
}
public boolean isFrame() {
return frame;
}
public int getMax() {
return max;
}
public int getMin() {
return min;
}
public boolean isRest() {
return rest;
}
public boolean isBlock() {
return block;
}
public String getParameterDesc() {
return parameterDesc;
}
}