| /******************************************************************************* |
| * Copyright (c) 2000, 2018 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.dltk.ui.dialogs; |
| |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| import org.eclipse.core.runtime.jobs.IJobManager; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.dltk.ast.Modifiers; |
| import org.eclipse.dltk.core.Flags; |
| import org.eclipse.dltk.core.IDLTKLanguageToolkit; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IProjectFragment; |
| import org.eclipse.dltk.core.IType; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.core.WorkingCopyOwner; |
| import org.eclipse.dltk.core.index2.search.ModelAccess; |
| import org.eclipse.dltk.core.search.IDLTKSearchConstants; |
| import org.eclipse.dltk.core.search.IDLTKSearchScope; |
| import org.eclipse.dltk.core.search.NopTypeNameRequestor; |
| import org.eclipse.dltk.core.search.SearchEngine; |
| import org.eclipse.dltk.core.search.TypeNameMatch; |
| import org.eclipse.dltk.core.search.TypeNameMatchRequestor; |
| import org.eclipse.dltk.internal.core.search.DLTKSearchTypeNameMatch; |
| import org.eclipse.dltk.internal.corext.util.Messages; |
| import org.eclipse.dltk.internal.corext.util.OpenTypeHistory; |
| import org.eclipse.dltk.internal.corext.util.Strings; |
| import org.eclipse.dltk.internal.corext.util.TypeFilter; |
| import org.eclipse.dltk.internal.corext.util.TypeInfoRequestorAdapter; |
| import org.eclipse.dltk.internal.ui.DLTKUIMessages; |
| import org.eclipse.dltk.internal.ui.dialogs.TextFieldNavigationHandler; |
| import org.eclipse.dltk.internal.ui.search.DLTKSearchScopeFactory; |
| import org.eclipse.dltk.internal.ui.util.TypeNameMatchLabelProvider; |
| import org.eclipse.dltk.internal.ui.workingsets.WorkingSetFilterActionGroup; |
| import org.eclipse.dltk.launching.IInterpreterInstall; |
| import org.eclipse.dltk.launching.IInterpreterInstallType; |
| import org.eclipse.dltk.launching.LibraryLocation; |
| import org.eclipse.dltk.launching.ScriptRuntime; |
| import org.eclipse.dltk.ui.DLTKUILanguageManager; |
| import org.eclipse.dltk.ui.DLTKUIPlugin; |
| import org.eclipse.dltk.ui.IDLTKUILanguageToolkit; |
| import org.eclipse.dltk.ui.ScriptElementImageProvider; |
| import org.eclipse.dltk.ui.ScriptElementLabels; |
| import org.eclipse.dltk.ui.util.ExceptionHandler; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.operation.IRunnableContext; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.text.ITextSelection; |
| import org.eclipse.jface.viewers.ILabelDecorator; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.jface.viewers.LabelProviderChangedEvent; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.IWorkingSet; |
| import org.eclipse.ui.WorkbenchException; |
| import org.eclipse.ui.XMLMemento; |
| import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog; |
| import org.eclipse.ui.dialogs.ISelectionStatusValidator; |
| import org.eclipse.ui.dialogs.SearchPattern; |
| |
| /** |
| * Shows a list of Java types to the user with a text entry field for a string |
| * pattern used to filter the list of types. |
| * |
| * @since 3.3 |
| */ |
| public class FilteredTypesSelectionDialog extends FilteredItemsSelectionDialog |
| implements ITypeSelectionComponent { |
| |
| private static final String DIALOG_SETTINGS = "org.eclipse.jdt.internal.ui.dialogs.FilteredTypesSelectionDialog"; //$NON-NLS-1$ |
| |
| private static final String WORKINGS_SET_SETTINGS = "WorkingSet"; //$NON-NLS-1$ |
| |
| private WorkingSetFilterActionGroup fFilterActionGroup; |
| |
| private final TypeItemLabelProvider fTypeInfoLabelProvider; |
| |
| private String fTitle; |
| |
| private IDLTKSearchScope fSearchScope; |
| |
| private boolean fAllowScopeSwitching; |
| |
| private final int fElementKinds; |
| |
| private final ITypeInfoFilterExtension fFilterExtension; |
| |
| private final TypeSelectionExtension fExtension; |
| |
| private ISelectionStatusValidator fValidator; |
| |
| private final TypeInfoUtil fTypeInfoUtil; |
| |
| private static boolean fgFirstTime = true; |
| |
| private final TypeItemsComparator fTypeItemsComparator; |
| |
| private int fTypeFilterVersion = 0; |
| |
| private IDLTKLanguageToolkit fToolkit; |
| |
| /** |
| * Creates new FilteredTypesSelectionDialog instance |
| * |
| * @param parent |
| * shell to parent the dialog on |
| * @param multi |
| * <code>true</code> if multiple selection is |
| * allowed |
| * @param context |
| * context used to execute long-running operations |
| * associated with this dialog |
| * @param scope |
| * scope used when searching for types |
| * @param elementKinds |
| * flags defining nature of searched elements; the |
| * only valid values are: |
| * <code>IJavaSearchConstants.TYPE</code> |
| * <code>IJavaSearchConstants.ANNOTATION_TYPE</code> |
| * <code>IJavaSearchConstants.INTERFACE</code> |
| * <code>IJavaSearchConstants.ENUM</code> |
| * <code>IJavaSearchConstants.CLASS_AND_INTERFACE</code> |
| * <code>IJavaSearchConstants.CLASS_AND_ENUM</code>. |
| * Please note that the bitwise OR combination of |
| * the elementary constants is not supported. |
| */ |
| public FilteredTypesSelectionDialog(Shell parent, boolean multi, |
| IRunnableContext context, IDLTKSearchScope scope, int elementKinds, |
| IDLTKLanguageToolkit toolkit) { |
| this(parent, multi, context, scope, elementKinds, null, toolkit); |
| } |
| |
| /** |
| * Creates new FilteredTypesSelectionDialog instance. |
| * |
| * @param shell |
| * shell to parent the dialog on |
| * @param multi |
| * <code>true</code> if multiple selection is |
| * allowed |
| * @param context |
| * context used to execute long-running operations |
| * associated with this dialog |
| * @param scope |
| * scope used when searching for types. If the scope |
| * is <code>null</code>, then workspace is scope is |
| * used as default, and the user can choose a |
| * working set as scope. |
| * @param elementKinds |
| * flags defining nature of searched elements; the |
| * only valid values are: |
| * <code>IJavaSearchConstants.TYPE</code> |
| * <code>IJavaSearchConstants.ANNOTATION_TYPE</code> |
| * <code>IJavaSearchConstants.INTERFACE</code> |
| * <code>IJavaSearchConstants.ENUM</code> |
| * <code>IJavaSearchConstants.CLASS_AND_INTERFACE</code> |
| * <code>IJavaSearchConstants.CLASS_AND_ENUM</code>. |
| * Please note that the bitwise OR combination of |
| * the elementary constants is not supported. |
| * @param extension |
| * an extension of the standard type selection |
| * dialog; See {@link TypeSelectionExtension} |
| */ |
| public FilteredTypesSelectionDialog(Shell shell, boolean multi, |
| IRunnableContext context, IDLTKSearchScope scope, int elementKinds, |
| TypeSelectionExtension extension, IDLTKLanguageToolkit toolkit) { |
| super(shell, multi); |
| |
| this.fToolkit = toolkit; |
| |
| setSelectionHistory(new TypeSelectionHistory()); |
| |
| if (scope == null) { |
| fAllowScopeSwitching = true; |
| scope = SearchEngine.createWorkspaceScope(toolkit); |
| } |
| // PlatformUI.getWorkbench().getHelpSystem().setHelp(shell, |
| // IJavaHelpContextIds.TYPE_SELECTION_DIALOG2); |
| |
| fElementKinds = elementKinds; |
| fExtension = extension; |
| fFilterExtension = (extension == null) ? null |
| : extension.getFilterExtension(); |
| fSearchScope = scope; |
| |
| if (extension != null) { |
| fValidator = extension.getSelectionValidator(); |
| } |
| |
| fTypeInfoUtil = new TypeInfoUtil( |
| extension != null ? extension.getImageProvider() : null); |
| |
| fTypeInfoLabelProvider = new TypeItemLabelProvider(); |
| |
| setListLabelProvider(fTypeInfoLabelProvider); |
| setListSelectionLabelDecorator(fTypeInfoLabelProvider); |
| setDetailsLabelProvider( |
| new TypeItemDetailsLabelProvider(fTypeInfoUtil)); |
| |
| fTypeItemsComparator = new TypeItemsComparator(); |
| } |
| |
| @Override |
| public void setTitle(String title) { |
| super.setTitle(title); |
| fTitle = title; |
| } |
| |
| /** |
| * Adds or replaces subtitle of the dialog |
| * |
| * @param text |
| * the new subtitle for this dialog |
| */ |
| private void setSubtitle(String text) { |
| if (text == null || text.length() == 0) { |
| getShell().setText(fTitle); |
| } else { |
| getShell().setText(Messages.format( |
| DLTKUIMessages.FilteredTypeSelectionDialog_titleFormat, |
| fTitle, text)); |
| } |
| } |
| |
| @Override |
| protected IDialogSettings getDialogSettings() { |
| IDialogSettings settings = DLTKUIPlugin.getDefault().getDialogSettings() |
| .getSection(DIALOG_SETTINGS); |
| |
| if (settings == null) { |
| settings = DLTKUIPlugin.getDefault().getDialogSettings() |
| .addNewSection(DIALOG_SETTINGS); |
| } |
| |
| return settings; |
| } |
| |
| @Override |
| protected void storeDialog(IDialogSettings settings) { |
| super.storeDialog(settings); |
| |
| if (fFilterActionGroup != null) { |
| XMLMemento memento = XMLMemento.createWriteRoot("workingSet"); //$NON-NLS-1$ |
| fFilterActionGroup.saveState(memento); |
| fFilterActionGroup.dispose(); |
| StringWriter writer = new StringWriter(); |
| try { |
| memento.save(writer); |
| settings.put(WORKINGS_SET_SETTINGS, |
| writer.getBuffer().toString()); |
| } catch (IOException e) { |
| // don't do anything. Simply don't store the settings |
| DLTKUIPlugin.log(e); |
| } |
| } |
| } |
| |
| @Override |
| protected void restoreDialog(IDialogSettings settings) { |
| super.restoreDialog(settings); |
| |
| fTypeInfoLabelProvider.setContainerInfo(true); |
| |
| if (fAllowScopeSwitching) { |
| String setting = settings.get(WORKINGS_SET_SETTINGS); |
| if (setting != null) { |
| try { |
| IMemento memento = XMLMemento |
| .createReadRoot(new StringReader(setting)); |
| fFilterActionGroup.restoreState(memento); |
| } catch (WorkbenchException e) { |
| // don't do anything. Simply don't restore the settings |
| DLTKUIPlugin.log(e); |
| } |
| } |
| IWorkingSet ws = fFilterActionGroup.getWorkingSet(); |
| if (ws == null || (ws.isAggregateWorkingSet() && ws.isEmpty())) { |
| setSearchScope(SearchEngine.createWorkspaceScope(fToolkit)); |
| setSubtitle(null); |
| } else { |
| setSearchScope(DLTKSearchScopeFactory.getInstance() |
| .createSearchScope(ws, true, fToolkit)); |
| setSubtitle(ws.getLabel()); |
| } |
| } |
| |
| // TypeNameMatch[] types = OpenTypeHistory.getInstance().getTypeInfos(); |
| // |
| // for (int i = 0; i < types.length; i++) { |
| // TypeNameMatch type = types[i]; |
| // accessedHistoryItem(type); |
| // } |
| } |
| |
| @Override |
| protected void fillViewMenu(IMenuManager menuManager) { |
| super.fillViewMenu(menuManager); |
| |
| if (fAllowScopeSwitching) { |
| fFilterActionGroup = new WorkingSetFilterActionGroup(getShell(), |
| DLTKUIPlugin.getActivePage(), event -> { |
| IWorkingSet ws = (IWorkingSet) event.getNewValue(); |
| if (ws == null || (ws.isAggregateWorkingSet() |
| && ws.isEmpty())) { |
| setSearchScope(SearchEngine |
| .createWorkspaceScope(fToolkit)); |
| setSubtitle(null); |
| } else { |
| setSearchScope(DLTKSearchScopeFactory.getInstance() |
| .createSearchScope(ws, true, fToolkit)); |
| setSubtitle(ws.getLabel()); |
| } |
| |
| applyFilter(); |
| }); |
| fFilterActionGroup.fillViewMenu(menuManager); |
| } |
| |
| // menuManager.add(new Separator()); |
| // menuManager.add(new TypeFiltersPreferencesAction()); |
| } |
| |
| @Override |
| protected Control createExtendedContentArea(Composite parent) { |
| Control addition = null; |
| |
| if (fExtension != null) { |
| |
| addition = fExtension.createContentArea(parent); |
| if (addition != null) { |
| GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| gd.horizontalSpan = 2; |
| addition.setLayoutData(gd); |
| |
| } |
| |
| fExtension.initialize(this); |
| } |
| |
| return addition; |
| } |
| |
| @Override |
| protected void setResult(List newResult) { |
| |
| List resultToReturn = new ArrayList(); |
| |
| for (int i = 0; i < newResult.size(); i++) { |
| if (newResult.get(i) instanceof TypeNameMatch) { |
| IType type = ((TypeNameMatch) newResult.get(i)).getType(); |
| if (type.exists()) { |
| // items are added to history in the |
| // org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#computeResult() |
| // method |
| resultToReturn.add(type); |
| } else { |
| TypeNameMatch typeInfo = (TypeNameMatch) newResult.get(i); |
| IProjectFragment root = typeInfo.getProjectFragment(); |
| IDLTKUILanguageToolkit uiToolkit = DLTKUILanguageManager |
| .getLanguageToolkit(fToolkit.getNatureId()); |
| ScriptElementLabels labels = uiToolkit |
| .getScriptElementLabels(); |
| String containerName = labels.getElementLabel(root, |
| ScriptElementLabels.ALL_FULLY_QUALIFIED); |
| String message = Messages.format( |
| DLTKUIMessages.FilteredTypesSelectionDialog_dialogMessage, |
| typeInfo.getFullyQualifiedName(), containerName); |
| MessageDialog.openError(getShell(), fTitle, message); |
| getSelectionHistory().remove(typeInfo); |
| } |
| } |
| } |
| |
| super.setResult(resultToReturn); |
| } |
| |
| @Override |
| public void create() { |
| super.create(); |
| Control patternControl = getPatternControl(); |
| if (patternControl instanceof Text) { |
| TextFieldNavigationHandler.install((Text) patternControl); |
| } |
| } |
| |
| @Override |
| public int open() { |
| if (getInitialPattern() == null) { |
| IWorkbenchWindow window = DLTKUIPlugin.getActiveWorkbenchWindow(); |
| if (window != null) { |
| ISelection selection = window.getSelectionService() |
| .getSelection(); |
| if (selection instanceof ITextSelection) { |
| String text = ((ITextSelection) selection).getText(); |
| if (text != null) { |
| text = text.trim(); |
| if (text.length() > 0) { |
| setInitialPattern(text, FULL_SELECTION); |
| } |
| } |
| } |
| } |
| } |
| return super.open(); |
| } |
| |
| /** |
| * Sets a new validator. |
| * |
| * @param validator |
| * the new validator |
| */ |
| public void setValidator(ISelectionStatusValidator validator) { |
| fValidator = validator; |
| } |
| |
| @Override |
| protected ItemsFilter createFilter() { |
| return new TypeItemsFilter(fSearchScope, fElementKinds, |
| fFilterExtension); |
| } |
| |
| @Override |
| protected Control createContents(Composite parent) { |
| Control contents = super.createContents(parent); |
| // if (ColoredViewersManager.showColoredLabels()) { |
| // if (contents instanceof Composite) { |
| // Table listControl = findTableControl((Composite) contents); |
| // if (listControl != null) { |
| // installOwnerDraw(listControl); |
| // } |
| // } |
| // } |
| return contents; |
| } |
| |
| // private void installOwnerDraw(Table tableControl) { |
| // new OwnerDrawSupport(tableControl) { // installs the owner draw |
| // // listeners |
| // public ColoredString getColoredLabel(Item item) { |
| // String text = item.getText(); |
| // ColoredString str = new ColoredString(text); |
| // int index = text.indexOf('-'); |
| // if (index != -1) { |
| // str.colorize(index, str.length() - index, |
| // ColoredJavaElementLabels.QUALIFIER_STYLE); |
| // } |
| // return str; |
| // } |
| // |
| // public Color getColor(String foregroundColorName, Display display) { |
| // return PlatformUI.getWorkbench().getThemeManager() |
| // .getCurrentTheme().getColorRegistry().get( |
| // foregroundColorName); |
| // } |
| // }; |
| // } |
| // |
| // private Table findTableControl(Composite composite) { |
| // Control[] children = composite.getChildren(); |
| // for (int i = 0; i < children.length; i++) { |
| // Control curr = children[i]; |
| // if (curr instanceof Table) { |
| // return (Table) curr; |
| // } else if (curr instanceof Composite) { |
| // Table res = findTableControl((Composite) curr); |
| // if (res != null) { |
| // return res; |
| // } |
| // } |
| // } |
| // return null; |
| // } |
| |
| @Override |
| protected void fillContentProvider(AbstractContentProvider provider, |
| ItemsFilter itemsFilter, IProgressMonitor progressMonitor) |
| throws CoreException { |
| TypeItemsFilter typeSearchFilter = (TypeItemsFilter) itemsFilter; |
| TypeSearchRequestor requestor = new TypeSearchRequestor(provider, |
| typeSearchFilter); |
| String typePattern = itemsFilter.getPattern(); |
| |
| progressMonitor.setTaskName( |
| DLTKUIMessages.FilteredTypesSelectionDialog_searchJob_taskName); |
| |
| IType[] types = new ModelAccess().findTypes(typePattern, |
| ModelAccess.convertSearchRule(itemsFilter.getMatchRule()), 0, |
| Modifiers.AccNameSpace, typeSearchFilter.getSearchScope(), |
| progressMonitor); |
| if (types != null) { |
| for (IType type : types) { |
| requestor.acceptTypeNameMatch( |
| new DLTKSearchTypeNameMatch(type, type.getFlags())); |
| } |
| } else { |
| |
| SearchEngine engine = new SearchEngine((WorkingCopyOwner) null); |
| String packPattern = typeSearchFilter.getPackagePattern(); |
| |
| /* |
| * Setting the filter into match everything mode avoids filtering |
| * twice by the same pattern (the search engine only provides |
| * filtered matches). For the case when the pattern is a camel case |
| * pattern with a terminator, the filter is not set to match |
| * everything mode because jdt.core's SearchPattern does not support |
| * that case. |
| */ |
| int matchRule = typeSearchFilter.getMatchRule(); |
| if (matchRule == SearchPattern.RULE_CAMELCASE_MATCH) { |
| // If the pattern is empty, the RULE_BLANK_MATCH will be chosen, |
| // so |
| // we don't have to check the pattern length |
| char lastChar = typePattern.charAt(typePattern.length() - 1); |
| |
| if (lastChar == '<' || lastChar == ' ') { |
| typePattern = typePattern.substring(0, |
| typePattern.length() - 1); |
| } else { |
| typeSearchFilter.setMatchEverythingMode(true); |
| } |
| } else { |
| typeSearchFilter.setMatchEverythingMode(true); |
| } |
| |
| try { |
| engine.searchAllTypeNames( |
| packPattern == null ? null : packPattern.toCharArray(), |
| typeSearchFilter.getPackageFlags(), // TODO: |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=176017 |
| typePattern.toCharArray(), matchRule, // TODO: |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=176017 |
| typeSearchFilter.getElementKind(), |
| typeSearchFilter.getSearchScope(), requestor, |
| IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, |
| progressMonitor); |
| } finally { |
| typeSearchFilter.setMatchEverythingMode(false); |
| } |
| } |
| } |
| |
| @Override |
| protected Comparator getItemsComparator() { |
| return fTypeItemsComparator; |
| } |
| |
| @Override |
| public String getElementName(Object item) { |
| TypeNameMatch type = (TypeNameMatch) item; |
| return fTypeInfoUtil.getText(type); |
| } |
| |
| @Override |
| protected IStatus validateItem(Object item) { |
| |
| if (item == null) |
| return new Status(IStatus.ERROR, DLTKUIPlugin.getPluginId(), |
| IStatus.ERROR, "", null); //$NON-NLS-1$ |
| |
| if (fValidator != null) { |
| IType type = ((TypeNameMatch) item).getType(); |
| if (!type.exists()) |
| return new Status(IStatus.ERROR, DLTKUIPlugin.getPluginId(), |
| IStatus.ERROR, |
| Messages.format( |
| DLTKUIMessages.FilteredTypesSelectionDialog_error_type_doesnot_exist, |
| ((TypeNameMatch) item).getFullyQualifiedName()), |
| null); |
| Object[] elements = { type }; |
| return fValidator.validate(elements); |
| } |
| return new Status(IStatus.OK, DLTKUIPlugin.getPluginId(), IStatus.OK, |
| "", null); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Sets search scope used when searching for types. |
| * |
| * @param scope |
| * the new scope |
| */ |
| private void setSearchScope(IDLTKSearchScope scope) { |
| fSearchScope = scope; |
| } |
| |
| /* |
| * We only have to ensure history consistency here since the search engine |
| * takes care of working copies. |
| */ |
| private static class ConsistencyRunnable implements IRunnableWithProgress { |
| private IDLTKUILanguageToolkit tookit; |
| |
| ConsistencyRunnable(IDLTKLanguageToolkit toolkit) { |
| this.tookit = DLTKUILanguageManager |
| .getLanguageToolkit(toolkit.getNatureId()); |
| } |
| |
| @Override |
| public void run(IProgressMonitor monitor) |
| throws InvocationTargetException, InterruptedException { |
| if (fgFirstTime) { |
| // Join the initialize after load job. |
| IJobManager manager = Job.getJobManager(); |
| manager.join(DLTKUIPlugin.PLUGIN_ID, monitor); |
| } |
| OpenTypeHistory history = OpenTypeHistory.getInstance(tookit); |
| if (fgFirstTime || history.isEmpty()) { |
| if (history.needConsistencyCheck()) { |
| monitor.beginTask( |
| DLTKUIMessages.TypeSelectionDialog_progress_consistency, |
| 100); |
| refreshSearchIndices(new SubProgressMonitor(monitor, 90)); |
| history.checkConsistency( |
| new SubProgressMonitor(monitor, 10)); |
| } else { |
| refreshSearchIndices(monitor); |
| } |
| monitor.done(); |
| fgFirstTime = false; |
| } else { |
| history.checkConsistency(monitor); |
| } |
| } |
| |
| public static boolean needsExecution(IDLTKLanguageToolkit toolkit) { |
| OpenTypeHistory history = OpenTypeHistory |
| .getInstance(DLTKUILanguageManager |
| .getLanguageToolkit(toolkit.getNatureId())); |
| return fgFirstTime || history.isEmpty() |
| || history.needConsistencyCheck(); |
| } |
| |
| private void refreshSearchIndices(IProgressMonitor monitor) |
| throws InvocationTargetException { |
| try { |
| new SearchEngine().searchAllTypeNames(null, 0, |
| // make sure we search a concrete name. This is faster |
| // according to Kent |
| "_______________".toCharArray(), //$NON-NLS-1$ |
| SearchPattern.RULE_EXACT_MATCH |
| | SearchPattern.RULE_CASE_SENSITIVE, |
| IDLTKSearchConstants.TYPE, |
| SearchEngine |
| .createWorkspaceScope(tookit.getCoreToolkit()), |
| new NopTypeNameRequestor(), |
| IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, |
| monitor); |
| } catch (ModelException e) { |
| throw new InvocationTargetException(e); |
| } |
| } |
| } |
| |
| @Override |
| public void reloadCache(boolean checkDuplicates, IProgressMonitor monitor) { |
| IProgressMonitor remainingMonitor; |
| if (ConsistencyRunnable.needsExecution(fToolkit)) { |
| monitor.beginTask( |
| DLTKUIMessages.TypeSelectionDialog_progress_consistency, |
| 10); |
| try { |
| ConsistencyRunnable runnable = new ConsistencyRunnable( |
| fToolkit); |
| runnable.run(new SubProgressMonitor(monitor, 1)); |
| } catch (InvocationTargetException e) { |
| ExceptionHandler.handle(e, |
| DLTKUIMessages.TypeSelectionDialog_error3Title, |
| DLTKUIMessages.TypeSelectionDialog_error3Message); |
| close(); |
| return; |
| } catch (InterruptedException e) { |
| // cancelled by user |
| close(); |
| return; |
| } |
| remainingMonitor = new SubProgressMonitor(monitor, 9); |
| } else { |
| remainingMonitor = monitor; |
| } |
| super.reloadCache(checkDuplicates, remainingMonitor); |
| monitor.done(); |
| } |
| |
| @Override |
| public void triggerSearch() { |
| fTypeFilterVersion++; |
| applyFilter(); |
| } |
| |
| /** |
| * A <code>LabelProvider</code> for (the table of) types. |
| */ |
| private class TypeItemLabelProvider extends LabelProvider |
| implements ILabelDecorator { |
| |
| private boolean fContainerInfo; |
| |
| /** |
| * Construct a new <code>TypeItemLabelProvider</code>. F |
| */ |
| public TypeItemLabelProvider() { |
| |
| } |
| |
| public void setContainerInfo(boolean containerInfo) { |
| fContainerInfo = containerInfo; |
| fireLabelProviderChanged(new LabelProviderChangedEvent(this)); |
| } |
| |
| @Override |
| public Image getImage(Object element) { |
| if (!(element instanceof TypeNameMatch)) { |
| return super.getImage(element); |
| } |
| |
| TypeNameMatch type = (TypeNameMatch) element; |
| |
| ImageDescriptor iD = ScriptElementImageProvider |
| .getTypeImageDescriptor(type.getModifiers(), false); |
| |
| return DLTKUIPlugin.getImageDescriptorRegistry().get(iD); |
| } |
| |
| @Override |
| public String getText(Object element) { |
| if (!(element instanceof TypeNameMatch)) { |
| return super.getText(element); |
| } |
| |
| if (fContainerInfo && isDuplicateElement(element)) { |
| return fTypeInfoUtil |
| .getFullyQualifiedText((TypeNameMatch) element); |
| } |
| |
| if (!fContainerInfo && isDuplicateElement(element)) { |
| return fTypeInfoUtil.getQualifiedText((TypeNameMatch) element); |
| } |
| |
| return fTypeInfoUtil.getText(element); |
| } |
| |
| @Override |
| public Image decorateImage(Image image, Object element) { |
| return null; |
| } |
| |
| @Override |
| public String decorateText(String text, Object element) { |
| if (!(element instanceof TypeNameMatch)) { |
| return null; |
| } |
| |
| if (fContainerInfo && isDuplicateElement(element)) { |
| return fTypeInfoUtil |
| .getFullyQualifiedText((TypeNameMatch) element); |
| } |
| |
| return fTypeInfoUtil.getQualifiedText((TypeNameMatch) element); |
| } |
| |
| } |
| |
| /** |
| * A <code>LabelProvider</code> for the label showing type details. |
| */ |
| private class TypeItemDetailsLabelProvider extends LabelProvider { |
| |
| private TypeNameMatchLabelProvider fLabelProvider; |
| |
| private final TypeInfoUtil fTypeInfoUtil; |
| |
| public TypeItemDetailsLabelProvider(TypeInfoUtil typeInfoUtil) { |
| fTypeInfoUtil = typeInfoUtil; |
| |
| fLabelProvider = new TypeNameMatchLabelProvider( |
| TypeNameMatchLabelProvider.SHOW_TYPE_ONLY |
| + TypeNameMatchLabelProvider.SHOW_FULLYQUALIFIED, |
| DLTKUILanguageManager |
| .getLanguageToolkit(fToolkit.getNatureId())); |
| } |
| |
| @Override |
| public Image getImage(Object element) { |
| if (element instanceof TypeNameMatch) { |
| return fLabelProvider.getImage((element)); |
| } |
| |
| return super.getImage(element); |
| } |
| |
| @Override |
| public String getText(Object element) { |
| if (element instanceof TypeNameMatch) { |
| return fTypeInfoUtil |
| .getQualificationText((TypeNameMatch) element); |
| } |
| |
| return super.getText(element); |
| } |
| } |
| |
| private class TypeInfoUtil { |
| |
| private final ITypeInfoImageProvider fProviderExtension; |
| |
| private final TypeInfoRequestorAdapter fAdapter = new TypeInfoRequestorAdapter(); |
| |
| private final Map fLib2Name = new HashMap(); |
| |
| private final String[] fInstallLocations; |
| |
| private final String[] fVMNames; |
| |
| private boolean fFullyQualifyDuplicates; |
| |
| public TypeInfoUtil(ITypeInfoImageProvider extension) { |
| fProviderExtension = extension; |
| List<String> locations = new ArrayList<>(); |
| List<String> labels = new ArrayList<>(); |
| IInterpreterInstallType[] installs = ScriptRuntime |
| .getInterpreterInstallTypes(fToolkit.getNatureId()); |
| for (int i = 0; i < installs.length; i++) { |
| processInterpreterInstallType(installs[i], locations, labels); |
| } |
| fInstallLocations = locations.toArray(new String[locations.size()]); |
| fVMNames = labels.toArray(new String[labels.size()]); |
| |
| } |
| |
| private void processInterpreterInstallType( |
| IInterpreterInstallType installType, List<String> locations, |
| List<String> labels) { |
| if (installType != null) { |
| IInterpreterInstall[] installs = installType |
| .getInterpreterInstalls(); |
| boolean isMac = Platform.OS_MACOSX.equals(Platform.getOS()); |
| final String HOME_SUFFIX = "/Home"; //$NON-NLS-1$ |
| for (int i = 0; i < installs.length; i++) { |
| String label = getFormattedLabel(installs[i].getName()); |
| LibraryLocation[] libLocations = installs[i] |
| .getLibraryLocations(); |
| if (libLocations != null) { |
| processLibraryLocation(libLocations, label); |
| } else { |
| String filePath = installs[i].getInstallLocation() |
| .toOSString(); |
| if (filePath != null) { |
| // on MacOS X install locations end in an additional |
| // "/Home" segment; remove it |
| if (isMac && filePath.endsWith(HOME_SUFFIX)) |
| filePath = filePath.substring(0, |
| filePath.length() - HOME_SUFFIX.length() |
| + 1); |
| locations.add(filePath); |
| labels.add(label); |
| } |
| } |
| } |
| } |
| } |
| |
| private void processLibraryLocation(LibraryLocation[] libLocations, |
| String label) { |
| for (int l = 0; l < libLocations.length; l++) { |
| LibraryLocation location = libLocations[l]; |
| fLib2Name.put(location.getLibraryPath().toOSString(), label); |
| } |
| } |
| |
| private String getFormattedLabel(String name) { |
| return Messages.format( |
| DLTKUIMessages.FilteredTypesSelectionDialog_library_name_format, |
| name); |
| } |
| |
| public String getText(Object element) { |
| return ((TypeNameMatch) element).getSimpleTypeName(); |
| } |
| |
| public String getQualifiedText(TypeNameMatch type) { |
| StringBuffer result = new StringBuffer(); |
| result.append(type.getSimpleTypeName()); |
| // String containerName = type.getTypeContainerName(); |
| // result.append(ScriptElementLabels.CONCAT_STRING); |
| // if (containerName.length() > 0) { |
| // result.append(containerName); |
| // } else { |
| // result.append(""); |
| // } |
| return result.toString(); |
| } |
| |
| public String getFullyQualifiedText(TypeNameMatch type) { |
| StringBuffer result = new StringBuffer(); |
| result.append(type.getSimpleTypeName()); |
| IType stype = type.getType(); |
| if (stype.getParent().getElementType() == IModelElement.TYPE) { |
| result.append(ScriptElementLabels.CONCAT_STRING); |
| IType parent = (IType) stype.getParent(); |
| result.append(parent.getTypeQualifiedName(".")); //$NON-NLS-1$ |
| } |
| // String containerName = type.getTypeContainerName(); |
| // if (containerName.length() > 0) { |
| // result.append(ScriptElementLabels.CONCAT_STRING); |
| // result.append(containerName); |
| // } |
| // result.append(ScriptElementLabels.CONCAT_STRING); |
| // result.append(getContainerName(type)); |
| return result.toString(); |
| } |
| |
| public String getQualificationText(TypeNameMatch type) { |
| StringBuffer result = new StringBuffer(); |
| result.append(type.getType().getTypeQualifiedName(".")); //$NON-NLS-1$ |
| result.append(ScriptElementLabels.CONCAT_STRING); |
| result.append(getContainerName(type)); |
| return result.toString(); |
| } |
| |
| private String getContainerName(TypeNameMatch type) { |
| IProjectFragment root = type.getProjectFragment(); |
| if (root.isExternal()) { |
| String name = root.getPath().toOSString(); |
| for (int i = 0; i < fInstallLocations.length; i++) { |
| if (name.startsWith(fInstallLocations[i])) { |
| return fVMNames[i]; |
| } |
| } |
| String lib = (String) fLib2Name.get(name); |
| if (lib != null) |
| return lib; |
| } |
| StringBuffer buf = new StringBuffer(); |
| ScriptElementLabels labels = DLTKUILanguageManager |
| .getLanguageToolkit(fToolkit.getNatureId()) |
| .getScriptElementLabels(); |
| labels.getProjectFragmentLabel(root, |
| ScriptElementLabels.ROOT_QUALIFIED |
| | ScriptElementLabels.ROOT_VARIABLE, |
| buf); |
| return buf.toString(); |
| } |
| } |
| |
| /** |
| * Filters types using pattern, scope, element kind and filter extension. |
| */ |
| private class TypeItemsFilter extends ItemsFilter { |
| |
| private static final int TYPE_MODIFIERS = Flags.AccAnnotation |
| | Flags.AccInterface; |
| |
| private final IDLTKSearchScope fScope; |
| |
| private final boolean fIsWorkspaceScope; |
| |
| private final int fElemKind; |
| |
| private final ITypeInfoFilterExtension fFilterExt; |
| |
| private final TypeInfoRequestorAdapter fAdapter = new TypeInfoRequestorAdapter(); |
| |
| private SearchPattern fPackageMatcher; |
| |
| private boolean fMatchEverything = false; |
| |
| private final int fMyTypeFilterVersion = fTypeFilterVersion; |
| |
| /** |
| * Creates instance of TypeItemsFilter |
| * |
| * @param scope |
| * @param elementKind |
| * @param extension |
| */ |
| public TypeItemsFilter(IDLTKSearchScope scope, int elementKind, |
| ITypeInfoFilterExtension extension) { |
| super(new TypeSearchPattern()); |
| fScope = scope; |
| fIsWorkspaceScope = scope == null ? false |
| : scope.equals(SearchEngine.createWorkspaceScope(fToolkit)); |
| fElemKind = elementKind; |
| fFilterExt = extension; |
| String stringPackage = ((TypeSearchPattern) patternMatcher) |
| .getPackagePattern(); |
| if (stringPackage != null) { |
| fPackageMatcher = new SearchPattern(); |
| fPackageMatcher.setPattern(stringPackage); |
| } else { |
| fPackageMatcher = null; |
| } |
| } |
| |
| @Override |
| public boolean isSubFilter(ItemsFilter filter) { |
| if (!super.isSubFilter(filter)) |
| return false; |
| TypeItemsFilter typeItemsFilter = (TypeItemsFilter) filter; |
| if (fScope != typeItemsFilter.getSearchScope()) |
| return false; |
| if (fMyTypeFilterVersion != typeItemsFilter |
| .getMyTypeFilterVersion()) |
| return false; |
| return getPattern().indexOf('.', |
| filter.getPattern().length()) == -1; |
| } |
| |
| @Override |
| public boolean equalsFilter(ItemsFilter iFilter) { |
| if (!super.equalsFilter(iFilter)) |
| return false; |
| if (!(iFilter instanceof TypeItemsFilter)) |
| return false; |
| TypeItemsFilter typeItemsFilter = (TypeItemsFilter) iFilter; |
| if (fScope != typeItemsFilter.getSearchScope()) |
| return false; |
| if (fMyTypeFilterVersion != typeItemsFilter |
| .getMyTypeFilterVersion()) |
| return false; |
| return true; |
| } |
| |
| public int getElementKind() { |
| return fElemKind; |
| } |
| |
| public IDLTKSearchScope getSearchScope() { |
| return fScope; |
| } |
| |
| public int getMyTypeFilterVersion() { |
| return fMyTypeFilterVersion; |
| } |
| |
| public String getPackagePattern() { |
| if (fPackageMatcher == null) |
| return null; |
| return fPackageMatcher.getPattern(); |
| } |
| |
| public int getPackageFlags() { |
| if (fPackageMatcher == null) |
| return SearchPattern.RULE_EXACT_MATCH; |
| |
| return fPackageMatcher.getMatchRule(); |
| } |
| |
| public boolean matchesRawNamePattern(TypeNameMatch type) { |
| return Strings.startsWithIgnoreCase(type.getSimpleTypeName(), |
| getPattern()); |
| } |
| |
| public boolean matchesFilterExtension(TypeNameMatch type) { |
| if (fFilterExt == null) |
| return true; |
| fAdapter.setMatch(type); |
| return fFilterExt.select(fAdapter); |
| } |
| |
| private boolean matchesName(TypeNameMatch type) { |
| return matches(type.getSimpleTypeName()); |
| } |
| |
| private boolean matchesPackage(TypeNameMatch type) { |
| if (fPackageMatcher == null) |
| return true; |
| return fPackageMatcher.matches(type.getPackageName()); |
| } |
| |
| private boolean matchesScope(TypeNameMatch type) { |
| if (fIsWorkspaceScope) |
| return true; |
| return fScope.encloses(type.getType()); |
| |
| } |
| |
| private boolean matchesModifiers(TypeNameMatch type) { |
| if (fElemKind == IDLTKSearchConstants.TYPE) |
| return true; |
| int modifiers = type.getModifiers() & TYPE_MODIFIERS; |
| switch (fElemKind) { |
| case IDLTKSearchConstants.TYPE: |
| return modifiers == 0; |
| case IDLTKSearchConstants.ANNOTATION_TYPE: |
| // return Flags.isAnnotation(modifiers); |
| return false; |
| } |
| return false; |
| } |
| |
| /** |
| * Set filter to "match everything" mode. |
| * |
| * @param matchEverything |
| * if <code>true</code>, |
| * {@link #matchItem(Object)} always returns |
| * true. If <code>false</code>, the filter is |
| * enabled. |
| */ |
| public void setMatchEverythingMode(boolean matchEverything) { |
| this.fMatchEverything = matchEverything; |
| } |
| |
| @Override |
| public boolean isConsistentItem(Object item) { |
| return true; |
| } |
| |
| @Override |
| public boolean matchItem(Object item) { |
| |
| if (fMatchEverything) |
| return true; |
| |
| TypeNameMatch type = (TypeNameMatch) item; |
| if (!(matchesPackage(type) && matchesModifiers(type) |
| && matchesScope(type) && matchesFilterExtension(type))) |
| return false; |
| return matchesName(type); |
| } |
| |
| @Override |
| public boolean matchesRawNamePattern(Object item) { |
| TypeNameMatch type = (TypeNameMatch) item; |
| return matchesRawNamePattern(type); |
| } |
| |
| } |
| |
| /** |
| * Extends functionality of SearchPatterns |
| */ |
| private static class TypeSearchPattern extends SearchPattern { |
| |
| private String packagePattern; |
| |
| @Override |
| public void setPattern(String stringPattern) { |
| String pattern = stringPattern; |
| String packPattern = null; |
| int index = stringPattern.lastIndexOf("."); //$NON-NLS-1$ |
| if (index != -1) { |
| packPattern = evaluatePackagePattern( |
| stringPattern.substring(0, index)); |
| pattern = stringPattern.substring(index + 1); |
| if (pattern.length() == 0) |
| pattern = "**"; //$NON-NLS-1$ |
| } |
| super.setPattern(pattern); |
| packagePattern = packPattern; |
| } |
| |
| /* |
| * Transforms o.e.j to o.e.j |
| */ |
| private String evaluatePackagePattern(String s) { |
| StringBuffer buf = new StringBuffer(); |
| boolean hasWildCard = false; |
| for (int i = 0; i < s.length(); i++) { |
| char ch = s.charAt(i); |
| if (ch == '.') { |
| if (!hasWildCard) { |
| buf.append('*'); |
| } |
| hasWildCard = false; |
| } else if (ch == '*' || ch == '?') { |
| hasWildCard = true; |
| } |
| buf.append(ch); |
| } |
| if (!hasWildCard) { |
| buf.append('*'); |
| } |
| return buf.toString(); |
| } |
| |
| @Override |
| protected boolean isNameCharAllowed(char nameChar) { |
| return super.isNameCharAllowed(nameChar); |
| } |
| |
| @Override |
| protected boolean isPatternCharAllowed(char patternChar) { |
| return super.isPatternCharAllowed(patternChar); |
| } |
| |
| @Override |
| protected boolean isValidCamelCaseChar(char ch) { |
| return super.isValidCamelCaseChar(ch); |
| } |
| |
| /** |
| * @return the packagePattern |
| */ |
| public String getPackagePattern() { |
| return packagePattern; |
| } |
| |
| } |
| |
| /** |
| * A <code>TypeSearchRequestor</code> collects matches filtered using |
| * <code>TypeItemsFilter</code>. The attached content provider is filled on |
| * the basis of the collected entries (instances of |
| * <code>TypeNameMatch</code>). |
| */ |
| private class TypeSearchRequestor extends TypeNameMatchRequestor { |
| private volatile boolean fStop; |
| |
| private final AbstractContentProvider fContentProvider; |
| |
| private final TypeItemsFilter fTypeItemsFilter; |
| Set addedNames = new HashSet(); |
| |
| public TypeSearchRequestor(AbstractContentProvider contentProvider, |
| TypeItemsFilter typeItemsFilter) { |
| super(); |
| fContentProvider = contentProvider; |
| fTypeItemsFilter = typeItemsFilter; |
| } |
| |
| @Override |
| public void acceptTypeNameMatch(TypeNameMatch match) { |
| if (fStop) |
| return; |
| if (new TypeFilter(DLTKUILanguageManager |
| .getLanguageToolkit(fToolkit.getNatureId())) |
| .isFiltered(match)) |
| return; |
| if (!addedNames.contains(match.getTypeQualifiedName())) { |
| addedNames.add(match.getTypeQualifiedName()); |
| if (fTypeItemsFilter.matchesFilterExtension(match)) |
| fContentProvider.add(match, fTypeItemsFilter); |
| } |
| } |
| } |
| |
| /** |
| * Compares TypeItems is used during sorting |
| */ |
| private class TypeItemsComparator implements Comparator { |
| |
| private final Map fLib2Name = new HashMap(); |
| |
| private final String[] fInstallLocations; |
| |
| private final String[] fVMNames; |
| |
| /** |
| * Creates new instance of TypeItemsComparator |
| */ |
| public TypeItemsComparator() { |
| List<String> locations = new ArrayList<>(); |
| List<String> labels = new ArrayList<>(); |
| IInterpreterInstallType[] installs = ScriptRuntime |
| .getInterpreterInstallTypes(); |
| for (int i = 0; i < installs.length; i++) { |
| processVMInstallType(installs[i], locations, labels); |
| } |
| fInstallLocations = locations.toArray(new String[locations.size()]); |
| fVMNames = labels.toArray(new String[labels.size()]); |
| } |
| |
| private void processVMInstallType(IInterpreterInstallType installType, |
| List<String> locations, List<String> labels) { |
| if (installType != null) { |
| IInterpreterInstall[] installs = installType |
| .getInterpreterInstalls(); |
| boolean isMac = Platform.OS_MACOSX.equals(Platform.getOS()); |
| final String HOME_SUFFIX = "/Home"; //$NON-NLS-1$ |
| for (int i = 0; i < installs.length; i++) { |
| String label = getFormattedLabel(installs[i].getName()); |
| LibraryLocation[] libLocations = installs[i] |
| .getLibraryLocations(); |
| if (libLocations != null) { |
| processLibraryLocation(libLocations, label); |
| } else { |
| String filePath = installs[i].getInstallLocation() |
| .toOSString(); |
| // on MacOS X install locations end in an additional |
| // "/Home" segment; remove it |
| if (isMac && filePath.endsWith(HOME_SUFFIX)) |
| filePath = filePath.substring(0, filePath.length() |
| - HOME_SUFFIX.length() + 1); |
| locations.add(filePath); |
| labels.add(label); |
| } |
| } |
| } |
| } |
| |
| private void processLibraryLocation(LibraryLocation[] libLocations, |
| String label) { |
| for (int l = 0; l < libLocations.length; l++) { |
| LibraryLocation location = libLocations[l]; |
| fLib2Name.put(location.getLibraryPath().toString(), label); |
| } |
| } |
| |
| private String getFormattedLabel(String name) { |
| return NLS.bind( |
| DLTKUIMessages.FilteredTypesSelectionDialog_library_name_format, |
| name); |
| } |
| |
| @Override |
| public int compare(Object left, Object right) { |
| |
| TypeNameMatch leftInfo = (TypeNameMatch) left; |
| TypeNameMatch rightInfo = (TypeNameMatch) right; |
| |
| int result = compareName(leftInfo.getSimpleTypeName(), |
| rightInfo.getSimpleTypeName()); |
| if (result != 0) |
| return result; |
| result = compareTypeContainerName(leftInfo.getTypeContainerName(), |
| rightInfo.getTypeContainerName()); |
| if (result != 0) |
| return result; |
| |
| int leftCategory = getElementTypeCategory(leftInfo); |
| int rightCategory = getElementTypeCategory(rightInfo); |
| if (leftCategory < rightCategory) |
| return -1; |
| if (leftCategory > rightCategory) |
| return +1; |
| return compareContainerName(leftInfo, rightInfo); |
| } |
| |
| private int compareName(String leftString, String rightString) { |
| int result = leftString.compareToIgnoreCase(rightString); |
| if (result != 0 || rightString.length() == 0) { |
| return result; |
| } else if (Strings.isLowerCase(leftString.charAt(0)) |
| && !Strings.isLowerCase(rightString.charAt(0))) { |
| return +1; |
| } else if (Strings.isLowerCase(rightString.charAt(0)) |
| && !Strings.isLowerCase(leftString.charAt(0))) { |
| return -1; |
| } else { |
| return leftString.compareTo(rightString); |
| } |
| } |
| |
| private int compareTypeContainerName(String leftString, |
| String rightString) { |
| int leftLength = leftString.length(); |
| int rightLength = rightString.length(); |
| if (leftLength == 0 && rightLength > 0) |
| return -1; |
| if (leftLength == 0 && rightLength == 0) |
| return 0; |
| if (leftLength > 0 && rightLength == 0) |
| return +1; |
| return compareName(leftString, rightString); |
| } |
| |
| private int compareContainerName(TypeNameMatch leftType, |
| TypeNameMatch rightType) { |
| return getContainerName(leftType) |
| .compareTo(getContainerName(rightType)); |
| } |
| |
| private String getContainerName(TypeNameMatch type) { |
| IProjectFragment root = type.getProjectFragment(); |
| if (root.isExternal()) { |
| String name = root.getPath().toOSString(); |
| for (int i = 0; i < fInstallLocations.length; i++) { |
| if (name.startsWith(fInstallLocations[i])) { |
| return fVMNames[i]; |
| } |
| } |
| String lib = (String) fLib2Name.get(name); |
| if (lib != null) |
| return lib; |
| } |
| StringBuffer buf = new StringBuffer(); |
| ScriptElementLabels labels = getUIToolkit() |
| .getScriptElementLabels(); |
| labels.getProjectFragmentLabel(root, |
| ScriptElementLabels.ROOT_QUALIFIED |
| | ScriptElementLabels.ROOT_VARIABLE, |
| buf); |
| return buf.toString(); |
| } |
| |
| private int getElementTypeCategory(TypeNameMatch type) { |
| try { |
| if (type.getProjectFragment() |
| .getKind() == IProjectFragment.K_SOURCE) |
| return 0; |
| } catch (ModelException e) { |
| DLTKUIPlugin.log(e); |
| } |
| return 1; |
| } |
| } |
| |
| private IDLTKUILanguageToolkit getUIToolkit() { |
| return DLTKUILanguageManager.getLanguageToolkit(fToolkit.getNatureId()); |
| } |
| |
| /** |
| * Extends the <code>SelectionHistory</code>, providing support for |
| * <code>OpenTypeHistory</code>. |
| */ |
| protected class TypeSelectionHistory extends SelectionHistory { |
| |
| /** |
| * Creates new instance of TypeSelectionHistory |
| */ |
| |
| public TypeSelectionHistory() { |
| super(); |
| } |
| |
| @Override |
| public synchronized void accessed(Object object) { |
| super.accessed(object); |
| } |
| |
| @Override |
| public synchronized boolean remove(Object element) { |
| OpenTypeHistory.getInstance(getUIToolkit()) |
| .remove((TypeNameMatch) element); |
| return super.remove(element); |
| } |
| |
| @Override |
| public void load(IMemento memento) { |
| TypeNameMatch[] types = OpenTypeHistory.getInstance(getUIToolkit()) |
| .getTypeInfos(); |
| |
| for (int i = 0; i < types.length; i++) { |
| TypeNameMatch type = types[i]; |
| accessed(type); |
| } |
| } |
| |
| @Override |
| public void save(IMemento memento) { |
| persistHistory(); |
| } |
| |
| /** |
| * Stores contents of the local history into persistent history |
| * container. |
| */ |
| private synchronized void persistHistory() { |
| if (getReturnCode() == OK) { |
| Object[] items = getHistoryItems(); |
| for (int i = 0; i < items.length; i++) { |
| OpenTypeHistory.getInstance(getUIToolkit()) |
| .accessed((TypeNameMatch) items[i]); |
| } |
| } |
| } |
| |
| @Override |
| protected Object restoreItemFromMemento(IMemento element) { |
| return null; |
| } |
| |
| @Override |
| protected void storeItemToMemento(Object item, IMemento element) { |
| |
| } |
| |
| } |
| |
| } |