use of org.eclipse.xtext.xbase.typesystem.references.LightweightTypeReference 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.xbase.typesystem.references.LightweightTypeReference in project xtext-xtend by eclipse.
the class AbstractAssignabilityTest method isAssignableFrom.
public void isAssignableFrom(final Pair<String, String> lhsAndParams, final String rhs, final boolean expectation) {
try {
StringConcatenation _builder = new StringConcatenation();
_builder.append("def ");
{
boolean _isNullOrEmpty = StringExtensions.isNullOrEmpty(lhsAndParams.getValue());
boolean _not = (!_isNullOrEmpty);
if (_not) {
_builder.append("<");
String _value = lhsAndParams.getValue();
_builder.append(_value);
_builder.append("> ");
}
}
_builder.append("void method(");
String _fixup = this.fixup(lhsAndParams.getKey());
_builder.append(_fixup);
_builder.append(" lhs, ");
String _fixup_1 = this.fixup(rhs);
_builder.append(_fixup_1);
_builder.append(" rhs) {}");
final String signature = _builder.toString();
final XtendFunction function = this.function(signature.toString());
final JvmOperation operation = this._iXtendJvmAssociations.getDirectlyInferredOperation(function);
LightweightTypeReference _xifexpression = null;
String _key = lhsAndParams.getKey();
boolean _tripleNotEquals = (_key != null);
if (_tripleNotEquals) {
_xifexpression = this.toLightweightTypeReference(IterableExtensions.<JvmFormalParameter>head(operation.getParameters()).getParameterType());
} else {
_xifexpression = this.getOwner().newAnyTypeReference();
}
final LightweightTypeReference lhsType = _xifexpression;
LightweightTypeReference _xifexpression_1 = null;
if ((rhs != null)) {
_xifexpression_1 = this.toLightweightTypeReference(IterableExtensions.<JvmFormalParameter>last(operation.getParameters()).getParameterType());
} else {
_xifexpression_1 = this.getOwner().newAnyTypeReference();
}
final LightweightTypeReference rhsType = _xifexpression_1;
String _simpleName = lhsType.getSimpleName();
String _plus = (_simpleName + " := ");
String _simpleName_1 = rhsType.getSimpleName();
String _plus_1 = (_plus + _simpleName_1);
Assert.assertEquals(_plus_1, Boolean.valueOf(expectation), Boolean.valueOf(this.testIsAssignable(lhsType, rhsType)));
if (expectation) {
List<LightweightTypeReference> _allSuperTypes = lhsType.getAllSuperTypes();
for (final LightweightTypeReference superType : _allSuperTypes) {
if (((superType.isArray() == lhsType.isArray()) || (lhsType.isArray() == rhsType.isArray()))) {
Assert.assertEquals(superType.toString(), Boolean.valueOf(expectation), Boolean.valueOf(this.testIsAssignable(superType, rhsType)));
}
}
}
} catch (Throwable _e) {
throw Exceptions.sneakyThrow(_e);
}
}
use of org.eclipse.xtext.xbase.typesystem.references.LightweightTypeReference in project xtext-xtend by eclipse.
the class ActualTypeArgumentCollectorTest method assertMapping.
public Map<JvmTypeParameter, List<LightweightBoundTypeArgument>> assertMapping(final Map<JvmTypeParameter, List<LightweightBoundTypeArgument>> mapping, final String typeParamName, final Triple<String, VarianceInfo, VarianceInfo>... mappedTypes) {
final Set<JvmTypeParameter> allKeys = mapping.keySet();
for (final JvmTypeParameter key : allKeys) {
String _simpleName = key.getSimpleName();
boolean _equals = Objects.equal(_simpleName, typeParamName);
if (_equals) {
Assert.assertNotNull(mappedTypes);
final List<LightweightBoundTypeArgument> mappingData = mapping.get(key);
final Function1<LightweightBoundTypeArgument, String> _function = (LightweightBoundTypeArgument it) -> {
StringConcatenation _builder = new StringConcatenation();
LightweightTypeReference _typeReference = it.getTypeReference();
_builder.append(_typeReference);
_builder.append("(");
VarianceInfo _declaredVariance = it.getDeclaredVariance();
_builder.append(_declaredVariance);
_builder.append("/");
VarianceInfo _actualVariance = it.getActualVariance();
_builder.append(_actualVariance);
_builder.append(")");
return _builder.toString();
};
Assert.assertEquals(ListExtensions.<LightweightBoundTypeArgument, String>map(mappingData, _function).toString(), ((List<Triple<String, VarianceInfo, VarianceInfo>>) Conversions.doWrapArray(mappedTypes)).size(), mappingData.size());
final Function1<LightweightBoundTypeArgument, Triple<String, VarianceInfo, VarianceInfo>> _function_1 = (LightweightBoundTypeArgument it) -> {
return Tuples.<String, VarianceInfo, VarianceInfo>create(it.getTypeReference().toString(), it.getDeclaredVariance(), it.getActualVariance());
};
Assert.assertEquals(IterableExtensions.<Triple<String, VarianceInfo, VarianceInfo>>toList(((Iterable<Triple<String, VarianceInfo, VarianceInfo>>) Conversions.doWrapArray(mappedTypes))), IterableExtensions.<Triple<String, VarianceInfo, VarianceInfo>>toList(ListExtensions.<LightweightBoundTypeArgument, Triple<String, VarianceInfo, VarianceInfo>>map(mappingData, _function_1)));
return mapping;
}
}
if ((mappedTypes != null)) {
StringConcatenation _builder = new StringConcatenation();
_builder.append("No mapping for ");
_builder.append(typeParamName);
_builder.append(" in ");
final Function1<JvmTypeParameter, String> _function_2 = (JvmTypeParameter it) -> {
return it.getSimpleName();
};
Iterable<String> _map = IterableExtensions.<JvmTypeParameter, String>map(mapping.keySet(), _function_2);
_builder.append(_map);
Assert.fail(_builder.toString());
}
return mapping;
}
use of org.eclipse.xtext.xbase.typesystem.references.LightweightTypeReference in project xtext-xtend by eclipse.
the class XtendCompiler method _toJavaStatement.
public void _toJavaStatement(RichString richString, ITreeAppendable b, boolean isReferenced) {
LightweightTypeReference actualType = getLightweightType(richString);
b = b.trace(richString);
if (actualType.isType(StringConcatenationClient.class)) {
String resultVariableName = b.declareSyntheticVariable(richString, "_client");
b.newLine();
b.append(actualType);
b.append(" ");
b.append(resultVariableName);
b.append(" = new ");
b.append(actualType);
b.append("() {");
b.openScope();
reassignThisInClosure(b, actualType.getType());
b.increaseIndentation().newLine();
b.append("@");
b.append(Override.class);
b.newLine().append("protected void appendTo(");
b.append(StringConcatenationClient.TargetStringConcatenation.class);
String variableName = b.declareSyntheticVariable(richString, "_builder");
b.append(" ").append(variableName).append(") {");
b.increaseIndentation();
RichStringPrepareCompiler compiler = new RichStringPrepareCompiler(b, variableName, richString);
richStringProcessor.process(richString, compiler, indentationHandler.get());
b.closeScope();
b.decreaseIndentation().newLine().append("}").decreaseIndentation().newLine().append("};");
} else {
// declare variable
String variableName = b.declareSyntheticVariable(richString, "_builder");
b.newLine();
b.append(StringConcatenation.class);
b.append(" ");
b.append(variableName);
b.append(" = new ");
b.append(StringConcatenation.class);
b.append("();");
RichStringPrepareCompiler compiler = new RichStringPrepareCompiler(b, variableName, richString);
richStringProcessor.process(richString, compiler, indentationHandler.get());
}
}
use of org.eclipse.xtext.xbase.typesystem.references.LightweightTypeReference in project xtext-xtend by eclipse.
the class DispatchMethodCompileStrategy method apply.
@Override
public void apply(/* @Nullable */
ITreeAppendable a) {
if (a == null)
throw new IllegalArgumentException("a is never null");
boolean needsElse = true;
int parameterCount = dispatchOperation.getParameters().size();
List<JvmOperation> sortedDispatchOperations = sorter.getAllDispatchCases(dispatchOperation);
boolean[] allCasesSameType = new boolean[parameterCount];
for (int i = 0; i < parameterCount; i++) {
allCasesSameType[i] = true;
JvmTypeReference dispatchParameterType = dispatchOperation.getParameters().get(i).getParameterType();
for (JvmOperation operation : sortedDispatchOperations) {
JvmFormalParameter parameter = operation.getParameters().get(i);
JvmTypeReference caseParameterType = parameter.getParameterType();
if (!Strings.equal(dispatchParameterType.getIdentifier(), caseParameterType.getIdentifier())) {
allCasesSameType[i] = false;
break;
}
}
}
ITypeReferenceOwner owner = new StandardTypeReferenceOwner(services, dispatchOperation);
for (JvmOperation operation : sortedDispatchOperations) {
ITreeAppendable operationAppendable = treeAppendableUtil.traceSignificant(a, operation, true);
final List<Later> laters = newArrayList();
for (int i = 0; i < parameterCount; i++) {
final JvmFormalParameter dispatchParam = dispatchOperation.getParameters().get(i);
final LightweightTypeReference dispatchParamType = owner.toLightweightTypeReference(dispatchParam.getParameterType());
final JvmFormalParameter caseParam = operation.getParameters().get(i);
final LightweightTypeReference caseParamType = owner.toLightweightTypeReference(caseParam.getParameterType());
final String name = getVarName(dispatchParam, operationAppendable);
if (caseParamType.isType(Void.class)) {
laters.add(new Later() {
@Override
public void exec(ITreeAppendable appendable) {
appendable.append(name).append(" == null");
}
});
} else if (!allCasesSameType[i]) {
laters.add(new Later() {
@Override
public void exec(ITreeAppendable appendable) {
if (caseParamType.isAssignableFrom(dispatchParamType, new TypeConformanceComputationArgument(true, false, true, true, false, false)) && !dispatchParamType.isPrimitive()) {
appendable.append(name).append(" != null");
} else {
appendable.append(name).append(" instanceof ");
JvmType type = caseParamType.getWrapperTypeIfPrimitive().getType();
if (type == null) {
throw new IllegalStateException(String.valueOf(caseParamType));
}
appendable.append(type);
}
}
});
}
}
// if it's not the first if append an 'else'
if (sortedDispatchOperations.get(0) != operation) {
operationAppendable.append(" else ");
}
if (laters.isEmpty()) {
needsElse = false;
if (sortedDispatchOperations.size() != 1) {
operationAppendable.append("{").increaseIndentation();
operationAppendable.newLine();
}
} else {
operationAppendable.append("if (");
operationAppendable.increaseIndentation().increaseIndentation();
Iterator<Later> iterator = laters.iterator();
while (iterator.hasNext()) {
iterator.next().exec(operationAppendable);
if (iterator.hasNext()) {
operationAppendable.newLine().append(" && ");
}
}
operationAppendable.decreaseIndentation().decreaseIndentation();
operationAppendable.append(") {").increaseIndentation();
operationAppendable.newLine();
}
final boolean isCurrentVoid = typeReferences.is(operation.getReturnType(), Void.TYPE);
final boolean isDispatchVoid = typeReferences.is(dispatchOperation.getReturnType(), Void.TYPE);
if (isDispatchVoid) {
generateActualDispatchCall(dispatchOperation, operation, operationAppendable, owner);
// we generate a redundant return statement here to get a better debugging experience
operationAppendable.append(";").newLine().append("return;");
} else {
if (isCurrentVoid) {
generateActualDispatchCall(dispatchOperation, operation, operationAppendable, owner);
operationAppendable.append(";").newLine().append("return null");
} else {
operationAppendable.append("return ");
generateActualDispatchCall(dispatchOperation, operation, operationAppendable, owner);
}
operationAppendable.append(";");
}
if (sortedDispatchOperations.size() != 1) {
operationAppendable.decreaseIndentation();
a.newLine().append("}");
}
}
if (needsElse) {
a.append(" else {").increaseIndentation();
a.newLine();
a.increaseIndentation();
a.append("throw new IllegalArgumentException(\"Unhandled parameter types: \" +").newLine();
JvmType jvmType = typeReferences.findDeclaredType("java.util.Arrays", dispatchOperation);
if (jvmType != null) {
a.append(jvmType);
} else {
a.append(Arrays.class.getSimpleName());
}
a.append(".<Object>asList(");
Iterator<JvmFormalParameter> iterator = dispatchOperation.getParameters().iterator();
while (iterator.hasNext()) {
JvmFormalParameter parameter = iterator.next();
final String name = getVarName(parameter, a);
a.append(name);
if (iterator.hasNext()) {
a.append(", ");
}
}
a.append(").toString());");
a.decreaseIndentation();
a.decreaseIndentation().newLine().append("}");
}
}
Aggregations