blob: 40526295475e623c85d0f071074f0d4eca957d58 [file] [log] [blame]
/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.ui.internal.text.dart;
import com.google.dart.engine.utilities.instrumentation.Instrumentation;
import com.google.dart.engine.utilities.instrumentation.InstrumentationBuilder;
import com.google.dart.tools.ui.DartToolsPlugin;
import com.google.dart.tools.ui.Messages;
import com.google.dart.tools.ui.text.dart.ContentAssistInvocationContext;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.action.LegacyActionTools;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.osgi.framework.Bundle;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Describes a category extension to the "javaCompletionProposalComputer" extension point.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public final class CompletionProposalCategory {
/** The extension schema name of the icon attribute. */
private static final String ICON = "icon"; //$NON-NLS-1$
private final String fId;
private final String fName;
private final IConfigurationElement fElement;
/**
* The image descriptor for this category, or <code>null</code> if none specified.
*/
private final ImageDescriptor fImage;
private boolean fIsSeparateCommand = true;
private boolean fIsEnabled = true;
private boolean fIsIncluded = true;
private final CompletionProposalComputerRegistry fRegistry;
private int fSortOrder = 0x10000;
private String fLastError = null;
CompletionProposalCategory(IConfigurationElement element,
CompletionProposalComputerRegistry registry) {
fElement = element;
fRegistry = registry;
IExtension parent = (IExtension) element.getParent();
fId = parent.getUniqueIdentifier();
checkNotNull(fId, "id"); //$NON-NLS-1$
String name = parent.getLabel();
if (name == null) {
fName = fId;
} else {
fName = name;
}
String icon = element.getAttribute(ICON);
ImageDescriptor img = null;
if (icon != null) {
Bundle bundle = getBundle();
if (bundle != null) {
Path path = new Path(icon);
URL url = FileLocator.find(bundle, path, null);
img = ImageDescriptor.createFromURL(url);
}
}
fImage = img;
}
CompletionProposalCategory(String id, String name, CompletionProposalComputerRegistry registry) {
fRegistry = registry;
fId = id;
fName = name;
fElement = null;
fImage = null;
}
/**
* Safely computes completion proposals of all computers of this category through their extension.
* If an extension is disabled, throws an exception or otherwise does not adhere to the contract
* described in {@link com.google.dart.tools.ui.text.dart.IDartCompletionProposalComputer}, it is
* disabled.
*
* @param context the invocation context passed on to the extension
* @param partition the partition type where to invocation occurred
* @param monitor the progress monitor passed on to the extension
* @return the list of computed completion proposals (element type:
* {@link org.eclipse.jface.text.contentassist.ICompletionProposal})
*/
public List<ICompletionProposal> computeCompletionProposals(
ContentAssistInvocationContext context, String partition, SubProgressMonitor monitor) {
InstrumentationBuilder instrumentation = Instrumentation.builder("CompletionProposals");
try {
fLastError = null;
List<ICompletionProposal> result = new ArrayList<ICompletionProposal>();
List descriptors = new ArrayList(fRegistry.getProposalComputerDescriptors(partition));
for (Iterator it = descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this) {
result.addAll(desc.computeCompletionProposals(context, monitor));
}
if (fLastError == null) {
fLastError = desc.getErrorMessage();
}
}
instrumentation.metric("Results-Count", result.size());
return result;
} finally {
instrumentation.log();
}
}
/**
* Safely computes context information objects of all computers of this category through their
* extension. If an extension is disabled, throws an exception or otherwise does not adhere to the
* contract described in
* {@link com.google.dart.tools.ui.text.dart.IDartCompletionProposalComputer}, it is disabled.
*
* @param context the invocation context passed on to the extension
* @param partition the partition type where to invocation occurred
* @param monitor the progress monitor passed on to the extension
* @return the list of computed context information objects (element type:
* {@link org.eclipse.jface.text.contentassist.IContextInformation})
*/
public List<IContextInformation> computeContextInformation(
ContentAssistInvocationContext context, String partition, SubProgressMonitor monitor) {
fLastError = null;
List<IContextInformation> result = new ArrayList<IContextInformation>();
List descriptors = new ArrayList(fRegistry.getProposalComputerDescriptors(partition));
for (Iterator it = descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this) {
result.addAll(desc.computeContextInformation(context, monitor));
}
if (fLastError == null) {
fLastError = desc.getErrorMessage();
}
}
return result;
}
/**
* Returns the name of the described extension without mnemonic hint in order to be displayed in a
* message.
*
* @return Returns the name
*/
public String getDisplayName() {
return LegacyActionTools.removeMnemonics(fName);
}
/**
* Returns the error message from the computers in this category.
*
* @return the error message from the computers in this category
*/
public String getErrorMessage() {
return fLastError;
}
/**
* Returns the identifier of the described extension.
*
* @return Returns the id
*/
public String getId() {
return fId;
}
/**
* Returns the image descriptor of the described category.
*
* @return the image descriptor of the described category
*/
public ImageDescriptor getImageDescriptor() {
return fImage;
}
/**
* Returns the name of the described extension.
*
* @return Returns the name
*/
public String getName() {
return fName;
}
/**
* @return sortOrder
*/
public int getSortOrder() {
return fSortOrder;
}
/**
* Returns <code>true</code> if the category contains any computers, <code>false</code> otherwise.
*
* @return <code>true</code> if the category contains any computers, <code>false</code> otherwise
*/
public boolean hasComputers() {
List descriptors = fRegistry.getProposalComputerDescriptors();
for (Iterator it = descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this) {
return true;
}
}
return false;
}
/**
* Returns <code>true</code> if the category contains any computers in the given partition,
* <code>false</code> otherwise.
*
* @param partition the partition
* @return <code>true</code> if the category contains any computers, <code>false</code> otherwise
*/
public boolean hasComputers(String partition) {
List descriptors = fRegistry.getProposalComputerDescriptors(partition);
for (Iterator it = descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this) {
return true;
}
}
return false;
}
public boolean isEnabled() {
return fIsEnabled;
}
/**
* @return included
*/
public boolean isIncluded() {
return fIsIncluded;
}
/**
* Returns the enablement state of the category.
*
* @return the enablement state of the category
*/
public boolean isSeparateCommand() {
return fIsSeparateCommand;
}
/**
* Notifies the computers in this category of a proposal computation session end.
*/
public void sessionEnded() {
List descriptors = new ArrayList(fRegistry.getProposalComputerDescriptors());
for (Iterator it = descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this) {
desc.sessionEnded();
}
if (fLastError == null) {
fLastError = desc.getErrorMessage();
}
}
}
/**
* Notifies the computers in this category of a proposal computation session start.
*/
public void sessionStarted() {
List descriptors = new ArrayList(fRegistry.getProposalComputerDescriptors());
for (Iterator it = descriptors.iterator(); it.hasNext();) {
CompletionProposalComputerDescriptor desc = (CompletionProposalComputerDescriptor) it.next();
if (desc.getCategory() == this) {
desc.sessionStarted();
}
if (fLastError == null) {
fLastError = desc.getErrorMessage();
}
}
}
public void setEnabled(boolean isEnabled) {
fIsEnabled = isEnabled;
}
/**
* @param included the included
*/
public void setIncluded(boolean included) {
fIsIncluded = included;
}
/**
* Sets the separate command state of the category.
*
* @param enabled the new enabled state.
*/
public void setSeparateCommand(boolean enabled) {
fIsSeparateCommand = enabled;
}
/**
* @param sortOrder the sortOrder
*/
public void setSortOrder(int sortOrder) {
fSortOrder = sortOrder;
}
/**
* Checks an element that must be defined according to the extension point schema. Throws an
* <code>InvalidRegistryObjectException</code> if <code>obj</code> is <code>null</code>.
*/
private void checkNotNull(Object obj, String attribute) throws InvalidRegistryObjectException {
if (obj == null) {
Object[] args = {getId(), fElement.getContributor().getName(), attribute};
String message = Messages.format(
DartTextMessages.CompletionProposalComputerDescriptor_illegal_attribute_message,
args);
IStatus status = new Status(
IStatus.WARNING,
DartToolsPlugin.getPluginId(),
IStatus.OK,
message,
null);
DartToolsPlugin.log(status);
throw new InvalidRegistryObjectException();
}
}
private Bundle getBundle() {
String namespace = fElement.getDeclaringExtension().getContributor().getName();
Bundle bundle = Platform.getBundle(namespace);
return bundle;
}
}