use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.
the class ConstraintExpressionFormula method inputVariables.
@Override
Collection<InferenceVariable> inputVariables(final InferenceContext18 context) {
// from 18.5.2.
if (this.left instanceof LambdaExpression) {
if (this.right instanceof InferenceVariable) {
return Collections.singletonList((InferenceVariable) this.right);
}
if (this.right.isFunctionalInterface(context.scope)) {
LambdaExpression lambda = (LambdaExpression) this.left;
ReferenceBinding targetType = (ReferenceBinding) this.right;
ParameterizedTypeBinding withWildCards = InferenceContext18.parameterizedWithWildcard(targetType);
if (withWildCards != null) {
targetType = ConstraintExpressionFormula.findGroundTargetType(context, lambda.enclosingScope, lambda, withWildCards);
}
if (targetType == null) {
return EMPTY_VARIABLE_LIST;
}
MethodBinding sam = targetType.getSingleAbstractMethod(context.scope, true);
final Set<InferenceVariable> variables = new LinkedHashSet<>();
if (lambda.argumentsTypeElided()) {
// i)
int len = sam.parameters.length;
for (int i = 0; i < len; i++) {
sam.parameters[i].collectInferenceVariables(variables);
}
}
if (sam.returnType != TypeBinding.VOID) {
// ii)
final TypeBinding r = sam.returnType;
LambdaExpression resolved = lambda.resolveExpressionExpecting(this.right, context.scope, context);
Expression[] resultExpressions = resolved != null ? resolved.resultExpressions() : null;
for (int i = 0, length = resultExpressions == null ? 0 : resultExpressions.length; i < length; i++) {
variables.addAll(new ConstraintExpressionFormula(resultExpressions[i], r, COMPATIBLE).inputVariables(context));
}
}
return variables;
}
} else if (this.left instanceof ReferenceExpression) {
if (this.right instanceof InferenceVariable) {
return Collections.singletonList((InferenceVariable) this.right);
}
if (this.right.isFunctionalInterface(context.scope) && !this.left.isExactMethodReference()) {
MethodBinding sam = this.right.getSingleAbstractMethod(context.scope, true);
final Set<InferenceVariable> variables = new LinkedHashSet<>();
int len = sam.parameters.length;
for (int i = 0; i < len; i++) {
sam.parameters[i].collectInferenceVariables(variables);
}
return variables;
}
} else if (this.left instanceof ConditionalExpression && this.left.isPolyExpression()) {
ConditionalExpression expr = (ConditionalExpression) this.left;
Set<InferenceVariable> variables = new LinkedHashSet<>();
variables.addAll(new ConstraintExpressionFormula(expr.valueIfTrue, this.right, COMPATIBLE).inputVariables(context));
variables.addAll(new ConstraintExpressionFormula(expr.valueIfFalse, this.right, COMPATIBLE).inputVariables(context));
return variables;
} else if (this.left instanceof SwitchExpression && this.left.isPolyExpression()) {
SwitchExpression expr = (SwitchExpression) this.left;
Set<InferenceVariable> variables = new LinkedHashSet<>();
for (Expression re : expr.resultExpressions) {
variables.addAll(new ConstraintExpressionFormula(re, this.right, COMPATIBLE).inputVariables(context));
}
return variables;
}
return EMPTY_VARIABLE_LIST;
}
use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.
the class ConstraintExpressionFormula method reduce.
@Override
public Object reduce(InferenceContext18 inferenceContext) throws InferenceFailureException {
if (this.relation == POTENTIALLY_COMPATIBLE) {
return this.left.isPotentiallyCompatibleWith(this.right, inferenceContext.scope) ? TRUE : FALSE;
}
// JLS 18.2.1
if (this.right.isProperType(true)) {
if (this.left.isCompatibleWith(this.right, inferenceContext.scope) || this.left.isBoxingCompatibleWith(this.right, inferenceContext.scope)) {
if (this.left.resolvedType != null && this.left.resolvedType.needsUncheckedConversion(this.right)) {
inferenceContext.usesUncheckedConversion = true;
}
return TRUE;
}
return FALSE;
}
if (!canBePolyExpression(this.left)) {
TypeBinding exprType = this.left.resolvedType;
if (exprType == null || !exprType.isValidBinding()) {
if (this.left instanceof MessageSend && ((MessageSend) this.left).actualReceiverType instanceof InferenceVariable)
// nothing valuable to infer from this
return null;
return FALSE;
}
return ConstraintTypeFormula.create(exprType, this.right, COMPATIBLE, this.isSoft);
} else {
// - parenthesized expression : these are transparent in our AST
if (this.left instanceof Invocation) {
Invocation invocation = (Invocation) this.left;
MethodBinding previousMethod = invocation.binding();
if (// can happen, e.g., if inside a copied lambda with ignored errors
previousMethod == null)
// -> proceed with no new constraints
return null;
MethodBinding method = previousMethod;
// ignore previous (inner) inference result and do a fresh start:
// avoid original(), since we only want to discard one level of instantiation
// (method type variables - not class type variables)!
method = previousMethod.shallowOriginal();
SuspendedInferenceRecord prevInvocation = inferenceContext.enterPolyInvocation(invocation, invocation.arguments());
// Invocation Applicability Inference: 18.5.1 & Invocation Type Inference: 18.5.2
InferenceContext18 innerCtx = null;
try {
Expression[] arguments = invocation.arguments();
TypeBinding[] argumentTypes = arguments == null ? Binding.NO_PARAMETERS : new TypeBinding[arguments.length];
for (int i = 0; i < argumentTypes.length; i++) argumentTypes[i] = arguments[i].resolvedType;
if (previousMethod instanceof ParameterizedGenericMethodBinding) {
// find the previous inner inference context to see what inference kind this invocation needs:
innerCtx = invocation.getInferenceContext((ParameterizedGenericMethodBinding) previousMethod);
if (innerCtx == null) {
/* No inference context -> the method was likely manufactured by Scope.findExactMethod -> assume it wasn't really poly after all.
-> proceed as for non-poly expressions.
*/
TypeBinding exprType = this.left.resolvedType;
if (exprType == null || !exprType.isValidBinding())
return FALSE;
return ConstraintTypeFormula.create(exprType, this.right, COMPATIBLE, this.isSoft);
}
if (innerCtx.stepCompleted >= InferenceContext18.APPLICABILITY_INFERRED) {
inferenceContext.integrateInnerInferenceB2(innerCtx);
} else {
// should not reach here.
return FALSE;
}
// b2 has been lifted, inferring poly invocation type amounts to lifting b3.
} else {
inferenceContext.inferenceKind = inferenceContext.getInferenceKind(previousMethod, argumentTypes);
boolean isDiamond = method.isConstructor() && this.left.isPolyExpression(method);
inferInvocationApplicability(inferenceContext, method, argumentTypes, isDiamond, inferenceContext.inferenceKind);
// b2 has been lifted, inferring poly invocation type amounts to lifting b3.
}
if (!inferenceContext.computeB3(invocation, this.right, method))
return FALSE;
// already incorporated
return null;
} finally {
inferenceContext.resumeSuspendedInference(prevInvocation, innerCtx);
}
} else if (this.left instanceof ConditionalExpression) {
ConditionalExpression conditional = (ConditionalExpression) this.left;
return new ConstraintFormula[] { new ConstraintExpressionFormula(conditional.valueIfTrue, this.right, this.relation, this.isSoft), new ConstraintExpressionFormula(conditional.valueIfFalse, this.right, this.relation, this.isSoft) };
} else if (this.left instanceof SwitchExpression) {
SwitchExpression se = (SwitchExpression) this.left;
ConstraintFormula[] cfs = new ConstraintFormula[se.resultExpressions.size()];
int i = 0;
for (Expression re : se.resultExpressions) {
cfs[i++] = new ConstraintExpressionFormula(re, this.right, this.relation, this.isSoft);
}
return cfs;
} else if (this.left instanceof LambdaExpression) {
LambdaExpression lambda = (LambdaExpression) this.left;
BlockScope scope = lambda.enclosingScope;
if (this.right instanceof InferenceVariable)
// assume inner inference will handle the fine print
return TRUE;
if (!this.right.isFunctionalInterface(scope))
return FALSE;
ReferenceBinding t = (ReferenceBinding) this.right;
ParameterizedTypeBinding withWildCards = InferenceContext18.parameterizedWithWildcard(t);
if (withWildCards != null) {
t = findGroundTargetType(inferenceContext, scope, lambda, withWildCards);
}
if (t == null)
return FALSE;
MethodBinding functionType = t.getSingleAbstractMethod(scope, true);
if (functionType == null)
return FALSE;
TypeBinding[] parameters = functionType.parameters;
if (parameters.length != lambda.arguments().length)
return FALSE;
if (lambda.argumentsTypeElided())
for (int i = 0; i < parameters.length; i++) if (!parameters[i].isProperType(true))
return FALSE;
lambda = lambda.resolveExpressionExpecting(t, inferenceContext.scope, inferenceContext);
if (lambda == null)
// not strictly unreduceable, but proceeding with TRUE would likely produce secondary errors
return FALSE;
if (functionType.returnType == TypeBinding.VOID) {
if (!lambda.isVoidCompatible())
return FALSE;
} else {
if (!lambda.isValueCompatible())
return FALSE;
}
List<ConstraintFormula> result = new ArrayList<>();
if (!lambda.argumentsTypeElided()) {
Argument[] arguments = lambda.arguments();
for (int i = 0; i < parameters.length; i++) result.add(ConstraintTypeFormula.create(parameters[i], arguments[i].type.resolvedType, SAME));
// in addition, ⟨T' <: T⟩:
if (lambda.resolvedType != null)
result.add(ConstraintTypeFormula.create(lambda.resolvedType, this.right, SUBTYPE));
}
if (functionType.returnType != TypeBinding.VOID) {
TypeBinding r = functionType.returnType;
Expression[] exprs = lambda.resultExpressions();
for (int i = 0, length = exprs == null ? 0 : exprs.length; i < length; i++) {
Expression expr = exprs[i];
if (r.isProperType(true) && expr.resolvedType != null) {
TypeBinding exprType = expr.resolvedType;
// "not compatible in an assignment context with R"?
if (!(expr.isConstantValueOfTypeAssignableToType(exprType, r) || exprType.isCompatibleWith(r) || expr.isBoxingCompatible(exprType, r, expr, scope)))
return FALSE;
} else {
result.add(new ConstraintExpressionFormula(expr, r, COMPATIBLE, this.isSoft));
}
}
}
if (result.size() == 0)
return TRUE;
return result.toArray(new ConstraintFormula[result.size()]);
} else if (this.left instanceof ReferenceExpression) {
return reduceReferenceExpressionCompatibility((ReferenceExpression) this.left, inferenceContext);
}
}
return FALSE;
}
use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.
the class CodeStream method generateSyntheticBodyForDeserializeLambda.
// TODO what about blowing the method limit? Ignore for now?
/**
* This is intended to match what javac generates. First there is a switch statement on the hashcode of the lambda method name - based on that
* an id is computed (0..N). An unrecognized hash gets the id -1. Then a second switch is on the id and each case here checks all the properties
* of the serialized lambda. If they all checkout OK an invokedynamic call to a bootstrap method targeting the altMetafactory. If any of the tests
* fail an IllegalArgumentException is thrown. This exception is not typically seen by the 'user', instead they seem to see a NPE when
* the lambda does not deserialize properly.
*/
public void generateSyntheticBodyForDeserializeLambda(SyntheticMethodBinding methodBinding, SyntheticMethodBinding[] syntheticMethodBindings) {
initializeMaxLocals(methodBinding);
// Compute a map of hashcodes to a list of synthetic methods whose names share a hashcode
Map hashcodesTosynthetics = new LinkedHashMap();
for (int i = 0, max = syntheticMethodBindings.length; i < max; i++) {
SyntheticMethodBinding syntheticMethodBinding = syntheticMethodBindings[i];
if (syntheticMethodBinding.lambda != null && syntheticMethodBinding.lambda.isSerializable || syntheticMethodBinding.serializableMethodRef != null) {
// TODO can I use > Java 1.4 features here?
Integer hashcode = Integer.valueOf(new String(syntheticMethodBinding.selector).hashCode());
List syntheticssForThisHashcode = (List) hashcodesTosynthetics.get(hashcode);
if (syntheticssForThisHashcode == null) {
syntheticssForThisHashcode = new ArrayList();
hashcodesTosynthetics.put(hashcode, syntheticssForThisHashcode);
}
syntheticssForThisHashcode.add(syntheticMethodBinding);
}
}
ClassScope scope = ((SourceTypeBinding) methodBinding.declaringClass).scope;
// Generate the first switch, on method name hashcode
aload_0();
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplMethodName, ConstantPool.GetImplMethodNameSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
astore_1();
// $NON-NLS-1$
LocalVariableBinding lvb1 = new LocalVariableBinding("hashcode".toCharArray(), scope.getJavaLangString(), 0, false);
lvb1.resolvedPosition = 1;
addVariable(lvb1);
iconst_m1();
istore_2();
// $NON-NLS-1$
LocalVariableBinding lvb2 = new LocalVariableBinding("id".toCharArray(), TypeBinding.INT, 0, false);
lvb2.resolvedPosition = 2;
addVariable(lvb2);
aload_1();
invokeStringHashCode();
BranchLabel label = new BranchLabel(this);
CaseLabel defaultLabel = new CaseLabel(this);
int numberOfHashcodes = hashcodesTosynthetics.size();
CaseLabel[] switchLabels = new CaseLabel[numberOfHashcodes];
int[] keys = new int[numberOfHashcodes];
int[] sortedIndexes = new int[numberOfHashcodes];
Set hashcodes = hashcodesTosynthetics.keySet();
Iterator hashcodeIterator = hashcodes.iterator();
int index = 0;
while (hashcodeIterator.hasNext()) {
Integer hashcode = (Integer) hashcodeIterator.next();
switchLabels[index] = new CaseLabel(this);
keys[index] = hashcode.intValue();
sortedIndexes[index] = index;
index++;
}
int[] localKeysCopy;
System.arraycopy(keys, 0, (localKeysCopy = new int[numberOfHashcodes]), 0, numberOfHashcodes);
sort(localKeysCopy, 0, numberOfHashcodes - 1, sortedIndexes);
// TODO need to use a tableswitch at some size threshold?
lookupswitch(defaultLabel, keys, sortedIndexes, switchLabels);
// TODO cope with multiple names that share the same hashcode
hashcodeIterator = hashcodes.iterator();
index = 0;
while (hashcodeIterator.hasNext()) {
Integer hashcode = (Integer) hashcodeIterator.next();
List synthetics = (List) hashcodesTosynthetics.get(hashcode);
switchLabels[index].place();
BranchLabel nextOne = new BranchLabel(this);
// the same name?
for (int j = 0, max = synthetics.size(); j < max; j++) {
SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding) synthetics.get(j);
aload_1();
ldc(new String(syntheticMethodBinding.selector));
invokeStringEquals();
ifeq(nextOne);
loadInt(index);
istore_2();
goto_(label);
nextOne.place();
nextOne = new BranchLabel(this);
}
index++;
goto_(label);
}
defaultLabel.place();
label.place();
int syntheticsCount = hashcodes.size();
// Second block is switching on the lambda id, -1 is the error (unrecognized) case
switchLabels = new CaseLabel[syntheticsCount];
keys = new int[syntheticsCount];
sortedIndexes = new int[syntheticsCount];
BranchLabel errorLabel = new BranchLabel(this);
defaultLabel = new CaseLabel(this);
iload_2();
for (int j = 0; j < syntheticsCount; j++) {
switchLabels[j] = new CaseLabel(this);
keys[j] = j;
sortedIndexes[j] = j;
}
System.arraycopy(keys, 0, (localKeysCopy = new int[syntheticsCount]), 0, syntheticsCount);
// TODO no need to sort here? They should all be in order
sort(localKeysCopy, 0, syntheticsCount - 1, sortedIndexes);
// TODO need to use a tableswitch at some size threshold?
lookupswitch(defaultLabel, keys, sortedIndexes, switchLabels);
hashcodeIterator = hashcodes.iterator();
int hashcodeIndex = 0;
while (hashcodeIterator.hasNext()) {
Integer hashcode = (Integer) hashcodeIterator.next();
List synthetics = (List) hashcodesTosynthetics.get(hashcode);
switchLabels[hashcodeIndex++].place();
BranchLabel nextOne = synthetics.size() > 1 ? new BranchLabel(this) : errorLabel;
// Loop through all lambdas that share the same hashcode
for (int j = 0, count = synthetics.size(); j < count; j++) {
SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding) synthetics.get(j);
// Compare ImplMethodKind
aload_0();
FunctionalExpression funcEx = syntheticMethodBinding.lambda != null ? syntheticMethodBinding.lambda : syntheticMethodBinding.serializableMethodRef;
MethodBinding mb = funcEx.binding;
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplMethodKind, ConstantPool.GetImplMethodKindSignature, TypeIds.T_int, TypeBinding.INT);
byte methodKind = 0;
if (mb.isStatic()) {
methodKind = ClassFileConstants.MethodHandleRefKindInvokeStatic;
} else if (mb.isPrivate()) {
methodKind = ClassFileConstants.MethodHandleRefKindInvokeSpecial;
} else if (mb.isConstructor()) {
methodKind = ClassFileConstants.MethodHandleRefKindNewInvokeSpecial;
} else if (mb.declaringClass.isInterface()) {
methodKind = ClassFileConstants.MethodHandleRefKindInvokeInterface;
} else {
methodKind = ClassFileConstants.MethodHandleRefKindInvokeVirtual;
}
// TODO see table below
bipush(methodKind);
if_icmpne(nextOne);
// Compare FunctionalInterfaceClass
aload_0();
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetFunctionalInterfaceClass, ConstantPool.GetFunctionalInterfaceClassSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
String functionalInterface = null;
final TypeBinding expectedType = funcEx.expectedType();
if (expectedType instanceof IntersectionTypeBinding18) {
functionalInterface = new String(((IntersectionTypeBinding18) expectedType).getSAMType(scope).constantPoolName());
} else {
functionalInterface = new String(expectedType.constantPoolName());
}
// e.g. "com/foo/X$Foo"
ldc(functionalInterface);
invokeObjectEquals();
ifeq(nextOne);
// Compare FunctionalInterfaceMethodName
aload_0();
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetFunctionalInterfaceMethodName, ConstantPool.GetFunctionalInterfaceMethodNameSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
// e.g. "m"
ldc(new String(funcEx.descriptor.selector));
invokeObjectEquals();
ifeq(nextOne);
// Compare FunctionalInterfaceMethodSignature
aload_0();
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetFunctionalInterfaceMethodSignature, ConstantPool.GetFunctionalInterfaceMethodSignatureSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
// e.g "()I"
ldc(new String(funcEx.descriptor.original().signature()));
invokeObjectEquals();
ifeq(nextOne);
// Compare ImplClass
aload_0();
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplClass, ConstantPool.GetImplClassSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
// e.g. "com/foo/X"
ldc(new String(mb.declaringClass.constantPoolName()));
invokeObjectEquals();
ifeq(nextOne);
// Compare ImplMethodSignature
aload_0();
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetImplMethodSignature, ConstantPool.GetImplMethodSignatureSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
// e.g. "(I)I"
ldc(new String(mb.signature()));
invokeObjectEquals();
ifeq(nextOne);
// Captured arguments
// $NON-NLS-1$
StringBuilder sig = new StringBuilder("(");
index = 0;
boolean isLambda = funcEx instanceof LambdaExpression;
TypeBinding receiverType = null;
SyntheticArgumentBinding[] outerLocalVariables = null;
if (isLambda) {
LambdaExpression lambdaEx = (LambdaExpression) funcEx;
if (lambdaEx.shouldCaptureInstance)
receiverType = mb.declaringClass;
outerLocalVariables = lambdaEx.outerLocalVariables;
} else {
ReferenceExpression refEx = (ReferenceExpression) funcEx;
if (refEx.haveReceiver)
receiverType = ((ReferenceExpression) funcEx).receiverType;
// Should never have outer locals
}
if (receiverType != null) {
aload_0();
loadInt(index++);
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
checkcast(receiverType);
sig.append(receiverType.signature());
}
for (int p = 0, max = outerLocalVariables == null ? 0 : outerLocalVariables.length; p < max; p++) {
TypeBinding varType = outerLocalVariables[p].type;
aload_0();
loadInt(index);
invoke(Opcodes.OPC_invokevirtual, 1, 1, ConstantPool.JavaLangInvokeSerializedLambdaConstantPoolName, ConstantPool.GetCapturedArg, ConstantPool.GetCapturedArgSignature, getPopularBinding(ConstantPool.JavaLangStringConstantPoolName));
if (varType.isBaseType()) {
checkcast(scope.boxing(varType));
generateUnboxingConversion(varType.id);
if (varType.id == TypeIds.T_JavaLangLong || varType.id == TypeIds.T_JavaLangDouble) {
index++;
}
} else {
checkcast(varType);
}
index++;
sig.append(varType.signature());
}
// $NON-NLS-1$
sig.append(")");
if (funcEx.resolvedType instanceof IntersectionTypeBinding18) {
sig.append(((IntersectionTypeBinding18) funcEx.resolvedType).getSAMType(scope).signature());
} else {
sig.append(funcEx.resolvedType.signature());
}
// Example: invokeDynamic(0, 0, 1, "m".toCharArray(), "()Lcom/foo/X$Foo;".toCharArray());
invokeDynamic(funcEx.bootstrapMethodNumber, index, 1, funcEx.descriptor.selector, sig.toString().toCharArray(), funcEx.resolvedType.id, funcEx.resolvedType);
areturn();
if (j < count - 1) {
nextOne.place();
nextOne = j < count - 2 ? new BranchLabel(this) : errorLabel;
}
}
}
removeVariable(lvb1);
removeVariable(lvb2);
defaultLabel.place();
errorLabel.place();
// Code: throw new IllegalArgumentException("Invalid lambda deserialization")
new_(scope.getJavaLangIllegalArgumentException());
dup();
// $NON-NLS-1$ // TODO into a constant?
ldc("Invalid lambda deserialization");
// invokespecial: java.lang.IllegalArgumentException.<init>(Ljava/lang/String;)V
invoke(Opcodes.OPC_invokespecial, // receiverAndArgsSize
2, // return type size
0, ConstantPool.JavaLangIllegalArgumentExceptionConstantPoolName, ConstantPool.Init, ConstantPool.IllegalArgumentExceptionConstructorSignature, null);
athrow();
}
use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.
the class ConstraintExceptionFormula method inputVariables.
@Override
Collection<InferenceVariable> inputVariables(final InferenceContext18 context) {
// from 18.5.2.
if (this.left instanceof LambdaExpression) {
if (this.right instanceof InferenceVariable) {
return Collections.singletonList((InferenceVariable) this.right);
}
if (this.right.isFunctionalInterface(context.scope)) {
LambdaExpression lambda = (LambdaExpression) this.left;
// TODO derive with target type?
MethodBinding sam = this.right.getSingleAbstractMethod(context.scope, true);
final Set<InferenceVariable> variables = new LinkedHashSet<>();
if (lambda.argumentsTypeElided()) {
// i)
int len = sam.parameters.length;
for (int i = 0; i < len; i++) {
sam.parameters[i].collectInferenceVariables(variables);
}
}
if (sam.returnType != TypeBinding.VOID) {
// ii)
sam.returnType.collectInferenceVariables(variables);
}
return variables;
}
} else if (this.left instanceof ReferenceExpression) {
if (this.right instanceof InferenceVariable) {
return Collections.singletonList((InferenceVariable) this.right);
}
if (this.right.isFunctionalInterface(context.scope)) {
// TODO: && this.left is inexact
// TODO derive with target type?
MethodBinding sam = this.right.getSingleAbstractMethod(context.scope, true);
final Set<InferenceVariable> variables = new LinkedHashSet<>();
int len = sam.parameters.length;
for (int i = 0; i < len; i++) {
sam.parameters[i].collectInferenceVariables(variables);
}
sam.returnType.collectInferenceVariables(variables);
return variables;
}
}
return EMPTY_VARIABLE_LIST;
}
use of org.eclipse.jdt.internal.compiler.ast.ReferenceExpression in project bazel-jdt-java-toolchain by salesforce.
the class ConstraintExceptionFormula method reduce.
@Override
public Object reduce(InferenceContext18 inferenceContext) {
// JLS 18.2.5
Scope scope = inferenceContext.scope;
if (!this.right.isFunctionalInterface(scope))
return FALSE;
MethodBinding sam = this.right.getSingleAbstractMethod(scope, true);
if (sam == null)
return FALSE;
if (this.left instanceof LambdaExpression) {
if (((LambdaExpression) this.left).argumentsTypeElided()) {
int nParam = sam.parameters.length;
for (int i = 0; i < nParam; i++) if (!sam.parameters[i].isProperType(true))
return FALSE;
}
if (sam.returnType != TypeBinding.VOID && !sam.returnType.isProperType(true))
return FALSE;
} else {
// reference expression
if (!((ReferenceExpression) this.left).isExactMethodReference()) {
int nParam = sam.parameters.length;
for (int i = 0; i < nParam; i++) if (!sam.parameters[i].isProperType(true))
return FALSE;
if (sam.returnType != TypeBinding.VOID && !sam.returnType.isProperType(true))
return FALSE;
}
}
TypeBinding[] thrown = sam.thrownExceptions;
InferenceVariable[] e = new InferenceVariable[thrown.length];
int n = 0;
for (int i = 0; i < thrown.length; i++) if (!thrown[i].isProperType(true))
// thrown[i] is not a proper type, since it's an exception it must be an inferenceVariable, right?
e[n++] = (InferenceVariable) thrown[i];
/* If throw specification does not encode any type parameters, there are no constraints to be gleaned/gathered from the throw sites.
See also that thrown exceptions are not allowed to influence compatibility and overload resolution.
*/
if (n == 0)
return TRUE;
TypeBinding[] ePrime = null;
if (this.left instanceof LambdaExpression) {
LambdaExpression lambda = ((LambdaExpression) this.left).resolveExpressionExpecting(this.right, inferenceContext.scope, inferenceContext);
if (lambda == null)
// cannot make use of this buggy constraint
return TRUE;
Set<TypeBinding> ePrimeSet = lambda.getThrownExceptions();
ePrime = ePrimeSet.toArray(new TypeBinding[ePrimeSet.size()]);
} else {
ReferenceExpression referenceExpression = ((ReferenceExpression) this.left).resolveExpressionExpecting(this.right, scope, inferenceContext);
MethodBinding method = referenceExpression != null ? referenceExpression.binding : null;
if (method != null)
ePrime = method.thrownExceptions;
}
if (ePrime == null)
return TRUE;
int m = ePrime.length;
List<ConstraintFormula> result = new ArrayList<>();
actual: for (int i = 0; i < m; i++) {
if (ePrime[i].isUncheckedException(false))
continue;
for (int j = 0; j < thrown.length; j++) if (thrown[j].isProperType(true) && ePrime[i].isCompatibleWith(thrown[j]))
continue actual;
for (int j = 0; j < n; j++) result.add(ConstraintTypeFormula.create(ePrime[i], e[j], SUBTYPE));
}
for (int j = 0; j < n; j++) inferenceContext.currentBounds.inThrows.add(e[j].prototype());
return result.toArray(new ConstraintFormula[result.size()]);
}
Aggregations