package tk.eclipse.plugin.jspeditor.editors; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner; import org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal; import org.eclipse.jdt.ui.text.java.CompletionProposalCollector; import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ContextInformation; import org.eclipse.jface.text.contentassist.ContextInformationValidator; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import tk.eclipse.plugin.htmleditor.HTMLPlugin; import tk.eclipse.plugin.htmleditor.HTMLUtil; /** * Provides code completion for JSP directives. * * @author Naoki Takezoe */ public class JSPDirectiveAssistProcessor implements IContentAssistProcessor { private Image tagImage; private Image attrImage; private Image valueImage; private IFile file; private static final String DIRECTIVES[] = { "include", "page", "taglib" }; private static final Map<String, String[]> ATTRIBUTES = new HashMap<String, String[]>(); static { ATTRIBUTES.put("include", new String[]{"file"}); ATTRIBUTES.put("page", new String[]{"language","extends","import","session","buffer","autoFlush","isThreadSafe", "info","errorPage","isErrorPage","contentType","pageEncoding"}); ATTRIBUTES.put("taglib", new String[]{"prefix","tagdir","uri"}); } public JSPDirectiveAssistProcessor(){ tagImage = HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_TAG); attrImage = HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_ATTR); valueImage = HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_VALUE); } public void update(JSPSourceEditor editor){ IEditorInput input = editor.getEditorInput(); if(input instanceof IFileEditorInput){ this.file = ((IFileEditorInput)input).getFile(); } } public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { String text = viewer.getDocument().get().substring(0, offset); int flag = 0; StringBuffer sb = new StringBuffer(); String directive = ""; String attrName = ""; //String attrValue = ""; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); if(c=='<'){ directive = ""; flag = 1; } else if(flag==1 && c=='%'){ flag = 2; } else if(flag==2 && c=='@'){ flag = 3; } else if(flag==3 && c=='%'){ sb.setLength(0); flag = 0; } else if(flag==3 && (c==' ' || c=='\t' || c=='\r' || c=='\n' || c=='=')){ if(directive.equals("")){ directive = sb.toString().trim(); } else { attrName = sb.toString().trim(); if(!attrName.equals("")){ flag = 4; } } sb.setLength(0); } else if(flag==4 && c=='"'){ sb.append(c); flag = 5; } else if(flag==5 && c=='"'){ sb.setLength(0); flag = 3; } else if(flag==3 || flag==5){ sb.append(c); } } String lastWord = sb.toString().trim(); if(directive.equals("")){ return getDirectives(lastWord, offset); } else if(directive.equals("page") && attrName.equals("import") && lastWord.startsWith("\"")){ return getImportValues(lastWord, offset); } else if(lastWord.startsWith("\"")){ return getAttributeValues(directive,attrName,lastWord,offset); } else { return getAttributes(directive, lastWord, offset); } } /** * Returns import completion proposals. */ private ICompletionProposal[] getImportValues(String lastWord, int offset){ try { if(this.file != null){ IJavaProject project = JavaCore.create(file.getProject()); CompletionProposalCollector collector = new CompletionProposalCollector(project); ICompilationUnit unit = HTMLUtil.getTemporaryCompilationUnit(project); String matchString = lastWord.replaceFirst("^\"", ""); int lastIndex = matchString.lastIndexOf(','); if(lastIndex >= 0){ //offset = offset + lastIndex; matchString = matchString.substring(lastIndex + 1); } String value = "import " + matchString; System.out.println(value); // TODO Debug HTMLUtil.setContentsToCU(unit, value); unit.codeComplete(value.length(), collector, DefaultWorkingCopyOwner.PRIMARY); IJavaCompletionProposal[] proposals = collector.getJavaCompletionProposals(); List<ICompletionProposal> result = new ArrayList<ICompletionProposal>(); for(int i=0;i<proposals.length;i++){ if(proposals[i] instanceof AbstractJavaCompletionProposal){ AbstractJavaCompletionProposal proposal = (AbstractJavaCompletionProposal)proposals[i]; proposal.setReplacementOffset(offset - matchString.trim().length()); proposal.setReplacementLength(matchString.length()); proposal.setReplacementString(proposal.getReplacementString().replaceFirst(";$", "")); proposal.setCursorPosition(proposal.getReplacementString().length()); result.add(proposal); } } return result.toArray(new ICompletionProposal[result.size()]); } } catch(Exception ex){ HTMLPlugin.logException(ex); } return new ICompletionProposal[0]; } /** * Returns attribute value completion prosposals. */ private ICompletionProposal[] getAttributeValues(String directive,String attr,String lastWord,int offset){ List<String> values = new ArrayList<String>(); if(directive.equals("page")){ if(attr.equals("autoFlush") || attr.equals("session") || attr.equals("isThreadSafe") || attr.equals("isErrorPage")){ values.add("true"); values.add("false"); } } if(directive.equals("taglib")){ if(attr.equals("uri")){ Map<String, String> innerTLD = HTMLPlugin.getInnerTLD(); Iterator<String> ite = innerTLD.keySet().iterator(); while(ite.hasNext()){ values.add(ite.next()); } IPreferenceStore store = HTMLPlugin.getDefault().getPreferenceStore(); String[] uri = store.getString(HTMLPlugin.PREF_TLD_URI).split("\n"); for(int i=0;i<uri.length;i++){ values.add(uri[i]); } } } lastWord = lastWord.substring(1); List<ICompletionProposal> assistInfos = new ArrayList<ICompletionProposal>(); for(int i=0;i<values.size();i++){ String value = values.get(i); if(value.startsWith(lastWord)){ assistInfos.add(new CompletionProposal( value, offset-lastWord.length(), lastWord.length(), value.length(), valueImage, value, null,null)); } } return assistInfos.toArray(new ICompletionProposal[assistInfos.size()]); } /** * Returns JSP direcive completion proposals. */ private ICompletionProposal[] getDirectives(String lastWord,int offset){ List<ICompletionProposal> assistInfos = new ArrayList<ICompletionProposal>(); for(int i=0;i<DIRECTIVES.length;i++){ String directive = DIRECTIVES[i]; if(directive.startsWith(lastWord)){ assistInfos.add(new CompletionProposal( directive, offset-lastWord.length(), lastWord.length(), directive.length(), tagImage, directive, null,null)); } } return assistInfos.toArray(new ICompletionProposal[assistInfos.size()]); } /** * Returns directive attribute completion proposals. */ private ICompletionProposal[] getAttributes(String directive,String lastWord,int offset){ String attrs[] = ATTRIBUTES.get(directive); if(attrs==null){ return new ICompletionProposal[0]; } List<ICompletionProposal> assistInfos = new ArrayList<ICompletionProposal>(); for(int i=0;i<attrs.length;i++){ String attrName = attrs[i]; String replace = attrName + "=\"\""; if(attrName.startsWith(lastWord)){ assistInfos.add(new CompletionProposal( replace, offset-lastWord.length(), lastWord.length(), replace.length() - 1, attrImage, attrName, null,null)); } } return assistInfos.toArray(new ICompletionProposal[assistInfos.size()]); } public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { ContextInformation[] info = new ContextInformation[0]; return info; } public char[] getCompletionProposalAutoActivationCharacters() { return new char[0]; } public char[] getContextInformationAutoActivationCharacters() { return new char[0]; } public IContextInformationValidator getContextInformationValidator() { return new ContextInformationValidator(this); } public String getErrorMessage() { return "Error"; } }