blob: 01bd957c90c67b6e7cf2835cc33ed8995d9b617a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 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
*
*******************************************************************************/
package org.eclipse.dltk.ui.text.completion;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.PreferenceConstants;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationExtension;
import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;
/**
* Computes Script completion proposals and context infos.
*/
public abstract class ScriptCompletionProposalComputer
extends AbstractScriptCompletionProposalComputer
implements IScriptCompletionProposalComputer {
private static final class ContextInformationWrapper
implements IContextInformation, IContextInformationExtension {
private final IContextInformation fContextInformation;
private int fPosition;
public ContextInformationWrapper(
IContextInformation contextInformation) {
fContextInformation = contextInformation;
}
@Override
public String getContextDisplayString() {
return fContextInformation.getContextDisplayString();
}
@Override
public Image getImage() {
return fContextInformation.getImage();
}
@Override
public String getInformationDisplayString() {
return fContextInformation.getInformationDisplayString();
}
@Override
public int getContextInformationPosition() {
return fPosition;
}
public void setContextInformationPosition(int position) {
fPosition = position;
}
@Override
public boolean equals(Object object) {
if (object instanceof ContextInformationWrapper)
return fContextInformation.equals(
((ContextInformationWrapper) object).fContextInformation);
else
return fContextInformation.equals(object);
}
}
private String fErrorMessage;
private List<IContextInformation> addContextInformations(
ScriptContentAssistInvocationContext context, int offset,
IProgressMonitor monitor) {
List<ICompletionProposal> proposals = computeScriptCompletionProposals(
offset, context, monitor);
List<IContextInformation> result = new ArrayList<>(proposals.size());
for (ICompletionProposal proposal : proposals) {
IContextInformation contextInformation = proposal
.getContextInformation();
if (contextInformation != null) {
ContextInformationWrapper wrapper = new ContextInformationWrapper(
contextInformation);
wrapper.setContextInformationPosition(offset);
result.add(wrapper);
}
}
return result;
}
private void handleCodeCompletionException(ModelException e,
ScriptContentAssistInvocationContext context) {
ISourceModule module = context.getSourceModule();
Shell shell = context.getViewer().getTextWidget().getShell();
if (e.isDoesNotExist()
&& !module.getScriptProject().isOnBuildpath(module)) {
IPreferenceStore store = DLTKUIPlugin.getDefault()
.getPreferenceStore();
boolean value = store.getBoolean(
PreferenceConstants.NOTIFICATION_NOT_ON_BUILDPATH_MESSAGE);
if (!value) {
MessageDialog.openInformation(shell,
ScriptTextMessages.CompletionProcessor_error_notOnBuildPath_title,
ScriptTextMessages.CompletionProcessor_error_notOnBuildPath_message);
}
store.setValue(
PreferenceConstants.NOTIFICATION_NOT_ON_BUILDPATH_MESSAGE,
true);
} else
ErrorDialog.openError(shell,
ScriptTextMessages.CompletionProcessor_error_accessing_title,
ScriptTextMessages.CompletionProcessor_error_accessing_message,
e.getStatus());
}
// Code template completion proposals for script language
protected List<ICompletionProposal> computeTemplateCompletionProposals(
int offset, ScriptContentAssistInvocationContext context,
IProgressMonitor monitor) {
TemplateCompletionProcessor templateProcessor = createTemplateProposalComputer(
context);
if (templateProcessor != null) {
ICompletionProposal[] proposals = templateProcessor
.computeCompletionProposals(context.getViewer(), offset);
if (proposals != null && proposals.length != 0) {
updateTemplateProposalRelevance(context, proposals);
}
return Arrays.asList(proposals);
}
return Collections.emptyList();
}
// Script language specific completion proposals like types or keywords
protected List<ICompletionProposal> computeScriptCompletionProposals(
int offset, ScriptContentAssistInvocationContext context,
IProgressMonitor monitor) {
// Source module getting
ISourceModule sourceModule = context.getSourceModule();
if (sourceModule == null) {
return Collections.emptyList();
}
// Create and configure collector
ScriptCompletionProposalCollector collector = createCollector(context);
if (collector == null) {
return Collections.emptyList();
}
collector.setInvocationContext(context);
Point selection = context.getViewer().getSelectedRange();
if (selection.y > 0) {
collector.setReplacementLength(selection.y);
}
// Filling collector with proposals
try {
if (DLTKCore.DEBUG_COMPLETION) {
IModelElement element = sourceModule.getElementAt(offset);
if (element != null) {
System.out.println("========= Model element: " //$NON-NLS-1$
+ element.getClass());
}
}
int timeout = DLTKUIPlugin.getDefault().getPreferenceStore()
.getInt(PreferenceConstants.CODEASSIST_TIMEOUT);
collector.startCompletion();
sourceModule.codeComplete(offset, collector, timeout);
collector.endCompletion();
} catch (ModelException e) {
handleCodeCompletionException(e, context);
}
ICompletionProposal[] proposals = collector
.getScriptCompletionProposals();
// Checking proposals
if (proposals.length == 0) {
String error = collector.getErrorMessage();
if (error != null && error.length() > 0) {
fErrorMessage = error;
}
return Collections.emptyList();
}
return Arrays.asList(proposals);
}
public ScriptCompletionProposalComputer() {
}
/*
* @seeorg.eclipse.jface.text.contentassist.ICompletionProposalComputer#
* computeContextInformation
* (org.eclipse.jface.text.contentassist.TextContentAssistInvocationContext,
* org.eclipse.core.runtime.IProgressMonitor)
*/
/*
* public List computeContextInformation(ContentAssistInvocationContext
* context, IProgressMonitor monitor) { if (context instanceof
* ScriptContentAssistInvocationContext) {
* ScriptContentAssistInvocationContext scriptContext=
* (ScriptContentAssistInvocationContext) context;
*
* int contextInformationPosition=
* guessContextInformationPosition(scriptContext); List result=
* addContextInformations(scriptContext, contextInformationPosition,
* monitor); return result; } return Collections.EMPTY_LIST; }
*/
// Completion proposals
@Override
public List<ICompletionProposal> computeCompletionProposals(
ContentAssistInvocationContext context, IProgressMonitor monitor) {
if (context instanceof ScriptContentAssistInvocationContext) {
ScriptContentAssistInvocationContext scriptContext = (ScriptContentAssistInvocationContext) context;
List<ICompletionProposal> proposals = new ArrayList<>();
// Language specific proposals (already sorted and etc.)
proposals.addAll(computeScriptCompletionProposals(
context.getInvocationOffset(), scriptContext, monitor));
// Template proposals (already sorted and etc.)
proposals.addAll(computeTemplateCompletionProposals(
context.getInvocationOffset(), scriptContext, monitor));
return proposals;
}
return Collections.emptyList();
}
protected int guessContextInformationPosition(
ContentAssistInvocationContext context) {
return context.getInvocationOffset();
}
@Override
public List<IContextInformation> computeContextInformation(
ContentAssistInvocationContext context, IProgressMonitor monitor) {//
if (context instanceof ScriptContentAssistInvocationContext) {
ScriptContentAssistInvocationContext scriptContext = (ScriptContentAssistInvocationContext) context;
int contextInformationPosition = guessContextInformationPosition(
scriptContext);
List<IContextInformation> result = addContextInformations(
scriptContext, contextInformationPosition, monitor);
return result;
}
return Collections.emptyList();
// List types = computeCompletionProposals(context, monitor);
// Iterator iter = types.iterator();
// List list = new ArrayList();
// while (iter.hasNext()) {
// Object o = iter
// .next();
// if( !( o instanceof IScriptCompletionProposal ) ) {
// continue;
// }
// IScriptCompletionProposal proposal = (IScriptCompletionProposal) o;
// // System.out.println("Proposal: " + proposal + ", info: "
// // + proposal.getContextInformation());
// // System.out.println(proposal.getClass());
// list.add(proposal.getContextInformation());
// }
// return list;
}
@Override
public String getErrorMessage() {
return fErrorMessage;
}
@Override
public void sessionStarted() {
}
@Override
public void sessionEnded() {
fErrorMessage = null;
}
/**
* Creates the template completion processor
*
* <p>
* Subclasses may return <code>null</code> if they do not wish to provide
* template support.
* </p>
*/
protected TemplateCompletionProcessor createTemplateProposalComputer(
ScriptContentAssistInvocationContext context) {
return null;
}
protected abstract ScriptCompletionProposalCollector createCollector(
ScriptContentAssistInvocationContext context);
}