/*******************************************************************************
* Copyright (c) 2011, 2016 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:
* Martin Schwab & Thomas Kallenberg - initial API and implementation
******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.togglefunction;
import java.util.ArrayList;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.internal.ui.refactoring.Container;
public class InsertionPointFinder {
private static ArrayList<ICPPASTFunctionDeclarator> allafterdeclarations;
private static ArrayList<ICPPASTFunctionDefinition> alldefinitionsoutside;
private static IASTDeclaration position;
public static IASTDeclaration findInsertionPoint(IASTTranslationUnit classunit,
IASTTranslationUnit functiondefunit, IASTFunctionDeclarator funcDecl) {
position = null;
findAllDeclarationsAfterInClass(classunit, funcDecl);
findAllDefinitionsoutSideClass(functiondefunit);
findRightPlace();
return position;
}
private static void findRightPlace() {
if (allafterdeclarations == null || alldefinitionsoutside == null)
return;
for(ICPPASTFunctionDeclarator decl: allafterdeclarations) {
String decl_name = decl.getName().toString();
for(ICPPASTFunctionDefinition def: alldefinitionsoutside) {
String def_name = null;
IASTName name = def.getDeclarator().getName();
if (name != null)
def_name = name.getLastName().toString();
if (decl_name.equals(def_name)) {
if (def.getParent() != null && def.getParent() instanceof ICPPASTTemplateDeclaration) {
position = (IASTDeclaration) def.getParent();
} else {
position = def;
}
return;
}
}
}
}
private static void findAllDeclarationsAfterInClass(IASTTranslationUnit classunit,
IASTFunctionDeclarator funcDecl) {
ICPPASTCompositeTypeSpecifier klass = getklass(classunit);
if (klass != null)
allafterdeclarations = getDeclarationsInClass(klass, funcDecl);
}
/**
* @param ast the translation unit where to find the definitions
*/
private static void findAllDefinitionsoutSideClass(IASTTranslationUnit ast) {
final ArrayList<ICPPASTFunctionDefinition> definitions = new ArrayList<ICPPASTFunctionDefinition>();
if (ast == null) {
alldefinitionsoutside = definitions;
return;
}
ast.accept(
new ASTVisitor() {
{
shouldVisitDeclarations = true;
}
@Override
public int visit(IASTDeclaration declaration) {
if (declaration instanceof ICPPASTFunctionDefinition) {
if (declaration.getParent() != null &&
ASTQueries.findAncestorWithType(declaration, CPPASTCompositeTypeSpecifier.class) != null) {
return PROCESS_CONTINUE;
}
definitions.add((ICPPASTFunctionDefinition) declaration);
}
return super.visit(declaration);
}
});
alldefinitionsoutside = definitions;
}
private static ArrayList<ICPPASTFunctionDeclarator> getDeclarationsInClass(ICPPASTCompositeTypeSpecifier klass, final IASTFunctionDeclarator selected) {
final ArrayList<ICPPASTFunctionDeclarator> declarations = new ArrayList<ICPPASTFunctionDeclarator>();
klass.accept(
new ASTVisitor() {
{
shouldVisitDeclarators = true;
}
boolean got = false;
@Override
public int visit(IASTDeclarator declarator) {
if (declarator instanceof ICPPASTFunctionDeclarator) {
if (((ICPPASTFunctionDeclarator) declarator) == selected) {
got = true;
}
if (got) {
declarations.add((ICPPASTFunctionDeclarator) declarator);
}
}
return super.visit(declarator);
}
});
return declarations;
}
private static ICPPASTCompositeTypeSpecifier getklass(IASTTranslationUnit unit) {
final Container<ICPPASTCompositeTypeSpecifier> result = new Container<ICPPASTCompositeTypeSpecifier>();
unit.accept(
new ASTVisitor() {
{
shouldVisitDeclSpecifiers = true;
}
@Override
public int visit(IASTDeclSpecifier declSpec) {
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
result.setObject((ICPPASTCompositeTypeSpecifier) declSpec);
return PROCESS_ABORT;
}
return super.visit(declSpec);
}
});
return result.getObject();
}
}