package org.eclipse.jdt.postfixcompletion.core;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.CompletionContext;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.codeassist.InternalCompletionContext;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.text.java.AbstractTemplateCompletionProposalComputer;
import org.eclipse.jdt.internal.ui.text.template.contentassist.TemplateEngine;
import org.eclipse.jdt.ui.text.java.CompletionProposalCollector;
import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.templates.ContextTypeRegistry;
import org.eclipse.jface.text.templates.TemplateContextType;
@SuppressWarnings("restriction")
public class PostfixCompletionProposalComputer extends AbstractTemplateCompletionProposalComputer {
private final PostfixTemplateEngine postfixCompletionTemplateEngine;
public PostfixCompletionProposalComputer() {
ContextTypeRegistry templateContextRegistry = JavaPlugin.getDefault().getTemplateContextRegistry();
postfixCompletionTemplateEngine = createTemplateEngine(templateContextRegistry, JavaStatementPostfixContextType.ID_ALL);
}
private static PostfixTemplateEngine createTemplateEngine(ContextTypeRegistry templateContextRegistry, String contextTypeId) {
TemplateContextType contextType = templateContextRegistry.getContextType(contextTypeId);
Assert.isNotNull(contextType);
return new PostfixTemplateEngine(contextType);
}
@Override
protected TemplateEngine computeCompletionEngine(JavaContentAssistInvocationContext context) {
ICompilationUnit unit = context.getCompilationUnit();
if (unit == null)
return null;
IJavaProject javaProject = unit.getJavaProject();
if (javaProject == null)
return null;
CompletionContext coreContext = context.getCoreContext();
if (coreContext != null) {
int tokenLocation= coreContext.getTokenLocation();
int tokenStart= coreContext.getTokenStart();
int tokenKind= coreContext.getTokenKind();
/*
// XXX print out tokenlocation stuff (debugging)
System.out.println("All Tokens: " + CompletionContext.TL_CONSTRUCTOR_START + " " + CompletionContext.TL_MEMBER_START + " " + CompletionContext.TL_STATEMENT_START);
System.out.println("Token Start: " + coreContext.getTokenStart());
System.out.println("Token End: " + coreContext.getTokenEnd());
System.out.println("Token Kind: " + coreContext.getTokenKind());
System.out.println("Token Location: " + coreContext.getTokenLocation());
System.out.println("Enclosing Element: " + coreContext.getEnclosingElement());
System.out.println("Offset: " + coreContext.getOffset());
System.out.println("Token Array: " + Arrays.toString(coreContext.getToken()));
System.out.println("Kind Tokens: " + CompletionContext.TOKEN_KIND_NAME + ", " + CompletionContext.TOKEN_KIND_STRING_LITERAL + ", " + CompletionContext.TOKEN_KIND_UNKNOWN);
*/
if (context.getViewer().getSelectedRange().y > 0) { // If there is an active selection we do not want to contribute to the CA
return null;
}
if ((tokenLocation == 0 && tokenStart > -1)
|| ((tokenLocation & CompletionContext.TL_MEMBER_START) != 0 && tokenKind == CompletionContext.TOKEN_KIND_NAME && tokenStart > -1)
|| (tokenLocation == 0 && isAfterDot(context.getDocument(), context.getInvocationOffset()))) {
analyzeCoreContext(context, coreContext);
return postfixCompletionTemplateEngine;
}
}
return null;
}
private void analyzeCoreContext(JavaContentAssistInvocationContext context,
CompletionContext coreContext) {
// Fetch the information of the InternalCompletionContext and update our template engine
if (coreContext instanceof InternalCompletionContext && ((InternalCompletionContext)coreContext).isExtended()) {
updateTemplateEngine((InternalCompletionContext)coreContext);
} else if (coreContext instanceof InternalCompletionContext && ((InternalCompletionContext)coreContext).isExtended() == false) {
// If the coreContext is not extended atm for some reason we have to extend it ourself in order to the needed information
final ICompilationUnit cu = context.getCompilationUnit();
final CompletionProposalCollector collector = new CompletionProposalCollector(cu) {
@Override
public void acceptContext(final CompletionContext context) {
super.acceptContext(context);
updateTemplateEngine((InternalCompletionContext) context);
}
};
collector.setInvocationContext(context);
collector.setRequireExtendedContext(true);
try {
cu.codeComplete(context.getInvocationOffset(), collector);
} catch (JavaModelException e) {
}
}
}
private void updateTemplateEngine(InternalCompletionContext context) {
ASTNode completionNode = context.getCompletionNode();
ASTNode completionNodeParent = context.getCompletionNodeParent();
postfixCompletionTemplateEngine.setASTNodes(completionNode, completionNodeParent);
}
/**
* Returns true if the given offset is directly after a dot character.
* @param document
* @param offset
* @return true if the given offset is directly after a dot character, false otherwise
*/
private boolean isAfterDot(IDocument document, int offset) {
try {
return document.get(offset - 1, 1).charAt(0) == '.';
} catch (BadLocationException e) {
return false;
}
}
}