/******************************************************************************* * Copyright (c) 2005, 2016 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.internal.debug.ui.contentassist; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.internal.corext.template.java.JavaContextType; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.text.java.JavaParameterListValidator; import org.eclipse.jdt.internal.ui.text.template.contentassist.TemplateEngine; import org.eclipse.jdt.ui.text.java.AbstractProposalSorter; import org.eclipse.jdt.ui.text.java.CompletionProposalComparator; import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.ContentAssistant; 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.jface.text.templates.TemplateContextType; /** * Completion processor for the Java debugger. This completion processor * operates on a client provided context. * * @since 3.2 */ public class JavaDebugContentAssistProcessor implements IContentAssistProcessor { private JavaDebugCompletionProposalCollector fCollector; private IContextInformationValidator fValidator; private TemplateEngine fJavaEngine; private TemplateEngine fStatementEngine; private String fErrorMessage = null; private char[] fProposalAutoActivationSet; private CompletionProposalComparator fComparator; private IJavaDebugContentAssistContext fContext; private ContentAssistant fAssistant; public JavaDebugContentAssistProcessor(IJavaDebugContentAssistContext context) { fContext = context; TemplateContextType contextType= JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(JavaContextType.ID_ALL); if (contextType != null) { fJavaEngine= new TemplateEngine(contextType); } contextType = JavaPlugin.getDefault().getTemplateContextRegistry().getContextType(JavaContextType.ID_STATEMENTS); if (contextType != null) { fStatementEngine= new TemplateEngine(contextType); } fComparator= new CompletionProposalComparator(); fAssistant= null; } public void setContentAssistant(ContentAssistant assistant) { fAssistant = assistant; } /** * @see IContentAssistProcessor#getErrorMessage() */ @Override public String getErrorMessage() { if (fErrorMessage != null) { return fErrorMessage; } if (fCollector != null) { return fCollector.getErrorMessage(); } return null; } /** * Sets the error message for why completions could not be resolved. * Clients should clear this before computing completions. * * @param string message */ private void setErrorMessage(String string) { if (string != null && string.length() == 0) { string = null; } fErrorMessage = string; } /** * @see IContentAssistProcessor#getContextInformationValidator() */ @Override public IContextInformationValidator getContextInformationValidator() { if (fValidator == null) { fValidator= new JavaParameterListValidator(); } return fValidator; } /** * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters() */ @Override public char[] getContextInformationAutoActivationCharacters() { return null; } /** * @see IContentAssistProcessor#computeContextInformation(ITextViewer, int) */ @Override public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { return null; } /** * @see IContentAssistProcessor#computeProposals(ITextViewer, int) */ @Override public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { setErrorMessage(null); try { IType type = fContext.getType(); IJavaProject project = type.getJavaProject(); String[][] locals = fContext.getLocalVariables(); int numLocals = 0; if (locals.length > 0) { numLocals = locals[0].length; } char[][] localVariableNames = new char[numLocals][]; char[][] localVariableTypeNames = new char[numLocals][]; for (int i = 0; i < numLocals; i++) { localVariableNames[i] = locals[0][i].toCharArray(); localVariableTypeNames[i] = locals[1][i].toCharArray(); } ITextSelection selection= (ITextSelection)viewer.getSelectionProvider().getSelection(); configureResultCollector(project, selection); int[] localModifiers= new int[localVariableNames.length]; Arrays.fill(localModifiers, 0); String snippet = viewer.getDocument().get(); char[] charSnippet = fContext.getSnippet(snippet).toCharArray(); type.codeComplete(charSnippet, fContext.getInsertionPosition(), documentOffset, localVariableTypeNames, localVariableNames, localModifiers, fContext.isStatic(), fCollector); List<IJavaCompletionProposal> total = new ArrayList<>(); total.addAll(Arrays.asList(fCollector.getJavaCompletionProposals())); if (fJavaEngine != null) { fJavaEngine.reset(); fJavaEngine.complete(viewer, documentOffset, null); total.addAll(Arrays.asList(fJavaEngine.getResults())); } if (fStatementEngine != null) { fStatementEngine.reset(); fStatementEngine.complete(viewer, documentOffset, null); total.addAll(Arrays.asList(fStatementEngine.getResults())); } //Order here and not in result collector to make sure that the order //applies to all proposals and not just those of the compilation unit. return order(total.toArray(new IJavaCompletionProposal[total.size()])); } catch (CoreException x) { setErrorMessage(x.getStatus().getMessage()); } finally { releaseCollector(); } return null; } /** * Order the given proposals. */ private IJavaCompletionProposal[] order(IJavaCompletionProposal[] proposals) { if (fAssistant == null) { Arrays.sort(proposals, fComparator); return proposals; } fAssistant.setSorter(new AbstractProposalSorter() { @Override public int compare(ICompletionProposal p1, ICompletionProposal p2) { return fComparator.compare(p1, p2); } }); return proposals; } /** * Configures the display result collection for the current code assist session */ private void configureResultCollector(IJavaProject project, ITextSelection selection) { fCollector = new JavaDebugCompletionProposalCollector(project); if (selection.getLength() != 0) { fCollector.setReplacementLength(selection.getLength()); } } /** * Tells this processor to order the proposals alphabetically. * * @param order <code>true</code> if proposals should be ordered. */ public void orderProposalsAlphabetically(boolean order) { fComparator.setOrderAlphabetically(order); } /** * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() */ @Override public char[] getCompletionProposalAutoActivationCharacters() { return fProposalAutoActivationSet; } /** * Sets this processor's set of characters triggering the activation of the * completion proposal computation. * * @param activationSet the activation set */ public void setCompletionProposalAutoActivationCharacters(char[] activationSet) { fProposalAutoActivationSet= activationSet; } /** * Clears reference to result proposal collector. */ private void releaseCollector() { if (fCollector != null && fCollector.getErrorMessage().length() > 0 && fErrorMessage != null) { setErrorMessage(fCollector.getErrorMessage()); } fCollector = null; } }