package com.sap.mi.tcs.editor; /** * */ import java.util.ArrayList; import java.util.HashMap; import java.util.Map.Entry; 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.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; /** * @author C5106462 * */ public class TcsCompletionProcessor implements IContentAssistProcessor { private HashMap<String,String> defaultCharacterisations = new HashMap<String, String>(); private HashMap<String,String> parameterNames = new HashMap<String, String>(); private String templatePrefixes = "+-*/%(?:"; private TcsTemplatesCompletionProcessor templateProcessor; /** * */ public TcsCompletionProcessor() { templateProcessor = new TcsTemplatesCompletionProcessor(); defaultCharacterisations.put("BYTESIZE", "Characterise the memory footprint in bytes"); defaultCharacterisations.put("NUMBER_OF_ELEMENTS", "Characterise the number of elements of a collection datatype"); defaultCharacterisations.put("STRUCTURE", "Characterise the structure of a datastructure"); defaultCharacterisations.put("VALUE", "Characterise the actual value of a variable"); defaultCharacterisations.put("TYPE", "Characterise the type of a variable"); // for (int i=0; i<context.length; i++){ // String[] parameterPrefixes = getPrefixesFor(context[i]); // for (String parameterPrefix : parameterPrefixes) { // if (parameterPrefix.startsWith("RETURN")) // parameterNames.put(parameterPrefix, "Call Result " + context[i].getParameterName()); // else // parameterNames.put(parameterPrefix, "Signature Parameter " + context[i].getParameterName()); // } // } } // private String[] getPrefixesFor(Object parameter) { // ArrayList<String> prefixes = new ArrayList<String>(); // prefixes.add(parameter.getParameterName()); // appendDatatypePrefixes(prefixes,parameter.getParameterName(),parameter.getDatatype__Parameter()); // return prefixes.toArray(new String[]{}); // } // // private void appendDatatypePrefixes(ArrayList<String> prefixes, // String parameterName, DataType datatype__Parameter) { // if (datatype__Parameter instanceof CollectionDataType) { // prefixes.add(parameterName+".INNER"); // appendDatatypePrefixes(prefixes,parameterName+".INNER", ((CollectionDataType)datatype__Parameter).getInnerType_CollectionDataType()); // } else if (datatype__Parameter instanceof CompositeDataType) { // CompositeDataType cdt = (CompositeDataType) datatype__Parameter; // for (InnerDeclaration inner : cdt.getInnerDeclaration_CompositeDataType()) { // prefixes.add(parameterName+"."+inner.getEntityName()); // appendDatatypePrefixes(prefixes, parameterName+"."+inner.getEntityName(), inner.getDatatype_InnerDeclaration()); // } // } // } /* (non-Javadoc) * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int) */ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { ArrayList<ICompletionProposal> resultList=new ArrayList<ICompletionProposal>(); String currentText = viewer.getDocument().get(); // compute variable characterisation completions (i.e., VALUE, TYPE, etc.) int lastDotIndex = currentText.substring(0,offset).lastIndexOf("."); if (isCharactersationCompletionApplicable(lastDotIndex,currentText)){ String typedFragment = currentText.substring(lastDotIndex+1, offset); addCompletionProposalsString(resultList, lastDotIndex, typedFragment, defaultCharacterisations); } // compute parameter from context completions (i.e., current input parameters) int lastIndex = getLastIndexOfTemplatePrefix(offset, currentText); if (isStartOfAtom(lastIndex, currentText)){ String typedFragment = currentText.substring(lastIndex+1, offset).trim(); addCompletionProposalsString(resultList, lastIndex, typedFragment, parameterNames); } // compute template completions (i.e., IntPMF, DoublePDF, etc.) if (isStartOfAtom(lastIndex, currentText)) { String typedFragment = currentText.substring(lastIndex+1, offset).trim(); for (ICompletionProposal p : templateProcessor.computeCompletionProposals(viewer, offset)){ if (p.getDisplayString().toUpperCase().startsWith(typedFragment.toUpperCase())){ resultList.add(p); } } } return resultList.toArray(new ICompletionProposal[]{}); } /** * Checks, whether the user is characterising a variable (i.e., typed a dot) * * @param offset * @param currentText * @return */ private boolean isCharactersationCompletionApplicable(int offset, String currentText){ return ( // there is a dot (offset>=-1) and it's not the first char (offset>=0) offset-1 >= 0 // ??? && offset-1 < currentText.length() // the first char before the dot was a letter && Character.isLetter(currentText.charAt(offset-1)) ); } /** * Checks, whether user started to type a atom. * * @param offset * @param currentText * @return */ private boolean isStartOfAtom(int offset, String currentText) { if (offset+1 < currentText.length() // cursor is not at last character && offset+1 >= 0){ // cursor is not at first character currentText = currentText.substring(offset+1); // cut of everything before cursor } String trimText = currentText.trim(); if (trimText.equals("")) // only whitespace after offset return true; char lastChar = trimText.charAt(trimText.length()-1); if (templatePrefixes.indexOf(lastChar) >= 0) // last character before current offset is one of the template prefixes return true; boolean hasOnlyChars = true; for (int i=0; i<trimText.length(); i++){ if (!Character.isLetter(trimText.charAt(i)) && trimText.charAt(i) != '.') hasOnlyChars = false; } if (hasOnlyChars) return true; return false; } private int getLastIndexOfTemplatePrefix(int offset, String currentText) { int lastIndex = -1; String templatePrefixesAndWS = templatePrefixes + " "; for (int i=0; i<templatePrefixesAndWS.length(); i++) { int newLastIndex = currentText.substring(0, offset).lastIndexOf( templatePrefixesAndWS.charAt(i)); if (newLastIndex > lastIndex) lastIndex = newLastIndex; } return lastIndex; } private void addCompletionProposalsString( ArrayList<ICompletionProposal> resultList, int lastIndex, String typedFragment, HashMap<String,String> completions) { for (Entry<String,String> entry : completions.entrySet()){ String completion = entry.getKey(); String description = entry.getValue(); if (completion.toUpperCase().startsWith(typedFragment.toUpperCase())){ IContextInformation info = new ContextInformation( completion, description); //$NON-NLS-1$ resultList.add(new CompletionProposal( completion, lastIndex+1, typedFragment.length(), completion.length(), null, completion + " - "+ description, info, description)); //$NON-NLS-1$ } } } /* (non-Javadoc) * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() */ public char[] getCompletionProposalAutoActivationCharacters() { ArrayList<Character> result = new ArrayList<Character>(); for (String parameterName : parameterNames.keySet()) result.add(parameterName.charAt(0)); for (int i=0; i < templatePrefixes.length(); i++) result.add(templatePrefixes.charAt(i)); result.add('.'); char[] realResult = new char[result.size()]; for (int i=0; i < result.size(); i++) realResult[i] = result.get(i); return realResult; } /* (non-Javadoc) * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int) */ public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { return null; } /* (non-Javadoc) * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters() */ public char[] getContextInformationAutoActivationCharacters() { return null; } /* (non-Javadoc) * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator() */ public IContextInformationValidator getContextInformationValidator() { return null; } /* (non-Javadoc) * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage() */ public String getErrorMessage() { return "No proposals available"; } }