/*******************************************************************************
* Copyright (c) 2010 Tomasz Wesolowski
* 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:
* Tomasz Wesolowski - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
import java.util.HashMap;
import org.eclipse.cdt.codan.core.cxx.CxxAstUtils;
import org.eclipse.cdt.codan.core.cxx.CxxAstUtils.NameFinderVisitor;
import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator;
import org.eclipse.cdt.codan.ui.AbstractAstRewriteQuickFix;
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.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.INodeFactory;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.ltk.core.refactoring.CompositeChange;
public class QuickFixCreateParameter extends AbstractAstRewriteQuickFix {
public String getLabel() {
return Messages.QuickFixCreateParameter_0;
}
@Override
public void modifyAST(IIndex index, IMarker marker) {
CxxAstUtils utils = CxxAstUtils.getInstance();
CompositeChange c = new CompositeChange(Messages.QuickFixCreateParameter_0);
try {
ITranslationUnit baseTU = getTranslationUnitViaEditor(marker);
IASTTranslationUnit baseAST = baseTU.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
IASTName astName = getASTNameFromMarker(marker, baseAST);
if (astName == null) {
return;
}
IASTDeclaration declaration = CxxAstUtils.getInstance().createDeclaration(astName, baseAST.getASTNodeFactory(), index);
// We'll need a FunctionParameterDeclaration later
final IASTDeclSpecifier finalDeclSpec = (IASTDeclSpecifier) declaration.getChildren()[0];
final IASTDeclarator finalDeclarator = (IASTDeclarator) declaration.getChildren()[1];
IASTFunctionDefinition function = utils.getEnclosingFunction(astName);
if (function == null) {
return;
}
// Find the function declarations
NameFinderVisitor nameFinderVisitor = new NameFinderVisitor();
function.accept(nameFinderVisitor);
IASTName funcName = nameFinderVisitor.name;
IBinding binding = funcName.resolveBinding();
IIndexName[] declarations = index.findNames(binding, IIndex.FIND_DECLARATIONS_DEFINITIONS);
if (declarations.length == 0) {
return;
}
HashMap<ITranslationUnit, IASTTranslationUnit> cachedASTs = new HashMap<ITranslationUnit, IASTTranslationUnit>();
HashMap<ITranslationUnit, ASTRewrite> cachedRewrites = new HashMap<ITranslationUnit, ASTRewrite>();
for (IIndexName iname : declarations) {
ITranslationUnit declTU = utils.getTranslationUnitFromIndexName(iname);
ASTRewrite rewrite;
IASTTranslationUnit declAST;
if (!cachedASTs.containsKey(declTU)) {
declAST = declTU.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
rewrite = ASTRewrite.create(declAST);
cachedASTs.put(declTU, declAST);
cachedRewrites.put(declTU, rewrite);
} else {
declAST = cachedASTs.get(declTU);
rewrite = cachedRewrites.get(declTU);
}
IASTFileLocation fileLocation = iname.getFileLocation();
IASTName declName = declAST.getNodeSelector(null).findEnclosingName(fileLocation.getNodeOffset(),
fileLocation.getNodeLength());
if (declName == null) {
continue;
}
INodeFactory factory = declAST.getASTNodeFactory();
IASTFunctionDeclarator functionDecl;
{
IASTNode n = declName;
while (n instanceof IASTName) {
n = n.getParent();
}
functionDecl = (IASTFunctionDeclarator) n;
}
IASTParameterDeclaration newParam = factory.newParameterDeclaration(finalDeclSpec, finalDeclarator);
rewrite.insertBefore(functionDecl, null, newParam, null);
}
for (ASTRewrite rewrite : cachedRewrites.values()) {
c.add(rewrite.rewriteAST());
}
c.perform(new NullProgressMonitor());
} catch (CoreException e) {
CheckersUiActivator.log(e);
}
}
@Override
public boolean isApplicable(IMarker marker) {
String problemArgument = getProblemArgument(marker, 1);
return problemArgument.contains(":func"); //$NON-NLS-1$
}
}