/******************************************************************************* * Copyright (c) 2005, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.ext.java.jdt.codeassistant; import org.eclipse.che.ide.ext.java.jdt.Images; import org.eclipse.che.ide.ext.java.jdt.codeassistant.api.JavaCompletionProposal; import org.eclipse.che.ide.ext.java.jdt.codeassistant.ui.StyledString; import org.eclipse.che.ide.ext.java.jdt.core.CompletionProposal; import org.eclipse.che.ide.ext.java.jdt.core.IJavaElement; import org.eclipse.che.ide.ext.java.jdt.core.JavaCore; import org.eclipse.che.ide.ext.java.jdt.core.compiler.CharOperation; import org.eclipse.che.ide.ext.java.jdt.core.dom.CompilationUnit; import org.eclipse.che.ide.ext.java.jdt.text.DefaultPositionUpdater; import org.eclipse.che.ide.ext.java.jdt.text.Document; import org.eclipse.che.ide.ext.java.jdt.text.PositionUpdater; import org.eclipse.che.ide.runtime.Assert; import org.eclipse.che.ide.api.text.BadLocationException; import org.eclipse.che.ide.api.text.BadPositionCategoryException; import org.eclipse.che.ide.api.text.Position; import org.eclipse.che.ide.api.text.Region; import org.eclipse.che.ide.api.text.RegionImpl; /** @since 3.2 */ public abstract class AbstractJavaCompletionProposal implements JavaCompletionProposal { /** A class to simplify tracking a reference position in a document. */ static final class ReferenceTracker { /** The reference position category name. */ private static final String CATEGORY = "reference_position"; //$NON-NLS-1$ /** The position updater of the reference position. */ private final PositionUpdater fPositionUpdater = new DefaultPositionUpdater(CATEGORY); /** The reference position. */ private final Position fPosition = new Position(0); /** * Called before document changes occur. It must be followed by a call to postReplace(). * * @param document * the document on which to track the reference position. * @param offset * the offset * @throws BadLocationException * if the offset describes an invalid range in this document */ public void preReplace(Document document, int offset) throws BadLocationException { fPosition.setOffset(offset); try { document.addPositionCategory(CATEGORY); document.addPositionUpdater(fPositionUpdater); document.addPosition(CATEGORY, fPosition); } catch (BadPositionCategoryException e) { // should not happen // Log.error(getClass(), e); //TODO log error } } /** * Called after the document changed occurred. It must be preceded by a call to preReplace(). * * @param document * the document on which to track the reference position. * @return offset after the replace */ public int postReplace(Document document) { try { document.removePosition(CATEGORY, fPosition); document.removePositionUpdater(fPositionUpdater); document.removePositionCategory(CATEGORY); } catch (BadPositionCategoryException e) { // should not happen // Log.error(getClass(), e); //TODO log error } return fPosition.getOffset(); } } // protected static final class ExitPolicy implements IExitPolicy { // // final char fExitCharacter; // private final IDocument fDocument; // // public ExitPolicy(char exitCharacter, IDocument document) { // fExitCharacter= exitCharacter; // fDocument= document; // } // // /* // * @see // org.eclipse.jdt.internal.ui.text.link.LinkedPositionUI.ExitPolicy#doExit(org.eclipse.jdt.internal.ui.text.link.LinkedPositionManager, // org.eclipse.swt.events.VerifyEvent, int, int) // */ // public ExitFlags doExit(LinkedModeModel environment, VerifyEvent event, int offset, int length) { // // if (event.character == fExitCharacter) { // if (environment.anyPositionContains(offset)) // return new ExitFlags(ILinkedModeListener.UPDATE_CARET, false); // else // return new ExitFlags(ILinkedModeListener.UPDATE_CARET, true); // } // // switch (event.character) { // case ';': // return new ExitFlags(ILinkedModeListener.NONE, true); // case SWT.CR: // // when entering an anonymous class as a parameter, we don't want // // to jump after the parenthesis when return is pressed // if (offset > 0) { // try { // if (fDocument.getChar(offset - 1) == '{') // return new ExitFlags(ILinkedModeListener.EXIT_ALL, true); // } catch (BadLocationException e) { // } // } // return null; // default: // return null; // } // } // // } private StyledString fDisplayString; private String fReplacementString; private int fReplacementOffset; private int fReplacementLength; private int fCursorPosition; private Images fImage; // private ContextInformation fContextInformation; private ProposalInfo fProposalInfo; private char[] fTriggerCharacters; private String fSortString; private int fRelevance; private boolean fIsInJavadoc; private CompilationUnit compilationUnit; private boolean fToggleEating; /** The invocation context of this completion proposal. Can be <code>null</code>. */ protected final JavaContentAssistInvocationContext fInvocationContext; /** Cache to store last validation state. */ private boolean fIsValidated = true; protected AbstractJavaCompletionProposal() { fInvocationContext = null; } protected AbstractJavaCompletionProposal(JavaContentAssistInvocationContext context) { fInvocationContext = context; compilationUnit = context.getCompilationUnit(); // TODO set configurable fToggleEating = true; } /* * @see ICompletionProposalExtension#getTriggerCharacters() */ public char[] getTriggerCharacters() { return fTriggerCharacters; } /** * Sets the trigger characters. * * @param triggerCharacters * The set of characters which can trigger the application of this completion proposal */ public void setTriggerCharacters(char[] triggerCharacters) { fTriggerCharacters = triggerCharacters; } /** * Sets the proposal info. * * @param proposalInfo * The additional information associated with this proposal or <code>null</code> */ public void setProposalInfo(ProposalInfo proposalInfo) { fProposalInfo = proposalInfo; } /** * Returns the additional proposal info, or <code>null</code> if none exists. * * @return the additional proposal info, or <code>null</code> if none exists */ protected ProposalInfo getProposalInfo() { return fProposalInfo; } /** * Sets the cursor position relative to the insertion offset. By default this is the length of the completion string (Cursor * positioned after the completion) * * @param cursorPosition * The cursorPosition to set */ public void setCursorPosition(int cursorPosition) { Assert.isTrue(cursorPosition >= 0); fCursorPosition = cursorPosition; } public int getCursorPosition() { return fCursorPosition; } /** {@inheritDoc} */ public final void apply(Document document) { // not used any longer apply(document, (char)0, getReplacementOffset() + getReplacementLength()); } /** {@inheritDoc} */ public void apply(Document document, char trigger, int offset) { int newLength = fInvocationContext.getInvocationOffset() - getReplacementOffset(); if ((insertCompletion() ^ fToggleEating) && newLength >= 0) setReplacementLength(newLength); if (isSupportingRequiredProposals()) { CompletionProposal coreProposal = ((MemberProposalInfo)getProposalInfo()).fProposal; CompletionProposal[] requiredProposals = coreProposal.getRequiredProposals(); for (int i = 0; requiredProposals != null && i < requiredProposals.length; i++) { int oldLen = document.getLength(); if (requiredProposals[i].getKind() == CompletionProposal.TYPE_REF) { LazyJavaCompletionProposal proposal = createRequiredTypeCompletionProposal(requiredProposals[i], fInvocationContext); proposal.apply(document); setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen); } else if (requiredProposals[i].getKind() == CompletionProposal.TYPE_IMPORT) { ImportCompletionProposal proposal = new ImportCompletionProposal(document, compilationUnit, requiredProposals[i], fInvocationContext, coreProposal.getKind()); proposal.setReplacementOffset(getReplacementOffset()); proposal.apply(document); setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen); } else if (requiredProposals[i].getKind() == CompletionProposal.METHOD_IMPORT) { ImportCompletionProposal proposal = new ImportCompletionProposal(document, compilationUnit, requiredProposals[i], fInvocationContext, coreProposal.getKind()); proposal.setReplacementOffset(getReplacementOffset()); proposal.apply(document); setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen); } else if (requiredProposals[i].getKind() == CompletionProposal.FIELD_IMPORT) { ImportCompletionProposal proposal = new ImportCompletionProposal(document, compilationUnit, requiredProposals[i], fInvocationContext, coreProposal.getKind()); proposal.setReplacementOffset(getReplacementOffset()); proposal.apply(document); setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen); } else { /* * In 3.3 we only support the above required proposals, see CompletionProposal#getRequiredProposals() */ Assert.isTrue(false); } } } try { boolean isSmartTrigger = isSmartTrigger(trigger); String replacement; if (isSmartTrigger || trigger == (char)0) { replacement = getReplacementString(); } else { StringBuffer buffer = new StringBuffer(getReplacementString()); // fix for PR #5533. Assumes that no eating takes place. if ((getCursorPosition() > 0 && getCursorPosition() <= buffer.length() && buffer .charAt(getCursorPosition() - 1) != trigger)) { buffer.insert(getCursorPosition(), trigger); setCursorPosition(getCursorPosition() + 1); } replacement = buffer.toString(); setReplacementString(replacement); } // reference position just at the end of the document change. int referenceOffset = getReplacementOffset() + getReplacementLength(); final ReferenceTracker referenceTracker = new ReferenceTracker(); referenceTracker.preReplace(document, referenceOffset); replace(document, getReplacementOffset(), getReplacementLength(), replacement); referenceOffset = referenceTracker.postReplace(document); setReplacementOffset(referenceOffset - (replacement == null ? 0 : replacement.length())); // // PR 47097 // if (isSmartTrigger) // handleSmartTrigger(document, trigger, referenceOffset); } catch (BadLocationException x) { // ignore } } /** * Creates the required type proposal. * * @param completionProposal * the core completion proposal * @param invocationContext * invocation context * @return the required type completion proposal * @since 3.5 */ protected LazyJavaCompletionProposal createRequiredTypeCompletionProposal(CompletionProposal completionProposal, JavaContentAssistInvocationContext invocationContext) { // if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES)) return (LazyJavaCompletionProposal)new FillArgumentNamesCompletionProposalCollector(invocationContext) .createJavaCompletionProposal(completionProposal); // else // return new LazyJavaTypeCompletionProposal(completionProposal, invocationContext); } private boolean isSmartTrigger(char trigger) { // return trigger == ';' && // JavaPlugin.getDefault().getCombinedPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SMART_SEMICOLON) // || trigger == '{' && // JavaPlugin.getDefault().getCombinedPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SMART_OPENING_BRACE); // TODO return false; } // private void handleSmartTrigger(IDocument document, char trigger, int referenceOffset) throws BadLocationException { // DocumentCommand cmd= new DocumentCommand() { // }; // // cmd.offset= referenceOffset; // cmd.length= 0; // cmd.text= Character.toString(trigger); // cmd.doit= true; // cmd.shiftsCaret= true; // cmd.caretOffset= getReplacementOffset() + getCursorPosition(); // // SmartSemicolonAutoEditStrategy strategy= new SmartSemicolonAutoEditStrategy(IJavaPartitions.JAVA_PARTITIONING); // strategy.customizeDocumentCommand(document, cmd); // // replace(document, cmd.offset, cmd.length, cmd.text); // setCursorPosition(cmd.caretOffset - getReplacementOffset() + cmd.text.length()); // } protected final void replace(Document document, int offset, int length, String string) throws BadLocationException { if (!document.get(offset, length).equals(string)) document.replace(offset, length, string); } // /* // * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension1#apply(org.eclipse.jface.text.ITextViewer, char, // int, int) // */ // public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) { // // IDocument document= viewer.getDocument(); // if (fTextViewer == null) // fTextViewer= viewer; // // // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96059 // // don't apply the proposal if for some reason we're not valid any longer // if (!isInJavadoc() && !validate(document, offset, null)) { // setCursorPosition(offset); // if (trigger != '\0') { // try { // document.replace(offset, 0, String.valueOf(trigger)); // setCursorPosition(getCursorPosition() + 1); // if (trigger == '(' && autocloseBrackets()) { // document.replace(getReplacementOffset() + getCursorPosition(), 0, ")"); //$NON-NLS-1$ // setUpLinkedMode(document, ')'); // } // } catch (BadLocationException x) { // // ignore // } // } // return; // } // // // don't eat if not in preferences, XOR with Ctrl // // but: if there is a selection, replace it! // Point selection= viewer.getSelectedRange(); // fToggleEating= (stateMask & SWT.CTRL) != 0; // int newLength= selection.x + selection.y - getReplacementOffset(); // if ((insertCompletion() ^ fToggleEating) && newLength >= 0) // setReplacementLength(newLength); // // apply(document, trigger, offset); // fToggleEating= false; // } /** * Tells whether the user toggled the insert mode by pressing the 'Ctrl' key. * * @return <code>true</code> if the insert mode is toggled, <code>false</code> otherwise * @since 3.5 */ protected boolean isInsertModeToggled() { return fToggleEating; } /** * Returns <code>true</code> if the proposal is within javadoc, <code>false</code> otherwise. * * @return <code>true</code> if the proposal is within javadoc, <code>false</code> otherwise */ protected boolean isInJavadoc() { return fIsInJavadoc; } /** * Sets the javadoc attribute. * * @param isInJavadoc * <code>true</code> if the proposal is within javadoc */ protected void setInJavadoc(boolean isInJavadoc) { fIsInJavadoc = isInJavadoc; } /* * @see ICompletionProposal#getSelection */ public Region getSelection(Document document) { if (!fIsValidated) return null; return new RegionImpl(getReplacementOffset() + getCursorPosition(), 0); } // /* // * @see ICompletionProposal#getContextInformation() // */ // public ContextInformation getContextInformation() // { // return fContextInformation; // } // /** // * Sets the context information. // * // * @param contextInformation The context information associated with this proposal // */ // public void setContextInformation(ContextInformation contextInformation) // { // fContextInformation = contextInformation; // } /* * @see ICompletionProposal#getDisplayString() */ public String getDisplayString() { if (fDisplayString != null) return fDisplayString.getString(); return ""; //$NON-NLS-1$ } // /* // * @see ICompletionProposal#getAdditionalProposalInfo() // */ // public Widget getAdditionalProposalInfo() { // if (getProposalInfo() != null) { // return getProposalInfo().getInfo(); // } // return null; // } /* * @see ICompletionProposalExtension#getContextInformationPosition() */ public int getContextInformationPosition() { // if (getContextInformation() == null) // return getReplacementOffset() - 1; return getReplacementOffset() + getCursorPosition(); } /** * Gets the replacement offset. * * @return Returns a int */ public int getReplacementOffset() { return fReplacementOffset; } /** * Sets the replacement offset. * * @param replacementOffset * The replacement offset to set */ public void setReplacementOffset(int replacementOffset) { Assert.isTrue(replacementOffset >= 0); fReplacementOffset = replacementOffset; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getCompletionOffset() */ public int getPrefixCompletionStart(Document document, int completionOffset) { return getReplacementOffset(); } /** * Gets the replacement length. * * @return Returns a int */ public int getReplacementLength() { return fReplacementLength; } /** * Sets the replacement length. * * @param replacementLength * The replacementLength to set */ public void setReplacementLength(int replacementLength) { Assert.isTrue(replacementLength >= 0); fReplacementLength = replacementLength; } /** * Gets the replacement string. * * @return Returns a String */ public String getReplacementString() { return fReplacementString; } /** * Sets the replacement string. * * @param replacementString * The replacement string to set */ public void setReplacementString(String replacementString) { Assert.isNotNull(replacementString); fReplacementString = replacementString; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getReplacementText() */ public CharSequence getPrefixCompletionText(Document document, int completionOffset) { if (!isCamelCaseMatching()) return getReplacementString(); String prefix = getPrefix(document, completionOffset); return getCamelCaseCompound(prefix, getReplacementString()); } /* * @see ICompletionProposal#getImage() */ public Images getImage() { return fImage; } /** * Sets the image. * * @param image * The image to set */ public void setImage(Images image) { fImage = image; } /* * @see ICompletionProposalExtension#isValidFor(IDocument, int) */ public boolean isValidFor(Document document, int offset) { // return validate(document, offset, null); // TODO return true; } // /* // * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, // org.eclipse.jface.text.DocumentEvent) // */ // public boolean validate(IDocument document, int offset, DocumentEvent event) { // // if (!isOffsetValid(offset)) // return fIsValidated= false; // // fIsValidated= isValidPrefix(getPrefix(document, offset)); // // if (fIsValidated && event != null) { // // adapt replacement range to document change // int delta= (event.fText == null ? 0 : event.fText.length()) - event.fLength; // final int newLength= Math.max(getReplacementLength() + delta, 0); // setReplacementLength(newLength); // } // // return fIsValidated; // } /** * Checks whether the given offset is valid for this proposal. * * @param offset * the caret offset * @return <code>true</code> if the offset is valid for this proposal * @since 3.5 */ protected boolean isOffsetValid(int offset) { return getReplacementOffset() <= offset; } // /** // * Checks whether <code>prefix</code> is a valid prefix for this proposal. Usually, while code // * completion is in progress, the user types and edits the prefix in the document in order to // * filter the proposal list. From {@link #validate(IDocument, int, DocumentEvent) }, the // * current prefix in the document is extracted and this method is called to find out whether the // * proposal is still valid. // * <p> // * The default implementation checks if <code>prefix</code> is a prefix of the proposal's // * {@link #getDisplayString() display string} using the {@link #isPrefix(String, String) } // * method. // * </p> // * // * @param prefix the current prefix in the document // * @return <code>true</code> if <code>prefix</code> is a valid prefix of this proposal // */ // protected boolean isValidPrefix(String prefix) { // /* // * See http://dev.eclipse.org/bugs/show_bug.cgi?id=17667 // * why we do not use the replacement string. // * String word= fReplacementString; // * // * Besides that bug we also use the display string // * for performance reasons, as computing the // * replacement string can be expensive. // */ // return isPrefix(prefix, TextProcessor.deprocess(getDisplayString())); // } /** * Gets the proposal's relevance. * * @return Returns a int */ public int getRelevance() { return fRelevance; } /** * Sets the proposal's relevance. * * @param relevance * The relevance to set */ public void setRelevance(int relevance) { fRelevance = relevance; } /** * Returns the text in <code>document</code> from {@link #getReplacementOffset()} to <code>offset</code>. Returns the empty * string if <code>offset</code> is before the replacement offset or if an exception occurs when accessing the document. * * @param document * the document * @param offset * the offset * @return the prefix */ protected String getPrefix(Document document, int offset) { try { int length = offset - getReplacementOffset(); if (length > 0) return document.get(getReplacementOffset(), length); } catch (BadLocationException x) { } return ""; //$NON-NLS-1$ } /** * Case insensitive comparison of <code>prefix</code> with the start of <code>string</code>. * * @param prefix * the prefix * @param string * the string to look for the prefix * @return <code>true</code> if the string begins with the given prefix and <code>false</code> if <code>prefix</code> is longer * than <code>string</code> or the string doesn't start with the given prefix * @since 3.2 */ protected boolean isPrefix(String prefix, String string) { if (prefix == null || string == null || prefix.length() > string.length()) return false; String start = string.substring(0, prefix.length()); return start.equalsIgnoreCase(prefix) || isCamelCaseMatching() && CharOperation.camelCaseMatch(prefix.toCharArray(), string.toCharArray()); } /** * Matches <code>prefix</code> against <code>string</code> and replaces the matched region by prefix. Case is preserved as much * as possible. This method returns <code>string</code> if camel case completion is disabled. Examples when camel case * completion is enabled: * <ul> * <li>getCamelCompound("NuPo", "NullPointerException") -> "NuPointerException"</li> * <li>getCamelCompound("NuPoE", "NullPointerException") -> "NuPoException"</li> * <li>getCamelCompound("hasCod", "hashCode") -> "hasCode"</li> * </ul> * * @param prefix * the prefix to match against * @param string * the string to match * @return a compound of prefix and any postfix taken from <code>string</code> * @since 3.2 */ protected final String getCamelCaseCompound(String prefix, String string) { if (prefix.length() > string.length()) return string; // a normal prefix - no camel case logic at all String start = string.substring(0, prefix.length()); if (start.equalsIgnoreCase(prefix)) return string; final char[] patternChars = prefix.toCharArray(); final char[] stringChars = string.toCharArray(); for (int i = 1; i <= stringChars.length; i++) if (CharOperation.camelCaseMatch(patternChars, 0, patternChars.length, stringChars, 0, i)) return prefix + string.substring(i); // Not a camel case match at all. // This should not happen -> stay with the default behavior return string; } /** * Returns true if camel case matching is enabled. * * @return <code>true</code> if camel case matching is enabled * @since 3.2 */ protected boolean isCamelCaseMatching() { String value = JavaCore.getOption(JavaCore.CODEASSIST_CAMEL_CASE_MATCH); return JavaCore.ENABLED.equals(value); } protected static boolean insertCompletion() { // IPreferenceStore preference= JavaPlugin.getDefault().getPreferenceStore(); // return preference.getBoolean(PreferenceConstants.CODEASSIST_INSERT_COMPLETION); return true; } // private static Color getForegroundColor() { // IPreferenceStore preference= JavaPlugin.getDefault().getPreferenceStore(); // RGB rgb= PreferenceConverter.getColor(preference, PreferenceConstants.CODEASSIST_REPLACEMENT_FOREGROUND); // JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools(); // return textTools.getColorManager().getColor(rgb); // } // // private static Color getBackgroundColor() { // IPreferenceStore preference= JavaPlugin.getDefault().getPreferenceStore(); // RGB rgb= PreferenceConverter.getColor(preference, PreferenceConstants.CODEASSIST_REPLACEMENT_BACKGROUND); // JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools(); // return textTools.getColorManager().getColor(rgb); // } // private void repairPresentation(ITextViewer viewer) { // if (fRememberedStyleRange != null) { // if (viewer instanceof ITextViewerExtension2) { // // attempts to reduce the redraw area // ITextViewerExtension2 viewer2= (ITextViewerExtension2)viewer; // viewer2.invalidateTextPresentation(fRememberedStyleRange.start, fRememberedStyleRange.length); // } else // viewer.invalidateTextPresentation(); // } // } // private void updateStyle(ITextViewer viewer) { // StyledText text= viewer.getTextWidget(); // int widgetOffset= getWidgetOffset(viewer, fRememberedStyleRange.start); // StyleRange range= new StyleRange(fRememberedStyleRange); // range.start= widgetOffset; // range.length= fRememberedStyleRange.length; // StyleRange currentRange= text.getStyleRangeAtOffset(widgetOffset); // if (currentRange != null) { // range.strikeout= currentRange.strikeout; // range.underline= currentRange.underline; // range.fontStyle= currentRange.fontStyle; // } // // // http://dev.eclipse.org/bugs/show_bug.cgi?id=34754 // try { // text.setStyleRange(range); // } catch (IllegalArgumentException x) { // // catching exception as offset + length might be outside of the text widget // fRememberedStyleRange= null; // } // } // /** // * Convert a document offset to the corresponding widget offset. // * // * @param viewer the text viewer // * @param documentOffset the document offset // * @return widget offset // * @since 3.6 // */ // private int getWidgetOffset(ITextViewer viewer, int documentOffset) { // if (viewer instanceof ITextViewerExtension5) { // ITextViewerExtension5 extension= (ITextViewerExtension5)viewer; // return extension.modelOffset2WidgetOffset(documentOffset); // } // IRegion visible= viewer.getVisibleRegion(); // int widgetOffset= documentOffset - visible.getOffset(); // if (widgetOffset > visible.getLength()) { // return -1; // } // return widgetOffset; // } // /** // * Creates a style range for the text viewer. // * // * @param viewer the text viewer // * @return the new style range for the text viewer or <code>null</code> // * @since 3.6 // */ // private StyleRange createStyleRange(ITextViewer viewer) { // StyledText text= viewer.getTextWidget(); // if (text == null || text.isDisposed()) // return null; // // int widgetCaret= text.getCaretOffset(); // // int modelCaret= 0; // if (viewer instanceof ITextViewerExtension5) { // ITextViewerExtension5 extension= (ITextViewerExtension5) viewer; // modelCaret= extension.widgetOffset2ModelOffset(widgetCaret); // } else { // IRegion visibleRegion= viewer.getVisibleRegion(); // modelCaret= widgetCaret + visibleRegion.getOffset(); // } // // if (modelCaret >= getReplacementOffset() + getReplacementLength()) // return null; // // int length= getReplacementOffset() + getReplacementLength() - modelCaret; // // Color foreground= getForegroundColor(); // Color background= getBackgroundColor(); // // return new StyleRange(modelCaret, length, foreground, background); // } // /* // * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(ITextViewer, boolean) // */ // public void selected(final ITextViewer viewer, boolean smartToggle) { // repairPresentation(viewer); // fRememberedStyleRange= null; // // if (!insertCompletion() ^ smartToggle) { // StyleRange range= createStyleRange(viewer); // if (range == null) // return; // // fRememberedStyleRange= range; // // if (viewer instanceof ITextViewerExtension4) { // if (fTextPresentationListener == null) { // fTextPresentationListener= new ITextPresentationListener() { // /* (non-Javadoc) // * @see org.eclipse.jface.text.ITextPresentationListener#applyTextPresentation(org.eclipse.jface.text.TextPresentation) // */ // public void applyTextPresentation(TextPresentation textPresentation) { // fRememberedStyleRange= createStyleRange(viewer); // if (fRememberedStyleRange != null) // textPresentation.mergeStyleRange(fRememberedStyleRange); // } // }; // ((ITextViewerExtension4)viewer).addTextPresentationListener(fTextPresentationListener); // } // repairPresentation(viewer); // } else // updateStyle(viewer); // } // } // /* // * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(ITextViewer) // */ // public void unselected(ITextViewer viewer) { // if (fTextPresentationListener != null) { // ((ITextViewerExtension4)viewer).removeTextPresentationListener(fTextPresentationListener); // fTextPresentationListener= null; // } // repairPresentation(viewer); // fRememberedStyleRange= null; // } // /* // * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getInformationControlCreator() // */ // public IInformationControlCreator getInformationControlCreator() { // Shell shell= JavaPlugin.getActiveWorkbenchShell(); // if (shell == null || !BrowserInformationControl.isAvailable(shell)) // return null; // // if (fCreator == null) { // /* // * FIXME: Take control creators (and link handling) out of JavadocHover, // * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=232024 // */ // JavadocHover.PresenterControlCreator presenterControlCreator= new JavadocHover.PresenterControlCreator(getSite()); // fCreator= new JavadocHover.HoverControlCreator(presenterControlCreator, true); // } // return fCreator; // } // // private IWorkbenchSite getSite() { // IWorkbenchPage page= JavaPlugin.getActivePage(); // if (page != null) { // IWorkbenchPart part= page.getActivePart(); // if (part != null) // return part.getSite(); // } // return null; // } public String getSortString() { return fSortString; } protected void setSortString(String string) { fSortString = string; } // protected ITextViewer getTextViewer() { // return fTextViewer; // } protected boolean isToggleEating() { return fToggleEating; } /** * Sets up a simple linked mode at {@link #getCursorPosition()} and an exit policy that will exit the mode when * <code>closingCharacter</code> is typed and an exit position at <code>getCursorPosition() + 1</code>. * * @param document * the document * @param closingCharacter * the exit character */ protected void setUpLinkedMode(Document document, char closingCharacter) { // TODO // if (getTextViewer() != null && autocloseBrackets()) { // int offset= getReplacementOffset() + getCursorPosition(); // int exit= getReplacementOffset() + getReplacementString().length(); // try { // LinkedPositionGroup group= new LinkedPositionGroup(); // group.addPosition(new LinkedPosition(document, offset, 0, LinkedPositionGroup.NO_STOP)); // // LinkedModeModel model= new LinkedModeModel(); // model.addGroup(group); // model.forceInstall(); // // LinkedModeUI ui= new EditorLinkedModeUI(model, getTextViewer()); // ui.setSimpleMode(true); // ui.setExitPolicy(new ExitPolicy(closingCharacter, document)); // ui.setExitPosition(getTextViewer(), exit, 0, Integer.MAX_VALUE); // ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER); // ui.enter(); // } catch (BadLocationException x) { // JavaPlugin.log(x); // } // } } protected boolean autocloseBrackets() { // IPreferenceStore preferenceStore= JavaPlugin.getDefault().getPreferenceStore(); // return preferenceStore.getBoolean(PreferenceConstants.EDITOR_CLOSE_BRACKETS); return true; } protected void setDisplayString(String string) { fDisplayString = new StyledString(string); } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension6#getStyledDisplayString() * @since 3.4 */ public StyledString getStyledDisplayString() { return fDisplayString; } public void setStyledDisplayString(StyledString text) { fDisplayString = text; } /* * @see java.lang.Object#toString() */ @Override public String toString() { return getDisplayString(); } /** * Returns the java element proposed by the receiver, possibly <code>null</code>. * * @return the java element proposed by the receiver, possibly <code>null</code> */ public IJavaElement getJavaElement() { if (getProposalInfo() != null) return getProposalInfo().getJavaElement(); return null; } /** * Tells whether required proposals are supported by this proposal. * * @return <code>true</code> if required proposals are supported by this proposal * @see CompletionProposal#getRequiredProposals() * @since 3.3 */ protected boolean isSupportingRequiredProposals() { if (fInvocationContext == null) return false; ProposalInfo proposalInfo = getProposalInfo(); if (!(proposalInfo instanceof MemberProposalInfo || proposalInfo instanceof AnonymousTypeProposalInfo)) return false; CompletionProposal proposal = ((MemberProposalInfo)proposalInfo).fProposal; return proposal != null && (proposal.getKind() == CompletionProposal.METHOD_REF // || proposal.getKind() == CompletionProposal.FIELD_REF // || proposal.getKind() == CompletionProposal.TYPE_REF // || proposal.getKind() == CompletionProposal.CONSTRUCTOR_INVOCATION // || proposal.getKind() == CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION); } }