From 04c84a628a4490f53716e0a7ee78f457921c8726 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Thu, 11 Jul 2013 12:06:03 -0400 Subject: [PATCH] Bug 411498: Content assist in Makefile Editor for builtin functions --- .../META-INF/MANIFEST.MF | 2 +- .../core/makefile/IAutomaticVariable.java | 23 ++ .../make/core/makefile/IBuiltinFunction.java | 32 +++ .../cdt/make/core/makefile/IMakefile.java | 12 + .../core/makefile/AbstractMakefile.java | 6 + .../internal/core/makefile/NullMakefile.java | 9 +- .../core/makefile/gnu/AutomaticVariable.java | 3 +- .../core/makefile/gnu/BuiltinFunction.java | 76 +++++ .../core/makefile/gnu/GNUMakefile.java | 68 ++++- .../core/makefile/posix/PosixMakefile.java | 7 + .../icons/obj16/builtin_func.png | Bin 0 -> 270 bytes .../cdt/make/internal/ui/MakeUIImages.java | 1 + .../editor/MakefileSourceConfiguration.java | 10 + .../ui/text/CompletionProposalComparator.java | 29 -- .../internal/ui/text/WordPartDetector.java | 9 +- .../makefile/MakefileCompletionProcessor.java | 260 ++++++++++++------ 16 files changed, 425 insertions(+), 122 deletions(-) create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IAutomaticVariable.java create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IBuiltinFunction.java create mode 100644 build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/BuiltinFunction.java create mode 100644 build/org.eclipse.cdt.make.ui/icons/obj16/builtin_func.png delete mode 100644 build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/CompletionProposalComparator.java diff --git a/build/org.eclipse.cdt.make.core/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.make.core/META-INF/MANIFEST.MF index fb8700a967e..b032ae5c173 100644 --- a/build/org.eclipse.cdt.make.core/META-INF/MANIFEST.MF +++ b/build/org.eclipse.cdt.make.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.make.core; singleton:=true -Bundle-Version: 7.2.0.qualifier +Bundle-Version: 7.3.0.qualifier Bundle-Activator: org.eclipse.cdt.make.core.MakeCorePlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IAutomaticVariable.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IAutomaticVariable.java new file mode 100644 index 00000000000..45111edb54a --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IAutomaticVariable.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2013,2013 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.make.core.makefile; + +import org.eclipse.cdt.make.core.makefile.gnu.IVariableDefinition; + +/** + * Interface fore built-in automatic variables. + * + * @noextend This class is not intended to be subclassed by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @since 7.3 + */ +public interface IAutomaticVariable extends IVariableDefinition { +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IBuiltinFunction.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IBuiltinFunction.java new file mode 100644 index 00000000000..0c54baeb608 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IBuiltinFunction.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2013,2013 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.make.core.makefile; + +/** + * Interface fore built-in internal functions. + * + * @noextend This class is not intended to be subclassed by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @since 7.3 + */ +public interface IBuiltinFunction extends IDirective { + + /** + * @return the name of the function + */ + String getName(); + + /** + * @return the value of the function + */ + StringBuffer getValue(); + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IMakefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IMakefile.java index d7a0f438584..73651f51d81 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IMakefile.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/core/makefile/IMakefile.java @@ -84,11 +84,23 @@ public interface IMakefile extends IParent { */ IDirective[] getBuiltins(); + /** + * @return all the built-in FunctionDefintions + * @since 7.3 + */ + IBuiltinFunction[] getBuiltinFunctions(); + /** * @return all the built-in MacroDefintions */ IMacroDefinition[] getBuiltinMacroDefinitions(); + /** + * @return all the built-in MacroDefintions + * @since 7.3 + */ + IAutomaticVariable[] getAutomaticVariables(); + /** * @return the built-in macro definition for name. */ diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/AbstractMakefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/AbstractMakefile.java index e93b5bc5f82..8d85114dfac 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/AbstractMakefile.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/AbstractMakefile.java @@ -14,6 +14,7 @@ import java.net.URI; import java.util.ArrayList; import java.util.List; +import org.eclipse.cdt.make.core.makefile.IBuiltinFunction; import org.eclipse.cdt.make.core.makefile.IDirective; import org.eclipse.cdt.make.core.makefile.IInferenceRule; import org.eclipse.cdt.make.core.makefile.IMacroDefinition; @@ -47,6 +48,11 @@ public abstract class AbstractMakefile extends Parent implements IMakefile { @Override public abstract IDirective[] getBuiltins(); + @Override + public IBuiltinFunction[] getBuiltinFunctions() { + return new IBuiltinFunction[0]; + } + @Override public IRule[] getRules() { IDirective[] stmts = getDirectives(true); diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/NullMakefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/NullMakefile.java index 17924fb2d13..71a03855dd3 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/NullMakefile.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/NullMakefile.java @@ -14,6 +14,7 @@ import java.io.IOException; import java.io.Reader; import java.net.URI; +import org.eclipse.cdt.make.core.makefile.IAutomaticVariable; import org.eclipse.cdt.make.core.makefile.IDirective; import org.eclipse.cdt.make.core.makefile.IMakefileReaderProvider; @@ -34,7 +35,8 @@ import org.eclipse.cdt.make.core.makefile.IMakefileReaderProvider; */ public class NullMakefile extends AbstractMakefile { - public final static IDirective[] EMPTY_DIRECTIVES = new IDirective[0]; + private final static IDirective[] EMPTY_DIRECTIVES = new IDirective[0]; + private final static IAutomaticVariable[] EMPTY_AUTOMATIC_VARIABLES = new IAutomaticVariable[0]; public NullMakefile() { super(null); @@ -50,6 +52,11 @@ public class NullMakefile extends AbstractMakefile { return EMPTY_DIRECTIVES; } + @Override + public IAutomaticVariable[] getAutomaticVariables() { + return EMPTY_AUTOMATIC_VARIABLES; + } + public void addDirective(IDirective directive) { } diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/AutomaticVariable.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/AutomaticVariable.java index df6862b510f..6a9e6013b4c 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/AutomaticVariable.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/AutomaticVariable.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.cdt.make.internal.core.makefile.gnu; +import org.eclipse.cdt.make.core.makefile.IAutomaticVariable; import org.eclipse.cdt.make.internal.core.makefile.Directive; @@ -20,7 +21,7 @@ import org.eclipse.cdt.make.internal.core.makefile.Directive; * @author Sebastian Bauer * @see "http://www.gnu.org/software/make/manual/make.html#Automatic-Variables" */ -public class AutomaticVariable extends VariableDefinition { +public class AutomaticVariable extends VariableDefinition implements IAutomaticVariable { public AutomaticVariable(Directive parent, String name, String description) { super(parent, name, new StringBuffer(description)); diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/BuiltinFunction.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/BuiltinFunction.java new file mode 100644 index 00000000000..1f062cf0013 --- /dev/null +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/BuiltinFunction.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2013,2013 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.make.internal.core.makefile.gnu; + +import org.eclipse.cdt.make.core.makefile.IBuiltinFunction; +import org.eclipse.cdt.make.core.makefile.IDirective; +import org.eclipse.cdt.make.core.makefile.IMakefile; +import org.eclipse.cdt.make.internal.core.makefile.Directive; + + +/** + * Represents GNUmakefile built-in internal functions. + */ +public class BuiltinFunction implements IBuiltinFunction { + private String name; + private Directive parent; + private StringBuffer sample; + + public BuiltinFunction(Directive parent, String sample) { + this.name = getNameFromSample(sample); + this.parent = parent; + this.sample = new StringBuffer(sample); + } + + private static String getNameFromSample(String sample) { + String name = sample; + if (sample.startsWith("$(") && sample.endsWith(")")) { //$NON-NLS-1$ //$NON-NLS-2$ + name = sample.substring(2, sample.length() - 1); + } + return name; + } + + @Override + public IDirective getParent() { + return parent; + } + + @Override + public int getStartLine() { + return -1; + } + + @Override + public int getEndLine() { + return -1; + } + + @Override + public IMakefile getMakefile() { + return null; + } + + @Override + public String getName() { + return name; + } + + @Override + public StringBuffer getValue() { + return sample; + } + + @Override + public String toString() { + return name; + } + +} diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/GNUMakefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/GNUMakefile.java index ff642da143e..d825159b9a6 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/GNUMakefile.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/GNUMakefile.java @@ -21,6 +21,8 @@ import java.util.Stack; import java.util.StringTokenizer; import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.makefile.IAutomaticVariable; +import org.eclipse.cdt.make.core.makefile.IBuiltinFunction; import org.eclipse.cdt.make.core.makefile.IDirective; import org.eclipse.cdt.make.core.makefile.IMakefileReaderProvider; import org.eclipse.cdt.make.core.makefile.gnu.IGNUMakefile; @@ -74,8 +76,9 @@ public class GNUMakefile extends AbstractMakefile implements IGNUMakefile { public static String FILE_SEPARATOR = System.getProperty("file.separator", "/"); //$NON-NLS-1$ //$NON-NLS-2$ private String[] includeDirectories = new String[0]; + private IDirective[] builtins = new IDirective[0]; @SuppressWarnings("nls") - private IDirective[] builtins = new IDirective[]{ + private IAutomaticVariable[] autoVariables = new IAutomaticVariable[]{ new AutomaticVariable(this, "@", MakefileMessages.getString("GNUMakefile.automaticVariable.at")), new AutomaticVariable(this, "%", MakefileMessages.getString("GNUMakefile.automaticVariable.percent")), new AutomaticVariable(this, "<", MakefileMessages.getString("GNUMakefile.automaticVariable.less")), @@ -85,6 +88,59 @@ public class GNUMakefile extends AbstractMakefile implements IGNUMakefile { new AutomaticVariable(this, "|", MakefileMessages.getString("GNUMakefile.automaticVariable.pipe")), new AutomaticVariable(this, "*", MakefileMessages.getString("GNUMakefile.automaticVariable.star")), }; + + @SuppressWarnings("nls") + private final static String[] functions = { + "subst", "patsubst", "strip", "findstring", + "filter", "filter-out", "sort", + "word", "words", "wordlist", "firstword", "lastword", + "dir", "notdir", + "suffix", "basename", "addsuffix", "addprefix", + "join", "wildcard", "realpath", "abspath", + "if", "or", "and", "foreach", + "call", "value", "eval", "origin", "flavor", + "shell", "error", "warning", "info", + }; + + @SuppressWarnings("nls") + private IBuiltinFunction[] builtinFunctions = new IBuiltinFunction[]{ + new BuiltinFunction(this, "$(subst from,to,text)"), + new BuiltinFunction(this, "$(patsubst pattern,replacement,text)"), + new BuiltinFunction(this, "$(strip string)"), + new BuiltinFunction(this, "$(findstring find,in)"), + new BuiltinFunction(this, "$(filter pattern,text)"), + new BuiltinFunction(this, "$(filter-out pattern,text)"), + new BuiltinFunction(this, "$(sort list)"), + new BuiltinFunction(this, "$(word n,text)"), + new BuiltinFunction(this, "$(words text)"), + new BuiltinFunction(this, "$(wordlist s,e,text)"), + new BuiltinFunction(this, "$(firstword names)"), + new BuiltinFunction(this, "$(lastword names)"), + new BuiltinFunction(this, "$(dir names)"), + new BuiltinFunction(this, "$(notdir names)"), + new BuiltinFunction(this, "$(suffix names)"), + new BuiltinFunction(this, "$(basename names)"), + new BuiltinFunction(this, "$(addsuffix suffix,names)"), + new BuiltinFunction(this, "$(addprefix prefix,names)"), + new BuiltinFunction(this, "$(join list1,list2)"), + new BuiltinFunction(this, "$(wildcard pattern)"), + new BuiltinFunction(this, "$(realpath names)"), + new BuiltinFunction(this, "$(abspath names)"), + new BuiltinFunction(this, "$(if condition,then-part,else-part)"), + new BuiltinFunction(this, "$(or condition1,condition2,...)"), + new BuiltinFunction(this, "$(and condition1,condition2,...)"), + new BuiltinFunction(this, "$(foreach var,list,text)"), + new BuiltinFunction(this, "$(call variable,param,...)"), + new BuiltinFunction(this, "$(value variable)"), + new BuiltinFunction(this, "$(eval expression)"), + new BuiltinFunction(this, "$(origin variable)"), + new BuiltinFunction(this, "$(flavor variable)"), + new BuiltinFunction(this, "$(shell command)"), + new BuiltinFunction(this, "$(error error: text)"), + new BuiltinFunction(this, "$(warning warning: text)"), + new BuiltinFunction(this, "$(info info: text)"), + }; + private IMakefileReaderProvider makefileReaderProvider; public GNUMakefile() { @@ -798,6 +854,16 @@ public class GNUMakefile extends AbstractMakefile implements IGNUMakefile { return builtins; } + @Override + public IAutomaticVariable[] getAutomaticVariables() { + return autoVariables; + } + + @Override + public IBuiltinFunction[] getBuiltinFunctions() { + return builtinFunctions; + } + @Override public void setIncludeDirectories(String[] dirs) { includeDirectories = dirs; diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixMakefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixMakefile.java index 73aef26a65c..f3fb7201944 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixMakefile.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/posix/PosixMakefile.java @@ -17,6 +17,7 @@ import java.io.Reader; import java.net.URI; import org.eclipse.cdt.make.core.MakeCorePlugin; +import org.eclipse.cdt.make.core.makefile.IAutomaticVariable; import org.eclipse.cdt.make.core.makefile.IDirective; import org.eclipse.cdt.make.core.makefile.IMakefileReaderProvider; import org.eclipse.cdt.make.internal.core.makefile.AbstractMakefile; @@ -64,6 +65,7 @@ import org.eclipse.core.runtime.CoreException; public class PosixMakefile extends AbstractMakefile { private IDirective[] builtins = new IDirective[0]; + private IAutomaticVariable[] automaticVariables = new IAutomaticVariable[0]; private IMakefileReaderProvider makefileReaderProvider; public PosixMakefile() { @@ -230,6 +232,11 @@ public class PosixMakefile extends AbstractMakefile { public IDirective[] getBuiltins() { return builtins; } + @Override + public IAutomaticVariable[] getAutomaticVariables() { + return automaticVariables; + } + protected SpecialRule processSpecialRule(String line) { line = line.trim(); diff --git a/build/org.eclipse.cdt.make.ui/icons/obj16/builtin_func.png b/build/org.eclipse.cdt.make.ui/icons/obj16/builtin_func.png new file mode 100644 index 0000000000000000000000000000000000000000..c9b500cd2ab44cb71529d97bddac7818d7e46f79 GIT binary patch literal 270 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Y$ZW{!9W@a@|Lkr1X71RT^vIy z<|HRb{Av&kesTZ){u423X=y2X+{<3svzOhyyYcVkrQ9`DY^UVr{r~sR_1fWD#M6mOsGSoSc@RndMs!~N#(0u%kYn&kJ_1-yUJ9^I70%*=dv zxwrU(Rgw}CKjilOFL}w-HT{CghnJEyK>{u>!UdjOHa@W2@#f*rA3rh+*v=PWk(ak$ z@aAFX8V1!VGiJ>E|Mze9i30`Y$G;svum7o2N@7~*CW{@4?LsF%8gMW&6iWHEu=ZQd P0C~&P)z4*}Q$iB}(QI%% literal 0 HcmV?d00001 diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeUIImages.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeUIImages.java index 2de0acfb3b5..ae601a8abc2 100644 --- a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeUIImages.java +++ b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/MakeUIImages.java @@ -52,6 +52,7 @@ public class MakeUIImages { public static final String IMG_OBJS_ENVIRONMENT = "icons/obj16/environment_obj.gif"; //$NON-NLS-1$ public static final String IMG_OBJS_ENV_VAR = "icons/obj16/envvar_obj.gif"; //$NON-NLS-1$ public static final String IMG_OBJS_AUTO_VARIABLE = "icons/obj16/var_auto.png"; //$NON-NLS-1$ + public static final String IMG_OBJS_FUNCTION = "icons/obj16/builtin_func.png"; //$NON-NLS-1$ public static final String IMG_ETOOL_MAKEFILE = "icons/etool16/makefile.gif"; //$NON-NLS-1$ public static final String IMG_ETOOL_TARGET_BUILD = "icons/etool16/target_build.png"; //$NON-NLS-1$ diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/editor/MakefileSourceConfiguration.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/editor/MakefileSourceConfiguration.java index 2f2b7d238dd..3296493a88c 100644 --- a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/editor/MakefileSourceConfiguration.java +++ b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/editor/MakefileSourceConfiguration.java @@ -23,7 +23,10 @@ import org.eclipse.cdt.make.internal.ui.text.makefile.MakefileReconcilingStrateg import org.eclipse.cdt.make.internal.ui.text.makefile.MakefileTextHover; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.ITextHover; import org.eclipse.jface.text.contentassist.ContentAssistant; import org.eclipse.jface.text.contentassist.IContentAssistant; @@ -38,6 +41,7 @@ import org.eclipse.jface.text.source.IAnnotationHover; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; public class MakefileSourceConfiguration extends TextSourceViewerConfiguration { @@ -95,6 +99,12 @@ public class MakefileSourceConfiguration extends TextSourceViewerConfiguration { assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY); assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE); assistant.setContextInformationPopupBackground(fColorManager.getColor(new RGB(255, 255, 255))); + assistant.setInformationControlCreator(new IInformationControlCreator() { + @Override + public IInformationControl createInformationControl(Shell parent) { + return new DefaultInformationControl(parent, false); + } + }); return assistant; } diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/CompletionProposalComparator.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/CompletionProposalComparator.java deleted file mode 100644 index 9390183ad7b..00000000000 --- a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/CompletionProposalComparator.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2013 QNX Software Systems 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: - * QNX Software Systems - Initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.make.internal.ui.text; - -import java.util.Comparator; - -import org.eclipse.jface.text.contentassist.ICompletionProposal; - -public class CompletionProposalComparator implements Comparator { - /** - * Constructor for CompletionProposalComparator. - */ - public CompletionProposalComparator() { - } - - @Override - public int compare(ICompletionProposal c1, ICompletionProposal c2) { - return c1.getDisplayString().compareToIgnoreCase(c2.getDisplayString()); - } - -} diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/WordPartDetector.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/WordPartDetector.java index 9907f9755d9..780e3975dcf 100644 --- a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/WordPartDetector.java +++ b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/WordPartDetector.java @@ -25,8 +25,8 @@ public class WordPartDetector { private enum WORDPART_TYPE { MACRO, - INCLUDE, FUNCTION_CALL, + INCLUDE, UNDETERMINED, } @@ -61,6 +61,11 @@ public class WordPartDetector { c = document.getChar(index); if (c == '$') { type = WORDPART_TYPE.MACRO; + int index2 = index + 1; + if (index2 < doc.getLength()) { + c = document.getChar(index2); + wordPart = doc.get(index2, endOffset - index2); + } return; } else if (Character.isWhitespace(c) || c == ')' || c == '}') { break; @@ -193,6 +198,6 @@ public class WordPartDetector { } private boolean isMakefileLetter(char c) { - return Character.isLetterOrDigit(c) || c == '_' || c == '.'; + return Character.isLetterOrDigit(c) || "_-.@%= 0; } } diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/makefile/MakefileCompletionProcessor.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/makefile/MakefileCompletionProcessor.java index 79098c5622b..39a1290c5b9 100644 --- a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/makefile/MakefileCompletionProcessor.java +++ b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/makefile/MakefileCompletionProcessor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 QNX Software Systems and others. + * Copyright (c) 2000, 2013 QNX Software Systems 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 @@ -7,21 +7,23 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Andrew Gvozdev *******************************************************************************/ package org.eclipse.cdt.make.internal.ui.text.makefile; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.List; +import org.eclipse.cdt.make.core.makefile.IAutomaticVariable; +import org.eclipse.cdt.make.core.makefile.IBuiltinFunction; import org.eclipse.cdt.make.core.makefile.IDirective; import org.eclipse.cdt.make.core.makefile.IMacroDefinition; import org.eclipse.cdt.make.core.makefile.IMakefile; -import org.eclipse.cdt.make.core.makefile.IRule; -import org.eclipse.cdt.make.internal.core.makefile.gnu.AutomaticVariable; +import org.eclipse.cdt.make.core.makefile.ITargetRule; import org.eclipse.cdt.make.internal.ui.MakeUIImages; import org.eclipse.cdt.make.internal.ui.MakeUIPlugin; -import org.eclipse.cdt.make.internal.ui.text.CompletionProposalComparator; import org.eclipse.cdt.make.internal.ui.text.WordPartDetector; import org.eclipse.cdt.make.ui.IWorkingCopyManager; import org.eclipse.cdt.ui.CDTSharedImages; @@ -61,42 +63,36 @@ public class MakefileCompletionProcessor implements IContentAssistProcessor { } } - public class DirectiveComparator implements Comparator { - @Override - public int compare(Object o1, Object o2) { - String name1; - String name2; - - if (o1 instanceof IMacroDefinition) { - name1 = ((IMacroDefinition)o1).getName(); - } else if (o1 instanceof IRule) { - name1 = ((IRule)o1).getTarget().toString(); - } else { - name1 =""; //$NON-NLS-1$ - } - - if (o2 instanceof IMacroDefinition) { - name2 = ((IMacroDefinition)o1).getName(); - } else if (o2 instanceof IRule) { - name2 = ((IRule)o1).getTarget().toString(); - } else { - name2 =""; //$NON-NLS-1$ - } - - //return String.CASE_INSENSITIVE_ORDER.compare(name1, name2); - return name1.compareToIgnoreCase(name2); - } - - } protected IContextInformationValidator fValidator = new Validator(); - protected Image imageMacro = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_VARIABLE); + protected Image imageFunction = MakeUIImages.getImage(MakeUIImages.IMG_OBJS_FUNCTION); + protected Image imageVariable = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_VARIABLE); protected Image imageAutomaticVariable = MakeUIImages.getImage(MakeUIImages.IMG_OBJS_AUTO_VARIABLE); protected Image imageTarget = MakeUIImages.getImage(MakeUIImages.IMG_OBJS_TARGET); - protected CompletionProposalComparator comparator = new CompletionProposalComparator(); protected IEditorPart fEditor; protected IWorkingCopyManager fManager; + private Comparator directivesComparator = new Comparator() { + @Override + public int compare(IDirective o1, IDirective o2) { + return o1.toString().compareToIgnoreCase(o2.toString()); + } + }; + + private class BracketHandler { + private char open; + private char closed; + private boolean found; + private String followingText; + public BracketHandler(String input) { + char firstChar = input.length() > 0 ? input.charAt(0) : 0; + open = firstChar == '{' ? '{' : '('; + closed = firstChar == '{' ? '}' : ')'; + found = firstChar == open; + followingText = found ? input.substring(1) : input; + } + } + public MakefileCompletionProcessor(IEditorPart editor) { fEditor = editor; fManager = MakeUIPlugin.getDefault().getWorkingCopyManager(); @@ -104,68 +100,161 @@ public class MakefileCompletionProcessor implements IContentAssistProcessor { @Override public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) { - WordPartDetector wordPart = new WordPartDetector(viewer.getDocument(), documentOffset); - boolean macro = wordPart.isMacro(); + List proposalList = new ArrayList(); IMakefile makefile = fManager.getWorkingCopy(fEditor.getEditorInput()); - IDirective[] statements = null; - if (macro) { - IDirective[] m1 = makefile.getMacroDefinitions(); - IDirective[] m2 = makefile.getBuiltinMacroDefinitions(); - statements = new IDirective[m1.length + m2.length]; - System.arraycopy(m1, 0, statements, 0, m1.length); - System.arraycopy(m2, 0, statements, m1.length, m2.length); + WordPartDetector wordPart = new WordPartDetector(viewer.getDocument(), documentOffset); + if (wordPart.isMacro()) { + IAutomaticVariable[] automaticVariables = makefile.getAutomaticVariables(); + proposalList.addAll(createCompletionProposals(wordPart, automaticVariables)); + + IMacroDefinition[] macroDefinitions = makefile.getMacroDefinitions(); + Arrays.sort(macroDefinitions, directivesComparator); + proposalList.addAll(createCompletionProposals(wordPart, macroDefinitions)); + + IBuiltinFunction[] builtinFunctions = makefile.getBuiltinFunctions(); + Arrays.sort(builtinFunctions, directivesComparator); + proposalList.addAll(createCompletionProposals(wordPart, builtinFunctions)); } else { - statements = makefile.getTargetRules(); + ITargetRule[] targetRules = makefile.getTargetRules(); + Arrays.sort(targetRules, directivesComparator); + proposalList.addAll(createCompletionProposals(wordPart, targetRules)); } - ArrayList proposalList = new ArrayList(statements.length); + return proposalList.toArray(new ICompletionProposal[proposalList.size()]); + } - // iterate over all the different categories - for (IDirective statement : statements) { - String name = null; - Image image = null; - String infoString = "";//getContentInfoString(name); //$NON-NLS-1$ - if (statement instanceof IMacroDefinition) { - name = ((IMacroDefinition) statement).getName(); - image = imageMacro; - infoString = ((IMacroDefinition)statement).getValue().toString(); - } else if (statement instanceof AutomaticVariable) { - name = ((IMacroDefinition) statement).getName(); - image = imageAutomaticVariable; - infoString = ((IMacroDefinition)statement).getValue().toString(); - } else if (statement instanceof IRule) { - name = ((IRule) statement).getTarget().toString(); - image = imageTarget; - infoString = name; - } - if (name != null && name.startsWith(wordPart.getName())) { - IContextInformation info = new ContextInformation(name, infoString); - String displayString = (name.equals(infoString) ? name : name + " - " + infoString); //$NON-NLS-1$ - ICompletionProposal result = - new CompletionProposal( - name, - wordPart.getOffset(), - wordPart.getName().length(), - name.length(), - image, - displayString, - info, - infoString); - proposalList.add(result); + private String macro(String name, BracketHandler bracket) { + if (bracket.found) { + name = bracket.open + name + bracket.closed; + } + return '$' + name; + } + + private ArrayList createCompletionProposals(WordPartDetector wordPart, IAutomaticVariable[] autoVars) { + ArrayList proposalList = new ArrayList(autoVars.length); + String wordPartName = wordPart.getName(); + BracketHandler bracket = new BracketHandler(wordPartName); + String partialName = bracket.followingText; + + for (IMacroDefinition autoVar : autoVars) { + String name = autoVar.getName(); + if (name.startsWith(partialName)) { + String replacement; + if (bracket.found) { + replacement = name + bracket.closed; + } else { + replacement = name; + } + CompletionProposal proposal = new CompletionProposal( + replacement, + wordPart.getOffset(), + partialName.length(), + replacement.length(), + imageAutomaticVariable, + macro(name, bracket) + " - " + autoVar.getValue().toString(), //$NON-NLS-1$ + null, + autoVar.getValue().toString()); + proposalList.add(proposal); } } - ICompletionProposal[] proposals = proposalList.toArray(new ICompletionProposal[0]); - Arrays.sort(proposals, comparator); - return proposals; + return proposalList; + } + + private ArrayList createCompletionProposals(WordPartDetector wordPart, IMacroDefinition[] macros) { + ArrayList proposalList = new ArrayList(macros.length); + + String wordPartName = wordPart.getName(); + BracketHandler bracket = new BracketHandler(wordPartName); + String partialName = bracket.followingText; + + for (IMacroDefinition macro : macros) { + String name = macro.getName(); + if (name.startsWith(partialName)) { + String replacement; + if (bracket.found) { + replacement = name + bracket.closed; + } else { + replacement = bracket.open + name + bracket.closed; + } + String displayString = name; + ICompletionProposal proposal = new CompletionProposal( + replacement, + wordPart.getOffset(), + partialName.length(), + replacement.length(), + imageVariable, + displayString, + null, + macro.getValue().toString()); + proposalList.add(proposal); + } + } + return proposalList; + } + + private ArrayList createCompletionProposals(WordPartDetector wordPart, IBuiltinFunction[] builtinFuns) { + ArrayList proposalList = new ArrayList(builtinFuns.length); + + String wordPartName = wordPart.getName(); + BracketHandler bracket = new BracketHandler(wordPartName); + String partialName = bracket.followingText; + + for (IBuiltinFunction builtinFun : builtinFuns) { + String name = builtinFun.getName(); + String replacement; + if (bracket.found) { + replacement = name + bracket.closed; + } else { + replacement = bracket.open + name + bracket.closed; + } + int indexComma = replacement.indexOf(','); + int cursorPosition = indexComma >= 0 ? indexComma : replacement.length() - 1; + if (name.startsWith(partialName)) { + ICompletionProposal proposal = new CompletionProposal( + replacement, + wordPart.getOffset(), + partialName.length(), + cursorPosition, + imageFunction, + "$" + bracket.open + name + bracket.closed, //$NON-NLS-1$ + null, + builtinFun.getValue().toString()); + proposalList.add(proposal); + } + } + return proposalList; + } + + private ArrayList createCompletionProposals(WordPartDetector wordPart, ITargetRule[] targets) { + ArrayList proposalList = new ArrayList(targets.length); + + String partialName = wordPart.getName(); + for (ITargetRule target : targets) { + String name = target.getTarget().toString(); + if (name.startsWith(partialName)) { + String replacement = name; + ICompletionProposal proposal = new CompletionProposal( + replacement, + wordPart.getOffset(), + partialName.length(), + replacement.length(), + imageTarget, + name, + null, + null); + proposalList.add(proposal); + } + } + return proposalList; } @Override public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) { WordPartDetector wordPart = new WordPartDetector(viewer.getDocument(), documentOffset); - boolean macro = wordPart.isMacro(); IMakefile makefile = fManager.getWorkingCopy(fEditor.getEditorInput()); ArrayList contextList = new ArrayList(); - if (macro) { + ArrayList contextInformationList = new ArrayList(); + if (wordPart.isMacro()) { IDirective[] statements = makefile.getMacroDefinitions(); for (IDirective statement : statements) { if (statement instanceof IMacroDefinition) { @@ -174,6 +263,7 @@ public class MakefileCompletionProcessor implements IContentAssistProcessor { String value = ((IMacroDefinition) statement).getValue().toString(); if (value != null && value.length() > 0) { contextList.add(value); + contextInformationList.add(new ContextInformation(imageVariable, wordPart.getName(), value)); } } } @@ -186,19 +276,15 @@ public class MakefileCompletionProcessor implements IContentAssistProcessor { String value = ((IMacroDefinition) statement).getValue().toString(); if (value != null && value.length() > 0) { contextList.add(value); + contextInformationList.add(new ContextInformation(imageAutomaticVariable, wordPart.getName(), value)); } } } } } - IContextInformation[] result = new IContextInformation[contextList.size()]; - for (int i = 0; i < result.length; i++) { - String context = contextList.get(i); - result[i] = new ContextInformation(imageMacro, wordPart.getName(), context); - } + IContextInformation[] result = contextInformationList.toArray(new IContextInformation[contextInformationList.size()]); return result; - } @Override