package org.rubypeople.rdt.internal.ui.text.ruby;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.rubypeople.rdt.core.IRubyScript;
import org.rubypeople.rdt.internal.corext.template.ruby.RubyContextType;
import org.rubypeople.rdt.internal.ui.RubyPlugin;
import org.rubypeople.rdt.internal.ui.RubyPluginImages;
import org.rubypeople.rdt.internal.ui.text.template.contentassist.TemplateEngine;
import org.rubypeople.rdt.internal.ui.text.template.contentassist.TemplateProposal;
import org.rubypeople.rdt.ui.text.RubyTextTools;
import org.rubypeople.rdt.ui.text.ruby.ContentAssistInvocationContext;
import org.rubypeople.rdt.ui.text.ruby.IRubyCompletionProposal;
import org.rubypeople.rdt.ui.text.ruby.IRubyCompletionProposalComputer;
public class TemplateCompletionProposalComputer implements IRubyCompletionProposalComputer {
private TemplateEngine fRubyTemplateEngine;
public TemplateCompletionProposalComputer() {
TemplateContextType contextType = RubyPlugin.getDefault().getTemplateContextRegistry().getContextType(RubyContextType.NAME);
if (contextType == null) {
contextType = new RubyContextType();
RubyPlugin.getDefault().getTemplateContextRegistry().addContextType(contextType);
}
if (contextType != null)
fRubyTemplateEngine = new TemplateEngine(contextType);
else
fRubyTemplateEngine = null;
}
public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
TemplateEngine engine = fRubyTemplateEngine;
if (engine != null) {
IRubyScript unit = null;
if (context instanceof RubyContentAssistInvocationContext) {
RubyContentAssistInvocationContext rContext = (RubyContentAssistInvocationContext) context;
unit = rContext.getRubyScript();
}
if (unit == null)
return Collections.EMPTY_LIST;
engine.reset();
engine.complete(context.getViewer(), context.getInvocationOffset(), unit);
TemplateProposal[] templateProposals = engine.getResults();
List result = new ArrayList(Arrays.asList(templateProposals));
IRubyCompletionProposal[] keyWordResults = getKeywordProposals(context);
if (keyWordResults.length > 0) {
// update relevance of template proposals that match with a
// keyword
// give those templates slightly more relevance than the keyword
// to
// sort them first
// remove keyword templates that don't have an equivalent
// keyword proposal
if (keyWordResults.length > 0) {
outer: for (int k = 0; k < templateProposals.length; k++) {
TemplateProposal curr = templateProposals[k];
String name = curr.getTemplate().getName();
for (int i = 0; i < keyWordResults.length; i++) {
String keyword = keyWordResults[i]
.getDisplayString();
if (name.startsWith(keyword)) {
curr.setRelevance(keyWordResults[i]
.getRelevance() + 1);
continue outer;
}
}
}
}
}
return result;
}
return Collections.EMPTY_LIST;
}
private IRubyCompletionProposal[] getKeywordProposals(ContentAssistInvocationContext context) {
List keywords = getKeywords();
List fKeywords = new ArrayList();
for (Iterator iter = keywords.iterator(); iter.hasNext();) {
String keyword = (String) iter.next();
String prefix = getCurrentPrefix(context.getDocument().get(), context.getInvocationOffset());
if (prefix.length() >= keyword.length())
continue;
fKeywords.add(createKeywordProposal(keyword, prefix, context.getInvocationOffset()));
}
return (IRubyCompletionProposal[]) fKeywords.toArray(new RubyCompletionProposal[fKeywords.size()]);
}
protected String getCurrentPrefix(String documentString, int documentOffset) {
int tokenLength = 0;
while ((documentOffset - tokenLength > 0)
&& !Character.isWhitespace(documentString.charAt(documentOffset
- tokenLength - 1)))
tokenLength++;
return documentString.substring((documentOffset - tokenLength), documentOffset);
}
private IRubyCompletionProposal createKeywordProposal(String keyword, String prefix, int documentOffset) {
String completion = keyword
.substring(prefix.length(), keyword.length());
return new RubyCompletionProposal(completion, documentOffset, completion.length(), RubyPluginImages.get(RubyPluginImages.IMG_OBJS_TEMPLATE), keyword, 0);
}
private List getKeywords() {
List list = new ArrayList();
String[] keywords = RubyTextTools.getKeyWords();
for (int i = 0; i < keywords.length; i++) {
list.add(keywords[i]);
}
return list;
}
public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
return Collections.EMPTY_LIST;
}
public String getErrorMessage() {
return null;
}
public void sessionEnded() {
}
public void sessionStarted() {
}
}