private static boolean locationNeedsParentheses(StructuralPropertyDescriptor locationInParent) { if (locationInParent instanceof ChildListPropertyDescriptor && locationInParent != InfixExpression.EXTENDED_OPERANDS_PROPERTY) { // e.g. argument lists of MethodInvocation, ClassInstanceCreation, dimensions of ArrayCreation ... return false; } if (locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY || locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY || locationInParent == ReturnStatement.EXPRESSION_PROPERTY || locationInParent == EnhancedForStatement.EXPRESSION_PROPERTY || locationInParent == ForStatement.EXPRESSION_PROPERTY || locationInParent == WhileStatement.EXPRESSION_PROPERTY || locationInParent == DoStatement.EXPRESSION_PROPERTY || locationInParent == AssertStatement.EXPRESSION_PROPERTY || locationInParent == AssertStatement.MESSAGE_PROPERTY || locationInParent == IfStatement.EXPRESSION_PROPERTY || locationInParent == SwitchStatement.EXPRESSION_PROPERTY || locationInParent == SwitchCase.EXPRESSION_PROPERTY || locationInParent == ArrayAccess.INDEX_PROPERTY || locationInParent == ThrowStatement.EXPRESSION_PROPERTY || locationInParent == SynchronizedStatement.EXPRESSION_PROPERTY || locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY) { return false; } return true; }
@Override public void endVisit(EnhancedForStatement node) { if (skipNode(node)) { return; } FlowInfo paramInfo = getFlowInfo(node.getParameter()); FlowInfo expressionInfo = getFlowInfo(node.getExpression()); FlowInfo actionInfo = getFlowInfo(node.getBody()); EnhancedForFlowInfo forInfo = createEnhancedFor(); setFlowInfo(node, forInfo); // If the for statement is the outermost loop then we only have to consider // the action. The parameter and expression are only evaluated once. if (node == fLoopNode) { forInfo.mergeAction(actionInfo, fFlowContext); } else { // Inner for loops are evaluated in the sequence expression, parameter, // action. forInfo.mergeExpression(expressionInfo, fFlowContext); forInfo.mergeParameter(paramInfo, fFlowContext); forInfo.mergeAction(actionInfo, fFlowContext); } forInfo.removeLabel(null); }
private Statement getParentLoopBody(ASTNode node) { Statement stmt = null; ASTNode start = node; while (start != null && !(start instanceof ForStatement) && !(start instanceof DoStatement) && !(start instanceof WhileStatement) && !(start instanceof EnhancedForStatement) && !(start instanceof SwitchStatement)) { start = start.getParent(); } if (start instanceof ForStatement) { stmt = ((ForStatement) start).getBody(); } else if (start instanceof DoStatement) { stmt = ((DoStatement) start).getBody(); } else if (start instanceof WhileStatement) { stmt = ((WhileStatement) start).getBody(); } else if (start instanceof EnhancedForStatement) { stmt = ((EnhancedForStatement) start).getBody(); } if (start != null && start.getParent() instanceof LabeledStatement) { LabeledStatement labeledStatement = (LabeledStatement) start.getParent(); fEnclosingLoopLabel = labeledStatement.getLabel(); } return stmt; }
private static void addEnhancedForWithoutTypeProposals(ICompilationUnit cu, ASTNode selectedNode, Collection<CUCorrectionProposal> proposals) { if (selectedNode instanceof SimpleName && (selectedNode.getLocationInParent() == SimpleType.NAME_PROPERTY || selectedNode.getLocationInParent() == NameQualifiedType.NAME_PROPERTY)) { ASTNode type= selectedNode.getParent(); if (type.getLocationInParent() == SingleVariableDeclaration.TYPE_PROPERTY) { SingleVariableDeclaration svd= (SingleVariableDeclaration) type.getParent(); if (svd.getLocationInParent() == EnhancedForStatement.PARAMETER_PROPERTY) { if (svd.getName().getLength() == 0) { SimpleName simpleName= (SimpleName) selectedNode; String name= simpleName.getIdentifier(); int relevance= StubUtility.hasLocalVariableName(cu.getJavaProject(), name) ? 10 : 7; String label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_create_loop_variable_description, BasicElementLabels.getJavaElementName(name)); proposals.add(new NewVariableCorrectionProposal(label, cu, NewVariableCorrectionProposal.LOCAL, simpleName, null, relevance)); } } } } }
private static boolean locationNeedsParentheses(StructuralPropertyDescriptor locationInParent) { if (locationInParent instanceof ChildListPropertyDescriptor && locationInParent != InfixExpression.EXTENDED_OPERANDS_PROPERTY) { // e.g. argument lists of MethodInvocation, ClassInstanceCreation, dimensions of ArrayCreation // ... return false; } if (locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY || locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY || locationInParent == ReturnStatement.EXPRESSION_PROPERTY || locationInParent == EnhancedForStatement.EXPRESSION_PROPERTY || locationInParent == ForStatement.EXPRESSION_PROPERTY || locationInParent == WhileStatement.EXPRESSION_PROPERTY || locationInParent == DoStatement.EXPRESSION_PROPERTY || locationInParent == AssertStatement.EXPRESSION_PROPERTY || locationInParent == AssertStatement.MESSAGE_PROPERTY || locationInParent == IfStatement.EXPRESSION_PROPERTY || locationInParent == SwitchStatement.EXPRESSION_PROPERTY || locationInParent == SwitchCase.EXPRESSION_PROPERTY || locationInParent == ArrayAccess.INDEX_PROPERTY || locationInParent == ThrowStatement.EXPRESSION_PROPERTY || locationInParent == SynchronizedStatement.EXPRESSION_PROPERTY || locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY) { return false; } return true; }
@Override public void endVisit(EnhancedForStatement node) { if (skipNode(node)) return; FlowInfo paramInfo = getFlowInfo(node.getParameter()); FlowInfo expressionInfo = getFlowInfo(node.getExpression()); FlowInfo actionInfo = getFlowInfo(node.getBody()); EnhancedForFlowInfo forInfo = createEnhancedFor(); setFlowInfo(node, forInfo); // If the for statement is the outermost loop then we only have to consider // the action. The parameter and expression are only evaluated once. if (node == fLoopNode) { forInfo.mergeAction(actionInfo, fFlowContext); } else { // Inner for loops are evaluated in the sequence expression, parameter, // action. forInfo.mergeExpression(expressionInfo, fFlowContext); forInfo.mergeParameter(paramInfo, fFlowContext); forInfo.mergeAction(actionInfo, fFlowContext); } forInfo.removeLabel(null); }
private static Set<EnhancedForStatement> getEnhancedForStatements(IMethod method, IProgressMonitor pm) throws JavaModelException { ICompilationUnit iCompilationUnit = method.getCompilationUnit(); // get the ASTParser of the method CompilationUnit compilationUnit = RefactoringASTParser.parseWithASTProvider(iCompilationUnit, true, new SubProgressMonitor(pm, 1)); // get the method declaration ASTNode. MethodDeclaration methodDeclarationNode = ASTNodeSearchUtil.getMethodDeclarationNode(method, compilationUnit); final Set<EnhancedForStatement> statements = new LinkedHashSet<EnhancedForStatement>(); // extract all enhanced for loop statements in the method. methodDeclarationNode.accept(new ASTVisitor() { @Override public boolean visit(EnhancedForStatement node) { statements.add(node); return super.visit(node); } }); return statements; }
@Override public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { try { final RefactoringStatus status = new RefactoringStatus(); for (IMethod method : methods) { Set<EnhancedForStatement> statements = getEnhancedForStatements(method, new SubProgressMonitor(pm, 1)); IProgressMonitor subMonitor = new SubProgressMonitor(pm, statements.size()); // check preconditions on each. statements.stream().forEach(s -> status.merge(checkEnhancedForStatement(s, method, subMonitor))); pm.worked(1); } return status; } finally { pm.done(); } }
@Override public boolean preNext(Statement curElement) { switch (curElement.getNodeType()) { case ASTNode.WHILE_STATEMENT: exportWhile((WhileStatement) curElement); break; case ASTNode.FOR_STATEMENT: exportFor((ForStatement) curElement); break; case ASTNode.ENHANCED_FOR_STATEMENT: exportForEach((EnhancedForStatement) curElement); break; case ASTNode.DO_STATEMENT: exportDoWhileStatement((DoStatement) curElement); break; } return true; }
@Override public void endVisit(EnhancedForStatement node) { if (skipNode(node)) return; FlowInfo paramInfo= getFlowInfo(node.getParameter()); FlowInfo expressionInfo= getFlowInfo(node.getExpression()); FlowInfo actionInfo= getFlowInfo(node.getBody()); EnhancedForFlowInfo forInfo= createEnhancedFor(); setFlowInfo(node, forInfo); // If the for statement is the outermost loop then we only have to consider // the action. The parameter and expression are only evaluated once. if (node == fLoopNode) { forInfo.mergeAction(actionInfo, fFlowContext); } else { // Inner for loops are evaluated in the sequence expression, parameter, // action. forInfo.mergeExpression(expressionInfo, fFlowContext); forInfo.mergeParameter(paramInfo, fFlowContext); forInfo.mergeAction(actionInfo, fFlowContext); } forInfo.removeLabel(null); }
private Statement getParentLoopBody(ASTNode node) { Statement stmt= null; ASTNode start= node; while (start != null && !(start instanceof ForStatement) && !(start instanceof DoStatement) && !(start instanceof WhileStatement) && !(start instanceof EnhancedForStatement) && !(start instanceof SwitchStatement)) { start= start.getParent(); } if (start instanceof ForStatement) { stmt= ((ForStatement)start).getBody(); } else if (start instanceof DoStatement) { stmt= ((DoStatement)start).getBody(); } else if (start instanceof WhileStatement) { stmt= ((WhileStatement)start).getBody(); } else if (start instanceof EnhancedForStatement) { stmt= ((EnhancedForStatement)start).getBody(); } if (start != null && start.getParent() instanceof LabeledStatement) { LabeledStatement labeledStatement= (LabeledStatement)start.getParent(); fEnclosingLoopLabel= labeledStatement.getLabel(); } return stmt; }
private static void addEnhancedForWithoutTypeProposals(ICompilationUnit cu, ASTNode selectedNode, Collection<ICommandAccess> proposals) { if (selectedNode instanceof SimpleName && (selectedNode.getLocationInParent() == SimpleType.NAME_PROPERTY || selectedNode.getLocationInParent() == NameQualifiedType.NAME_PROPERTY)) { ASTNode type= selectedNode.getParent(); if (type.getLocationInParent() == SingleVariableDeclaration.TYPE_PROPERTY) { SingleVariableDeclaration svd= (SingleVariableDeclaration) type.getParent(); if (svd.getLocationInParent() == EnhancedForStatement.PARAMETER_PROPERTY) { if (svd.getName().getLength() == 0) { SimpleName simpleName= (SimpleName) selectedNode; String name= simpleName.getIdentifier(); int relevance= StubUtility.hasLocalVariableName(cu.getJavaProject(), name) ? 10 : 7; String label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_create_loop_variable_description, BasicElementLabels.getJavaElementName(name)); Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL); proposals.add(new NewVariableCorrectionProposal(label, cu, NewVariableCorrectionProposal.LOCAL, simpleName, null, relevance, image)); } } } } }
private static boolean isLastStatementInEnclosingMethodOrLambda(Statement statement) { ASTNode currentStructure= statement; ASTNode currentParent= statement.getParent(); while (!(currentParent instanceof MethodDeclaration || currentParent instanceof LambdaExpression)) { // should not be in a loop if (currentParent instanceof ForStatement || currentParent instanceof EnhancedForStatement || currentParent instanceof WhileStatement || currentParent instanceof DoStatement) { return false; } if (currentParent instanceof Block) { Block parentBlock= (Block) currentParent; if (parentBlock.statements().indexOf(currentStructure) != parentBlock.statements().size() - 1) { // not last statement in the block return false; } } currentStructure= currentParent; currentParent= currentParent.getParent(); } return true; }
/** * 'for(' parameter ':' expression ') {' body '}' */ @Override public boolean visit(final EnhancedForStatement node) { final int lineNo = lineStart(node); // new dependence final IResolvedLine rd = createDependence(LK_ENHANCED_FOR, lineNo, mdg.parent()); // add this definition rd.definitions().add( factory.resolveExpression(node.getParameter().getName(), node, null, false, true)); // collect uses for this control predicate appendDependences(rd, node.getExpression(), null, false); // recursively append dependences appendRecursive(lineNo, rd, node.getBody()); // do not visit children return false; }
@Override protected void repairBug(ASTRewrite rewrite, CompilationUnit workingUnit, BugInstance bug) throws BugResolutionException { ASTNode node = getASTNode(workingUnit, bug.getPrimarySourceLineAnnotation()); this.typeSource = ImportRewrite.create(workingUnit, true); // these imports won't get added automatically this.rewrite = rewrite; this.ast = rewrite.getAST(); EntrySetResolutionVisitor visitor = new EntrySetResolutionVisitor(); node.accept(visitor); EnhancedForStatement replacement = makeReplacementForLoop(visitor); rewrite.replace(visitor.ancestorForLoop, replacement, null); addImports(rewrite, workingUnit, ImportUtil.filterOutJavaLangImports(typeSource.getAddedImports())); addImports(rewrite, workingUnit, "java.util.Map"); // shouldn't be necessary. Allows us to use Map.entry }
@SuppressWarnings("unchecked") private EnhancedForStatement makeReplacementForLoop(EntrySetResolutionVisitor visitor) { // this would be map.keySet(). // We need this to get the type of map and get the variable name of map MethodInvocation oldLoopExpression = (MethodInvocation) visitor.ancestorForLoop.getExpression(); // for(Parameter : Expression) EnhancedForStatement replacement = ast.newEnhancedForStatement(); replacement.setParameter(makeEntrySetParameter(oldLoopExpression)); replacement.setExpression(makeCallToEntrySet(oldLoopExpression)); List<Statement> replacementBlockStatements = ((Block) replacement.getBody()).statements(); // create new statement to replace the key object (e.g. the String s that used to be in the for each) replacementBlockStatements.add(makeNewKeyStatement(visitor)); // replace the call to map.get() with a call to entry.getValue() replacementBlockStatements.add(makeNewValueStatement(visitor)); // transfer the rest of the statements in the old block copyRestOfBlock(replacementBlockStatements, visitor); return replacement; }
@Override public boolean visit(MethodInvocation node) { if (ancestorForLoop != null) { return false; } if (!"get".equals(node.getName().getIdentifier())) { return true; // there may be a nested method invocation } valueTypeName = node.resolveTypeBinding().getName(); // for description message this.ancestorForLoop = TraversalUtil.findClosestAncestor(node, EnhancedForStatement.class); this.badMapGetStatement = TraversalUtil.findClosestAncestor(node, Statement.class); // if this is null, it was an anonymous use this.badMapGetVariableFragment = TraversalUtil.findClosestAncestor(node, VariableDeclarationFragment.class); if (badMapGetVariableFragment == null) { this.badMapGetMethodInvocation = node; // this is an anonymous usage, and will need to be replaced } return false; }
private boolean isLoopStatement(Block block) { ASTNode parent = block.getParent(); return parent instanceof WhileStatement || parent instanceof ForStatement || parent instanceof DoStatement || parent instanceof EnhancedForStatement || parent instanceof IfStatement; }
/** * Returns true if a node at a given location is a body of a control statement. Such body nodes are * interesting as when replacing them, it has to be evaluates if a Block is needed instead. * E.g. <code> if (x) do(); -> if (x) { do1(); do2() } </code> * * @param locationInParent Location of the body node * @return Returns true if the location is a body node location of a control statement. */ public static boolean isControlStatementBody(StructuralPropertyDescriptor locationInParent) { return locationInParent == IfStatement.THEN_STATEMENT_PROPERTY || locationInParent == IfStatement.ELSE_STATEMENT_PROPERTY || locationInParent == ForStatement.BODY_PROPERTY || locationInParent == EnhancedForStatement.BODY_PROPERTY || locationInParent == WhileStatement.BODY_PROPERTY || locationInParent == DoStatement.BODY_PROPERTY; }
@Override public void endVisit(EnhancedForStatement node) { if (skipNode(node)) { return; } EnhancedForFlowInfo forInfo = createEnhancedFor(); setFlowInfo(node, forInfo); forInfo.mergeParameter(getFlowInfo(node.getParameter()), fFlowContext); forInfo.mergeExpression(getFlowInfo(node.getExpression()), fFlowContext); forInfo.mergeAction(getFlowInfo(node.getBody()), fFlowContext); forInfo.removeLabel(null); }
@Override public void endVisit(EnhancedForStatement node) { if (getSelection().getEndVisitSelectionMode(node) == Selection.AFTER) { if (node.getParameter() == getFirstSelectedNode()) { invalidSelection(RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_for_initializer, JavaStatusContext.create(fCUnit, getSelection())); } } super.endVisit(node); }
private boolean isEnhancedForStatementVariable(Statement statement, SimpleName name) { if (statement instanceof EnhancedForStatement) { EnhancedForStatement forStatement= (EnhancedForStatement) statement; SingleVariableDeclaration param= forStatement.getParameter(); return param.getType() == name.getParent(); // strange recovery, see https://bugs.eclipse.org/180456 } return false; }
/** {@inheritDoc} */ @Override public boolean visit(EnhancedForStatement node) { handle(node.getBody(), EnhancedForStatement.BODY_PROPERTY); return super.visit(node); }
public boolean isDangligIf() { List<Statement> statements = fDeclaration.getBody().statements(); if (statements.size() != 1) return false; ASTNode p = statements.get(0); while (true) { if (p instanceof IfStatement) { return ((IfStatement) p).getElseStatement() == null; } else { ChildPropertyDescriptor childD; if (p instanceof WhileStatement) { childD = WhileStatement.BODY_PROPERTY; } else if (p instanceof ForStatement) { childD = ForStatement.BODY_PROPERTY; } else if (p instanceof EnhancedForStatement) { childD = EnhancedForStatement.BODY_PROPERTY; } else if (p instanceof DoStatement) { childD = DoStatement.BODY_PROPERTY; } else if (p instanceof LabeledStatement) { childD = LabeledStatement.BODY_PROPERTY; } else { return false; } Statement body = (Statement) p.getStructuralProperty(childD); if (body instanceof Block) { return false; } else { p = body; } } } }
private void insertAt(ASTNode target, Statement declaration) { ASTRewrite rewrite = fCURewrite.getASTRewrite(); TextEditGroup groupDescription = fCURewrite.createGroupDescription( RefactoringCoreMessages.ExtractTempRefactoring_declare_local_variable); ASTNode parent = target.getParent(); StructuralPropertyDescriptor locationInParent = target.getLocationInParent(); while (locationInParent != Block.STATEMENTS_PROPERTY && locationInParent != SwitchStatement.STATEMENTS_PROPERTY) { if (locationInParent == IfStatement.THEN_STATEMENT_PROPERTY || locationInParent == IfStatement.ELSE_STATEMENT_PROPERTY || locationInParent == ForStatement.BODY_PROPERTY || locationInParent == EnhancedForStatement.BODY_PROPERTY || locationInParent == DoStatement.BODY_PROPERTY || locationInParent == WhileStatement.BODY_PROPERTY) { // create intermediate block if target was the body property of a control statement: Block replacement = rewrite.getAST().newBlock(); ListRewrite replacementRewrite = rewrite.getListRewrite(replacement, Block.STATEMENTS_PROPERTY); replacementRewrite.insertFirst(declaration, null); replacementRewrite.insertLast(rewrite.createMoveTarget(target), null); rewrite.replace(target, replacement, groupDescription); return; } target = parent; parent = parent.getParent(); locationInParent = target.getLocationInParent(); } ListRewrite listRewrite = rewrite.getListRewrite(parent, (ChildListPropertyDescriptor) locationInParent); listRewrite.insertBefore(declaration, target, groupDescription); }
@Override public void endVisit(EnhancedForStatement node) { if (getSelection().getEndVisitSelectionMode(node) == Selection.AFTER) { if (node.getParameter() == getFirstSelectedNode()) { invalidSelection( RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_for_initializer, JavaStatusContext.create(fCUnit, getSelection())); } } super.endVisit(node); }
private static void addEnhancedForWithoutTypeProposals( ICompilationUnit cu, ASTNode selectedNode, Collection<ICommandAccess> proposals) { if (selectedNode instanceof SimpleName && (selectedNode.getLocationInParent() == SimpleType.NAME_PROPERTY || selectedNode.getLocationInParent() == NameQualifiedType.NAME_PROPERTY)) { ASTNode type = selectedNode.getParent(); if (type.getLocationInParent() == SingleVariableDeclaration.TYPE_PROPERTY) { SingleVariableDeclaration svd = (SingleVariableDeclaration) type.getParent(); if (svd.getLocationInParent() == EnhancedForStatement.PARAMETER_PROPERTY) { if (svd.getName().getLength() == 0) { SimpleName simpleName = (SimpleName) selectedNode; String name = simpleName.getIdentifier(); int relevance = StubUtility.hasLocalVariableName(cu.getJavaProject(), name) ? 10 : 7; String label = Messages.format( CorrectionMessages .UnresolvedElementsSubProcessor_create_loop_variable_description, BasicElementLabels.getJavaElementName(name)); Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL); proposals.add( new NewVariableCorrectionProposal( label, cu, NewVariableCorrectionProposal.LOCAL, simpleName, null, relevance, image)); } } } } }
/** * Helper to generate a <code>foreach</code> loop to iterate over an {@link Iterable}. * * @param ast the {@link AST} instance to rewrite the loop to * @return the complete {@link ASTRewrite} object */ private ASTRewrite generateForEachRewrite(AST ast) { EnhancedForStatement loopStatement = ast.newEnhancedForStatement(); ASTRewrite rewrite = ASTRewrite.create(ast); ITypeBinding loopOverType = extractElementType(ast); // generate name proposals and add them to the variable declaration SimpleName forDeclarationName = resolveLinkedVariableNameWithProposals(rewrite, loopOverType.getName(), null, true); SingleVariableDeclaration forLoopInitializer = ast.newSingleVariableDeclaration(); forLoopInitializer.setType( getImportRewrite() .addImport( loopOverType, ast, new ContextSensitiveImportRewriteContext(fCurrentNode, getImportRewrite()))); forLoopInitializer.setName(forDeclarationName); loopStatement.setParameter(forLoopInitializer); loopStatement.setExpression((Expression) rewrite.createCopyTarget(fCurrentExpression)); Block forLoopBody = ast.newBlock(); forLoopBody.statements().add(createBlankLineStatementWithCursorPosition(rewrite)); loopStatement.setBody(forLoopBody); rewrite.replace(fCurrentNode, loopStatement, null); return rewrite; }
private boolean isEnhancedForStatementVariable(Statement statement, SimpleName name) { if (statement instanceof EnhancedForStatement) { EnhancedForStatement forStatement = (EnhancedForStatement) statement; SingleVariableDeclaration param = forStatement.getParameter(); return param.getType() == name.getParent(); // strange recovery, see https://bugs.eclipse.org/180456 } return false; }
/** {@inheritDoc} */ @Override public void endVisit(EnhancedForStatement node) { // TODO-JRO Implement method endVisit logger.warn("Method endVisit not implemented!"); super.endVisit(node); }
private static boolean enhancedForStatementIteratesOverCollection(EnhancedForStatement enhancedForStatement, IProgressMonitor pm) { Expression expression = enhancedForStatement.getExpression(); ITypeBinding nodeBindingType = expression.resolveTypeBinding(); // Checking if the enhancedForStatement implement or extend collection if (nodeBindingType.isArray()) { return true; } else { // getting the class-name to check if it's part of Collection String fullTypeName = nodeBindingType.getQualifiedName(); String typeName = fullTypeName.split("<")[0]; if (typeName.equals("java.util.Collection")) { return false; } // STEP 1: getting java the element of the type, IType iTypeElement = (IType) nodeBindingType.getJavaElement(); try { // STEP 2: getting java iTypeHeirchay, ITypeHierarchy iTypeHeirchay = iTypeElement.newSupertypeHierarchy(pm); // STEP 3: checking if Collections class being implemented IType[] superInterface = iTypeHeirchay.getAllInterfaces(); for (IType iType : superInterface) { String interfaceName = iType.getFullyQualifiedParameterizedName(); if (interfaceName.startsWith("java.util.Collection")) { return false; } } } catch (JavaModelException e) { e.printStackTrace(); } } return true; }
/** * Determines the source of the collection that is iterated in the given foreach-loop. The source is either a * parameter or a return value of a procedure (method or constructor). This information is required to fetch * information about the average size of the collection from the feedback handler. * * @param foreachStatement * @param methodDeclaration * @return */ public final Optional<CollectionSource> getSource(final EnhancedForStatement foreachStatement, final MethodDeclaration methodDeclaration) { final Expression expression = foreachStatement.getExpression(); // Case 1: the for loop contains a variable; 'for(Object item : items)' if (expression instanceof SimpleName) { final String variableName = expression.toString(); // Case 1a: the variable of the for loop is a method parameter of the containing method final Optional<Integer> position = getParameterPosition(variableName, methodDeclaration); if (position.isPresent()) { return Optional.of(new CollectionSource(new MethodDeclarationExtension(methodDeclaration).createCorrelatingProcedure(), position.get())); } // Case 1b: the variable of the for-loop is locally defined inside the method final Optional<Procedure> procedure = getLocalVariableProcedureAssignment(variableName, methodDeclaration, foreachStatement.getStartPosition()); if (procedure.isPresent()) { return Optional.of(new CollectionSource(procedure.get())); } // Case 1c: the variable is a field of the containing class // TODO enhancement: Support cases where the collection is a class field (if possible). // This case is tricky with SCA, because you don't know which code of the class already has been executed. // Therefore one can not simply search for assignments of the class field. // A solution could be to look at all the call traces that are executed when the loop is executed. This might help // to find out which code is executed and then in combination with SCA to find the place where the collection is // set. But this would require many calls to the Feedback handler which could make the build very slow. } // Case 2: the for loop contains a method invocation; example: 'for(Object item : getItems())' else if (expression instanceof MethodInvocation) { final MethodInvocationExtension methodInvocationExtension = new MethodInvocationExtension((MethodInvocation) expression); return Optional.of(new CollectionSource(methodInvocationExtension.createCorrelatingProcedure())); } return Optional.absent(); }
/** * Determines if this ASTNode is a conditional statement. * Conditional statements include: if,do,while,for,switch * @param node * @return */ public static boolean isConditional(ASTNode node){ if(node instanceof IfStatement) return true; if(node instanceof DoStatement) return true; if(node instanceof EnhancedForStatement) return true; if(node instanceof ForStatement) return true; if(node instanceof SwitchStatement) return true; if(node instanceof WhileStatement) return true; return false; }
/** * We don't really need anything in particular from this statement, * but since it has an expression and a body, we only want to * investigate the expression part to determine if it needs to * be in the slice. */ public boolean visit(EnhancedForStatement node){ if(this.options.contains(Slicer.Options.CONTROL_EXPRESSIONS_ONLY)){ /* Visit the expression part. */ node.getExpression().accept(this); /* Don't visit the children. */ return false; } else return true; }
/** * We want to track the variables from the expression only. */ public boolean visit(EnhancedForStatement node){ /* Visit the expression part. */ node.getExpression().accept(this); /* Don't visit the children. */ return false; }