mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-02 22:05:44 +02:00
Patch form Thomas Fletcher to improve on completion.
This commit is contained in:
parent
aa3f10c491
commit
5248cce011
9 changed files with 784 additions and 176 deletions
|
@ -1,3 +1,21 @@
|
||||||
|
2003-06-24 Thomas Fletcher
|
||||||
|
|
||||||
|
- Proposals will now include additional help information with them
|
||||||
|
if it is available (same as JDT). This opens the door for being
|
||||||
|
able to write a Javadoc/Doxygen parser and integrating live,
|
||||||
|
context specific, help.
|
||||||
|
- On function completions a hover is now shown above the function
|
||||||
|
(same as JDT) with the argument information as it is being filled in.
|
||||||
|
|
||||||
|
* src/org/eclipse/cdt/internal/ui/editor/DefaultCEditorTextHover.java
|
||||||
|
* src/org/eclipse/cdt/internal/ui/text/CCompletionProcessor.java
|
||||||
|
* src/org/eclipse/cdt/internal/ui/text/CCompletionProposal.java
|
||||||
|
* src/org/eclipse/cdt/internal/ui/text/CParameterListValidator.java
|
||||||
|
* src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
|
||||||
|
* src/org/eclipse/cdt/internal/ui/text/CWordFinder.java
|
||||||
|
* src/org/eclipse/cdt/ui/IFunctionSummary.java
|
||||||
|
* src/org/eclipse/cdt/ui/FunctionPrototypeSummary.java
|
||||||
|
|
||||||
2003-06-23 John Camelon
|
2003-06-23 John Camelon
|
||||||
Updated Factory infrastructure, constructors, etc.
|
Updated Factory infrastructure, constructors, etc.
|
||||||
Introduced Preprocessor class for transitive closure calc. client.
|
Introduced Preprocessor class for transitive closure calc. client.
|
||||||
|
|
|
@ -60,9 +60,14 @@ public class DefaultCEditorTextHover implements ITextHover
|
||||||
|
|
||||||
IFunctionSummary fs = CCompletionContributorManager.getDefault().getFunctionInfo(expression);
|
IFunctionSummary fs = CCompletionContributorManager.getDefault().getFunctionInfo(expression);
|
||||||
if(fs != null) {
|
if(fs != null) {
|
||||||
buffer.append("<b>" + HTMLPrinter.convertToHTMLContent(expression) +
|
buffer.append("<b>");
|
||||||
"()</b> - " + HTMLPrinter.convertToHTMLContent(fs.getSummary()) +
|
buffer.append(HTMLPrinter.convertToHTMLContent(fs.getName()));
|
||||||
"<br><br>" + HTMLPrinter.convertToHTMLContent(fs.getSynopsis()));
|
buffer.append("()</b>");
|
||||||
|
buffer.append(HTMLPrinter.convertToHTMLContent(fs.getPrototype().getPrototypeString(false)));
|
||||||
|
if(fs.getDescription() != null) {
|
||||||
|
buffer.append("<br><br>");
|
||||||
|
buffer.append(HTMLPrinter.convertToHTMLContent(fs.getDescription()));
|
||||||
|
}
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < buffer.length(); i++) {
|
for(i = 0; i < buffer.length(); i++) {
|
||||||
if(buffer.charAt(i) == '\\') {
|
if(buffer.charAt(i) == '\\') {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.eclipse.cdt.internal.ui.editor.CEditor;
|
||||||
import org.eclipse.cdt.internal.ui.text.template.TemplateEngine;
|
import org.eclipse.cdt.internal.ui.text.template.TemplateEngine;
|
||||||
import org.eclipse.cdt.ui.CElementLabelProvider;
|
import org.eclipse.cdt.ui.CElementLabelProvider;
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
import org.eclipse.cdt.ui.FunctionPrototypeSummary;
|
||||||
import org.eclipse.cdt.ui.IFunctionSummary;
|
import org.eclipse.cdt.ui.IFunctionSummary;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
|
@ -28,6 +29,7 @@ import org.eclipse.jface.text.BadLocationException;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.jface.text.IDocument;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.ITextViewer;
|
import org.eclipse.jface.text.ITextViewer;
|
||||||
|
import org.eclipse.jface.text.contentassist.ContextInformation;
|
||||||
import org.eclipse.jface.text.contentassist.ICompletionProposal;
|
import org.eclipse.jface.text.contentassist.ICompletionProposal;
|
||||||
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
|
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
|
||||||
import org.eclipse.jface.text.contentassist.IContextInformation;
|
import org.eclipse.jface.text.contentassist.IContextInformation;
|
||||||
|
@ -46,8 +48,10 @@ public class CCompletionProcessor implements IContentAssistProcessor {
|
||||||
private CEditor fEditor;
|
private CEditor fEditor;
|
||||||
private char[] fProposalAutoActivationSet;
|
private char[] fProposalAutoActivationSet;
|
||||||
private CCompletionProposalComparator fComparator;
|
private CCompletionProposalComparator fComparator;
|
||||||
private TemplateEngine[] fTemplateEngine;
|
private IContextInformationValidator fValidator;
|
||||||
|
|
||||||
|
private TemplateEngine[] fTemplateEngine;
|
||||||
|
|
||||||
private boolean fRestrictToMatchingCase;
|
private boolean fRestrictToMatchingCase;
|
||||||
private boolean fAllowAddIncludes;
|
private boolean fAllowAddIncludes;
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ public class CCompletionProcessor implements IContentAssistProcessor {
|
||||||
|
|
||||||
public CCompletionProcessor(IEditorPart editor) {
|
public CCompletionProcessor(IEditorPart editor) {
|
||||||
fEditor = (CEditor) editor;
|
fEditor = (CEditor) editor;
|
||||||
|
|
||||||
//Determine if this is a C or a C++ file for the context completion + //This is _totally_ ugly and likely belongs in the main editor class.
|
//Determine if this is a C or a C++ file for the context completion + //This is _totally_ ugly and likely belongs in the main editor class.
|
||||||
String contextNames[] = new String[2];
|
String contextNames[] = new String[2];
|
||||||
ArrayList templateList = new ArrayList(2);
|
ArrayList templateList = new ArrayList(2);
|
||||||
|
@ -123,7 +127,10 @@ public class CCompletionProcessor implements IContentAssistProcessor {
|
||||||
* @see IContentAssistProcessor#getContextInformationValidator()
|
* @see IContentAssistProcessor#getContextInformationValidator()
|
||||||
*/
|
*/
|
||||||
public IContextInformationValidator getContextInformationValidator() {
|
public IContextInformationValidator getContextInformationValidator() {
|
||||||
return null;
|
if(fValidator == null) {
|
||||||
|
fValidator = new CParameterListValidator();
|
||||||
|
}
|
||||||
|
return fValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -133,6 +140,13 @@ public class CCompletionProcessor implements IContentAssistProcessor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
|
||||||
|
*/
|
||||||
|
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
|
* @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
|
||||||
*/
|
*/
|
||||||
|
@ -150,13 +164,6 @@ public class CCompletionProcessor implements IContentAssistProcessor {
|
||||||
fProposalAutoActivationSet = activationSet;
|
fProposalAutoActivationSet = activationSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
|
|
||||||
*/
|
|
||||||
public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells this processor to restrict is proposals to those
|
* Tells this processor to restrict is proposals to those
|
||||||
* starting with matching cases.
|
* starting with matching cases.
|
||||||
|
@ -238,14 +245,7 @@ public class CCompletionProcessor implements IContentAssistProcessor {
|
||||||
* applies to all proposals and not just those of the compilation unit.
|
* applies to all proposals and not just those of the compilation unit.
|
||||||
*/
|
*/
|
||||||
order(results);
|
order(results);
|
||||||
if ((results.length == 1)
|
return results;
|
||||||
&& (CUIPlugin.getDefault().getPreferenceStore().getBoolean(ContentAssistPreference.AUTOINSERT))) {
|
|
||||||
results[0].apply(document);
|
|
||||||
// Trick the content assistant into thinking we have no proposals
|
|
||||||
return new ICCompletionProposal[0];
|
|
||||||
} else {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -256,102 +256,140 @@ public class CCompletionProcessor implements IContentAssistProcessor {
|
||||||
return proposals;
|
return proposals;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addProjectCompletions(IProject project, IRegion region, String frag, ArrayList completions) {
|
|
||||||
IndexModel model = IndexModel.getDefault();
|
|
||||||
|
|
||||||
ITagEntry[] tags = model.query(project, frag + "*", false, false);
|
|
||||||
if (tags != null && tags.length > 0) {
|
|
||||||
// We have some matches!
|
|
||||||
for (int i = 0; i < tags.length; i++) {
|
|
||||||
|
|
||||||
String fname = tags[i].getTagName();
|
|
||||||
|
|
||||||
int kind = tags[i].getKind();
|
|
||||||
|
|
||||||
if (kind == TagFlags.T_FUNCTION || kind == TagFlags.T_PROTOTYPE) {
|
|
||||||
fname = fname + "()";
|
|
||||||
}
|
|
||||||
String proto = fname + " - " + tags[i].getPattern();
|
|
||||||
//System.out.println("tagmatch " + fname + " proto " + proto + " type" + tags[i].getKind());
|
|
||||||
if (tags[i].getKind() != TagFlags.T_MEMBER) {
|
|
||||||
completions.add(new CCompletionProposal(fname, region.getOffset(), region.getLength(),
|
|
||||||
//fname.length() + 1,
|
|
||||||
getTagImage(kind), proto.equals("") ? (fname + "()") : proto,
|
|
||||||
//null,
|
|
||||||
//null));
|
|
||||||
3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate the actual proposals for C
|
* Evaluate the actual proposals for C
|
||||||
*/
|
*/
|
||||||
private ICCompletionProposal[] evalProposals(IDocument document, int pos, int length) {
|
private ICCompletionProposal[] evalProposals(IDocument document, int pos, int length) {
|
||||||
IRegion region;
|
boolean isDereference = false;
|
||||||
|
IRegion region;
|
||||||
String frag = "";
|
String frag = "";
|
||||||
|
|
||||||
// Move back the pos by one the position is 0-based
|
// Move back the pos by one the position is 0-based
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
pos--;
|
pos--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, check if we're on a space or trying to open a struct/union
|
// TODO: Check to see if we are trying to open for a structure/class, then
|
||||||
|
// provide that structure's completion instead of the function/variable
|
||||||
|
// completions. This needs to be properly dealt with so that we can
|
||||||
|
// offer completion proposals.
|
||||||
if (pos > 1) {
|
if (pos > 1) {
|
||||||
|
int struct_pos = pos;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// If we're on a space and the previous character is valid text,
|
//While we aren't on a space, then go back and look for
|
||||||
// parse the previous word.
|
// . or a -> then determine the structure variable type.
|
||||||
if (!Character.isJavaIdentifierPart(document.getChar(pos))) {
|
while(document.getChar(struct_pos) == ' ') {
|
||||||
pos--;
|
struct_pos--;
|
||||||
if (!Character.isJavaIdentifierPart(document.getChar(pos))) {
|
|
||||||
pos--;
|
|
||||||
// Comment out the dereference code, only useful once we can
|
|
||||||
// know variable types to go fish back structure members
|
|
||||||
//if (document.getChar(offset) == '.') {
|
|
||||||
// isDereference = true;
|
|
||||||
// offset--;
|
|
||||||
//} else if ((document.getChar(offset) == '>') && (document.getChar(offset - 1) == '-')) {
|
|
||||||
// isDereference = true;
|
|
||||||
// offset -= 2;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (BadLocationException e) {
|
|
||||||
|
if (document.getChar(struct_pos) == '.') {
|
||||||
|
isDereference = true;
|
||||||
|
pos -= struct_pos - 1;
|
||||||
|
} else if ((document.getChar(struct_pos) == '>') && (document.getChar(struct_pos - 1) == '-')) {
|
||||||
|
isDereference = true;
|
||||||
|
pos -= struct_pos - 2;
|
||||||
|
} else {
|
||||||
|
isDereference = false;
|
||||||
|
}
|
||||||
|
} catch (BadLocationException ex) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current "word"
|
// Get the current "word", it might be a variable or another starter
|
||||||
region = CWordFinder.findWord(document, pos);
|
region = CWordFinder.findWord(document, pos);
|
||||||
|
if(region == null) {
|
||||||
// If we're currently
|
return null; //Bail out on error
|
||||||
try {
|
}
|
||||||
if (region != null) {
|
|
||||||
frag = document.get(region.getOffset(), region.getLength());
|
//@@@ TODO: Implement the structure member completion
|
||||||
frag = frag.trim();
|
if(isDereference) {
|
||||||
// No word is selected
|
|
||||||
if (frag.length() == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (BadLocationException x) {
|
|
||||||
// ignore
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Based on the frag name, build a list of completion proposals
|
|
||||||
// We look in two places: the content outline and the libs
|
try {
|
||||||
|
frag = document.get(region.getOffset(), region.getLength());
|
||||||
|
frag = frag.trim();
|
||||||
|
} catch (BadLocationException ex) {
|
||||||
|
return null; //Bail out on error
|
||||||
|
}
|
||||||
|
|
||||||
|
//If there is no fragment, then see if we are in a function
|
||||||
|
if(frag.length() == 0) {
|
||||||
|
IRegion funcregion;
|
||||||
|
String funcfrag = "";
|
||||||
|
|
||||||
|
funcregion = CWordFinder.findFunction(document, pos + 1);
|
||||||
|
if(funcregion != null) {
|
||||||
|
try {
|
||||||
|
funcfrag = document.get(funcregion.getOffset(), funcregion.getLength());
|
||||||
|
funcfrag = funcfrag.trim();
|
||||||
|
} catch(Exception ex) {
|
||||||
|
funcfrag = "";
|
||||||
|
}
|
||||||
|
if(funcfrag.length() == 0) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
//@@@ Add some marker here to indicate different path!
|
||||||
|
region = funcregion;
|
||||||
|
frag = funcfrag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on the frag name, build a list of completion proposals
|
||||||
ArrayList completions = new ArrayList();
|
ArrayList completions = new ArrayList();
|
||||||
|
|
||||||
// Look in index manager
|
// Look in index manager
|
||||||
|
addProposalsFromModel(region, frag, completions);
|
||||||
|
|
||||||
|
// Loot in the contributed completions
|
||||||
|
addProposalsFromCompletionContributors(region, frag, completions);
|
||||||
|
|
||||||
|
return (ICCompletionProposal[]) completions.toArray(new ICCompletionProposal[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addProposalsFromCompletionContributors(IRegion region, String frag, ArrayList completions) {
|
||||||
|
IFunctionSummary[] summary;
|
||||||
|
|
||||||
|
summary = CCompletionContributorManager.getDefault().getMatchingFunctions(frag);
|
||||||
|
if(summary == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < summary.length; i++) {
|
||||||
|
String fname = summary[i].getName() + "()";
|
||||||
|
String fdesc = summary[i].getDescription();
|
||||||
|
IFunctionSummary.IFunctionPrototypeSummary fproto = summary[i].getPrototype();
|
||||||
|
String fargs = fproto.getArguments();
|
||||||
|
|
||||||
|
CCompletionProposal proposal;
|
||||||
|
proposal = new CCompletionProposal(fname,
|
||||||
|
region.getOffset(),
|
||||||
|
region.getLength(),
|
||||||
|
getTagImage(TagFlags.T_FUNCTION),
|
||||||
|
fproto.getPrototypeString(true),
|
||||||
|
2);
|
||||||
|
|
||||||
|
if(fdesc != null) {
|
||||||
|
proposal.setAdditionalProposalInfo(fdesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fargs != null && fargs.length() > 0) {
|
||||||
|
proposal.setContextInformation(new ContextInformation(fname, fargs));
|
||||||
|
}
|
||||||
|
|
||||||
|
completions.add(proposal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addProposalsFromModel(IRegion region, String frag, ArrayList completions) {
|
||||||
IProject project = null;
|
IProject project = null;
|
||||||
IEditorInput input = fEditor.getEditorInput();
|
IEditorInput input = fEditor.getEditorInput();
|
||||||
if (input instanceof IFileEditorInput) {
|
if (input instanceof IFileEditorInput) {
|
||||||
project = ((IFileEditorInput) input).getFile().getProject();
|
project = ((IFileEditorInput) input).getFile().getProject();
|
||||||
|
|
||||||
// Bail out quickly, if the project was deleted.
|
// Bail out quickly, if the project was deleted.
|
||||||
if (!project.exists()) {
|
if (!project.exists()) {
|
||||||
project = null;
|
project = null;
|
||||||
|
@ -370,26 +408,54 @@ public class CCompletionProcessor implements IContentAssistProcessor {
|
||||||
}
|
}
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IFunctionSummary[] summary;
|
private void addProjectCompletions(IProject project, IRegion region, String frag, ArrayList completions) {
|
||||||
|
IndexModel model = IndexModel.getDefault();
|
||||||
|
|
||||||
//UserHelpFunctionInfo inf = plugin.getFunctionInfo();
|
ITagEntry[] tags = model.query(project, frag + "*", false, false);
|
||||||
summary = CCompletionContributorManager.getDefault().getMatchingFunctions(frag);
|
if (tags != null && tags.length > 0) {
|
||||||
if (summary != null) {
|
for (int i = 0; i < tags.length; i++) {
|
||||||
for (int i = 0; i < summary.length; i++) {
|
String fname = tags[i].getTagName();
|
||||||
String fname = summary[i].getName();
|
FunctionPrototypeSummary fproto = null;
|
||||||
String proto = summary[i].getPrototype();
|
int kind = tags[i].getKind();
|
||||||
completions.add(new CCompletionProposal(fname + "()", region.getOffset(), region.getLength(),
|
|
||||||
//fname.length() + 1,
|
if (kind == TagFlags.T_FUNCTION || kind == TagFlags.T_PROTOTYPE) {
|
||||||
CPluginImages.get(CPluginImages.IMG_OBJS_FUNCTION), proto.equals("") ? (fname + "()") : proto,
|
fname = fname + "()";
|
||||||
//null,
|
}
|
||||||
//null));
|
|
||||||
2));
|
if(tags[i].getPattern() != null) {
|
||||||
|
try {
|
||||||
|
fproto = new FunctionPrototypeSummary(tags[i].getPattern());
|
||||||
|
} catch(Exception ex) {
|
||||||
|
fproto = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(fproto == null) {
|
||||||
|
fproto = new FunctionPrototypeSummary(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.out.println("tagmatch " + fname + " proto " + proto + " type" + tags[i].getKind());
|
||||||
|
if (kind != TagFlags.T_MEMBER) {
|
||||||
|
CCompletionProposal proposal;
|
||||||
|
proposal = new CCompletionProposal(fname,
|
||||||
|
region.getOffset(),
|
||||||
|
region.getLength(),
|
||||||
|
getTagImage(kind),
|
||||||
|
fproto.getPrototypeString(true),
|
||||||
|
3);
|
||||||
|
completions.add(proposal);
|
||||||
|
|
||||||
|
//No summary information available yet
|
||||||
|
|
||||||
|
String fargs = fproto.getArguments();
|
||||||
|
if(fargs != null && fargs.length() > 0) {
|
||||||
|
proposal.setContextInformation(new ContextInformation(fname, fargs));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (ICCompletionProposal[]) completions.toArray(new ICCompletionProposal[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image getTagImage(int kind) {
|
private Image getTagImage(int kind) {
|
||||||
|
|
|
@ -7,22 +7,22 @@ package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
|
||||||
import org.eclipse.jface.text.contentassist.IContextInformation;
|
import org.eclipse.jface.text.contentassist.IContextInformation;
|
||||||
import org.eclipse.jface.util.Assert;
|
import org.eclipse.jface.util.Assert;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.graphics.Point;
|
import org.eclipse.swt.graphics.Point;
|
||||||
|
|
||||||
|
public class CCompletionProposal implements ICCompletionProposal, ICompletionProposalExtension {
|
||||||
public class CCompletionProposal implements ICCompletionProposal {
|
|
||||||
private String fDisplayString;
|
private String fDisplayString;
|
||||||
private String fReplacementString;
|
private String fReplacementString;
|
||||||
|
private String fAdditionalInfoString;
|
||||||
private int fReplacementOffset;
|
private int fReplacementOffset;
|
||||||
private int fReplacementLength;
|
private int fReplacementLength;
|
||||||
private int fCursorPosition;
|
private int fCursorPosition;
|
||||||
private Image fImage;
|
private Image fImage;
|
||||||
private IContextInformation fContextInformation;
|
private IContextInformation fContextInformation;
|
||||||
private int fContextInformationPosition;
|
private int fContextInformationPosition;
|
||||||
//private ProposalInfo fProposalInfo;
|
|
||||||
//private IImportDeclaration fImportDeclaration;
|
//private IImportDeclaration fImportDeclaration;
|
||||||
private char[] fTriggerCharacters;
|
private char[] fTriggerCharacters;
|
||||||
|
|
||||||
|
@ -50,13 +50,20 @@ public class CCompletionProposal implements ICCompletionProposal {
|
||||||
fDisplayString= displayString != null ? displayString : replacementString;
|
fDisplayString= displayString != null ? displayString : replacementString;
|
||||||
fRelevance= relevance;
|
fRelevance= relevance;
|
||||||
|
|
||||||
fCursorPosition= replacementString.length();
|
//@@@ Is this the best way to do this, likely it isn't
|
||||||
|
if(replacementString.indexOf("()") == -1) { //Not replacing with a function
|
||||||
|
fCursorPosition = replacementString.length();
|
||||||
|
} else if(displayString.indexOf("()") == -1) { //Assume that there are arguments between ()
|
||||||
|
fCursorPosition = replacementString.length() - 1;
|
||||||
|
} else {
|
||||||
|
fCursorPosition = replacementString.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
fAdditionalInfoString = null;
|
||||||
fContextInformation= null;
|
fContextInformation= null;
|
||||||
fContextInformationPosition= -1;
|
fContextInformationPosition= -1;
|
||||||
//fIncludeDeclaration= null;
|
//fIncludeDeclaration= null;
|
||||||
fTriggerCharacters= null;
|
fTriggerCharacters= null;
|
||||||
//fProposalInfo= null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,14 +92,6 @@ public class CCompletionProposal implements ICCompletionProposal {
|
||||||
fTriggerCharacters= triggerCharacters;
|
fTriggerCharacters= triggerCharacters;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the proposal info.
|
|
||||||
* @param additionalProposalInfo The additional information associated with this proposal or <code>null</code>
|
|
||||||
*
|
|
||||||
public void setProposalInfo(ProposalInfo proposalInfo) {
|
|
||||||
fProposalInfo= proposalInfo;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the cursor position relative to the insertion offset. By default this is the length of the completion string
|
* Sets the cursor position relative to the insertion offset. By default this is the length of the completion string
|
||||||
* (Cursor positioned after the completion)
|
* (Cursor positioned after the completion)
|
||||||
|
@ -146,22 +145,49 @@ public class CCompletionProposal implements ICCompletionProposal {
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see ICompletionProposal#apply
|
||||||
|
*/
|
||||||
|
public void apply(IDocument document) {
|
||||||
|
apply(document, (char) 0, fReplacementOffset + fReplacementLength);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* In this case we need to apply the completion proposal intelligently.
|
||||||
|
* This means that if we are applying it to a function, we don't wipe
|
||||||
|
* out the internal arguments, and if the proposal is a function, and it
|
||||||
|
* already is bracketed, then don't put those brackets in.
|
||||||
|
*
|
||||||
* @see ICompletionProposalExtension#apply(IDocument, char, int)
|
* @see ICompletionProposalExtension#apply(IDocument, char, int)
|
||||||
*/
|
*/
|
||||||
public void apply(IDocument document, char trigger, int offset) {
|
public void apply(IDocument document, char trigger, int offset) {
|
||||||
|
int functionBracketIndex;
|
||||||
|
boolean isBeforeBracket;
|
||||||
|
String replacementStringCopy = fReplacementString;
|
||||||
|
|
||||||
|
//If just providing context information, then don't move the cursor
|
||||||
|
if(offset != (fReplacementOffset + fReplacementLength)) {
|
||||||
|
fCursorPosition = offset - fReplacementOffset;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
functionBracketIndex = fReplacementString.indexOf("()");
|
||||||
|
isBeforeBracket = document.getChar(fReplacementOffset + fReplacementLength) == '(';
|
||||||
|
|
||||||
// patch replacement length
|
//Strip the brackets off the function if inserting right before brackets
|
||||||
int delta= offset - (fReplacementOffset + fReplacementLength);
|
if(functionBracketIndex != -1 && isBeforeBracket) {
|
||||||
if (delta > 0)
|
replacementStringCopy = fReplacementString.substring(0, functionBracketIndex);
|
||||||
fReplacementLength += delta;
|
}
|
||||||
|
} catch(Exception ex) {
|
||||||
|
/* Ignore */
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
if (trigger == (char) 0) {
|
if (trigger == (char) 0) {
|
||||||
replace(document, fReplacementOffset, fReplacementLength, fReplacementString);
|
replace(document, fReplacementOffset, fReplacementLength, replacementStringCopy);
|
||||||
} else {
|
} else {
|
||||||
StringBuffer buffer= new StringBuffer(fReplacementString);
|
StringBuffer buffer= new StringBuffer(replacementStringCopy);
|
||||||
|
|
||||||
// fix for PR #5533. Assumes that no eating takes place.
|
// fix for PR #5533. Assumes that no eating takes place.
|
||||||
if ((fCursorPosition > 0 && fCursorPosition <= buffer.length() && buffer.charAt(fCursorPosition - 1) != trigger)) {
|
if ((fCursorPosition > 0 && fCursorPosition <= buffer.length() && buffer.charAt(fCursorPosition - 1) != trigger)) {
|
||||||
|
@ -172,6 +198,12 @@ public class CCompletionProposal implements ICCompletionProposal {
|
||||||
replace(document, fReplacementOffset, fReplacementLength, buffer.toString());
|
replace(document, fReplacementOffset, fReplacementLength, buffer.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The replacement length is used to calculate the new cursor position,
|
||||||
|
* so after we update the includes adjust the replacement offset.
|
||||||
|
* NOTE: This won't work if the include is added after the offset,
|
||||||
|
* such as might be the case with #include completions.
|
||||||
|
*/
|
||||||
int oldLen= document.getLength();
|
int oldLen= document.getLength();
|
||||||
applyIncludes(document);
|
applyIncludes(document);
|
||||||
fReplacementOffset += document.getLength() - oldLen;
|
fReplacementOffset += document.getLength() - oldLen;
|
||||||
|
@ -186,13 +218,6 @@ public class CCompletionProposal implements ICCompletionProposal {
|
||||||
if (!document.get(offset, length).equals(string))
|
if (!document.get(offset, length).equals(string))
|
||||||
document.replace(offset, length, string);
|
document.replace(offset, length, string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICompletionProposal#apply
|
|
||||||
*/
|
|
||||||
public void apply(IDocument document) {
|
|
||||||
apply(document, (char) 0, fReplacementOffset + fReplacementLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see ICompletionProposal#getSelection
|
* @see ICompletionProposal#getSelection
|
||||||
|
@ -222,14 +247,20 @@ public class CCompletionProposal implements ICCompletionProposal {
|
||||||
return fDisplayString;
|
return fDisplayString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the additional information which will be shown when this
|
||||||
|
* proposal is selected in the popup list.
|
||||||
|
* @param infoString
|
||||||
|
*/
|
||||||
|
public void setAdditionalProposalInfo(String infoString) {
|
||||||
|
fAdditionalInfoString = infoString;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see ICompletionProposal#getAdditionalProposalInfo()
|
* @see ICompletionProposal#getAdditionalProposalInfo()
|
||||||
*/
|
*/
|
||||||
public String getAdditionalProposalInfo() {
|
public String getAdditionalProposalInfo() {
|
||||||
//if (fProposalInfo != null) {
|
return fAdditionalInfoString;
|
||||||
// return fProposalInfo.getInfo();
|
|
||||||
//}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -245,6 +276,27 @@ public class CCompletionProposal implements ICCompletionProposal {
|
||||||
public int getContextInformationPosition() {
|
public int getContextInformationPosition() {
|
||||||
return fReplacementOffset + fContextInformationPosition;
|
return fReplacementOffset + fContextInformationPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see ICompletionProposalExtension#isValidFor(IDocument, int)
|
||||||
|
*/
|
||||||
|
public boolean isValidFor(IDocument document, int offset) {
|
||||||
|
if (offset < fReplacementOffset)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int replacementLength= fReplacementString == null ? 0 : fReplacementString.length();
|
||||||
|
if (offset >= fReplacementOffset + replacementLength)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
int length= offset - fReplacementOffset;
|
||||||
|
String start= document.get(fReplacementOffset, length);
|
||||||
|
return fReplacementString.substring(0, length).equalsIgnoreCase(start);
|
||||||
|
} catch (BadLocationException x) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the replacement offset.
|
* Gets the replacement offset.
|
||||||
|
@ -303,28 +355,6 @@ public class CCompletionProposal implements ICCompletionProposal {
|
||||||
public void setImage(Image image) {
|
public void setImage(Image image) {
|
||||||
fImage= image;
|
fImage= image;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see ICompletionProposalExtension#isValidFor(IDocument, int)
|
|
||||||
*/
|
|
||||||
public boolean isValidFor(IDocument document, int offset) {
|
|
||||||
|
|
||||||
if (offset < fReplacementOffset)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int replacementLength= fReplacementString == null ? 0 : fReplacementString.length();
|
|
||||||
if (offset >= fReplacementOffset + replacementLength)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
int length= offset - fReplacementOffset;
|
|
||||||
String start= document.get(fReplacementOffset, length);
|
|
||||||
return fReplacementString.substring(0, length).equalsIgnoreCase(start);
|
|
||||||
} catch (BadLocationException x) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the proposal's relevance.
|
* Gets the proposal's relevance.
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.custom.StyleRange;
|
||||||
|
|
||||||
|
import org.eclipse.jface.text.Assert;
|
||||||
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.jface.text.ITextViewer;
|
||||||
|
import org.eclipse.jface.text.TextPresentation;
|
||||||
|
import org.eclipse.jface.text.contentassist.IContextInformation;
|
||||||
|
import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
|
||||||
|
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides the function parameter parsing for the C/C++ Editor hover
|
||||||
|
* It is based heavily on the Java class JavaParameterListValidator
|
||||||
|
*
|
||||||
|
* @author thomasf
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CParameterListValidator implements IContextInformationValidator, IContextInformationPresenter {
|
||||||
|
private int fPosition;
|
||||||
|
private ITextViewer fViewer;
|
||||||
|
private IContextInformation fInformation;
|
||||||
|
|
||||||
|
private int fCurrentParameter;
|
||||||
|
|
||||||
|
public CParameterListValidator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IContextInformationValidator#install(IContextInformation, ITextViewer, int)
|
||||||
|
* @see IContextInformationPresenter#install(IContextInformation, ITextViewer, int)
|
||||||
|
*/
|
||||||
|
public void install(IContextInformation info, ITextViewer viewer, int documentPosition) {
|
||||||
|
|
||||||
|
fPosition= documentPosition;
|
||||||
|
fViewer= viewer;
|
||||||
|
fInformation= info;
|
||||||
|
|
||||||
|
fCurrentParameter= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getCommentEnd(IDocument d, int pos, int end) throws BadLocationException {
|
||||||
|
while (pos < end) {
|
||||||
|
char curr= d.getChar(pos);
|
||||||
|
pos++;
|
||||||
|
if (curr == '*') {
|
||||||
|
if (pos < end && d.getChar(pos) == '/') {
|
||||||
|
return pos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getStringEnd(IDocument d, int pos, int end, char ch) throws BadLocationException {
|
||||||
|
while (pos < end) {
|
||||||
|
char curr= d.getChar(pos);
|
||||||
|
pos++;
|
||||||
|
if (curr == '\\') {
|
||||||
|
// ignore escaped characters
|
||||||
|
pos++;
|
||||||
|
} else if (curr == ch) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getCharCount(IDocument document, int start, int end,
|
||||||
|
char increment, char decrement, boolean considerNesting) throws BadLocationException {
|
||||||
|
|
||||||
|
Assert.isTrue((increment != 0 || decrement != 0) && increment != decrement);
|
||||||
|
|
||||||
|
int nestingLevel= 0;
|
||||||
|
int charCount= 0;
|
||||||
|
while (start < end) {
|
||||||
|
char curr= document.getChar(start++);
|
||||||
|
switch (curr) {
|
||||||
|
case '/':
|
||||||
|
if (start < end) {
|
||||||
|
char next= document.getChar(start);
|
||||||
|
if (next == '*') {
|
||||||
|
// a comment starts, advance to the comment end
|
||||||
|
start= getCommentEnd(document, start + 1, end);
|
||||||
|
} else if (next == '/') {
|
||||||
|
// '//'-comment: nothing to do anymore on this line
|
||||||
|
start= end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
if (start < end) {
|
||||||
|
char next= document.getChar(start);
|
||||||
|
if (next == '/') {
|
||||||
|
// we have been in a comment: forget what we read before
|
||||||
|
charCount= 0;
|
||||||
|
++ start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
case '\'':
|
||||||
|
start= getStringEnd(document, start, end, curr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
if (considerNesting) {
|
||||||
|
|
||||||
|
if ('(' == curr)
|
||||||
|
++ nestingLevel;
|
||||||
|
else if (')' == curr)
|
||||||
|
-- nestingLevel;
|
||||||
|
|
||||||
|
if (nestingLevel != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (increment != 0) {
|
||||||
|
if (curr == increment)
|
||||||
|
++ charCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decrement != 0) {
|
||||||
|
if (curr == decrement)
|
||||||
|
-- charCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return charCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IContextInformationValidator#isContextInformationValid(int)
|
||||||
|
*/
|
||||||
|
public boolean isContextInformationValid(int position) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (position < fPosition)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IDocument document= fViewer.getDocument();
|
||||||
|
IRegion line= document.getLineInformationOfOffset(fPosition);
|
||||||
|
|
||||||
|
if (position > line.getOffset() + line.getLength())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (getCharCount(document, fPosition, position, '(', ')', false) >= 0);
|
||||||
|
|
||||||
|
} catch (BadLocationException x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see IContextInformationPresenter#updatePresentation(int, TextPresentation)
|
||||||
|
*/
|
||||||
|
public boolean updatePresentation(int position, TextPresentation presentation) {
|
||||||
|
|
||||||
|
int currentParameter= -1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
currentParameter= getCharCount(fViewer.getDocument(), fPosition, position, ',', (char) 0, true);
|
||||||
|
} catch (BadLocationException x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fCurrentParameter != -1) {
|
||||||
|
if (currentParameter == fCurrentParameter)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
presentation.clear();
|
||||||
|
fCurrentParameter= currentParameter;
|
||||||
|
|
||||||
|
String s= fInformation.getInformationDisplayString().trim();
|
||||||
|
|
||||||
|
int start= 0;
|
||||||
|
int occurrences= 0;
|
||||||
|
while (occurrences < fCurrentParameter) {
|
||||||
|
int found= s.indexOf(',', start);
|
||||||
|
if (found == -1)
|
||||||
|
break;
|
||||||
|
start= found + 1;
|
||||||
|
++ occurrences;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (occurrences < fCurrentParameter) {
|
||||||
|
presentation.addStyleRange(new StyleRange(0, s.length(), null, null, SWT.NORMAL));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start == -1)
|
||||||
|
start= 0;
|
||||||
|
|
||||||
|
int end= s.indexOf(',', start);
|
||||||
|
if (end == -1)
|
||||||
|
end= s.length();
|
||||||
|
|
||||||
|
if (start > 0)
|
||||||
|
presentation.addStyleRange(new StyleRange(0, start, null, null, SWT.NORMAL));
|
||||||
|
|
||||||
|
if (end > start)
|
||||||
|
presentation.addStyleRange(new StyleRange(start, end - start, null, null, SWT.BOLD));
|
||||||
|
|
||||||
|
if (end < s.length())
|
||||||
|
presentation.addStyleRange(new StyleRange(end, s.length() - end, null, null, SWT.NORMAL));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.jface.text.IInformationControlCreator;
|
||||||
import org.eclipse.jface.text.ITextDoubleClickStrategy;
|
import org.eclipse.jface.text.ITextDoubleClickStrategy;
|
||||||
import org.eclipse.jface.text.ITextHover;
|
import org.eclipse.jface.text.ITextHover;
|
||||||
import org.eclipse.jface.text.contentassist.ContentAssistant;
|
import org.eclipse.jface.text.contentassist.ContentAssistant;
|
||||||
|
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
|
||||||
import org.eclipse.jface.text.contentassist.IContentAssistant;
|
import org.eclipse.jface.text.contentassist.IContentAssistant;
|
||||||
import org.eclipse.jface.text.formatter.ContentFormatter;
|
import org.eclipse.jface.text.formatter.ContentFormatter;
|
||||||
import org.eclipse.jface.text.formatter.IContentFormatter;
|
import org.eclipse.jface.text.formatter.IContentFormatter;
|
||||||
|
@ -158,7 +159,6 @@ public class CSourceViewerConfiguration extends SourceViewerConfiguration {
|
||||||
reconciler.setDamager(dr, CPartitionScanner.C_MULTILINE_COMMENT);
|
reconciler.setDamager(dr, CPartitionScanner.C_MULTILINE_COMMENT);
|
||||||
reconciler.setRepairer(dr, CPartitionScanner.C_MULTILINE_COMMENT);
|
reconciler.setRepairer(dr, CPartitionScanner.C_MULTILINE_COMMENT);
|
||||||
|
|
||||||
|
|
||||||
return reconciler;
|
return reconciler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,15 +167,30 @@ public class CSourceViewerConfiguration extends SourceViewerConfiguration {
|
||||||
* @see SourceViewerConfiguration#getContentAssistant(ISourceViewer)
|
* @see SourceViewerConfiguration#getContentAssistant(ISourceViewer)
|
||||||
*/
|
*/
|
||||||
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
|
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
|
||||||
|
if(getEditor() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
ContentAssistant assistant = new ContentAssistant();
|
ContentAssistant assistant = new ContentAssistant();
|
||||||
// IFile file = (sourceViewer).
|
|
||||||
assistant.setContentAssistProcessor(new CCompletionProcessor(fEditor), IDocument.DEFAULT_CONTENT_TYPE);
|
IContentAssistProcessor processor = new CCompletionProcessor(getEditor());
|
||||||
|
assistant.setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
|
||||||
|
|
||||||
|
//Will this work as a replacement for the configuration lines below?
|
||||||
|
//ContentAssistPreference.configure(assistant, getPreferenceStore());
|
||||||
|
|
||||||
|
assistant.enableAutoInsert(CUIPlugin.getDefault().getPreferenceStore().getBoolean(ContentAssistPreference.AUTOINSERT));
|
||||||
assistant.enableAutoActivation(true);
|
assistant.enableAutoActivation(true);
|
||||||
assistant.setAutoActivationDelay(500);
|
assistant.setAutoActivationDelay(500);
|
||||||
assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
|
assistant.setProposalPopupOrientation(IContentAssistant.PROPOSAL_OVERLAY);
|
||||||
|
|
||||||
|
assistant.setContextInformationPopupOrientation(ContentAssistant.CONTEXT_INFO_ABOVE);
|
||||||
|
assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
|
||||||
|
|
||||||
return assistant;
|
return assistant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SourceViewerConfiguration#getReconciler(ISourceViewer)
|
* @see SourceViewerConfiguration#getReconciler(ISourceViewer)
|
||||||
*/
|
*/
|
||||||
|
@ -367,7 +382,7 @@ public class CSourceViewerConfiguration extends SourceViewerConfiguration {
|
||||||
public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer, final boolean cutDown) {
|
public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer, final boolean cutDown) {
|
||||||
return new IInformationControlCreator() {
|
return new IInformationControlCreator() {
|
||||||
public IInformationControl createInformationControl(Shell parent) {
|
public IInformationControl createInformationControl(Shell parent) {
|
||||||
int style= cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
|
int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
|
||||||
return new DefaultInformationControl(parent, style, new HTMLTextPresenter(cutDown));
|
return new DefaultInformationControl(parent, style, new HTMLTextPresenter(cutDown));
|
||||||
// return new HoverBrowserControl(parent);
|
// return new HoverBrowserControl(parent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,31 @@ import org.eclipse.jface.text.IDocument;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.Region;
|
import org.eclipse.jface.text.Region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a helper class for the text editor to be able to determine,
|
||||||
|
* given a particular offset in a document, various candidates segments
|
||||||
|
* for things like context help, proposals and hovering.
|
||||||
|
*/
|
||||||
public class CWordFinder
|
public class CWordFinder
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* This method determines for a given offset into a given document
|
||||||
|
* what the region is which defines the current word. A word is
|
||||||
|
* defined as the set of non "C" identifiers. So assuming that !
|
||||||
|
* indicated the current cursor postion:
|
||||||
|
* !afunction(int a, int b) --> word = length 0
|
||||||
|
* afunc!tion(int a, int b) --> word = afunction
|
||||||
|
* afunction!(int a, int b) --> word = afunction
|
||||||
|
* afunction(!int a, int b) --> word = length 0
|
||||||
|
* afunction(int a,! int b) --> word = length 0
|
||||||
|
* afunction(!) --> word = length 0
|
||||||
|
* @param document The document to be examined
|
||||||
|
* @param offset The offset into the document where a word should
|
||||||
|
* be idendified.
|
||||||
|
* @return The region defining the current word, which may be a
|
||||||
|
* region of length 0 if the offset is not in a word, or null if
|
||||||
|
* there is an error accessing the docment data.
|
||||||
|
*/
|
||||||
public static IRegion findWord( IDocument document, int offset )
|
public static IRegion findWord( IDocument document, int offset )
|
||||||
{
|
{
|
||||||
int start = -1;
|
int start = -1;
|
||||||
|
@ -63,6 +85,121 @@ public class CWordFinder
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will determine the region for the name of the function
|
||||||
|
* within which the current offset is contained.
|
||||||
|
* @param document The document to be examined
|
||||||
|
* @param offset The offset into the document where a word should
|
||||||
|
* be idendified.
|
||||||
|
* @return The region defining the current word, which may be a
|
||||||
|
* region of length 0 if the offset is not in a function, or null if
|
||||||
|
* there is an error accessing the docment data.
|
||||||
|
*/
|
||||||
|
public static IRegion findFunction( IDocument document, int offset )
|
||||||
|
{
|
||||||
|
int leftbracket = -1;
|
||||||
|
int leftbracketcount = 0;
|
||||||
|
int rightbracket = -1;
|
||||||
|
int rightbracketcount = 0;
|
||||||
|
int functionstart = -1;
|
||||||
|
int functionend = -1;
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int length = document.getLength();
|
||||||
|
int pos;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
//Find most relevant right bracket from our position
|
||||||
|
pos = offset;
|
||||||
|
rightbracketcount = leftbracketcount = 0;
|
||||||
|
while(pos < length) {
|
||||||
|
c = document.getChar( pos );
|
||||||
|
|
||||||
|
if( c == ')') {
|
||||||
|
rightbracketcount++;
|
||||||
|
if(rightbracketcount >= leftbracketcount) {
|
||||||
|
rightbracket = pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == '(') {
|
||||||
|
leftbracketcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == ';') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rightbracket == -1 ) {
|
||||||
|
return new Region(offset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Now backtrack our way from the rightbracket to the left
|
||||||
|
pos = rightbracket;
|
||||||
|
rightbracketcount = leftbracketcount = 0;
|
||||||
|
while(pos >= 0) {
|
||||||
|
c = document.getChar( pos );
|
||||||
|
|
||||||
|
if( c == ')') {
|
||||||
|
rightbracketcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == '(') {
|
||||||
|
leftbracketcount++;
|
||||||
|
if(leftbracketcount >= rightbracketcount) {
|
||||||
|
leftbracket = pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c == ';') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( leftbracket == -1 ) {
|
||||||
|
return new Region(offset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Now work our way to the function name
|
||||||
|
pos = leftbracket - 1;
|
||||||
|
while(pos >= 0) {
|
||||||
|
c = document.getChar( pos );
|
||||||
|
if(functionend == -1 && c == ' ' ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Character.isJavaIdentifierPart(c)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
functionstart = pos;
|
||||||
|
if(functionend == -1) {
|
||||||
|
functionend = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
} catch( BadLocationException x ) {
|
||||||
|
/* Ignore */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionstart > -1 && functionend > -1) {
|
||||||
|
return new Region(functionstart, functionend - functionstart + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.eclipse.cdt.ui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is a helper class which takes care of implementing some of the
|
||||||
|
* function prototype parsing and stripping.
|
||||||
|
*/
|
||||||
|
public class FunctionPrototypeSummary implements IFunctionSummary.IFunctionPrototypeSummary {
|
||||||
|
String fname;
|
||||||
|
String freturn;
|
||||||
|
String farguments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a prototype which matches the format
|
||||||
|
* returntype function(arguments)
|
||||||
|
* @param properProto
|
||||||
|
*/
|
||||||
|
public FunctionPrototypeSummary(String proto) {
|
||||||
|
int leftbracket = proto.indexOf('(');
|
||||||
|
int rightbracket = proto.lastIndexOf(')');
|
||||||
|
farguments = proto.substring(leftbracket + 1, rightbracket);
|
||||||
|
|
||||||
|
int nameend = leftbracket - 1;
|
||||||
|
while(proto.charAt(nameend) == ' ') {
|
||||||
|
nameend--;
|
||||||
|
}
|
||||||
|
int namestart = nameend;
|
||||||
|
while(namestart > 0 && proto.charAt(namestart) != ' ') {
|
||||||
|
namestart--;
|
||||||
|
}
|
||||||
|
fname = proto.substring(namestart, nameend + 1).trim();
|
||||||
|
|
||||||
|
if(namestart == 0) {
|
||||||
|
freturn = "void";
|
||||||
|
} else {
|
||||||
|
freturn = proto.substring(0, namestart).trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReturnType() {
|
||||||
|
return freturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getArguments() {
|
||||||
|
return farguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrototypeString(boolean namefirst) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
if(!namefirst) {
|
||||||
|
buffer.append(getArguments());
|
||||||
|
buffer.append(" ");
|
||||||
|
}
|
||||||
|
buffer.append(getName());
|
||||||
|
buffer.append("(");
|
||||||
|
if(getArguments() != null) {
|
||||||
|
buffer.append(getArguments());
|
||||||
|
}
|
||||||
|
buffer.append(")");
|
||||||
|
if(namefirst) {
|
||||||
|
buffer.append(" ");
|
||||||
|
buffer.append(getReturnType());
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,28 +7,80 @@ package org.eclipse.cdt.ui;
|
||||||
|
|
||||||
public interface IFunctionSummary {
|
public interface IFunctionSummary {
|
||||||
|
|
||||||
|
public interface IFunctionPrototypeSummary {
|
||||||
|
/**
|
||||||
|
* Get the name of the function. This should be the
|
||||||
|
* same as for IFunctionSummary.
|
||||||
|
* ie "int main(int argc, char **argv)" --> "main"
|
||||||
|
* @return The name of the function without any additional
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the return type of the function.
|
||||||
|
* ie "int main(int argc, char **argv)" --> "int"
|
||||||
|
* @return A string containing the return type of the
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
public String getReturnType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the arguments of the function.
|
||||||
|
* ie "int main(int argc, char **argv)" --> "int argc, char **argv"
|
||||||
|
* @return A string containing the arguments of the
|
||||||
|
* function, or null if the function has no arguments.
|
||||||
|
*/
|
||||||
|
public String getArguments();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a nice user defined string. The format of
|
||||||
|
* which depends on the variable namefirst
|
||||||
|
* namefirst == true: main(int argc, char **argv) int
|
||||||
|
* namefirst == false: int main(int argc, char **argv);
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getPrototypeString(boolean namefirst);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the function
|
* Gets the name of the function. This is the simple
|
||||||
|
* name without any additional return or argument information.
|
||||||
|
* The function "int main(int argc, char **argv)" would
|
||||||
|
* return "main"
|
||||||
|
* @return The name of the function without any additional
|
||||||
|
* information
|
||||||
*/
|
*/
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the full namespace qualifier for this function
|
||||||
|
* (generally C++ only)
|
||||||
|
* @return The string of the fully qualified namespace for
|
||||||
|
* this function, or null if the namespace is not known.
|
||||||
|
*/
|
||||||
|
public String getNamespace();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description of the function. This string can be
|
||||||
|
* either text or HTML coded and is displayed as part of the
|
||||||
|
* hover help and as the context proposal information.
|
||||||
|
* @return A description for this function, or null if no
|
||||||
|
* description is available.
|
||||||
|
*/
|
||||||
|
public String getDescription();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the function summary
|
* Gets the prototype description for this function.
|
||||||
|
* @return The IFunctionPrototypeSummary describing the
|
||||||
|
* prototype for this function
|
||||||
*/
|
*/
|
||||||
public String getSummary();
|
public IFunctionPrototypeSummary getPrototype();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the function prototype
|
|
||||||
*/
|
|
||||||
public String getPrototype();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the function synopsis
|
|
||||||
*/
|
|
||||||
public String getSynopsis();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get headers required by this function
|
* Get headers required by this function
|
||||||
|
* @return A list of IRequiredInclude definitions, or null if no
|
||||||
|
* include definitions are available.
|
||||||
*/
|
*/
|
||||||
public IRequiredInclude[] getIncludes();
|
public IRequiredInclude[] getIncludes();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue