@SuppressWarnings("incomplete-switch")
	protected CandidateCompareResult compareTo(AbstractPendingLinkingCandidate<?> right, boolean invalid) {
		{
			CandidateCompareResult arityCompareResult = compareByArityWith(right);
			switch(arityCompareResult) {
				case SUSPICIOUS_OTHER:
					throw new IllegalStateException();
				case EQUALLY_INVALID:
					invalid = true;
					break;
				case OTHER:
				case THIS:
					return arityCompareResult;
				
			}
		}
		{
			boolean visible = isVisible();
			if (visible != right.isVisible()) {
				if (visible)
					return CandidateCompareResult.THIS;
				return CandidateCompareResult.OTHER;
			} else if (!visible) {
				invalid = true;
			}
		}
		{
			CandidateCompareResult typeArityCompareResult = compareByArity(getTypeArityMismatch(), right.getTypeArityMismatch());
			switch(typeArityCompareResult) {
				case SUSPICIOUS_OTHER:
					throw new IllegalStateException();
				case EQUALLY_INVALID:
					invalid = true;
					break;
				case OTHER:
				case THIS:
					return typeArityCompareResult;
				
			}
		}
		{
			CandidateCompareResult nameCompareResult = compareByName(right);
			switch(nameCompareResult) {
				case SUSPICIOUS_OTHER:
					throw new IllegalStateException();
				case EQUALLY_INVALID:
					invalid = true;
					break;
				case OTHER:
				case THIS:
					return nameCompareResult;
			}
		}
		{
			CandidateCompareResult argumentTypeCompareResult = compareByArgumentTypes(right);
			switch(argumentTypeCompareResult) {
				case EQUALLY_INVALID:
					invalid = true;
					break;
				case SUSPICIOUS_OTHER:
				case OTHER:
				case THIS:
					return argumentTypeCompareResult;
				
			}
		}
		{
			CandidateCompareResult typeArgumentCompareResult = compareByTypeArguments(right);
			switch(typeArgumentCompareResult) {
				case SUSPICIOUS_OTHER:
					throw new IllegalStateException();
				case EQUALLY_INVALID:
					invalid = true;
					break;
				case OTHER:
				case THIS:
					return typeArgumentCompareResult;
				
			}
		}
		if (isVarArgs() != right.isVarArgs()) {
			if (isVarArgs())
				return CandidateCompareResult.OTHER;
			return CandidateCompareResult.THIS;
		}
		// member feature calls done on type literals have precedence over instance calls, i.e. R.array binds to R$array rather than Class.isArray()
		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=437660
		if (getExpression() instanceof XMemberFeatureCall && !getFeature().getSimpleName().equals(right.getFeature().getSimpleName())) {
			if (isTypeLiteral() && !right.isTypeLiteral()) {
				return CandidateCompareResult.THIS;
			} else if (right.isTypeLiteral() && !isTypeLiteral()){
				return CandidateCompareResult.OTHER;
			}
		}
		if(isTypeLiteral() && !right.isTypeLiteral()) {
			return CandidateCompareResult.OTHER;
		}
		{
			CandidateCompareResult bucketCompareResult = compareByBucket(right);
			switch(bucketCompareResult) {
				case SUSPICIOUS_OTHER:
					throw new IllegalStateException();
				case EQUALLY_INVALID:
					invalid = true;
					break;
				case OTHER:
				case THIS:
					return bucketCompareResult;
				
			}
		}
		if (invalid)
			return CandidateCompareResult.EQUALLY_INVALID;
		return CandidateCompareResult.AMBIGUOUS;
	}
@ SuppressWarnings ( "incomplete-switch" ) protected CandidateCompareResult compareTo ( AbstractPendingLinkingCandidate < ? > right , boolean invalid ) { { CandidateCompareResult arityCompareResult = compareByArityWith ( right ) ; switch ( arityCompareResult ) { case SUSPICIOUS_OTHER : throw new IllegalStateException ( ) ; case EQUALLY_INVALID : invalid = true ; break ; case OTHER : case THIS : return arityCompareResult ; } } { boolean visible = isVisible ( ) ; if ( visible != right . isVisible ( ) ) { if ( visible ) return CandidateCompareResult . THIS ; return CandidateCompareResult . OTHER ; } else if ( ! visible ) { invalid = true ; } } { CandidateCompareResult typeArityCompareResult = compareByArity ( getTypeArityMismatch ( ) , right . getTypeArityMismatch ( ) ) ; switch ( typeArityCompareResult ) { case SUSPICIOUS_OTHER : throw new IllegalStateException ( ) ; case EQUALLY_INVALID : invalid = true ; break ; case OTHER : case THIS : return typeArityCompareResult ; } } { CandidateCompareResult nameCompareResult = compareByName ( right ) ; switch ( nameCompareResult ) { case SUSPICIOUS_OTHER : throw new IllegalStateException ( ) ; case EQUALLY_INVALID : invalid = true ; break ; case OTHER : case THIS : return nameCompareResult ; } } { CandidateCompareResult argumentTypeCompareResult = compareByArgumentTypes ( right ) ; switch ( argumentTypeCompareResult ) { case EQUALLY_INVALID : invalid = true ; break ; case SUSPICIOUS_OTHER : case OTHER : case THIS : return argumentTypeCompareResult ; } } { CandidateCompareResult typeArgumentCompareResult = compareByTypeArguments ( right ) ; switch ( typeArgumentCompareResult ) { case SUSPICIOUS_OTHER : throw new IllegalStateException ( ) ; case EQUALLY_INVALID : invalid = true ; break ; case OTHER : case THIS : return typeArgumentCompareResult ; } } if ( isVarArgs ( ) != right . isVarArgs ( ) ) { if ( isVarArgs ( ) ) return CandidateCompareResult . OTHER ; return CandidateCompareResult . THIS ; } if ( getExpression ( ) instanceof XMemberFeatureCall && ! getFeature ( ) . getSimpleName ( ) . equals ( right . getFeature ( ) . getSimpleName ( ) ) ) { if ( isTypeLiteral ( ) && ! right . isTypeLiteral ( ) ) { return CandidateCompareResult . THIS ; } else if ( right . isTypeLiteral ( ) && ! isTypeLiteral ( ) ) { return CandidateCompareResult . OTHER ; } } if ( isTypeLiteral ( ) && ! right . isTypeLiteral ( ) ) { return CandidateCompareResult . OTHER ; } { CandidateCompareResult bucketCompareResult = compareByBucket ( right ) ; switch ( bucketCompareResult ) { case SUSPICIOUS_OTHER : throw new IllegalStateException ( ) ; case EQUALLY_INVALID : invalid = true ; break ; case OTHER : case THIS : return bucketCompareResult ; } } if ( invalid ) return CandidateCompareResult . EQUALLY_INVALID ; return CandidateCompareResult . AMBIGUOUS ; }
Returns {@code CandidateCompareResult#THIS} if this candidate is better, {@code CandidateCompareResult#OTHER} if the
right candidate was better, {@code CandidateCompareResult#AMBIGUOUS} if both candidates are valid
but ambiguous or {@code CandidateCompareResult#EQUALLY_INVALID} if both candidates are
ambiguous but erroneous.

The invalid flag indicates if we already know that both candidates are equally invalid.