package org.testng.eclipse.refactoring;
import java.util.List;
import com.google.common.collect.Lists;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.ui.text.java.IQuickAssistProcessor;
import org.testng.eclipse.ui.conversion.BaseQuickAssistProcessor;
import org.testng.eclipse.ui.conversion.IRewriteProvider;
import org.testng.eclipse.ui.conversion.JUnitRewriteCorrectionProposal;
/**
* The assist processor that presents all the TestNG related code assists.
*
* @author Cedric Beust <cedric@beust.com>
*/
public class TestNGQuickAssistProcessor
extends BaseQuickAssistProcessor
implements IQuickAssistProcessor
{
private TestNGVisitor m_visitor;
private CompilationUnit m_astRoot;
private AST m_ast;
private ICompilationUnit m_compilationUnit;
public boolean hasAssists(IInvocationContext context) throws CoreException {
init(context);
return hasPushAssists(m_visitor) || hasPullAssists(m_visitor)
|| hasAssertImportAssists(m_visitor);
}
private static boolean hasAssertImportAssists(TestNGVisitor visitor) {
return visitor.getAsserts().size() > 0;
}
/**
* Initialize the AST. This method needs to be called every time, otherwise we
* might store a tree that then gets obsoleted by changes in the editor.
*/
private void init(IInvocationContext context) {
//
// Prepare the AST for rewriting
//
m_compilationUnit = context.getCompilationUnit();
// Create a DOM/AST from a ICompilationUnit
m_astRoot = createCompilationUnit(m_compilationUnit);
m_ast = context.getASTRoot().getAST();
// Populate the TestNGVisitor with the information we'll be needing
// to do the rewriting
m_visitor = new TestNGVisitor();
m_astRoot.accept(m_visitor);
}
private static boolean hasPushAssists(TestNGVisitor visitor) {
return visitor.getTestClassAnnotation() != null;
}
private static boolean hasPullAssists(TestNGVisitor visitor) {
Annotation testClass = visitor.getTestClassAnnotation();
return visitor.getTestMethods().size() > 0 && testClass == null;
}
public IJavaCompletionProposal[] getAssists(IInvocationContext context,
IProblemLocation[] locations) throws CoreException
{
List<IJavaCompletionProposal> vResult = Lists.newArrayList();
init(context);
if (hasAssists(context)) {
//
// Only show applicable TestNG refactorings
//
List<IRewriteProvider> providers = Lists.newArrayList();
if (hasPushAssists(m_visitor)) providers.add(new PushTestRewriter());
if (hasPullAssists(m_visitor)) providers.add(new PullTestRewriter());
if (hasAssertImportAssists(m_visitor)) {
String node = findAssertInContext(context);
if (node != null) providers.add(new ImportAssertRewriter(node));
}
for (IRewriteProvider provider : providers) {
ASTRewrite rewriter = provider.createRewriter(m_astRoot, m_ast);
vResult.add(new JUnitRewriteCorrectionProposal(
provider.getName(), m_compilationUnit, rewriter, 1));
}
}
return vResult.toArray(new IJavaCompletionProposal[vResult.size()]);
}
private String findAssertInContext(IInvocationContext context) {
ASTNode node = context.getCoveringNode();
while (node != null) {
if (node instanceof MethodInvocation) {
String nodeName = ((MethodInvocation) node).getName().toString();
if (m_visitor.getAsserts().contains(nodeName)) {
return nodeName;
}
}
node = node.getParent();
}
return null;
}
}