use of org.eclipse.xtext.common.types.JvmOperation in project xtext-xtend by eclipse.
the class XtendValidator method checkOperatorSignature.
@Check
public void checkOperatorSignature(XtendFunction function) {
String functionName = function.getName();
if (functionName != null) {
QualifiedName qualifiedName = QualifiedName.create(functionName);
QualifiedName operator = operatorMapping.getOperator(qualifiedName);
if (operator != null) {
JvmOperation operation = associations.getDirectlyInferredOperation(function);
if (operation != null) {
int parameterSize = operation.getParameters().size();
if (function.isStatic()) {
if (operatorMapping.isUnaryOperator(operator) && operatorMapping.isBinaryOperator(operator)) {
if (parameterSize < 1) {
addIssue("The static operator '" + operator + "' requires at least one argument.", function, XtendPackage.Literals.XTEND_FUNCTION__NAME, INVALID_OPERATOR_SIGNATURE);
} else if (parameterSize > 2) {
addIssue("The static operator '" + operator + "' allows at most two arguments.", function, XtendPackage.Literals.XTEND_FUNCTION__NAME, INVALID_OPERATOR_SIGNATURE);
}
} else if (operatorMapping.isUnaryOperator(operator)) {
if (parameterSize != 1) {
addIssue("The static unary operator '" + operator + "' requires exactly one argument.", function, XtendPackage.Literals.XTEND_FUNCTION__NAME, INVALID_OPERATOR_SIGNATURE);
}
} else if (parameterSize != 2) {
addIssue("The static binary operator '" + operator + "' requires exactly two arguments.", function, XtendPackage.Literals.XTEND_FUNCTION__NAME, INVALID_OPERATOR_SIGNATURE);
}
} else {
if (operatorMapping.isUnaryOperator(operator) && operatorMapping.isBinaryOperator(operator)) {
if (parameterSize > 2) {
addIssue("The operator '" + operator + "' allows at most two arguments.", function, XtendPackage.Literals.XTEND_FUNCTION__NAME, INVALID_OPERATOR_SIGNATURE);
}
} else if (operatorMapping.isUnaryOperator(operator)) {
if (parameterSize > 1) {
addIssue("The unary operator '" + operator + "' allows at most one argument.", function, XtendPackage.Literals.XTEND_FUNCTION__NAME, INVALID_OPERATOR_SIGNATURE);
}
} else if (parameterSize == 0) {
addIssue("The binary operator '" + operator + "' requires at least one argument.", function, XtendPackage.Literals.XTEND_FUNCTION__NAME, INVALID_OPERATOR_SIGNATURE);
} else if (parameterSize > 2) {
addIssue("The binary operator '" + operator + "' allows at most two arguments.", function, XtendPackage.Literals.XTEND_FUNCTION__NAME, INVALID_OPERATOR_SIGNATURE);
}
}
}
}
}
}
use of org.eclipse.xtext.common.types.JvmOperation in project xtext-xtend by eclipse.
the class XtendValidator method checkDispatchFunctions.
@Check
public void checkDispatchFunctions(XtendClass clazz) {
JvmGenericType type = associations.getInferredType(clazz);
if (type != null) {
Multimap<DispatchHelper.DispatchSignature, JvmOperation> dispatchMethods = dispatchHelper.getDeclaredOrEnhancedDispatchMethods(type);
checkDispatchNonDispatchConflict(clazz, dispatchMethods);
for (DispatchHelper.DispatchSignature signature : dispatchMethods.keySet()) {
Collection<JvmOperation> dispatchOperations = dispatchMethods.get(signature);
JvmOperation syntheticDispatchMethod = dispatchHelper.getDispatcherOperation(type, signature);
if (syntheticDispatchMethod != null) {
JvmOperation overriddenOperation = overrideHelper.findOverriddenOperation(syntheticDispatchMethod);
Boolean expectStatic = null;
if (overriddenOperation != null) {
if (isMorePrivateThan(syntheticDispatchMethod.getVisibility(), overriddenOperation.getVisibility())) {
String msg = "Synthetic dispatch method reduces visibility of overridden method " + overriddenOperation.getIdentifier();
addDispatchError(type, dispatchOperations, msg, null, OVERRIDE_REDUCES_VISIBILITY);
}
expectStatic = overriddenOperation.isStatic();
}
LightweightTypeReference dispatchMethodReturnType = getActualType(clazz, syntheticDispatchMethod);
if (dispatchOperations.size() == 1) {
JvmOperation singleOp = dispatchOperations.iterator().next();
XtendFunction function = associations.getXtendFunction(singleOp);
addIssue("Single dispatch method.", function, XTEND_MEMBER__MODIFIERS, function.getModifiers().indexOf("dispatch"), SINGLE_DISPATCH_FUNCTION);
} else {
Multimap<List<JvmType>, JvmOperation> signatures = HashMultimap.create();
boolean[] allPrimitive = new boolean[signature.getArity()];
Arrays.fill(allPrimitive, true);
boolean isFirstLocalOperation = true;
JvmVisibility commonVisibility = null;
Boolean commonStatic = null;
for (JvmOperation jvmOperation : dispatchOperations) {
signatures.put(getParamTypes(jvmOperation, true), jvmOperation);
for (int i = 0; i < jvmOperation.getParameters().size(); i++) {
JvmFormalParameter parameter = jvmOperation.getParameters().get(i);
if (!(parameter.getParameterType().getType() instanceof JvmPrimitiveType)) {
allPrimitive[i] = false;
}
}
if (jvmOperation.getDeclaringType() == type) {
if (expectStatic != null) {
if (expectStatic && !jvmOperation.isStatic()) {
String msg = "The dispatch method must be static because the dispatch methods in the superclass are static.";
addDispatchError(jvmOperation, msg, "static", DISPATCH_FUNCTIONS_STATIC_EXPECTED);
}
if (!expectStatic && jvmOperation.isStatic()) {
String msg = "The dispatch method must not be static because the dispatch methods in the superclass are not static.";
addDispatchError(jvmOperation, msg, "static", DISPATCH_FUNCTIONS_NON_STATIC_EXPECTED);
}
}
if (isFirstLocalOperation) {
commonVisibility = jvmOperation.getVisibility();
commonStatic = jvmOperation.isStatic();
isFirstLocalOperation = false;
} else {
if (jvmOperation.getVisibility() != commonVisibility) {
commonVisibility = null;
}
if (commonStatic != null && commonStatic != jvmOperation.isStatic()) {
commonStatic = null;
}
}
// TODO move validation to type computation
if (dispatchMethodReturnType != null) {
XtendFunction function = associations.getXtendFunction(jvmOperation);
if (function != null) {
LightweightTypeReference operationType = getActualType(function.getExpression(), jvmOperation);
if (!dispatchMethodReturnType.isAssignableFrom(operationType)) {
error("Incompatible return type of dispatch method. Expected " + dispatchMethodReturnType.getHumanReadableName() + " but was " + operationType.getHumanReadableName(), function, XtendPackage.Literals.XTEND_FUNCTION__RETURN_TYPE, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, INCOMPATIBLE_RETURN_TYPE);
}
}
}
}
}
if (commonVisibility == null) {
addDispatchError(type, dispatchOperations, "All local dispatch methods must have the same visibility.", null, DISPATCH_FUNCTIONS_WITH_DIFFERENT_VISIBILITY);
}
if (expectStatic == null && commonStatic == null) {
addDispatchError(type, dispatchOperations, "Static and non-static dispatch methods can not be mixed.", "static", DISPATCH_FUNCTIONS_MIXED_STATIC_AND_NON_STATIC);
}
for (final List<JvmType> paramTypes : signatures.keySet()) {
Collection<JvmOperation> ops = signatures.get(paramTypes);
if (ops.size() > 1) {
if (Iterables.any(ops, new Predicate<JvmOperation>() {
@Override
public boolean apply(JvmOperation input) {
return !getParamTypes(input, false).equals(paramTypes);
}
})) {
for (JvmOperation jvmOperation : ops) {
XtendFunction function = associations.getXtendFunction(jvmOperation);
error("Duplicate dispatch methods. Primitives cannot overload their wrapper types in dispatch methods.", function, null, DUPLICATE_METHOD);
}
}
}
}
for (int i = 0; i < allPrimitive.length; i++) {
if (allPrimitive[i]) {
Iterator<JvmOperation> operationIter = dispatchOperations.iterator();
JvmType paramType1 = operationIter.next().getParameters().get(i).getParameterType().getType();
while (operationIter.hasNext()) {
JvmType paramType2 = operationIter.next().getParameters().get(i).getParameterType().getType();
if (!paramType2.equals(paramType1)) {
for (JvmOperation jvmOperation : dispatchOperations) {
XtendFunction function = associations.getXtendFunction(jvmOperation);
addIssue("Dispatch methods have arguments with different primitive types.", function, XTEND_EXECUTABLE__PARAMETERS, i, DISPATCH_FUNCTIONS_DIFFERENT_PRIMITIVE_ARGS);
}
break;
}
}
}
}
}
}
}
}
}
use of org.eclipse.xtext.common.types.JvmOperation in project xtext-xtend by eclipse.
the class XtendValidator method checkNonRawTypeInferred.
@Check
public void checkNonRawTypeInferred(XtendFunction function) {
if (function.getReturnType() == null) {
JvmOperation operation = associations.getDirectlyInferredOperation(function);
// operation could have been removed by AA, thus the resource is possibly null
if (operation != null && operation.eResource() != null) {
JvmTypeReference returnType = operation.getReturnType();
validateInferredType(returnType, function, "The inferred return type ", XTEND_FUNCTION__NAME);
}
}
}
use of org.eclipse.xtext.common.types.JvmOperation in project xtext-xtend by eclipse.
the class XtendValidator method checkImplicitReturn.
@Check
protected void checkImplicitReturn(final XtendFunction method) {
if (isIgnored(IMPLICIT_RETURN))
return;
JvmOperation jvmOperation = associations.getDirectlyInferredOperation(method);
IResolvedTypes types = batchTypeResolver.resolveTypes(method);
if (jvmOperation != null && types.getActualType(jvmOperation).isPrimitiveVoid())
return;
implicitReturnFinder.findImplicitReturns(method.getExpression(), new Acceptor() {
@Override
public void accept(XExpression implicitReturn) {
if (method.getExpression() == implicitReturn)
return;
addIssue("Implicit return", implicitReturn, IMPLICIT_RETURN);
}
});
}
use of org.eclipse.xtext.common.types.JvmOperation in project xtext-xtend by eclipse.
the class MutableJvmMethodDeclarationImpl method setAbstract.
@Override
public void setAbstract(final boolean isAbstract) {
this.checkMutable();
this.getDelegate().setAbstract(isAbstract);
if (isAbstract) {
JvmOperation _delegate = this.getDelegate();
_delegate.setDefault(false);
}
}
Aggregations