private boolean needsIdCast(Expression lhs, Expression rhs) { ITypeBinding lhsType = lhs.getTypeBinding(); ITypeBinding rhsType = rhs.getTypeBinding(); return !lhsType.isPrimitive() && !rhsType.isPrimitive() && !lhsType.isAssignmentCompatible(rhsType) && !rhsType.isAssignmentCompatible(lhsType); }
/* * Evaluates possible return expressions. The favourite expression is returned. */ private Expression evaluateReturnExpressions( AST ast, ITypeBinding returnBinding, int returnOffset) { CompilationUnit root = (CompilationUnit) fMethodDecl.getRoot(); Expression result = null; if (returnBinding != null) { ScopeAnalyzer analyzer = new ScopeAnalyzer(root); IBinding[] bindings = analyzer.getDeclarationsInScope( returnOffset, ScopeAnalyzer.VARIABLES | ScopeAnalyzer.CHECK_VISIBILITY); for (int i = 0; i < bindings.length; i++) { IVariableBinding curr = (IVariableBinding) bindings[i]; ITypeBinding type = curr.getType(); if (type != null && type.isAssignmentCompatible(returnBinding) && testModifier(curr)) { if (result == null) { result = ast.newSimpleName(curr.getName()); } addLinkedPositionProposal(RETURN_EXPRESSION_KEY, curr.getName(), null); } } } Expression defaultExpression = ASTNodeFactory.newDefaultExpression( ast, fMethodDecl.getReturnType2(), fMethodDecl.getExtraDimensions()); addLinkedPositionProposal(RETURN_EXPRESSION_KEY, ASTNodes.asString(defaultExpression), null); if (result == null) { return defaultExpression; } return result; }
/** * Check if the method can be called with the given arguments. Used when we don't have a direct * link to the method that is invoked (for example: Action.create(...)). */ public static boolean isApplicableToCall(Iterable<ITypeBinding> args, IMethodBinding meth) { int[] i = {0}; ITypeBinding[] params = meth.getParameterTypes(); for (ITypeBinding arg : args) { if (params.length <= i[0] || !arg.isAssignmentCompatible(params[i[0]++])) { return false; } } return true; }
private boolean needsCast(Expression expr, ITypeBinding expectedType, boolean shouldCastFromId) { ITypeBinding declaredType = getDeclaredType(expr); if (declaredType == null) { return false; } ITypeBinding exprType = typeEnv.mapType(expr.getTypeBinding()); declaredType = typeEnv.mapType(declaredType); if ( // In general we do not need to cast primitive types. exprType.isPrimitive() // In most cases we don't need to cast from an id type. However, if the // expression is being dereferenced then the compiler needs the type // info. || (typeEnv.isIdType(declaredType) && !shouldCastFromId) // If the declared type can be assigned into the actual type, or the // expected type, then the compiler already has sufficient type info. || typeEnv.isIdType(exprType) || typeEnv.isIdType(expectedType) || declaredType.isAssignmentCompatible(exprType) || declaredType.isAssignmentCompatible(expectedType)) { return false; } return true; }
/** * Given a JDT type binding created by the parser, either replace it with an iOS equivalent, or * return the given type. */ public ITypeBinding mapType(ITypeBinding binding) { if (binding == null) { // happens when mapping a primitive type return null; } // getTypeDeclaration will return the canonical binding for the type with // type parameters and type annotations removed. Note that getErasure() does // not strip type annotations. binding = binding.getTypeDeclaration(); if (binding.isArray()) { return resolveArrayType(binding.getComponentType()); } ITypeBinding newBinding = typeMap.get(binding); if (newBinding == null && binding.isAssignmentCompatible(javaClassType)) { newBinding = typeMap.get(javaClassType); } return newBinding != null ? newBinding : binding; }
@Override public void endVisit(CastExpression node) { ITypeBinding type = node.getType().getTypeBinding(); Expression expr = node.getExpression(); ITypeBinding exprType = expr.getTypeBinding(); // TODO(kirbs): Implement correct conversion of Java 8 intersection types to Objective-C. if (node.getType().isIntersectionType() && !Options.isJava8Translator()) { // Technically we can't currently get here, but as we add support and change flags in the // future this should alert us to implement intersection types. assert false : "not implemented yet"; } if (BindingUtil.isFloatingPoint(exprType)) { assert type.isPrimitive(); // Java wouldn't allow a cast from primitive to non-primitive. switch (type.getBinaryName().charAt(0)) { case 'J': node.replaceWith(rewriteFloatToIntegralCast(type, expr, "JreFpToLong", type)); return; case 'C': node.replaceWith(rewriteFloatToIntegralCast(type, expr, "JreFpToChar", type)); return; case 'B': case 'S': case 'I': node.replaceWith( rewriteFloatToIntegralCast(type, expr, "JreFpToInt", typeEnv.resolveJavaType("int"))); return; } // else fall-through. } // Lean on Java's type-checking. if (!type.isPrimitive() && exprType.isAssignmentCompatible(type.getErasure())) { node.replaceWith(TreeUtil.remove(expr)); return; } FunctionInvocation castCheck = createCastCheck(type, expr); if (castCheck != null) { node.setExpression(castCheck); } }
/*(non-Javadoc) * @see org.eclipse.jdt.internal.ui.text.correction.ASTRewriteCorrectionProposal#getRewrite() */ @Override protected ASTRewrite getRewrite() { AST ast = fMethodDecl.getAST(); ITypeBinding returnBinding = getReturnTypeBinding(); if (fExistingReturn != null) { ASTRewrite rewrite = ASTRewrite.create(ast); Expression expression = evaluateReturnExpressions(ast, returnBinding, fExistingReturn.getStartPosition()); if (expression != null) { rewrite.set(fExistingReturn, ReturnStatement.EXPRESSION_PROPERTY, expression, null); addLinkedPosition(rewrite.track(expression), true, RETURN_EXPRESSION_KEY); } return rewrite; } else { ASTRewrite rewrite = ASTRewrite.create(ast); Block block = fMethodDecl.getBody(); List<Statement> statements = block.statements(); int nStatements = statements.size(); ASTNode lastStatement = null; if (nStatements > 0) { lastStatement = statements.get(nStatements - 1); } if (returnBinding != null && lastStatement instanceof ExpressionStatement && lastStatement.getNodeType() != ASTNode.ASSIGNMENT) { Expression expression = ((ExpressionStatement) lastStatement).getExpression(); ITypeBinding binding = expression.resolveTypeBinding(); if (binding != null && binding.isAssignmentCompatible(returnBinding)) { Expression placeHolder = (Expression) rewrite.createMoveTarget(expression); ReturnStatement returnStatement = ast.newReturnStatement(); returnStatement.setExpression(placeHolder); rewrite.replace(lastStatement, returnStatement, null); return rewrite; } } int offset; if (lastStatement == null) { offset = block.getStartPosition() + 1; } else { offset = lastStatement.getStartPosition() + lastStatement.getLength(); } ReturnStatement returnStatement = ast.newReturnStatement(); Expression expression = evaluateReturnExpressions(ast, returnBinding, offset); returnStatement.setExpression(expression); rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY).insertLast(returnStatement, null); addLinkedPosition( rewrite.track(returnStatement.getExpression()), true, RETURN_EXPRESSION_KEY); return rewrite; } }