From a818ec2e05119b0a03c8e114a53f87762b20c03d Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 26 Mar 2015 21:01:11 +0000 Subject: [PATCH 1/4] LANG: new build target: create p2repo from existing published repo. --- releng/build.xml | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/releng/build.xml b/releng/build.xml index 8dff28f0b..557fd5cba 100644 --- a/releng/build.xml +++ b/releng/build.xml @@ -44,12 +44,11 @@ overwriting the previous one. (This removes history from the git repo it is push - - - + + @@ -73,6 +72,8 @@ overwriting the previous one. (This removes history from the git repo it is push + + @@ -98,7 +99,7 @@ overwriting the previous one. (This removes history from the git repo it is push - + @@ -128,5 +129,19 @@ overwriting the previous one. (This removes history from the git repo it is push + + + + + + + + + + + + + + \ No newline at end of file From da074d277c82f01ddb20d607aeecafc8d71d1b8e Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Fri, 27 Mar 2015 12:50:04 +0000 Subject: [PATCH 2/4] Eclipse Optimizer docs --- documentation/UserGuide.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/documentation/UserGuide.md b/documentation/UserGuide.md index 9ad8c1049..45152d5c3 100644 --- a/documentation/UserGuide.md +++ b/documentation/UserGuide.md @@ -6,20 +6,10 @@ the major functionalities available. ### Eclipse basics If you are new to Eclipse, you can learn some of the basics of the Eclipse IDE with this short intro article: - [An introduction to Eclipse for Visual Studio users ](http://www.ibm.com/developerworks/opensource/library/os-eclipse-visualstudio/) -Also, to improve Eclipse performance on modern machines, it is recommended you increase the memory available to -the JVM. You can do so by modifying the _`eclipse.ini`_ file in your Eclipse installation. The two VM parameters -in _`eclipse.ini`_ to note are _-Xms_ (initial Java heap size) and _-Xmx_ (maximum Java heap size). For a machine -with 4Gb of RAM or more, the following is recommended as minimum values: - -``` --vmargs --Xms256m --Xmx1024m -``` +Also, to improve Eclipse performance and startup time, it is recommended you tweak the JVM parameters. There is a tool called Eclipse Optimizer that can do that automatically, it is recommended you use it. Read more about it [here](http://www.infoq.com/news/2015/03/eclipse-optimizer). (Installing/enabling the JRebel optimization is not necessary as that only applies to Java developers) ### Project setup From a32366e3f1b43d7589dcc5740e2dc8fa753234da Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Tue, 31 Mar 2015 17:07:16 +0100 Subject: [PATCH 3/4] Initial port of JDT's ContentAssistProcessor and related classes. --- ...AbstractLangSourceViewerConfiguration.java | 6 + .../jdt/internal/corext/util/Messages.java | 40 ++ .../eclipse/jdt/internal/ui/JavaPlugin.java | 12 + .../jdt/internal/ui/JavaUIMessages.java | 20 + .../ui/text/java/AlphabeticSorter.java | 35 + .../text/java/CompletionProposalCategory.java | 399 +++++++++++ .../CompletionProposalComputerDescriptor.java | 69 ++ .../ui/text/java/ContentAssistProcessor.java | 633 ++++++++++++++++++ .../ui/text/java/JavaTextMessages.java | 40 ++ .../ui/text/java/AbstractProposalSorter.java | 84 +++ .../java/CompletionProposalComparator.java | 71 ++ .../java/ContentAssistInvocationContext.java | 179 +++++ .../ui/text/java/IJavaCompletionProposal.java | 38 ++ .../java/IJavaCompletionProposalComputer.java | 73 ++ .../LANGUAGE_SourceViewerConfiguration.java | 10 + 15 files changed, 1709 insertions(+) create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/internal/corext/util/Messages.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/JavaPlugin.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/JavaUIMessages.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/AlphabeticSorter.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerDescriptor.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/AbstractProposalSorter.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/CompletionProposalComparator.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/ContentAssistInvocationContext.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/IJavaCompletionProposal.java create mode 100644 plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/IJavaCompletionProposalComputer.java diff --git a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/text/AbstractLangSourceViewerConfiguration.java b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/text/AbstractLangSourceViewerConfiguration.java index 31d009403..148ad53fc 100644 --- a/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/text/AbstractLangSourceViewerConfiguration.java +++ b/plugin_ide.ui/src-lang/melnorme/lang/ide/ui/text/AbstractLangSourceViewerConfiguration.java @@ -35,6 +35,7 @@ import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.IContentAssistant; import org.eclipse.jface.text.presentation.IPresentationReconciler; import org.eclipse.jface.text.presentation.PresentationReconciler; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; @@ -216,4 +217,9 @@ public String[] getDefaultPrefixes(ISourceViewer sourceViewer, String contentTyp protected abstract String getToggleCommentPrefix(); + @Override + public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { + return super.getContentAssistant(sourceViewer); + } + } \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/corext/util/Messages.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/corext/util/Messages.java new file mode 100644 index 000000000..e682a6b72 --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/corext/util/Messages.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 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.corext.util; + +import java.text.MessageFormat; + + +/** + * Helper class to format message strings. + * + * @since 3.1 + * BM: we modified this to use Java's MessageFormat + */ +public class Messages { + + public static String format(String message, Object object) { + return MessageFormat.format(message, new Object[] { object}); + } + + public static String format(String message, Object[] objects) { + return MessageFormat.format(message, objects); + } + + public static String format_2(String message, Object... objects) { + return MessageFormat.format(message, objects); + } + + + private Messages() { + // Not for instantiation + } +} diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/JavaPlugin.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/JavaPlugin.java new file mode 100644 index 000000000..0db500c1e --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/JavaPlugin.java @@ -0,0 +1,12 @@ +package org.eclipse.jdt.internal.ui; + +import melnorme.lang.ide.ui.LangUIPlugin; + + +public abstract class JavaPlugin extends LangUIPlugin { + + public static LangUIPlugin getDefault() { + return LangUIPlugin.getInstance(); + } + +} diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/JavaUIMessages.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/JavaUIMessages.java new file mode 100644 index 000000000..4c105ff10 --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/JavaUIMessages.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015, 2015 Bruno Medeiros and other Contributors. + * 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: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.ui; + +public interface JavaUIMessages { + + String OptionalMessageDialog_dontShowAgain = + "Do not show this &message again"; + String JavaEditor_codeassist_noCompletions = + "No completions available."; + +} \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/AlphabeticSorter.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/AlphabeticSorter.java new file mode 100644 index 000000000..f82b23d5f --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/AlphabeticSorter.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2006, 2011 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.ui.text.java; + +import org.eclipse.jface.text.contentassist.ICompletionProposal; + +import org.eclipse.jdt.ui.text.java.AbstractProposalSorter; +import org.eclipse.jdt.ui.text.java.CompletionProposalComparator; + +/** + * A alphabetic proposal based sorter. + * + * @since 3.2 + */ +public final class AlphabeticSorter extends AbstractProposalSorter { + + protected final CompletionProposalComparator fComparator= new CompletionProposalComparator(true); + + public AlphabeticSorter() { + } + + @Override + public int compare(ICompletionProposal p1, ICompletionProposal p2) { + return fComparator.compare(p1, p2); + } + +} \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java new file mode 100644 index 000000000..03bc531a2 --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/CompletionProposalCategory.java @@ -0,0 +1,399 @@ +/******************************************************************************* + * Copyright (c) 2005, 2013 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 + * Paul Fullbright - content assist category enablement - http://bugs.eclipse.org/345213 + * Marcel Bruch - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 + * Lars Vogel - convert to foreach loop - https://bugs.eclipse.org/bugs/show_bug.cgi?id=406478 + *******************************************************************************/ +package org.eclipse.jdt.internal.ui.text.java; + +import java.util.ArrayList; +import java.util.List; + +import melnorme.utilbox.collections.ArrayList2; + +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; +import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer; +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.eclipse.core.expressions.EvaluationContext; +//import org.eclipse.core.expressions.EvaluationResult; +//import org.eclipse.core.expressions.Expression; +//import org.eclipse.core.expressions.ExpressionConverter; +//import org.eclipse.core.expressions.ExpressionTagNames; +//import org.eclipse.jdt.core.IJavaProject; + + +/** + * Describes a category extension to the "javaCompletionProposalComputer" extension point. + * + * @since 3.2 + */ +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 null if none specified. */ + private final ImageDescriptor fImage; + +// /** The enablement expression for this category, or null if none specified. */ +// private final Expression fEnablementExpression; + + private boolean fIsSeparateCommand= true; + private boolean fIsEnabled= true; + private boolean fIsIncluded= true; +// private final CompletionProposalComputerRegistry fRegistry; + + private int fSortOrder= 0xffff - 1; + private String fLastError= null; + + /** + * Flag indicating whether any completion engine associated with this category requests + * resorting of its proposals after filtering is triggered. Filtering is, e.g., triggered when a + * user continues typing with an open completion window. + * + * @since 3.8 + */ + private boolean fNeedsSortingAfterFiltering; + + protected final List computers; + +// CompletionProposalCategory(IConfigurationElement element, CompletionProposalComputerRegistry registry) throws CoreException { +// 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; +// +// IConfigurationElement[] children= fElement.getChildren(ExpressionTagNames.ENABLEMENT); +// if (children.length == 1) { +// ExpressionConverter parser= ExpressionConverter.getDefault(); +// fEnablementExpression = parser.perform(children[0]); +// } +// else { +// fEnablementExpression = null; +// } +// +// 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, ArrayList2 computers) { +// fRegistry= registry; + fId= id; + fName= name; + this.computers = computers; +// fElement= null; +// fEnablementExpression = null; + fImage= null; + } + + /** + * Returns the identifier of the described extension. + */ + public String getId() { + return fId; + } + + public String getName() { + return fName; + } + + protected List getComputers() { + return computers; + } + + @SuppressWarnings("unused") + protected List getComputers(String partition) { + return getComputers(); + } + + /** + * @return the error message from the computers in this category + */ + public String getErrorMessage() { + return fLastError; + } + +// private Bundle getBundle() { +// String namespace= fElement.getDeclaringExtension().getContributor().getName(); +// Bundle bundle= Platform.getBundle(namespace); +// return bundle; +// } + +// /** +// * Checks that the given attribute value is not null. +// * +// * @param value the element to be checked +// * @param attribute the attribute +// * @throws CoreException if value is null +// */ +// private void checkNotNull(Object value, String attribute) throws CoreException { +// if (value == null) { +// Object[] args= { getId(), fElement.getContributor().getName(), attribute }; +// String message= Messages.format( +// JavaTextMessages.CompletionProposalComputerDescriptor_illegal_attribute_message, args); +// IStatus status= new Status(IStatus.WARNING, JavaPlugin.getPluginId(), IStatus.OK, message, null); +// throw new CoreException(status); +// } +// } + +// /** +// * Returns the enablement element of the described extension. +// * +// * @return the enablement expression or null if it is not specified +// * @since 3.8.1 +// */ +// Expression getEnablementExpression() { +// return fEnablementExpression; +// } + + /** + * 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 image descriptor of the described category. + * + * @return the image descriptor of the described category + */ + public ImageDescriptor getImageDescriptor() { + return fImage; + } + + /** + * Sets the separate command state of the category. + * + * @param enabled the new enabled state. + */ + public void setSeparateCommand(boolean enabled) { + fIsSeparateCommand= enabled; + } + + /** + * @return the enablement state of the category + */ + public boolean isSeparateCommand() { + return fIsSeparateCommand; + } + + /** + * @param included the included + */ + public void setIncluded(boolean included) { + fIsIncluded= included; + } + + /** + * @return included + */ + public boolean isIncluded() { + return fIsIncluded; + } + + public boolean isEnabled() { + return fIsEnabled; + } + + public void setEnabled(boolean isEnabled) { + fIsEnabled= isEnabled; + } + +// /** +// * Returns true if the category contains any computers, false +// * otherwise. +// * +// * @return true if the category contains any computers, false +// * otherwise +// */ +// public boolean hasComputers() { +// List descriptors= fRegistry.getProposalComputerDescriptors(); +// for (CompletionProposalComputerDescriptor desc : descriptors) { +// if (desc.getCategory() == this) +// return true; +// } +// return false; +// } +// +// /** +// * Returns true if the category contains any computers in the given partition, false +// * otherwise. +// * +// * @param partition the partition +// * @return true if the category contains any computers, false +// * otherwise +// */ +// public boolean hasComputers(String partition) { +// List descriptors= fRegistry.getProposalComputerDescriptors(partition); +// for (CompletionProposalComputerDescriptor desc : descriptors) { +// if (desc.getCategory() == this) +// return true; +// } +// return false; +// } + + /** + * @return sortOrder + */ + public int getSortOrder() { + return fSortOrder; + } + + /** + * @param sortOrder the sortOrder + */ + public void setSortOrder(int sortOrder) { + fSortOrder= sortOrder; + } + +// /** +// * Determines if the project matches any enablement expression defined on the extension. +// * +// * @param javaProject the Java project against which to test the enablement expression, can be +// * null +// * @return true if any enablement expression matches the given project or if the +// * project is null or no enablement expression is specified, +// * false otherwise +// * @since 3.8 +// */ +// public boolean matches(IJavaProject javaProject) { +// if (fEnablementExpression == null) { +// return true; +// } +// +// if (javaProject == null) { +// return false; +// } +// +// try { +// EvaluationContext evalContext= new EvaluationContext(null, javaProject); +// evalContext.addVariable("project", javaProject); //$NON-NLS-1$ +// return fEnablementExpression.evaluate(evalContext) == EvaluationResult.TRUE; +// } catch (CoreException e) { +// JavaPlugin.log(e); +// } +// +// return false; +// } + + /** + * 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 IJavaCompletionProposalComputer}, 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 computeCompletionProposals(ContentAssistInvocationContext context, + String partition, SubProgressMonitor monitor) { + fLastError= null; + List result= new ArrayList(); + List descriptors= getComputers(partition); + for (CompletionProposalComputerDescriptor desc : descriptors) { + result.addAll(desc.computeCompletionProposals(context, monitor)); + + if (fLastError == null && desc.getErrorMessage() != null) + fLastError= desc.getErrorMessage(); + } + return result; + } + + /** + * 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 IJavaCompletionProposalComputer}, 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 computeContextInformation(ContentAssistInvocationContext context, + String partition, SubProgressMonitor monitor) { + fLastError= null; + List result= new ArrayList(); + List descriptors= getComputers(partition); + for (CompletionProposalComputerDescriptor desc : descriptors) { + if((isIncluded() || isSeparateCommand())) + result.addAll(desc.computeContextInformation(context, monitor)); + if (fLastError == null) + fLastError= desc.getErrorMessage(); + } + return result; + } + + /** + * Notifies the computers in this category of a proposal computation session start. + */ + public void sessionStarted() { + List descriptors= getComputers(); + for (CompletionProposalComputerDescriptor desc : descriptors) { + desc.sessionStarted(); + fNeedsSortingAfterFiltering= fNeedsSortingAfterFiltering || desc.isSortingAfterFilteringNeeded(); + if (fLastError == null) + fLastError= desc.getErrorMessage(); + } + } + + /** + * Notifies the computers in this category of a proposal computation session end. + */ + public void sessionEnded() { + fNeedsSortingAfterFiltering= false; + List descriptors= getComputers(); + for (CompletionProposalComputerDescriptor desc : descriptors) { + desc.sessionEnded(); + if (fLastError == null) + fLastError= desc.getErrorMessage(); + } + } + + /** + * Returns whether any completion proposal computer associated with this category requires + * proposals to be sorted again after filtering. + * + * @return true if any completion proposal computer in this category requires + * proposals to be sorted. + */ + public boolean isSortingAfterFilteringNeeded() { + return fNeedsSortingAfterFiltering; + } +} diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerDescriptor.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerDescriptor.java new file mode 100644 index 000000000..72fde32d1 --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/CompletionProposalComputerDescriptor.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2015, 2015 Bruno Medeiros and other Contributors. + * 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: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.ui.text.java; + +import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; + +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; +import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContextInformation; + +public abstract class CompletionProposalComputerDescriptor { + + /** + * Tells whether this proposal engine provides dynamic content that needs to be sorted after its + * proposal have been filtered. Filtering happens, e.g., when a user continues typing with an + * open completion window. + * + * @since 3.8 + */ + private boolean fNeedsSortingAfterFiltering; + + protected final IJavaCompletionProposalComputer proposalComputer; + + public CompletionProposalComputerDescriptor(IJavaCompletionProposalComputer proposalComputer) { + this.proposalComputer = assertNotNull(proposalComputer); + + } + + public boolean isSortingAfterFilteringNeeded() { + return fNeedsSortingAfterFiltering; + } + public IJavaCompletionProposalComputer getComputer() { + return proposalComputer; + } + + + public abstract List computeCompletionProposals(ContentAssistInvocationContext context, + IProgressMonitor monitor); + + public abstract List computeContextInformation(ContentAssistInvocationContext context, + IProgressMonitor monitor); + + public String getErrorMessage() { + return getComputer().getErrorMessage(); + } + + public void sessionStarted() { + IJavaCompletionProposalComputer computer= getComputer(); + computer.sessionStarted(); + } + + public void sessionEnded() { + IJavaCompletionProposalComputer computer= getComputer(); + computer.sessionEnded(); + } + +} \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java new file mode 100644 index 000000000..1e16b93e5 --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/ContentAssistProcessor.java @@ -0,0 +1,633 @@ +/******************************************************************************* + * Copyright (c) 2005, 2013 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 + * Paul Fullbright - content assist category enablement - http://bugs.eclipse.org/345213 + * Marcel Bruch - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 + * Lars Vogel - convert to foreach loop - https://bugs.eclipse.org/bugs/show_bug.cgi?id=406478 + *******************************************************************************/ +package org.eclipse.jdt.internal.ui.text.java; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jdt.internal.corext.util.Messages; +import org.eclipse.jdt.internal.ui.JavaUIMessages; +//import org.eclipse.jdt.ui.PreferenceConstants; +import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; +import org.eclipse.jface.bindings.TriggerSequence; +import org.eclipse.jface.bindings.keys.KeySequence; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.ContentAssistEvent; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.jface.text.contentassist.ICompletionListener; +import org.eclipse.jface.text.contentassist.ICompletionListenerExtension; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContentAssistantExtension2; +import org.eclipse.jface.text.contentassist.IContentAssistantExtension3; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.keys.IBindingService; +import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; + + +/** + * A content assist processor that aggregates the proposals of the + * {@link org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer}s contributed via the + * org.eclipse.jdt.ui.javaCompletionProposalComputer extension point. + *

+ * Subclasses may extend: + *

    + *
  • createContext to provide the context object passed to the computers
  • + *
  • createProgressMonitor to change the way progress is reported
  • + *
  • filterAndSort to add sorting and filtering
  • + *
  • getContextInformationValidator to add context validation (needed if any + * contexts are provided)
  • + *
  • getErrorMessage to change error reporting
  • + *
+ *

+ * + * @since 3.2 + */ +public class ContentAssistProcessor implements IContentAssistProcessor { + + + private final class CompletionListener implements ICompletionListener, ICompletionListenerExtension { + @Override + public void assistSessionStarted(ContentAssistEvent event) { + if (event.processor != ContentAssistProcessor.this) + return; + + fIterationGesture= getIterationGesture(); + KeySequence binding= getIterationBinding(); + + // This may show the warning dialog if all categories are disabled + setCategoryIteration(); + for (CompletionProposalCategory cat : getCategoriesToNotify()) { + cat.sessionStarted(); + } + + fRepetition= 0; + if (event.assistant instanceof IContentAssistantExtension2) { + IContentAssistantExtension2 extension= (IContentAssistantExtension2) event.assistant; + + if (fCategoryIteration.size() == 1) { + extension.setRepeatedInvocationMode(false); + extension.setShowEmptyList(false); + } else { + extension.setRepeatedInvocationMode(true); + extension.setStatusLineVisible(true); + extension.setStatusMessage(createIterationMessage()); + extension.setShowEmptyList(true); + if (extension instanceof IContentAssistantExtension3) { + IContentAssistantExtension3 ext3= (IContentAssistantExtension3) extension; + ((ContentAssistant) ext3).setRepeatedInvocationTrigger(binding); + } + } + + } + } + + /** + * Returns the categories that need to be notified when a session starts and ends. + * + * @return the current categories + * @since 3.8.1 + */ + private Set getCategoriesToNotify() { + Set currentCategories= new HashSet<>(fCategories.size()); + + // Currently enabled categories for this session + if (fCategoryIteration != null) { + Iterator> it= fCategoryIteration.iterator(); + while (it.hasNext()) + currentCategories.addAll(it.next()); + } + + // Backwards compatibility: notify all categories which have no enablement expression + for (CompletionProposalCategory cat : fCategories) { + if (true) + currentCategories.add(cat); + } + + return currentCategories; + } + + @Override + public void assistSessionEnded(ContentAssistEvent event) { + if (event.processor != ContentAssistProcessor.this) + return; + + for (CompletionProposalCategory cat : getCategoriesToNotify()) { + cat.sessionEnded(); + } + + fCategoryIteration= null; + fRepetition= -1; + fIterationGesture= null; + if (event.assistant instanceof IContentAssistantExtension2) { + IContentAssistantExtension2 extension= (IContentAssistantExtension2) event.assistant; + extension.setShowEmptyList(false); + extension.setRepeatedInvocationMode(false); + extension.setStatusLineVisible(false); + if (extension instanceof IContentAssistantExtension3) { + IContentAssistantExtension3 ext3= (IContentAssistantExtension3) extension; + ((ContentAssistant) ext3).setRepeatedInvocationTrigger(null); + } + } + } + + @Override + public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) { + } + + @Override + public void assistSessionRestarted(ContentAssistEvent event) { + fRepetition= 0; + } + } + + private static final boolean DEBUG= Platform.inDebugMode(); + +// /** +// * Dialog settings key for the "all categories are disabled" warning dialog. See +// * {@link OptionalMessageDialog}. +// * +// * @since 3.3 +// */ +// private static final String PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY= "EmptyDefaultAssistCategory"; + + private static final Comparator ORDER_COMPARATOR= + new Comparator() { + @Override + public int compare(CompletionProposalCategory d1, CompletionProposalCategory d2) { + return d1.getSortOrder() - d2.getSortOrder(); + } + }; + + protected final List fCategories; + protected final String fPartition; + protected final ContentAssistant fAssistant; + + protected char[] fCompletionAutoActivationCharacters; + + /* cycling stuff */ + protected int fRepetition= -1; + protected List> fCategoryIteration= null; + protected String fIterationGesture= null; + protected int fNumberOfComputedResults= 0; + protected String fErrorMessage; + +// private CompletionProposalComputerRegistry fComputerRegistry; + + /** + * Flag indicating whether any completion engine associated with this processor requests + * resorting of its proposals after filtering is triggered. Filtering is, e.g., triggered when a + * user continues typing with an open completion window. + * + * @since 3.8 + */ + private boolean fNeedsSortingAfterFiltering; + + + public ContentAssistProcessor(ContentAssistant assistant, String partition, + List fCategories) { + Assert.isNotNull(partition); + Assert.isNotNull(assistant); + this.fPartition= partition; + this.fCategories= fCategories; + this.fAssistant= assistant; + this.fAssistant.addCompletionListener(new CompletionListener()); + } + + @Override + public final ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { + long start= DEBUG ? System.currentTimeMillis() : 0; + + clearState(); + + IProgressMonitor monitor= createProgressMonitor(); + monitor.beginTask(JavaTextMessages.ContentAssistProcessor_computing_proposals, fCategories.size() + 1); + + ContentAssistInvocationContext context= createContext(viewer, offset); + long setup= DEBUG ? System.currentTimeMillis() : 0; + + List proposals= collectProposals(monitor, context); + monitor.subTask(JavaTextMessages.ContentAssistProcessor_collecting_proposals); + long collect= DEBUG ? System.currentTimeMillis() : 0; + + monitor.subTask(JavaTextMessages.ContentAssistProcessor_sorting_proposals); + if (fNeedsSortingAfterFiltering) + setContentAssistSorter(); + else + proposals= sortProposals(proposals, monitor, context); + fNumberOfComputedResults= proposals.size(); + long filter= DEBUG ? System.currentTimeMillis() : 0; + + ICompletionProposal[] result= proposals.toArray(new ICompletionProposal[proposals.size()]); + monitor.done(); + + if (DEBUG) { + System.err.println("Code Assist Stats (" + result.length + " proposals)"); //$NON-NLS-1$ //$NON-NLS-2$ + System.err.println("Code Assist (setup):\t" + (setup - start) ); //$NON-NLS-1$ + System.err.println("Code Assist (collect):\t" + (collect - setup) ); //$NON-NLS-1$ + System.err.println("Code Assist (sort):\t" + (filter - collect) ); //$NON-NLS-1$ + } + + return result; + } + + private void clearState() { + fErrorMessage=null; + fNumberOfComputedResults= 0; + } + + protected List collectProposals(IProgressMonitor monitor, + ContentAssistInvocationContext context) { + boolean needsSortingAfterFiltering= false; + List proposals= new ArrayList(); + List providers= getCategories(); + for (CompletionProposalCategory cat : providers) { + List computed= cat.computeCompletionProposals(context, fPartition, + new SubProgressMonitor(monitor, 1)); + proposals.addAll(computed); + needsSortingAfterFiltering= needsSortingAfterFiltering || + (cat.isSortingAfterFilteringNeeded() && !computed.isEmpty()); + if (fErrorMessage == null) + fErrorMessage= cat.getErrorMessage(); + } + if (fNeedsSortingAfterFiltering && !needsSortingAfterFiltering) + fAssistant.setSorter(null); + fNeedsSortingAfterFiltering= needsSortingAfterFiltering; + return proposals; + } + + /** + * Filters and sorts the proposals. The passed list may be modified + * and returned, or a new list may be created and returned. + * + * @param proposals the list of collected proposals (element type: + * {@link ICompletionProposal}) + * @param monitor a progress monitor + * @param context TODO + * @return the list of filtered and sorted proposals, ready for + * display (element type: {@link ICompletionProposal}) + */ + protected List sortProposals(List proposals, IProgressMonitor monitor, + ContentAssistInvocationContext context) { + return proposals; + } + + @Override + public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { + clearState(); + + IProgressMonitor monitor= createProgressMonitor(); + monitor.beginTask(JavaTextMessages.ContentAssistProcessor_computing_contexts, fCategories.size() + 1); + + monitor.subTask(JavaTextMessages.ContentAssistProcessor_collecting_contexts); + List proposals= collectContextInformation(viewer, offset, monitor); + + monitor.subTask(JavaTextMessages.ContentAssistProcessor_sorting_contexts); + List filtered= filterAndSortContextInformation(proposals, monitor); + fNumberOfComputedResults= filtered.size(); + + IContextInformation[] result= filtered.toArray(new IContextInformation[filtered.size()]); + monitor.done(); + return result; + } + + protected List collectContextInformation(ITextViewer viewer, int offset, + IProgressMonitor monitor) { + List proposals= new ArrayList(); + ContentAssistInvocationContext context= createContext(viewer, offset); + + List providers= getCategories(); + for (CompletionProposalCategory cat : providers) { + List computed= cat.computeContextInformation(context, fPartition, + new SubProgressMonitor(monitor, 1)); + proposals.addAll(computed); + if (fErrorMessage == null) + fErrorMessage= cat.getErrorMessage(); + } + + return proposals; + } + + /** + * Filters and sorts the context information objects. The passed + * list may be modified and returned, or a new list may be created + * and returned. + * + * @param contexts the list of collected proposals (element type: + * {@link IContextInformation}) + * @param monitor a progress monitor + * @return the list of filtered and sorted proposals, ready for + * display (element type: {@link IContextInformation}) + */ + protected List filterAndSortContextInformation(List contexts, + IProgressMonitor monitor) { + return contexts; + } + + /** + * Sets this processor's set of characters triggering the activation of the + * completion proposal computation. + * + * @param activationSet the activation set + */ + public final void setCompletionProposalAutoActivationCharacters(char[] activationSet) { + fCompletionAutoActivationCharacters= activationSet; + } + + + @Override + public final char[] getCompletionProposalAutoActivationCharacters() { + return fCompletionAutoActivationCharacters; + } + + @Override + public char[] getContextInformationAutoActivationCharacters() { + return null; + } + + @Override + public String getErrorMessage() { + if (fErrorMessage != null) + return fErrorMessage; + if (fNumberOfComputedResults > 0) + return null; + return JavaUIMessages.JavaEditor_codeassist_noCompletions; + } + + @Override + public IContextInformationValidator getContextInformationValidator() { + return null; + } + + /** + * Creates a progress monitor. + *

+ * The default implementation creates a + * NullProgressMonitor. + *

+ * + * @return a progress monitor + */ + protected IProgressMonitor createProgressMonitor() { + return new NullProgressMonitor(); + } + + /** + * Creates the context that is passed to the completion proposal computers. + * + * @param viewer the viewer that content assist is invoked on + * @param offset the content assist offset + * @return the context to be passed to the computers + */ + protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset) { + return new ContentAssistInvocationContext(viewer, offset); + } + + private List getCategories() { + if (fCategoryIteration == null) + return fCategories; + + int iteration= fRepetition % fCategoryIteration.size(); + fAssistant.setStatusMessage(createIterationMessage()); + fAssistant.setEmptyMessage(createEmptyMessage()); + fRepetition++; + +// fAssistant.setShowMessage(fRepetition % 2 != 0); + + return fCategoryIteration.get(iteration); + } + + // This may show the warning dialog if all categories are disabled + private void setCategoryIteration() { + fCategoryIteration= getCategoryIteration(); + } + + private List> getCategoryIteration() { + List> sequence= new ArrayList>(); + sequence.add(getDefaultCategories()); + for (CompletionProposalCategory cat : getSeparateCategories()) { + sequence.add(Collections.singletonList(cat)); + } + return sequence; + } + + private List getDefaultCategories() { + // default mix - enable all included computers + List included= getDefaultCategoriesUnchecked(); + +// if (fComputerRegistry.hasUninstalledComputers(fPartition, included)) { +// if (informUserAboutEmptyDefaultCategory()) { +// // preferences were restored - recompute the default categories +// included= getDefaultCategoriesUnchecked(); +// } +// fComputerRegistry.resetUnistalledComputers(); +// } + + return included; + } + + private List getDefaultCategoriesUnchecked() { + List included= new ArrayList(); + for (CompletionProposalCategory category : fCategories) { + if (checkDefaultEnablement(category)) + included.add(category); + } + return included; + } + + /** + * Determine whether the category is enabled by default. + * + * @param category the category to check + * @return true if this category is enabled by default, false + * otherwise + * @since 3.8 + */ + protected boolean checkDefaultEnablement(CompletionProposalCategory category) { + return category.isIncluded(); + } + +// /** +// * Informs the user about the fact that there are no enabled categories in the default content +// * assist set and shows a link to the preferences. +// * +// * @return true if the default should be restored +// * @since 3.3 +// */ +// private boolean informUserAboutEmptyDefaultCategory() { +// if (OptionalMessageDialog.isDialogEnabled(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY)) { +// final Shell shell= WorkbenchUtils.getActiveWorkbenchShell(); +// String title= JavaTextMessages.ContentAssistProcessor_all_disabled_title; +// String message= JavaTextMessages.ContentAssistProcessor_all_disabled_message; +// // see PreferencePage#createControl for the 'defaults' label +// final String restoreButtonLabel= JFaceResources.getString("defaults"); //$NON-NLS-1$ +// final String linkMessage= Messages.format(JavaTextMessages.ContentAssistProcessor_all_disabled_preference_link, LegacyActionTools.removeMnemonics(restoreButtonLabel)); +// final int restoreId= IDialogConstants.CLIENT_ID + 10; +// final int settingsId= IDialogConstants.CLIENT_ID + 11; +// final OptionalMessageDialog dialog= new OptionalMessageDialog(PREF_WARN_ABOUT_EMPTY_ASSIST_CATEGORY, shell, title, null /* default image */, message, MessageDialog.WARNING, new String[] { restoreButtonLabel, IDialogConstants.CLOSE_LABEL }, 1) { +// @Override +// protected Control createCustomArea(Composite composite) { +// // wrap link and checkbox in one composite without space +// Composite parent= new Composite(composite, SWT.NONE); +// GridLayout layout= new GridLayout(); +// layout.marginHeight= 0; +// layout.marginWidth= 0; +// layout.verticalSpacing= 0; +// parent.setLayout(layout); +// +// Composite linkComposite= new Composite(parent, SWT.NONE); +// layout= new GridLayout(); +// layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); +// layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); +// layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); +// linkComposite.setLayout(layout); +// +// Link link= new Link(linkComposite, SWT.NONE); +// link.setText(linkMessage); +// link.addSelectionListener(new SelectionAdapter() { +// @Override +// public void widgetSelected(SelectionEvent e) { +// setReturnCode(settingsId); +// close(); +// } +// }); +// GridData gridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false); +// gridData.widthHint= this.getMinimumMessageWidth(); +// link.setLayoutData(gridData); +// +// // create checkbox and "don't show this message" prompt +// super.createCustomArea(parent); +// +// return parent; +// } +// +// @Override +// protected void createButtonsForButtonBar(Composite parent) { +// Button[] buttons= new Button[2]; +// buttons[0]= createButton(parent, restoreId, restoreButtonLabel, false); +// buttons[1]= createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, true); +// setButtons(buttons); +// } +// }; +// int returnValue= dialog.open(); +// if (restoreId == returnValue || settingsId == returnValue) { +// if (restoreId == returnValue) { +// IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); +// store.setToDefault(PreferenceConstants.CODEASSIST_CATEGORY_ORDER); +// store.setToDefault(PreferenceConstants.CODEASSIST_EXCLUDED_CATEGORIES); +// } +// if (settingsId == returnValue) { +// PreferencesUtil.createPreferenceDialogOn(shell, +// "org.eclipse.jdt.ui.preferences.CodeAssistPreferenceAdvanced", null, null).open(); +// } +// fComputerRegistry.reload(); +// return true; +// } +// } +// return false; +// } + + private List getSeparateCategories() { + ArrayList sorted= new ArrayList(); + for (CompletionProposalCategory category : fCategories) { + if (checkSeparateEnablement(category)) + sorted.add(category); + } + Collections.sort(sorted, ORDER_COMPARATOR); + return sorted; + } + + /** + * Determine whether the category is enabled for separate use. + * + * @param category the category to check + * @return true if this category is enabled for separate use, false + * otherwise + * @since 3.8 + */ + protected boolean checkSeparateEnablement(CompletionProposalCategory category) { + return category.isSeparateCommand(); + } + + private String createEmptyMessage() { + return Messages.format_2(JavaTextMessages.ContentAssistProcessor_empty_message, + getCategoryLabel(fRepetition)); + } + + private String createIterationMessage() { + return Messages.format_2(JavaTextMessages.ContentAssistProcessor_toggle_affordance_update_message, + getCategoryLabel(fRepetition), fIterationGesture, getCategoryLabel(fRepetition + 1)); + } + + private String getCategoryLabel(int repetition) { + int iteration= repetition % fCategoryIteration.size(); + if (iteration == 0) + return JavaTextMessages.ContentAssistProcessor_defaultProposalCategory; + return toString(fCategoryIteration.get(iteration).get(0)); + } + + protected String toString(CompletionProposalCategory category) { + return category.getDisplayName(); + } + + private String getIterationGesture() { + TriggerSequence binding= getIterationBinding(); + return binding != null ? + Messages.format_2(JavaTextMessages.ContentAssistProcessor_toggle_affordance_press_gesture, + binding.format() ) + : JavaTextMessages.ContentAssistProcessor_toggle_affordance_click_gesture; + } + + protected KeySequence getIterationBinding() { + final IBindingService bindingSvc= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class); + TriggerSequence binding= bindingSvc.getBestActiveBindingFor( + ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); + if (binding instanceof KeySequence) + return (KeySequence) binding; + return null; + } + + /** + * Sets the current proposal sorter into the content assistant. + * + * @since 3.8 + * @see ProposalSorterRegistry#getCurrentSorter() the sorter used if true + */ + private void setContentAssistSorter() { +// ProposalSorterHandle currentSorter= ProposalSorterRegistry.getDefault().getCurrentSorter(); +// try { +// fAssistant.setSorter(currentSorter.getSorter()); +// } catch (InvalidRegistryObjectException x) { +// JavaPlugin.log(currentSorter.createExceptionStatus(x)); +// } catch (CoreException x) { +// JavaPlugin.log(currentSorter.createExceptionStatus(x)); +// } catch (RuntimeException x) { +// JavaPlugin.log(currentSorter.createExceptionStatus(x)); +// } + fAssistant.setSorter(new AlphabeticSorter()); + } + +} diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java new file mode 100644 index 000000000..a366dfb6e --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/internal/ui/text/java/JavaTextMessages.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015, 2015 Bruno Medeiros and other Contributors. + * 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: + * Bruno Medeiros - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.internal.ui.text.java; + +public interface JavaTextMessages { + + String ContentAssistProcessor_computing_proposals = + "Computing completion proposals"; + String ContentAssistProcessor_collecting_proposals = + "Collecting proposals"; + String ContentAssistProcessor_sorting_proposals = + "Sorting"; + + String ContentAssistProcessor_computing_contexts = + "Computing context information"; + String ContentAssistProcessor_collecting_contexts = + "Collecting context information"; + String ContentAssistProcessor_sorting_contexts = + "Sorting"; + + String ContentAssistProcessor_empty_message = "No {0}"; + String ContentAssistProcessor_toggle_affordance_update_message = "{1} to show {2}"; + String ContentAssistProcessor_defaultProposalCategory = "Default Proposals"; + String ContentAssistProcessor_toggle_affordance_press_gesture = "Press ''{0}''"; + String ContentAssistProcessor_toggle_affordance_click_gesture = "Click"; + String ContentAssistProcessor_all_disabled_title = "Content Assist Problem"; + String ContentAssistProcessor_all_disabled_message = + "Some content proposal kinds have been uninstalled. It is recommended to review the content assist settings."; + String ContentAssistProcessor_all_disabled_preference_link = + "Change the settings on the Advanced Content Assist preference page or click ''{0}'' to restore the default behavior."; + +} diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/AbstractProposalSorter.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/AbstractProposalSorter.java new file mode 100644 index 000000000..e79e9f042 --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/AbstractProposalSorter.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2006, 2012 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 + * Marcel Bruch - [content assist] Allow to re-sort proposals - https://bugs.eclipse.org/bugs/show_bug.cgi?id=350991 + *******************************************************************************/ +package org.eclipse.jdt.ui.text.java; + +import java.util.Comparator; + +import org.eclipse.core.runtime.IConfigurationElement; + +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.ICompletionProposalSorter; + +/** + * Abstract base class for sorters contributed to the + * org.eclipse.jdt.ui.javaCompletionProposalSorters extension point. + *

+ * Subclasses need to implement {@link #compare(ICompletionProposal, ICompletionProposal)} and may + * override {@link #beginSorting(ContentAssistInvocationContext) beginSorting} and + * {@link #endSorting() endSorting}. + *

+ *

+ * The orderings imposed by a subclass need not be consistent with equals. + *

+ * + * @since 3.2 + */ +public abstract class AbstractProposalSorter implements Comparator, ICompletionProposalSorter { + + /** + * Creates a new sorter. Note that subclasses must provide a zero-argument constructor to be + * instantiatable via {@link IConfigurationElement#createExecutableExtension(String)}. + */ + protected AbstractProposalSorter() { + } + + /** + * Called once before initial sorting starts the first time. + *

+ * Note: As of 3.8 a completion proposal computer can request that proposals + * are resorted. If such a computer is active, then this method will not be called. + *

+ *

+ * Clients may override, the default implementation does nothing. + *

+ * + * @param context the context of the content assist invocation + */ + public void beginSorting(ContentAssistInvocationContext context) { + } + + /** + * The orderings imposed by an implementation need not be consistent with equals. + * + * @param p1 the first proposal to be compared + * @param p2 the second proposal to be compared + * @return a negative integer, zero, or a positive integer as the first argument is less than, + * equal to, or greater than the second + * + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @Override + public abstract int compare(ICompletionProposal p1, ICompletionProposal p2); + + /** + * Called once after the initial sorting finished. + *

+ * Note: As of 3.8 a completion proposal computer can request that proposals + * are resorted. If such a computer is active, then this method will not be called. + *

+ *

+ * Clients may override, the default implementation does nothing. + *

+ */ + public void endSorting() { + } +} diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/CompletionProposalComparator.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/CompletionProposalComparator.java new file mode 100644 index 000000000..f855fcf1d --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/CompletionProposalComparator.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 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.Comparator; + +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.templates.TemplateProposal; + +/** + * Comparator for java completion proposals. Completion proposals can be sorted by relevance or + * alphabetically. + *

+ * Note: this comparator imposes orderings that are inconsistent with equals. + *

+ * + * @since 3.1 + */ +public class CompletionProposalComparator implements Comparator { + + protected final boolean fOrderAlphabetically; + + public CompletionProposalComparator() { + fOrderAlphabetically= false; + } + + public CompletionProposalComparator(boolean fOrderAlphabetically) { + this.fOrderAlphabetically= fOrderAlphabetically; + } + + @Override + public int compare(ICompletionProposal p1, ICompletionProposal p2) { + if (!fOrderAlphabetically) { + int r1= getRelevance(p1); + int r2= getRelevance(p2); + int relevanceDif= r2 - r1; + if (relevanceDif != 0) { + return relevanceDif; + } + } + + return getSortKey(p1).compareToIgnoreCase(getSortKey(p2)); + } + + protected String getSortKey(ICompletionProposal p) { +// if (p instanceof AbstractJavaCompletionProposal) +// return ((AbstractJavaCompletionProposal) p).getSortString(); + return p.getDisplayString(); + } + + protected int getRelevance(ICompletionProposal obj) { + if (obj instanceof IJavaCompletionProposal) { + IJavaCompletionProposal jcp= (IJavaCompletionProposal) obj; + return jcp.getRelevance(); + } else if (obj instanceof TemplateProposal) { + TemplateProposal tp= (TemplateProposal) obj; + return tp.getRelevance(); + } + // catch all + return 0; + } + +} \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/ContentAssistInvocationContext.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/ContentAssistInvocationContext.java new file mode 100644 index 000000000..d8746d905 --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/ContentAssistInvocationContext.java @@ -0,0 +1,179 @@ +/******************************************************************************* + * Copyright (c) 2005, 2011 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 org.eclipse.core.runtime.Assert; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; + +/** + * Describes the context of an invocation of content assist in a text viewer. The context knows the + * document, the invocation offset and can lazily compute the identifier prefix preceding the + * invocation offset. It may know the viewer. + *

+ * Subclasses may add information to their environment. For example, source code editors may provide + * specific context information such as an AST. + *

+ *

+ * Clients may instantiate and subclass. + *

+ * + * @since 3.2 + */ +public class ContentAssistInvocationContext { + + /* state */ + private final ITextViewer fViewer; + private final IDocument fDocument; + private final int fOffset; + + /* cached additional info */ + private CharSequence fPrefix; + + public ContentAssistInvocationContext(ITextViewer viewer) { + this(viewer, viewer.getSelectedRange().x); + } + + /** + * Creates a new context for the given viewer and offset. + * + * @param viewer the text viewer that content assist is invoked in + * @param offset the offset into the viewer's document where content assist is invoked at + */ + public ContentAssistInvocationContext(ITextViewer viewer, int offset) { + Assert.isNotNull(viewer); + fViewer= viewer; + fDocument= null; + fOffset= offset; + } + + /** + * Creates a new context with no viewer or invocation offset set. + */ + protected ContentAssistInvocationContext() { + fDocument= null; + fViewer= null; + fOffset= -1; + } + + /** + * Creates a new context for the given document and offset. + * + * @param document the document that content assist is invoked in + * @param offset the offset into the document where content assist is invoked at + */ + public ContentAssistInvocationContext(IDocument document, int offset) { + Assert.isNotNull(document); + Assert.isTrue(offset >= 0); + fViewer= null; + fDocument= document; + fOffset= offset; + } + + public final int getInvocationOffset() { + return fOffset; + } + + /** @return the viewer, possibly null */ + public final ITextViewer getViewer() { + return fViewer; + } + + /** + * Returns the document that content assist is invoked on, or null if not known. + * + * @return the document or null + */ + public IDocument getDocument() { + if (fDocument == null) { + if (fViewer == null) + return null; + return fViewer.getDocument(); + } + return fDocument; + } + + /** + * Computes the identifier (as specified by {@link Character#isJavaIdentifierPart(char)}) that + * immediately precedes the invocation offset. + * + * @return the prefix preceding the content assist invocation offset, null if + * there is no document + * @throws BadLocationException if accessing the document fails + */ + public CharSequence computeIdentifierPrefix() throws BadLocationException { + if (fPrefix == null) { + IDocument document= getDocument(); + if (document == null) + return null; + int end= getInvocationOffset(); + int start= end; + while (--start >= 0) { + if (!Character.isJavaIdentifierPart(document.getChar(start))) + break; + } + start++; + fPrefix= document.get(start, end - start); + } + + return fPrefix; + } + + /** + * Invocation contexts are equal if they describe the same context and are of the same type. + * This implementation checks for null values and class equality. Subclasses + * should extend this method by adding checks for their context relevant fields (but not + * necessarily cached values). + *

+ * Example: + * + *

+	 * class MyContext extends ContentAssistInvocationContext {
+	 * 	private final Object fState;
+	 * 	private Object fCachedInfo;
+	 *
+	 * 	...
+	 *
+	 * 	public boolean equals(Object obj) {
+	 * 		if (!super.equals(obj))
+	 * 			return false;
+	 * 		MyContext other= (MyContext) obj;
+	 * 		return fState.equals(other.fState);
+	 * 	}
+	 * }
+	 * 
+ * + *

+ *

+ * Subclasses should also extend {@link Object#hashCode()}. + *

+ * + * @param obj {@inheritDoc} + * @return {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (!getClass().equals(obj.getClass())) + return false; + ContentAssistInvocationContext other= (ContentAssistInvocationContext) obj; + return (fViewer == null && other.fViewer == null || fViewer != null && fViewer.equals(other.fViewer)) && fOffset == other.fOffset && (fDocument == null && other.fDocument == null || fDocument != null && fDocument.equals(other.fDocument)); + } + + @Override + public int hashCode() { + return 23459213 << 5 | (fViewer == null ? 0 : fViewer.hashCode() << 3) | fOffset; + } + +} \ No newline at end of file diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/IJavaCompletionProposal.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/IJavaCompletionProposal.java new file mode 100644 index 000000000..64885843b --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/IJavaCompletionProposal.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2000, 2012 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 org.eclipse.jface.text.contentassist.ICompletionProposal; + +/** + * A completion proposal with a relevance value. + * The relevance value is used to sort the completion proposals. Proposals with higher relevance + * should be listed before proposals with lower relevance. + *

+ * This interface can be implemented by clients. + *

+ * + * @see org.eclipse.jface.text.contentassist.ICompletionProposal + * @since 2.1 + */ +public interface IJavaCompletionProposal extends ICompletionProposal { + + /** + * Returns the relevance of this completion proposal. + *

+ * The relevance is used to determine if this proposal is more + * relevant than another proposal.

+ * + * @return the relevance of this completion proposal in the range of [0, 1000] + */ + int getRelevance(); + +} diff --git a/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/IJavaCompletionProposalComputer.java b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/IJavaCompletionProposalComputer.java new file mode 100644 index 000000000..9aaa09893 --- /dev/null +++ b/plugin_ide.ui/src-lang/org/eclipse/jdt/ui/text/java/IJavaCompletionProposalComputer.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 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.List; + +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContextInformation; + +/** + * Computes completions and context information displayed by the Java editor content assistant. + * Contributions to the org.eclipse.jdt.ui.javaCompletionProposalComputer extension point + * must implement this interface. + * + * @since 3.2 + */ +public interface IJavaCompletionProposalComputer { + /** + * Informs the computer that a content assist session has started. This call will always be + * followed by a {@link #sessionEnded()} call, but not necessarily by calls to + * {@linkplain #computeCompletionProposals(ContentAssistInvocationContext, IProgressMonitor) computeCompletionProposals} + * or + * {@linkplain #computeContextInformation(ContentAssistInvocationContext, IProgressMonitor) computeContextInformation}. + */ + void sessionStarted(); + + /** + * Returns a list of completion proposals valid at the given invocation context. + * + * @param context the context of the content assist invocation + * @param monitor a progress monitor to report progress. The monitor is private to this + * invocation, i.e. there is no need for the receiver to spawn a sub monitor. + * @return a list of completion proposals (element type: {@link ICompletionProposal}) + */ + List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor); + + /** + * Returns context information objects valid at the given invocation context. + * + * @param context the context of the content assist invocation + * @param monitor a progress monitor to report progress. The monitor is private to this + * invocation, i.e. there is no need for the receiver to spawn a sub monitor. + * @return a list of context information objects (element type: {@link IContextInformation}) + */ + List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor); + + /** + * Returns the reason why this computer was unable to produce any completion proposals or + * context information. + * + * @return an error message or null if no error occurred + */ + String getErrorMessage(); + + /** + * Informs the computer that a content assist session has ended. This call will always be after + * any calls to + * {@linkplain #computeCompletionProposals(ContentAssistInvocationContext, IProgressMonitor) computeCompletionProposals} + * and + * {@linkplain #computeContextInformation(ContentAssistInvocationContext, IProgressMonitor) computeContextInformation}. + */ + void sessionEnded(); +} diff --git a/plugin_ide.ui/src/LANG_PROJECT_ID/ide/ui/editor/LANGUAGE_SourceViewerConfiguration.java b/plugin_ide.ui/src/LANG_PROJECT_ID/ide/ui/editor/LANGUAGE_SourceViewerConfiguration.java index 159f72fda..7deb954d1 100644 --- a/plugin_ide.ui/src/LANG_PROJECT_ID/ide/ui/editor/LANGUAGE_SourceViewerConfiguration.java +++ b/plugin_ide.ui/src/LANG_PROJECT_ID/ide/ui/editor/LANGUAGE_SourceViewerConfiguration.java @@ -17,9 +17,11 @@ import melnorme.lang.ide.ui.text.AbstractLangSourceViewerConfiguration; import org.eclipse.cdt.ui.text.IColorManager; +import org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.IContentAssistant; import org.eclipse.jface.text.source.ISourceViewer; import LANG_PROJECT_ID.ide.ui.text.LANGUAGE_CodeScanner; @@ -66,4 +68,12 @@ public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, Str } } + /** + * TODO: Use {@link ContentAssistProcessor} + */ + @Override + public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { + return super.getContentAssistant(sourceViewer); + } + } \ No newline at end of file From bbf7462ab4cbf95582067ae93c4e0d28871e973f Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Tue, 31 Mar 2015 15:59:56 +0100 Subject: [PATCH 4/4] LANG: API change, needs review of all indirect users of LangProjectBuilderExt.runBuildTool_2() --- .../core/operations/AbstractToolsManager.java | 27 ++----------------- .../operations/LangProjectBuilderExt.java | 20 ++++++++------ .../melnorme/lang/utils/ProcessUtils.java | 7 ++++- 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/AbstractToolsManager.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/AbstractToolsManager.java index d5cd0be4e..94d9535f1 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/AbstractToolsManager.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/AbstractToolsManager.java @@ -11,15 +11,12 @@ package melnorme.lang.ide.core.operations; import melnorme.lang.ide.core.ILangOperationsListener_Actual; -import melnorme.lang.ide.core.utils.EclipseUtils; -import melnorme.lang.ide.core.utils.ResourceUtils; import melnorme.lang.ide.core.utils.process.AbstractRunProcessTask; import melnorme.lang.ide.core.utils.process.RunExternalProcessTask; import melnorme.lang.tooling.data.StatusLevel; import melnorme.utilbox.concurrency.OperationCancellation; import melnorme.utilbox.core.CommonException; import melnorme.utilbox.misc.ListenerListHelper; -import melnorme.utilbox.misc.Location; import melnorme.utilbox.process.ExternalProcessHelper.ExternalProcessResult; import melnorme.utilbox.process.ExternalProcessNotifyingHelper; @@ -56,30 +53,10 @@ public RunExternalProcessTask newRunToolTask(ProcessBuilder pb, IProject project return new RunExternalProcessTask(pb, project, pm, this); } - public ExternalProcessResult runTool(IProject project, IProgressMonitor pm, ProcessBuilder pb) - throws CoreException, OperationCancellation { - // Note: project can be null - return runTool(project, pm, pb, null, false); - } - - public ExternalProcessResult runTool(IProject project, IProgressMonitor pm, ProcessBuilder pb, - String processInput, boolean throwOnNonZero) - throws CoreException, OperationCancellation { - Location workingDir = project == null ? null : ResourceUtils.getProjectLocation(project); - if(workingDir != null) { - pb.directory(workingDir.toFile()); - } - - EclipseUtils.checkMonitorCancelation(pm); - - return newRunToolTask(pb, project, pm).runProcess(processInput, throwOnNonZero); - } - /* ----------------- ----------------- */ - public ExternalProcessResult runEngineTool( - ProcessBuilder pb, String clientInput, IProgressMonitor pm - ) throws CoreException, OperationCancellation { + public ExternalProcessResult runEngineTool(ProcessBuilder pb, String clientInput, IProgressMonitor pm) + throws CoreException, OperationCancellation { return new RunEngineClientOperation(pb, pm).runProcess(clientInput); } diff --git a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/LangProjectBuilderExt.java b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/LangProjectBuilderExt.java index 782f3517d..ff0f180b1 100644 --- a/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/LangProjectBuilderExt.java +++ b/plugin_ide.core/src-lang/melnorme/lang/ide/core/operations/LangProjectBuilderExt.java @@ -32,15 +32,19 @@ public LangProjectBuilderExt() { super(); } - protected ExternalProcessResult runBuildTool(IProgressMonitor monitor, ProcessBuilder pb) + protected ExternalProcessResult runBuildTool_2(IProgressMonitor monitor, ProcessBuilder pb) throws CoreException, OperationCancellation { - return getToolManager().runTool(getProject(), monitor, pb); + return getToolManager().newRunToolTask(pb, getProject(), monitor).runProcess(); } protected ExternalProcessResult runBuildTool(IProgressMonitor monitor, ArrayList2 toolCmdLine) throws CoreException, OperationCancellation { - ProcessBuilder pb = ProcessUtils.createProcessBuilder(toolCmdLine, null); - return runBuildTool(monitor, pb); + ProcessBuilder pb = createProcessBuilder(toolCmdLine); + return runBuildTool_2(monitor, pb); + } + + protected ProcessBuilder createProcessBuilder(ArrayList2 toolCmdLine) throws CoreException { + return ProcessUtils.createProcessBuilder(toolCmdLine, getProjectLocation()); } protected Location getProjectLocation() throws CoreException { @@ -75,7 +79,7 @@ public IProject[] execute(IProject project, IProgressMonitor monitor) ProcessBuilder pb = createBuildPB(); - ExternalProcessResult buildAllResult = runBuildTool(monitor, pb); + ExternalProcessResult buildAllResult = runBuildTool_2(monitor, pb); doBuild_processBuildResult(buildAllResult); return null; @@ -102,10 +106,10 @@ protected void clean(IProgressMonitor monitor) throws CoreException { } } + protected abstract ProcessBuilder createCleanPB() throws CoreException; + protected void doClean(IProgressMonitor monitor, ProcessBuilder pb) throws CoreException, OperationCancellation { - runBuildTool(monitor, pb); + runBuildTool_2(monitor, pb); } - protected abstract ProcessBuilder createCleanPB() throws CoreException; - } \ No newline at end of file diff --git a/plugin_tooling/src-lang/melnorme/lang/utils/ProcessUtils.java b/plugin_tooling/src-lang/melnorme/lang/utils/ProcessUtils.java index ad0cb2f7c..7e59dabb7 100644 --- a/plugin_tooling/src-lang/melnorme/lang/utils/ProcessUtils.java +++ b/plugin_tooling/src-lang/melnorme/lang/utils/ProcessUtils.java @@ -15,10 +15,15 @@ import java.io.File; import java.util.List; +import melnorme.utilbox.misc.Location; import melnorme.utilbox.misc.MiscUtil; public class ProcessUtils { - + + public static ProcessBuilder createProcessBuilder(List commandLine, Location workingDir) { + return createProcessBuilder(commandLine, workingDir.toFile()); + } + public static ProcessBuilder createProcessBuilder(List commandLine, File workingDir) { assertTrue(commandLine.size() > 0);