/* * JBoss by Red Hat * Copyright 2006-2009, Red Hat Middleware, LLC, and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.ide.eclipse.freemarker.editor; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateCompletionProcessor; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.swt.graphics.Image; import org.jboss.ide.eclipse.freemarker.Plugin; import org.jboss.ide.eclipse.freemarker.configuration.ConfigurationManager; import org.jboss.ide.eclipse.freemarker.configuration.ContextValue; import org.jboss.ide.eclipse.freemarker.model.CompletionDirective; import org.jboss.ide.eclipse.freemarker.model.CompletionInterpolation; import org.jboss.ide.eclipse.freemarker.model.CompletionMacroInstance; import org.jboss.ide.eclipse.freemarker.model.Item; import org.jboss.ide.eclipse.freemarker.model.ItemSet; import org.jboss.ide.eclipse.freemarker.model.MacroInstance; /** * @author <a href="mailto:joe@binamics.com">Joe Hudson</a> */ public class CompletionProcessor extends TemplateCompletionProcessor implements IContentAssistProcessor { private Editor editor; private static final ICompletionProposal[] NO_COMPLETIONS = new ICompletionProposal[0]; public CompletionProcessor (Editor editor) { this.editor = editor; } public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { try { ItemSet directiveSet = editor.getItemSet(); Map context = new HashMap(); ContextValue[] values = ConfigurationManager.getInstance(editor.getProject()).getContextValues(editor.getFile(), true); for (int i=0; i<values.length; i++) { context.put(values[i].name, values[i].objClass); } Item directive = directiveSet.getSelectedItem(offset); if (null != directive) { return directive.getCompletionProposals(offset, context); } else { // we might be starting something Item item = editor.getItemSet().getPreviousItem(offset); int topOffset = 0; if (null != item) topOffset = item.getRegion().getOffset() + item.getRegion().getLength(); // check for directives and macro calls try { for (int i=offset-1; i>=topOffset; i--) { char c = editor.getDocument().getChar(i); if (c == '>' || c == ']') break; if (c == '<' || c == '[') { if (editor.getDocument().getLength() > i) { char c2 = editor.getDocument().getChar(i+1); if (c2 == '#') { CompletionDirective completionDirective = new CompletionDirective( i, offset - i, editor.getItemSet(), (ISourceViewer) viewer, (IResource) editor.getFile()); completionDirective.setItemSet(editor.getItemSet()); return completionDirective.getCompletionProposals(offset, context); } else if (c2 == '@') { CompletionMacroInstance completionMacroInstance = new CompletionMacroInstance( editor.getDocument().get(i, offset - i), i, editor.getItemSet(), editor.getFile()); completionMacroInstance.setItemSet(editor.getItemSet()); return completionMacroInstance.getCompletionProposals(offset, context); } else if (c2 == '/') { if (editor.getDocument().getLength() < i+3 || editor.getDocument().getChar(i+2) == ' ' || editor.getDocument().getChar(i+2) == '\r' || editor.getDocument().getChar(i+2) == '\n') { Item stackItem = editor.getItemSet().getPreviousStartItem(offset); StringBuffer value = new StringBuffer(); if (null != stackItem && stackItem instanceof MacroInstance) value.append("@"); //$NON-NLS-1$ else value.append("#"); //$NON-NLS-1$ String name = null; if (null != stackItem) name = stackItem.getFirstToken(); if (null != name) value.append(name); if (c == '<') value.append('>'); else value.append(']'); ICompletionProposal completionProposal = new CompletionProposal( value.toString(), offset, 0, offset+value.toString().length()); return new ICompletionProposal[]{completionProposal}; } } else { return NO_COMPLETIONS; } } } } } catch (BadLocationException e) { return NO_COMPLETIONS; } // check for interpolations try { for (int i=offset-1; i>=topOffset; i--) { char c = editor.getDocument().getChar(i); if (c == '\n') break; else if (c == '$') { if (editor.getDocument().getLength() > i) { char c2 = editor.getDocument().getChar(i+1); if (c2 == '{') { int j = offset; while (editor.getDocument().getLength() > j) { char c3 = editor.getDocument().getChar(j); if (Character.isWhitespace(c3) || c3 == '(' || c3 == '.' || c3 == ')' || c3 == '}' || c3 == '?') { // j = j-1; break; } j++; } CompletionInterpolation interpolation = new CompletionInterpolation( editor.getDocument().get(i, j - i), i, editor.getItemSet(), editor.getFile()); interpolation.setParentItem(editor.getItemSet().getPreviousStartItem(offset)); return interpolation.getCompletionProposals(offset, context); } } } } } catch (BadLocationException e) { return NO_COMPLETIONS; } } } catch (Exception e) { Plugin.log(e); } return NO_COMPLETIONS; } protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) { return null; } protected Image getImage(Template template) { return null; } protected Template[] getTemplates(String contextTypeId) { return null; } public char[] getCompletionProposalAutoActivationCharacters() { return new char[]{'.', '$', '#', '@', '/', '?', '{'}; } }