/* * 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; }
private ITypeBinding[] computeTypeVariables(ITypeBinding[] bindings) { Selection selection = getSelection(); Set<ITypeBinding> result = new HashSet<>(); // first remove all type variables that come from outside of the method // or are covered by the selection CompilationUnit compilationUnit = (CompilationUnit) fEnclosingBodyDeclaration.getRoot(); for (int i = 0; i < bindings.length; i++) { ASTNode decl = compilationUnit.findDeclaringNode(bindings[i]); if (decl == null || (!selection.covers(decl) && decl.getParent() instanceof MethodDeclaration)) result.add(bindings[i]); } // all all type variables which are needed since a local variable uses it for (int i = 0; i < fArguments.length; i++) { IVariableBinding arg = fArguments[i]; ITypeBinding type = arg.getType(); if (type != null && type.isTypeVariable()) { ASTNode decl = compilationUnit.findDeclaringNode(type); if (decl == null || (!selection.covers(decl) && decl.getParent() instanceof MethodDeclaration)) result.add(type); } } return result.toArray(new ITypeBinding[result.size()]); }
public static boolean isPrimitiveConstant(IVariableBinding binding) { return isFinal(binding) && binding.getType().isPrimitive() && binding.getConstantValue() != null // Exclude local variables declared final. && binding.getDeclaringClass() != null; }
@Override public void endVisit(SuperMethodInvocation node) { Name qualifier = node.getQualifier(); if (qualifier == null) { return; } IMethodBinding method = node.getMethodBinding(); ITypeBinding exprType = node.getTypeBinding(); IVariableBinding var = TreeUtil.getVariableBinding(qualifier); assert var != null : "Expected qualifier to be a variable"; ITypeBinding qualifierType = var.getType(); SuperMethodBindingPair superMethod = new SuperMethodBindingPair(qualifierType, method); superMethods.add(superMethod); FunctionBinding binding = new FunctionBinding(getSuperFunctionName(superMethod), exprType, qualifierType); binding.addParameters(qualifierType, typeEnv.getIdType()); binding.addParameters(method.getParameterTypes()); FunctionInvocation invocation = new FunctionInvocation(binding, exprType); List<Expression> args = invocation.getArguments(); args.add(TreeUtil.remove(qualifier)); String selectorExpr = UnicodeUtils.format("@selector(%s)", nameTable.getMethodSelector(method)); args.add(new NativeExpression(selectorExpr, typeEnv.getIdType())); TreeUtil.copyList(node.getArguments(), args); node.replaceWith(invocation); }
private Statement createVolatileRetainStatement(IVariableBinding var) { ITypeBinding idType = typeEnv.resolveIOSType("id"); FunctionInvocation invocation = new FunctionInvocation("JreRetainVolatile", idType, idType, null); invocation .getArguments() .add( new PrefixExpression( typeEnv.getPointerType(var.getType()), PrefixExpression.Operator.ADDRESS_OF, new SimpleName(var))); return new ExpressionStatement(invocation); }
private List<Statement> getFieldAdjustments(TypeDeclaration node) { List<Statement> adjustments = Lists.newArrayList(); for (VariableDeclarationFragment decl : TreeUtil.getAllFields(node)) { IVariableBinding var = decl.getVariableBinding(); if (BindingUtil.isStatic(var) || var.getType().isPrimitive()) { continue; } boolean isWeak = BindingUtil.isWeakReference(var); boolean isVolatile = BindingUtil.isVolatile(var); if (isWeak && !isVolatile) { adjustments.add(createReleaseStatement(var)); } else if (!isWeak && isVolatile) { adjustments.add(createVolatileRetainStatement(var)); } } return adjustments; }
@Override public boolean visit(ClassInstanceCreation node) { ITypeBinding newType = node.getTypeBinding().getTypeDeclaration(); ITypeBinding declaringClass = newType.getDeclaringClass(); if (Modifier.isStatic(newType.getModifiers()) || declaringClass == null) { return true; } GeneratedMethodBinding binding = new GeneratedMethodBinding(node.getMethodBinding().getMethodDeclaration()); node.setMethodBinding(binding); addOuterArg(node, binding, declaringClass); for (IVariableBinding capturedVar : getCapturedVariables(node)) { node.getArguments().add(new SimpleName(capturedVar)); binding.addParameter(capturedVar.getType()); } assert binding.isVarargs() || node.getArguments().size() == binding.getParameterTypes().length; return true; }
/** List has a toArray() method that uses array types. */ public void testAbstractMethodsAddedWithArrayType() { String source = "import java.util.List; public abstract class Test implements List<Object> { " + "public boolean isEmpty() { return true; } }"; CompilationUnit unit = translateType("Test", source); List<AbstractTypeDeclaration> types = unit.getTypes(); assertEquals(1, types.size()); assertTrue(types.get(0) instanceof TypeDeclaration); TypeDeclaration testType = (TypeDeclaration) types.get(0); List<MethodDeclaration> methods = TreeUtil.getMethodDeclarationsList(testType); assertEquals(26, methods.size()); // verify added methods are abstract, and that existing method wasn't changed for (MethodDeclaration m : methods) { int modifiers = m.getModifiers(); String name = m.getName().getIdentifier(); if (name.equals("isEmpty")) { assertFalse(Modifier.isAbstract(modifiers)); } else if (name.equals(NameTable.FINALIZE_METHOD) || name.equals(NameTable.DEALLOC_METHOD) || name.equals(NameTable.INIT_NAME)) { // it's ok. } else { // it's an added method assertTrue(Modifier.isAbstract(modifiers)); ITypeBinding returnType = m.getReturnType().getTypeBinding(); if (name.equals("toArray")) { assertEquals("IOSObjectArray", returnType.getName()); if (!m.getParameters().isEmpty()) { assertEquals(1, m.getParameters().size()); SingleVariableDeclaration param = m.getParameters().get(0); IVariableBinding paramBinding = param.getVariableBinding(); assertTrue(paramBinding.getType().isArray()); } } } } }
// We generate the runtime debug method +memDebugStaticReferences. // This method will return an array of NSNumber containing pointers (casted into unsigned long) // to the objects referenced by a class variable with a strong reference. // It will be useful for debug purpose. // // Arrays returned by -memDebugStaticReferences and -memDebugStaticReferencesNames (see below) // must be the same size. // // In case of a Java enum, valuesVarNameis the name of the array of enum values. private void printStaticReferencesMethod(List<FieldDeclaration> fields, String valuesVarName) { if (Options.memoryDebug()) { if (!Options.useReferenceCounting()) { println("+ (NSArray *)memDebugStaticReferences {"); println(" return nil;"); println("}"); return; } println("+ (NSArray *)memDebugStaticReferences {"); println(" NSMutableArray *result = [NSMutableArray array];"); for (FieldDeclaration f : fields) { if (Modifier.isStatic(f.getModifiers())) { for (VariableDeclarationFragment var : ASTUtil.getFragments(f)) { IVariableBinding binding = Types.getVariableBinding(var); // All non-primitive static variables are strong references. if (!binding.getType().isPrimitive()) { String name = NameTable.getStaticVarQualifiedName(binding); println( String.format( " [result addObject:[JreMemDebugStrongReference " + "strongReferenceWithObject:%s name:@\"%s\"]];", name, name)); } } } } if (valuesVarName != null) { println( String.format( " [result addObject:[JreMemDebugStrongReference " + "strongReferenceWithObject:%s name:@\"enumValues\"]];", valuesVarName)); } println(" return result;"); println("}\n"); } }
private void printStaticVars(List<FieldDeclaration> fields, boolean isInterface) { boolean hadStaticVar = false; for (FieldDeclaration f : fields) { if (Modifier.isStatic(f.getModifiers()) || isInterface) { for (VariableDeclarationFragment var : ASTUtil.getFragments(f)) { IVariableBinding binding = Types.getVariableBinding(var); if (!BindingUtil.isPrimitiveConstant(binding)) { String name = NameTable.getStaticVarQualifiedName(binding); String objcType = NameTable.getObjCType(binding.getType()); Expression initializer = var.getInitializer(); if (initializer != null) { printf("static %s %s = %s;\n", objcType, name, generateExpression(initializer)); } else { printf("static %s %s;\n", objcType, name); } hadStaticVar = true; } } } } if (hadStaticVar) { newline(); } }
private Example makeExample( MethodDeclaration node, Set<? extends Expression> envolvedInvocations, List<ApiMethod> envolvedApiMethods) { // Visitor responsável por realizar o slicing de programas SlicingStatementVisitor visitor = new SlicingStatementVisitor(node, new HashSet<ASTNode>(envolvedInvocations)); node.accept(visitor); Collection<Statement> relatedStatements = visitor.getSlicedStatements(); ASTNode newAST = ASTUtil.copyStatements(node.getBody(), relatedStatements, AST.newAST(AST.JLS3)); if (!relatedStatements.isEmpty()) { LOGGER.error("Some statements were not included!"); } if (newAST == null) { LOGGER.error("Slicing process failed for node "); // TODO Se AST retornada for nula é porque faltou incluir statement(s) return null; } else if (((Block) newAST).statements().isEmpty()) { LOGGER.error("Slicing process failed for node "); // TODO Se o Block retornado for vazio é porque faltou incluir statement(s) return null; } ASTUtil.removeEmptyBlocks((Block) newAST); // Adiciona declarações de variáveis que não foram encontradas no escopo do método // Para facilitar, tipos iguais são declarados no mesmo Statement Set<String> additionalDeclarationLines = new HashSet<String>(); Map<ITypeBinding, List<IVariableBinding>> typesMap = new HashMap<ITypeBinding, List<IVariableBinding>>(); for (IVariableBinding ivb : visitor.getUndiscoveredDeclarations()) { if (!typesMap.containsKey(ivb.getType())) { typesMap.put(ivb.getType(), new ArrayList<IVariableBinding>(2)); } typesMap.get(ivb.getType()).add(ivb); } for (ITypeBinding typeBinding : typesMap.keySet()) { List<IVariableBinding> variableBindings = typesMap.get(typeBinding); Stack<VariableDeclarationFragment> fragments = new Stack<VariableDeclarationFragment>(); for (IVariableBinding ivb : variableBindings) { VariableDeclarationFragment declarationFragment = newAST.getAST().newVariableDeclarationFragment(); declarationFragment.setName(newAST.getAST().newSimpleName(ivb.getName())); fragments.add(declarationFragment); } VariableDeclarationStatement statement = newAST.getAST().newVariableDeclarationStatement(fragments.pop()); while (!fragments.isEmpty()) { statement.fragments().add(fragments.pop()); } statement.setType(this.getType(typeBinding, newAST.getAST())); additionalDeclarationLines.add(statement.toString()); ((Block) newAST).statements().add(0, statement); } Example example = new Example(); example.setAttachment(this.attachmentMap.get(node.getRoot())); example.setApiMethods(new HashSet<ApiElement>(envolvedApiMethods)); example.setImports(visitor.getImports()); for (Expression seed : envolvedInvocations) { example.getSeeds().add(seed.toString()); } example.setSourceMethod(node.toString()); example.setAddedAt(new Date(System.currentTimeMillis())); try { IMethodBinding nodeBinding = node.resolveBinding(); if (!this.methodMap.containsKey(nodeBinding)) { ApiClass newApiClass = new ApiClass(nodeBinding.getDeclaringClass().getQualifiedName()); methodDeclarationHandler(node, newApiClass); } example.setSourceMethodCall(this.methodMap.get(nodeBinding).getFullName()); } catch (Exception e) { LOGGER.error(e); if (example.getSourceMethodCall() == null) { example.setSourceMethodCall("?"); } } String codeExample = newAST.toString(); for (String line : additionalDeclarationLines) { codeExample = codeExample.replace( line, line.replace("\n", "").concat(" ").concat("//initialized previously").concat("\n")); } // FIXME codeExample = codeExample.replaceAll("(\\{\n)(\\s+)(\\})", "$1 //do something \n$3"); try { example.setCodeExample(codeExample); example.setFormattedCodeExample(ASTUtil.codeFormatter(codeExample)); } catch (Exception e) { LOGGER.error(e); if (example.getFormattedCodeExample() == null) { example.setFormattedCodeExample(codeExample); } } // TODO Obter métricas do exemplo example .getMetrics() .put(ExampleMetric.LOC.name(), example.getFormattedCodeExample().split("\n").length - 1); example.getMetrics().put(ExampleMetric.ARGUMENTS.name(), visitor.getNumberOfArguments()); example .getMetrics() .put(ExampleMetric.DECISION_STATEMENTS.name(), visitor.getNumberOfDecisionStatements()); example.getMetrics().put(ExampleMetric.INVOCATIONS.name(), visitor.getNumberOfInvocations()); example .getMetrics() .put(ExampleMetric.NULL_ARGUMENTS.name(), visitor.getNumberOfNullArguments()); example .getMetrics() .put(ExampleMetric.PRIMITIVE_ARGUMENTS.name(), visitor.getNumberOfPrimitiveArguments()); example .getMetrics() .put(ExampleMetric.FIELD_ARGUMENTS.name(), visitor.getNumberOfFieldArguments()); example .getMetrics() .put( ExampleMetric.UNDISCOVERED_DECLARATIONS.name(), visitor.getNumberOfUndiscoveredDeclarations()); example .getMetrics() .put(ExampleMetric.UNHANDLED_EXCEPTIONS.name(), visitor.getNumberOfUnhandledExceptions()); return example; }