| /******************************************************************************* |
| * Copyright (c) 2000, 2018 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.jdt.ui.text.java; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.swt.graphics.Image; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.viewers.StyledString; |
| |
| import org.eclipse.jface.text.contentassist.IContextInformation; |
| |
| import org.eclipse.jdt.core.CompletionContext; |
| import org.eclipse.jdt.core.CompletionProposal; |
| import org.eclipse.jdt.core.CompletionRequestor; |
| import org.eclipse.jdt.core.IClasspathEntry; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jdt.core.compiler.IProblem; |
| import org.eclipse.jdt.core.formatter.CodeFormatter; |
| |
| import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil; |
| import org.eclipse.jdt.internal.corext.util.CollectionsUtil; |
| import org.eclipse.jdt.internal.corext.util.TypeFilter; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.preferences.formatter.FormatterProfileManager; |
| import org.eclipse.jdt.internal.ui.text.java.AnnotationAtttributeProposalInfo; |
| import org.eclipse.jdt.internal.ui.text.java.AnonymousTypeCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.AnonymousTypeProposalInfo; |
| import org.eclipse.jdt.internal.ui.text.java.FieldProposalInfo; |
| import org.eclipse.jdt.internal.ui.text.java.GetterSetterCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.JavaFieldWithCastedReceiverCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.JavaMethodCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.LazyJavaTypeCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.LazyModuleCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.LazyPackageCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.MethodDeclarationCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.MethodProposalInfo; |
| import org.eclipse.jdt.internal.ui.text.java.OverrideCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.java.ProposalContextInformation; |
| import org.eclipse.jdt.internal.ui.text.java.RelevanceComputer; |
| import org.eclipse.jdt.internal.ui.text.javadoc.JavadocInlineTagCompletionProposal; |
| import org.eclipse.jdt.internal.ui.text.javadoc.JavadocLinkTypeCompletionProposal; |
| import org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry; |
| |
| /** |
| * Java UI implementation of <code>CompletionRequestor</code>. Produces |
| * {@link IJavaCompletionProposal}s from the proposal descriptors received via |
| * the <code>CompletionRequestor</code> interface. |
| * <p> |
| * The lifecycle of a <code>CompletionProposalCollector</code> instance is very |
| * simple: |
| * <pre> |
| * ICompilationUnit unit= ... |
| * int offset= ... |
| * |
| * CompletionProposalCollector collector= new CompletionProposalCollector(unit); |
| * unit.codeComplete(offset, collector); |
| * IJavaCompletionProposal[] proposals= collector.getJavaCompletionProposals(); |
| * String errorMessage= collector.getErrorMessage(); |
| * |
| * // display / process proposals |
| * </pre> |
| * Note that after a code completion operation, the collector will store any |
| * received proposals, which may require a considerable amount of memory, so the |
| * collector should not be kept as a reference after a completion operation. |
| * </p> |
| * <p> |
| * Clients may instantiate or subclass. |
| * </p> |
| * @since 3.1 |
| */ |
| public class CompletionProposalCollector extends CompletionRequestor { |
| /** Triggers for method proposals without parameters. Do not modify. */ |
| protected final static char[] METHOD_TRIGGERS= new char[] { ';', ',', '.', '\t', '[', ' ' }; |
| /** Triggers for method proposals. Do not modify. */ |
| protected final static char[] METHOD_WITH_ARGUMENTS_TRIGGERS= new char[] { '(', '-', ' ' }; |
| /** Triggers for types. Do not modify. */ |
| protected final static char[] TYPE_TRIGGERS= new char[] { '.', '\t', '[', '(', ' ' }; |
| /** Triggers for variables. Do not modify. */ |
| protected final static char[] VAR_TRIGGER= new char[] { '\t', ' ', '=', ';', '.' }; |
| |
| private final CompletionProposalLabelProvider fLabelProvider= new CompletionProposalLabelProvider(); |
| private final ImageDescriptorRegistry fRegistry= JavaPlugin.getImageDescriptorRegistry(); |
| |
| private final List<IJavaCompletionProposal> fJavaProposals= new ArrayList<>(); |
| private final List<IJavaCompletionProposal> fKeywords= new ArrayList<>(); |
| private final Set<String> fSuggestedMethodNames= new HashSet<>(); |
| |
| private final ICompilationUnit fCompilationUnit; |
| private final IJavaProject fJavaProject; |
| private int fUserReplacementLength; |
| |
| private CompletionContext fContext; |
| private IProblem fLastProblem; |
| |
| /* performance instrumentation */ |
| private long fStartTime; |
| private long fUITime; |
| |
| /** |
| * The UI invocation context or <code>null</code>. |
| * |
| * @since 3.2 |
| */ |
| private JavaContentAssistInvocationContext fInvocationContext; |
| |
| private boolean fIsTestCodeExcluded; |
| |
| /** |
| * Creates a new instance ready to collect proposals. If the passed |
| * <code>ICompilationUnit</code> is not contained in an |
| * {@link IJavaProject}, no javadoc will be available as |
| * {@link org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() additional info} |
| * on the created proposals. |
| * |
| * @param cu the compilation unit that the result collector will operate on |
| */ |
| public CompletionProposalCollector(ICompilationUnit cu) { |
| this(cu.getJavaProject(), cu, false); |
| } |
| |
| /** |
| * Creates a new instance ready to collect proposals. Note that proposals |
| * for anonymous types and method declarations are not created when using |
| * this constructor, as those need to know the compilation unit that they |
| * are created on. Use |
| * {@link CompletionProposalCollector#CompletionProposalCollector(ICompilationUnit)} |
| * instead to get all proposals. |
| * <p> |
| * If the passed Java project is <code>null</code>, no javadoc will be |
| * available as |
| * {@link org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() additional info} |
| * on the created (e.g. method and type) proposals. |
| * </p> |
| * @param project the project that the result collector will operate on, or |
| * <code>null</code> |
| */ |
| public CompletionProposalCollector(IJavaProject project) { |
| this(project, null, false); |
| } |
| |
| private CompletionProposalCollector(IJavaProject project, ICompilationUnit cu, boolean ignoreAll) { |
| super(ignoreAll); |
| fJavaProject= project; |
| fCompilationUnit= cu; |
| |
| fIsTestCodeExcluded = cu != null && !isTestSource(project, cu); |
| |
| fUserReplacementLength= -1; |
| if (!ignoreAll) { |
| setRequireExtendedContext(true); |
| } |
| } |
| |
| private boolean isTestSource(IJavaProject project, ICompilationUnit cu) { |
| try { |
| IClasspathEntry[] resolvedClasspath= project.getResolvedClasspath(true); |
| final IPath resourcePath= cu.getResource().getFullPath(); |
| for (IClasspathEntry e : resolvedClasspath) { |
| if (e.getEntryKind() == IClasspathEntry.CPE_SOURCE) { |
| if (e.isTest()) { |
| if (e.getPath().isPrefixOf(resourcePath)) { |
| return true; |
| } |
| } |
| } |
| } |
| } catch (JavaModelException e) { |
| return false; |
| } |
| return false; |
| } |
| |
| /** |
| * @since 3.14 |
| */ |
| @Override |
| public boolean isTestCodeExcluded() { |
| return fIsTestCodeExcluded; |
| } |
| |
| /** |
| * Creates a new instance ready to collect proposals. If the passed |
| * <code>ICompilationUnit</code> is not contained in an |
| * {@link IJavaProject}, no javadoc will be available as |
| * {@link org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() additional info} |
| * on the created proposals. |
| * |
| * @param cu the compilation unit that the result collector will operate on |
| * @param ignoreAll <code>true</code> to ignore all kinds of completion proposals |
| * @since 3.4 |
| */ |
| public CompletionProposalCollector(ICompilationUnit cu, boolean ignoreAll) { |
| this(cu.getJavaProject(), cu, ignoreAll); |
| } |
| |
| @Override |
| public void setIgnored(int completionProposalKind, boolean ignore) { |
| super.setIgnored(completionProposalKind, ignore); |
| if (completionProposalKind == CompletionProposal.METHOD_DECLARATION && !ignore) { |
| setRequireExtendedContext(true); |
| } |
| } |
| |
| /** |
| * Sets the invocation context. |
| * <p> |
| * Subclasses may extend. |
| * </p> |
| * |
| * @param context the invocation context |
| * @see #getInvocationContext() |
| * @since 3.2 |
| */ |
| public void setInvocationContext(JavaContentAssistInvocationContext context) { |
| Assert.isNotNull(context); |
| fInvocationContext= context; |
| context.setCollector(this); |
| } |
| |
| /** |
| * Returns the invocation context. If none has been set via |
| * {@link #setInvocationContext(JavaContentAssistInvocationContext)}, a new one is created. |
| * |
| * @return invocationContext the invocation context |
| * @since 3.2 |
| */ |
| protected final JavaContentAssistInvocationContext getInvocationContext() { |
| if (fInvocationContext == null) { |
| ICompilationUnit cu= getCompilationUnit(); |
| if (cu != null) |
| setInvocationContext(new JavaContentAssistInvocationContext(cu)); |
| else |
| setInvocationContext(new JavaContentAssistInvocationContext(fJavaProject)); |
| } |
| return fInvocationContext; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Subclasses may replace, but usually should not need to. Consider |
| * replacing |
| * {@linkplain #createJavaCompletionProposal(CompletionProposal) createJavaCompletionProposal} |
| * instead. |
| * </p> |
| */ |
| @Override |
| public void accept(CompletionProposal proposal) { |
| long start= JavaPlugin.DEBUG_RESULT_COLLECTOR ? System.currentTimeMillis() : 0; |
| try { |
| if (isFiltered(proposal)) |
| return; |
| |
| if (proposal.getKind() == CompletionProposal.POTENTIAL_METHOD_DECLARATION) { |
| acceptPotentialMethodDeclaration(proposal); |
| } else { |
| IJavaCompletionProposal javaProposal= createJavaCompletionProposal(proposal); |
| if (javaProposal != null) { |
| fJavaProposals.add(javaProposal); |
| if (proposal.getKind() == CompletionProposal.KEYWORD) |
| fKeywords.add(javaProposal); |
| } |
| } |
| } catch (IllegalArgumentException e) { |
| // all signature processing method may throw IAEs |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=84657 |
| // don't abort, but log and show all the valid proposals |
| JavaPlugin.log(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.OK, "Exception when processing proposal for: " + String.valueOf(proposal.getCompletion()), e)); //$NON-NLS-1$ |
| } |
| |
| if (JavaPlugin.DEBUG_RESULT_COLLECTOR) fUITime += System.currentTimeMillis() - start; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Subclasses may extend, but usually should not need to. |
| * </p> |
| * @see #getContext() |
| */ |
| @Override |
| public void acceptContext(CompletionContext context) { |
| fContext= context; |
| fLabelProvider.setContext(context); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * Subclasses may extend, but must call the super implementation. |
| */ |
| @Override |
| public void beginReporting() { |
| if (JavaPlugin.DEBUG_RESULT_COLLECTOR) { |
| fStartTime= System.currentTimeMillis(); |
| fUITime= 0; |
| } |
| |
| fLastProblem= null; |
| fJavaProposals.clear(); |
| fKeywords.clear(); |
| fSuggestedMethodNames.clear(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * Subclasses may extend, but must call the super implementation. |
| */ |
| @Override |
| public void completionFailure(IProblem problem) { |
| fLastProblem= problem; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * Subclasses may extend, but must call the super implementation. |
| */ |
| @Override |
| public void endReporting() { |
| if (JavaPlugin.DEBUG_RESULT_COLLECTOR) { |
| long total= System.currentTimeMillis() - fStartTime; |
| System.err.println("Core Collector (core):\t" + (total - fUITime)); //$NON-NLS-1$ |
| System.err.println("Core Collector (ui):\t" + fUITime); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Returns an error message about any error that may have occurred during |
| * code completion, or the empty string if none. |
| * <p> |
| * Subclasses may replace or extend. |
| * </p> |
| * @return an error message or the empty string |
| */ |
| public String getErrorMessage() { |
| if (fLastProblem != null) |
| return fLastProblem.getMessage(); |
| return ""; //$NON-NLS-1$ |
| } |
| |
| /** |
| * Returns the unsorted list of received proposals. |
| * |
| * @return the unsorted list of received proposals |
| */ |
| public final IJavaCompletionProposal[] getJavaCompletionProposals() { |
| return CollectionsUtil.toArray(fJavaProposals, IJavaCompletionProposal.class); |
| } |
| |
| /** |
| * Returns the unsorted list of received keyword proposals. |
| * |
| * @return the unsorted list of received keyword proposals |
| */ |
| public final IJavaCompletionProposal[] getKeywordCompletionProposals() { |
| return CollectionsUtil.toArray(fKeywords, IJavaCompletionProposal.class); |
| } |
| |
| /** |
| * If the replacement length is set, it overrides the length returned from |
| * the content assist infrastructure. Use this setting if code assist is |
| * called with a none empty selection. |
| * |
| * @param length the new replacement length, relative to the code assist |
| * offset. Must be equal to or greater than zero. |
| */ |
| public final void setReplacementLength(int length) { |
| Assert.isLegal(length >= 0); |
| fUserReplacementLength= length; |
| } |
| |
| /** |
| * Computes the relevance for a given <code>CompletionProposal</code>. |
| * <p> |
| * Subclasses may replace, but usually should not need to. |
| * </p> |
| * @param proposal the proposal to compute the relevance for |
| * @return the relevance for <code>proposal</code> |
| */ |
| protected int computeRelevance(CompletionProposal proposal) { |
| return RelevanceComputer.computeRelevance(proposal); |
| } |
| |
| /** |
| * Creates a new java completion proposal from a core proposal. This may |
| * involve computing the display label and setting up some context. |
| * <p> |
| * This method is called for every proposal that will be displayed to the |
| * user, which may be hundreds. Implementations should therefore defer as |
| * much work as possible: Labels should be computed lazily to leverage |
| * virtual table usage, and any information only needed when |
| * <em>applying</em> a proposal should not be computed yet. |
| * </p> |
| * <p> |
| * Implementations may return <code>null</code> if a proposal should not |
| * be included in the list presented to the user. |
| * </p> |
| * <p> |
| * Subclasses may extend or replace this method. |
| * </p> |
| * |
| * @param proposal the core completion proposal to create a UI proposal for |
| * @return the created java completion proposal, or <code>null</code> if |
| * no proposal should be displayed |
| */ |
| protected IJavaCompletionProposal createJavaCompletionProposal(CompletionProposal proposal) { |
| switch (proposal.getKind()) { |
| case CompletionProposal.KEYWORD: |
| return createKeywordProposal(proposal); |
| case CompletionProposal.PACKAGE_REF: |
| return createPackageProposal(proposal); |
| case CompletionProposal.MODULE_REF: |
| return createModuleProposal(proposal); |
| case CompletionProposal.MODULE_DECLARATION: |
| return createModuleProposal(proposal); |
| case CompletionProposal.TYPE_REF: |
| return createTypeProposal(proposal); |
| case CompletionProposal.JAVADOC_TYPE_REF: |
| return createJavadocLinkTypeProposal(proposal); |
| case CompletionProposal.FIELD_REF: |
| case CompletionProposal.JAVADOC_FIELD_REF: |
| case CompletionProposal.JAVADOC_VALUE_REF: |
| return createFieldProposal(proposal); |
| case CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER: |
| return createFieldWithCastedReceiverProposal(proposal); |
| case CompletionProposal.METHOD_REF: |
| case CompletionProposal.CONSTRUCTOR_INVOCATION: |
| case CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER: |
| case CompletionProposal.METHOD_NAME_REFERENCE: |
| case CompletionProposal.JAVADOC_METHOD_REF: |
| return createMethodReferenceProposal(proposal); |
| case CompletionProposal.METHOD_DECLARATION: |
| return createMethodDeclarationProposal(proposal); |
| case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION: |
| return createAnonymousTypeProposal(proposal, getInvocationContext()); |
| case CompletionProposal.ANONYMOUS_CLASS_DECLARATION: |
| return createAnonymousTypeProposal(proposal, null); |
| case CompletionProposal.LABEL_REF: |
| return createLabelProposal(proposal); |
| case CompletionProposal.LOCAL_VARIABLE_REF: |
| case CompletionProposal.VARIABLE_DECLARATION: |
| return createLocalVariableProposal(proposal); |
| case CompletionProposal.ANNOTATION_ATTRIBUTE_REF: |
| return createAnnotationAttributeReferenceProposal(proposal); |
| case CompletionProposal.JAVADOC_BLOCK_TAG: |
| case CompletionProposal.JAVADOC_PARAM_REF: |
| return createJavadocSimpleProposal(proposal); |
| case CompletionProposal.JAVADOC_INLINE_TAG: |
| return createJavadocInlineTagProposal(proposal); |
| case CompletionProposal.POTENTIAL_METHOD_DECLARATION: |
| default: |
| return null; |
| } |
| } |
| |
| /** |
| * Creates the context information for a given method reference proposal. |
| * The passed proposal must be of kind {@link CompletionProposal#METHOD_REF}. |
| * |
| * @param methodProposal the method proposal for which to create context information |
| * @return the context information for <code>methodProposal</code> |
| */ |
| protected final IContextInformation createMethodContextInformation(CompletionProposal methodProposal) { |
| Assert.isTrue(methodProposal.getKind() == CompletionProposal.METHOD_REF); |
| return new ProposalContextInformation(methodProposal); |
| } |
| |
| /** |
| * Returns the compilation unit that the receiver operates on, or |
| * <code>null</code> if the <code>IJavaProject</code> constructor was |
| * used to create the receiver. |
| * |
| * @return the compilation unit that the receiver operates on, or |
| * <code>null</code> |
| */ |
| protected final ICompilationUnit getCompilationUnit() { |
| return fCompilationUnit; |
| } |
| |
| /** |
| * Returns the <code>CompletionContext</code> for this completion operation. |
| |
| * @return the <code>CompletionContext</code> for this completion operation |
| * @see CompletionRequestor#acceptContext(CompletionContext) |
| */ |
| protected final CompletionContext getContext() { |
| return fContext; |
| } |
| |
| /** |
| * Returns a cached image for the given descriptor. |
| * |
| * @param descriptor the image descriptor to get an image for, may be |
| * <code>null</code> |
| * @return the image corresponding to <code>descriptor</code> |
| */ |
| protected final Image getImage(ImageDescriptor descriptor) { |
| return (descriptor == null) ? null : fRegistry.get(descriptor); |
| } |
| |
| /** |
| * Returns the proposal label provider used by the receiver. |
| * |
| * @return the proposal label provider used by the receiver |
| */ |
| protected final CompletionProposalLabelProvider getLabelProvider() { |
| return fLabelProvider; |
| } |
| |
| /** |
| * Returns the replacement length of a given completion proposal. The |
| * replacement length is usually the difference between the return values of |
| * <code>proposal.getReplaceEnd</code> and |
| * <code>proposal.getReplaceStart</code>, but this behavior may be |
| * overridden by calling {@link #setReplacementLength(int)}. |
| * |
| * @param proposal the completion proposal to get the replacement length for |
| * @return the replacement length for <code>proposal</code> |
| */ |
| protected final int getLength(CompletionProposal proposal) { |
| int start= proposal.getReplaceStart(); |
| int end= proposal.getReplaceEnd(); |
| int length; |
| if (fUserReplacementLength == -1) { |
| length= end - start; |
| } else { |
| length= fUserReplacementLength; |
| // extend length to begin at start |
| int behindCompletion= proposal.getCompletionLocation() + 1; |
| if (start < behindCompletion) { |
| length+= behindCompletion - start; |
| } |
| } |
| return length; |
| } |
| |
| /** |
| * Returns <code>true</code> if <code>proposal</code> is filtered, e.g. |
| * should not be proposed to the user, <code>false</code> if it is valid. |
| * <p> |
| * Subclasses may extends this method. The default implementation filters |
| * proposals set to be ignored via |
| * {@linkplain CompletionRequestor#setIgnored(int, boolean) setIgnored} and |
| * types set to be ignored in the preferences. |
| * </p> |
| * |
| * @param proposal the proposal to filter |
| * @return <code>true</code> to filter <code>proposal</code>, |
| * <code>false</code> to let it pass |
| */ |
| protected boolean isFiltered(CompletionProposal proposal) { |
| if (isIgnored(proposal.getKind())) |
| return true; |
| char[] declaringType= getDeclaringType(proposal); |
| return declaringType!= null && TypeFilter.isFiltered(declaringType); |
| } |
| |
| /** |
| * Returns the type signature of the declaring type of a |
| * <code>CompletionProposal</code>, or <code>null</code> for proposals |
| * that do not have a declaring type. The return value is <em>not</em> |
| * <code>null</code> for proposals of the following kinds: |
| * <ul> |
| * <li>METHOD_DECLARATION</li> |
| * <li>METHOD_NAME_REFERENCE</li> |
| * <li>METHOD_REF</li> |
| * <li>ANNOTATION_ATTRIBUTE_REF</li> |
| * <li>POTENTIAL_METHOD_DECLARATION</li> |
| * <li>ANONYMOUS_CLASS_DECLARATION</li> |
| * <li>FIELD_REF</li> |
| * <li>PACKAGE_REF (returns the package name, but no type)</li> |
| * <li>MODULE_REF (returns the module name, but no type)</li> |
| * <li>MODULE_DECLARATION (returns the possible name of the module that is being declared, but no type)</li> |
| * <li>TYPE_REF</li> |
| * </ul> |
| * |
| * @param proposal the completion proposal to get the declaring type for |
| * @return the type signature of the declaring type, or <code>null</code> if there is none |
| * @see Signature#toCharArray(char[]) |
| */ |
| protected final char[] getDeclaringType(CompletionProposal proposal) { |
| switch (proposal.getKind()) { |
| case CompletionProposal.METHOD_DECLARATION: |
| case CompletionProposal.METHOD_NAME_REFERENCE: |
| case CompletionProposal.JAVADOC_METHOD_REF: |
| case CompletionProposal.METHOD_REF: |
| case CompletionProposal.CONSTRUCTOR_INVOCATION: |
| case CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION: |
| case CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER: |
| case CompletionProposal.ANNOTATION_ATTRIBUTE_REF: |
| case CompletionProposal.POTENTIAL_METHOD_DECLARATION: |
| case CompletionProposal.ANONYMOUS_CLASS_DECLARATION: |
| case CompletionProposal.FIELD_REF: |
| case CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER: |
| case CompletionProposal.JAVADOC_FIELD_REF: |
| case CompletionProposal.JAVADOC_VALUE_REF: |
| char[] declaration= proposal.getDeclarationSignature(); |
| // special methods may not have a declaring type: methods defined on arrays etc. |
| // Currently known: class literals don't have a declaring type - use Object |
| if (declaration == null) |
| return "java.lang.Object".toCharArray(); //$NON-NLS-1$ |
| return Signature.toCharArray(declaration); |
| case CompletionProposal.PACKAGE_REF: |
| case CompletionProposal.MODULE_REF: |
| case CompletionProposal.MODULE_DECLARATION: |
| return proposal.getDeclarationSignature(); |
| case CompletionProposal.JAVADOC_TYPE_REF: |
| case CompletionProposal.TYPE_REF: |
| return Signature.toCharArray(proposal.getSignature()); |
| case CompletionProposal.LOCAL_VARIABLE_REF: |
| case CompletionProposal.VARIABLE_DECLARATION: |
| case CompletionProposal.KEYWORD: |
| case CompletionProposal.LABEL_REF: |
| case CompletionProposal.JAVADOC_BLOCK_TAG: |
| case CompletionProposal.JAVADOC_INLINE_TAG: |
| case CompletionProposal.JAVADOC_PARAM_REF: |
| return null; |
| default: |
| Assert.isTrue(false); |
| return null; |
| } |
| } |
| |
| private void acceptPotentialMethodDeclaration(CompletionProposal proposal) { |
| try { |
| IJavaElement enclosingElement= null; |
| if (getContext().isExtended()) { |
| enclosingElement= getContext().getEnclosingElement(); |
| } else if (fCompilationUnit != null) { |
| // kept for backward compatibility: CU is not reconciled at this moment, information is missing (bug 70005) |
| enclosingElement= fCompilationUnit.getElementAt(proposal.getCompletionLocation() + 1); |
| } |
| if (enclosingElement == null) |
| return; |
| IType type= (IType) enclosingElement.getAncestor(IJavaElement.TYPE); |
| if (type != null) { |
| String prefix= String.valueOf(proposal.getName()); |
| int completionStart= proposal.getReplaceStart(); |
| int completionEnd= proposal.getReplaceEnd(); |
| int relevance= computeRelevance(proposal); |
| |
| GetterSetterCompletionProposal.evaluateProposals(type, prefix, completionStart, completionEnd - completionStart, relevance + 2, fSuggestedMethodNames, fJavaProposals); |
| MethodDeclarationCompletionProposal.evaluateProposals(type, prefix, completionStart, completionEnd - completionStart, relevance, fSuggestedMethodNames, fJavaProposals); |
| } |
| } catch (CoreException e) { |
| JavaPlugin.log(e); |
| } |
| } |
| |
| private IJavaCompletionProposal createAnnotationAttributeReferenceProposal(CompletionProposal proposal) { |
| StyledString displayString= fLabelProvider.createLabelWithTypeAndDeclaration(proposal); |
| ImageDescriptor descriptor= fLabelProvider.createMethodImageDescriptor(proposal); |
| String completion= String.valueOf(proposal.getCompletion()); |
| JavaCompletionProposal javaProposal= new JavaCompletionProposal(completion, proposal.getReplaceStart(), getLength(proposal), getImage(descriptor), displayString, computeRelevance(proposal)); |
| if (fJavaProject != null) |
| javaProposal.setProposalInfo(new AnnotationAtttributeProposalInfo(fJavaProject, proposal)); |
| return javaProposal; |
| } |
| |
| private IJavaCompletionProposal createAnonymousTypeProposal(CompletionProposal proposal, JavaContentAssistInvocationContext invocationContext) { |
| if (fCompilationUnit == null || fJavaProject == null) |
| return null; |
| |
| char[] declarationKey= proposal.getDeclarationKey(); |
| if (declarationKey == null) |
| return null; |
| |
| try { |
| IJavaElement element= fJavaProject.findElement(new String(declarationKey), null); |
| if (!(element instanceof IType)) |
| return null; |
| |
| IType type= (IType) element; |
| |
| String completion= String.valueOf(proposal.getCompletion()); |
| int start= proposal.getReplaceStart(); |
| int length= getLength(proposal); |
| int relevance= computeRelevance(proposal); |
| |
| StyledString label= fLabelProvider.createAnonymousTypeLabel(proposal); |
| |
| JavaCompletionProposal javaProposal= new AnonymousTypeCompletionProposal(fJavaProject, fCompilationUnit, invocationContext, start, length, completion, label, String.valueOf(proposal |
| .getDeclarationSignature()), type, relevance); |
| javaProposal.setProposalInfo(new AnonymousTypeProposalInfo(fJavaProject, proposal)); |
| return javaProposal; |
| } catch (JavaModelException e) { |
| return null; |
| } |
| } |
| |
| private IJavaCompletionProposal createFieldProposal(CompletionProposal proposal) { |
| String completion= String.valueOf(proposal.getCompletion()); |
| int start= proposal.getReplaceStart(); |
| int length= getLength(proposal); |
| StyledString label= fLabelProvider.createStyledLabel(proposal); |
| Image image= getImage(fLabelProvider.createFieldImageDescriptor(proposal)); |
| int relevance= computeRelevance(proposal); |
| |
| JavaCompletionProposal javaProposal= new JavaCompletionProposal(completion, start, length, image, label, relevance, getContext().isInJavadoc(), getInvocationContext()); |
| if (fJavaProject != null) |
| javaProposal.setProposalInfo(new FieldProposalInfo(fJavaProject, proposal)); |
| |
| javaProposal.setTriggerCharacters(VAR_TRIGGER); |
| |
| return javaProposal; |
| } |
| |
| /** |
| * Creates the Java completion proposal for the JDT Core |
| * {@link CompletionProposal#FIELD_REF_WITH_CASTED_RECEIVER} proposal. |
| * |
| * @param proposal the JDT Core proposal |
| * @return the Java completion proposal |
| * @since 3.4 |
| */ |
| private IJavaCompletionProposal createFieldWithCastedReceiverProposal(CompletionProposal proposal) { |
| String completion= String.valueOf(proposal.getCompletion()); |
| completion= CodeFormatterUtil.format(CodeFormatter.K_EXPRESSION, completion, 0, "\n", FormatterProfileManager.getProjectSettings(fJavaProject)); //$NON-NLS-1$ |
| int start= proposal.getReplaceStart(); |
| int length= getLength(proposal); |
| StyledString label= fLabelProvider.createStyledLabel(proposal); |
| Image image= getImage(fLabelProvider.createFieldImageDescriptor(proposal)); |
| int relevance= computeRelevance(proposal); |
| |
| JavaCompletionProposal javaProposal= new JavaFieldWithCastedReceiverCompletionProposal(completion, start, length, image, label, relevance, getContext().isInJavadoc(), getInvocationContext(), proposal); |
| if (fJavaProject != null) |
| javaProposal.setProposalInfo(new FieldProposalInfo(fJavaProject, proposal)); |
| |
| javaProposal.setTriggerCharacters(VAR_TRIGGER); |
| |
| return javaProposal; |
| } |
| |
| private IJavaCompletionProposal createJavadocSimpleProposal(CompletionProposal javadocProposal) { |
| // TODO do better with javadoc proposals |
| // String completion= String.valueOf(proposal.getCompletion()); |
| // int start= proposal.getReplaceStart(); |
| // int length= getLength(proposal); |
| // String label= fLabelProvider.createSimpleLabel(proposal); |
| // Image image= getImage(fLabelProvider.createImageDescriptor(proposal)); |
| // int relevance= computeRelevance(proposal); |
| // |
| // JavaCompletionProposal javaProposal= new JavaCompletionProposal(completion, start, length, image, label, relevance); |
| // if (fJavaProject != null) |
| // javaProposal.setProposalInfo(new FieldProposalInfo(fJavaProject, proposal)); |
| // |
| // javaProposal.setTriggerCharacters(VAR_TRIGGER); |
| // |
| // return javaProposal; |
| LazyJavaCompletionProposal proposal = new LazyJavaCompletionProposal(javadocProposal, getInvocationContext()); |
| // adaptLength(proposal, javadocProposal); |
| return proposal; |
| } |
| |
| private IJavaCompletionProposal createJavadocInlineTagProposal(CompletionProposal javadocProposal) { |
| LazyJavaCompletionProposal proposal= new JavadocInlineTagCompletionProposal(javadocProposal, getInvocationContext()); |
| adaptLength(proposal, javadocProposal); |
| return proposal; |
| } |
| |
| private IJavaCompletionProposal createKeywordProposal(CompletionProposal proposal) { |
| String completion= String.valueOf(proposal.getCompletion()); |
| int start= proposal.getReplaceStart(); |
| int length= getLength(proposal); |
| StyledString label= fLabelProvider.createSimpleLabel(proposal); |
| int relevance= computeRelevance(proposal); |
| return new JavaCompletionProposal(completion, start, length, null, label, relevance); |
| } |
| |
| private IJavaCompletionProposal createLabelProposal(CompletionProposal proposal) { |
| String completion= String.valueOf(proposal.getCompletion()); |
| int start= proposal.getReplaceStart(); |
| int length= getLength(proposal); |
| StyledString label= fLabelProvider.createSimpleLabel(proposal); |
| int relevance= computeRelevance(proposal); |
| |
| return new JavaCompletionProposal(completion, start, length, null, label, relevance); |
| } |
| |
| private IJavaCompletionProposal createLocalVariableProposal(CompletionProposal proposal) { |
| String completion= String.valueOf(proposal.getCompletion()); |
| int start= proposal.getReplaceStart(); |
| int length= getLength(proposal); |
| Image image= getImage(fLabelProvider.createLocalImageDescriptor(proposal)); |
| StyledString label= fLabelProvider.createSimpleLabelWithType(proposal); |
| int relevance= computeRelevance(proposal); |
| final JavaCompletionProposal javaProposal= new JavaCompletionProposal(completion, start, length, image, label, relevance); |
| javaProposal.setTriggerCharacters(VAR_TRIGGER); |
| return javaProposal; |
| } |
| |
| private IJavaCompletionProposal createMethodDeclarationProposal(CompletionProposal proposal) { |
| if (fCompilationUnit == null || fJavaProject == null) |
| return null; |
| |
| String name= String.valueOf(proposal.getName()); |
| String[] paramTypes= Signature.getParameterTypes(String.valueOf(proposal.getSignature())); |
| for (int index= 0; index < paramTypes.length; index++) |
| paramTypes[index]= Signature.toString(paramTypes[index]); |
| int start= proposal.getReplaceStart(); |
| int length= getLength(proposal); |
| |
| StyledString label= fLabelProvider.createOverrideMethodProposalLabel(proposal); |
| |
| JavaCompletionProposal javaProposal= new OverrideCompletionProposal(fJavaProject, fCompilationUnit, name, paramTypes, start, length, label, String.valueOf(proposal.getCompletion())); |
| javaProposal.setImage(getImage(fLabelProvider.createMethodImageDescriptor(proposal))); |
| javaProposal.setProposalInfo(new MethodProposalInfo(fJavaProject, proposal)); |
| javaProposal.setRelevance(computeRelevance(proposal)); |
| |
| fSuggestedMethodNames.add(new String(name)); |
| return javaProposal; |
| } |
| |
| private IJavaCompletionProposal createMethodReferenceProposal(CompletionProposal methodProposal) { |
| LazyJavaCompletionProposal proposal= new JavaMethodCompletionProposal(methodProposal, getInvocationContext()); |
| adaptLength(proposal, methodProposal); |
| return proposal; |
| } |
| |
| private void adaptLength(LazyJavaCompletionProposal proposal, CompletionProposal coreProposal) { |
| if (fUserReplacementLength != -1) { |
| proposal.setReplacementLength(getLength(coreProposal)); |
| } |
| } |
| |
| private IJavaCompletionProposal createModuleProposal(CompletionProposal proposal) { |
| return new LazyModuleCompletionProposal(proposal, getInvocationContext()); |
| } |
| |
| private IJavaCompletionProposal createPackageProposal(CompletionProposal proposal) { |
| return new LazyPackageCompletionProposal(proposal, getInvocationContext()); |
| } |
| |
| private IJavaCompletionProposal createTypeProposal(CompletionProposal typeProposal) { |
| LazyJavaCompletionProposal proposal= new LazyJavaTypeCompletionProposal(typeProposal, getInvocationContext()); |
| adaptLength(proposal, typeProposal); |
| return proposal; |
| } |
| |
| private IJavaCompletionProposal createJavadocLinkTypeProposal(CompletionProposal typeProposal) { |
| LazyJavaCompletionProposal proposal= new JavadocLinkTypeCompletionProposal(typeProposal, getInvocationContext()); |
| adaptLength(proposal, typeProposal); |
| return proposal; |
| } |
| } |