/******************************************************************************* * Copyright (c) 2009 Institute for Software, HSR Hochschule fuer Technik * Rapperswil, University of applied sciences and others * 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: * Institute for Software - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.extractfunction; import java.util.ArrayList; import java.util.List; import java.util.Vector; import java.util.Map.Entry; import org.eclipse.core.resources.IFile; import org.eclipse.text.edits.TextEditGroup; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; import org.eclipse.cdt.internal.ui.refactoring.NodeContainer; import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; final class SimilarFinderVisitor extends ASTVisitor { private final ExtractFunctionRefactoring refactoring; private final Vector<IASTNode> trail; private final IASTName name; private final List<IASTNode> stmts; private int i; private NodeContainer similarContainer; private final List<IASTStatement> stmtToReplace = new ArrayList<IASTStatement>(); private final ModificationCollector collector; SimilarFinderVisitor(ExtractFunctionRefactoring refactoring, ModificationCollector collector, Vector<IASTNode> trail, IFile file, IASTName name, List<IASTNode> stmts, String title) { this.refactoring = refactoring; this.trail = trail; this.name = name; this.stmts = stmts; this.collector = collector; this.similarContainer = new NodeContainer(); shouldVisitStatements = true; } @Override public int visit(IASTStatement stmt) { boolean isAllreadyInMainRefactoring = isInSelection(stmt); if ((!isAllreadyInMainRefactoring) && this.refactoring.isStatementInTrail(stmt, trail, this.refactoring.getIndex())) { stmtToReplace.add(stmt); similarContainer.add(stmt); ++i; if (i == stmts.size()) { // Found similar code boolean similarOnReturnWays = true; for (NameInformation nameInfo : similarContainer.getAllAfterUsedNames()) { if (this.refactoring.names.containsKey(nameInfo.getDeclaration().getRawSignature())) { Integer nameOrderNumber = this.refactoring.names.get(nameInfo.getDeclaration().getRawSignature()); if (this.refactoring.nameTrail.containsValue(nameOrderNumber)) { String orgName = null; boolean found = false; for (Entry<String, Integer> entry : this.refactoring.nameTrail.entrySet()) { if (entry.getValue().equals(nameOrderNumber)) { orgName = entry.getKey(); } } if (orgName != null) { for (NameInformation orgNameInfo : this.refactoring.container.getAllAfterUsedNamesChoosenByUser()) { if (orgName.equals(orgNameInfo.getDeclaration().getRawSignature())) { found = true; } } } if (!found) { similarOnReturnWays = false; } } } } if (similarOnReturnWays) { IASTNode call = refactoring.getMethodCall(name, this.refactoring.nameTrail, this.refactoring.names, this.refactoring.container, similarContainer); ASTRewrite rewrite = collector.rewriterForTranslationUnit(stmtToReplace.get(0).getTranslationUnit()); TextEditGroup editGroup = new TextEditGroup(Messages.SimilarFinderVisitor_replaceDuplicateCode); rewrite.replace(stmtToReplace.get(0), call, editGroup); if (stmtToReplace.size() > 1) { for (int i = 1; i < stmtToReplace.size(); ++i) { rewrite.remove(stmtToReplace.get(i), editGroup); } } } clear(); } return PROCESS_SKIP; } else { clear(); return super.visit(stmt); } } private boolean isInSelection(IASTStatement stmt) { List<IASTNode>nodes = this.refactoring.container.getNodesToWrite(); for (IASTNode node : nodes) { if (node.equals(stmt)) { return true; } } return false; } private void clear() { i = 0; this.refactoring.names.clear(); similarContainer = new NodeContainer(); this.refactoring.namesCounter.setObject(ExtractFunctionRefactoring.NULL_INTEGER); this.refactoring.trailPos.setObject(ExtractFunctionRefactoring.NULL_INTEGER); stmtToReplace.clear(); } }