All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jdt.internal.compiler.lookup.ConstraintExceptionFormula Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2013, 2014 GK Software AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Stephan Herrmann - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;

/**
 * Constraint formula expressing that a given expression must have an exception type.
 * 
    *
  • Expression containsthrows T
  • *
*/ public class ConstraintExceptionFormula extends ConstraintFormula { FunctionalExpression left; public ConstraintExceptionFormula(FunctionalExpression left, TypeBinding type) { this.left = left; this.right = type; this.relation = EXCEPTIONS_CONTAINED; } 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)) e[n++] = (InferenceVariable) thrown[i]; // thrown[i] is not a proper type, since it's an exception it must be an inferenceVariable, right? /* 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).getResolvedCopyForInferenceTargeting(this.right); if (lambda == null) return TRUE; // cannot make use of this buggy constraint Set ePrimeSet = lambda.getThrownExceptions(); ePrime = ePrimeSet.toArray(new TypeBinding[ePrimeSet.size()]); } else { ReferenceExpression referenceExpression = (ReferenceExpression)this.left; MethodBinding method = referenceExpression.findCompileTimeMethodTargeting(this.right, scope); if (method != null) ePrime = method.thrownExceptions; } if (ePrime == null) return TRUE; int m = ePrime.length; List 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]); return result.toArray(new ConstraintFormula[result.size()]); } Collection 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; MethodBinding sam = this.right.getSingleAbstractMethod(context.scope, true); // TODO derive with target type? final Set variables = new HashSet(); 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 MethodBinding sam = this.right.getSingleAbstractMethod(context.scope, true); // TODO derive with target type? final Set variables = new HashSet(); 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; } public String toString() { StringBuffer buf = new StringBuffer().append(LEFT_ANGLE_BRACKET); this.left.printExpression(4, buf); buf.append(" \u2286throws "); //$NON-NLS-1$ appendTypeName(buf, this.right); buf.append(RIGHT_ANGLE_BRACKET); return buf.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy