mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Improve content assist auto-activation check, related to bugs 126871 and 193728
This commit is contained in:
parent
39053ae062
commit
d12b37a95c
6 changed files with 83 additions and 81 deletions
|
@ -175,7 +175,7 @@ public class ContentAssistTests extends BaseUITestCase {
|
||||||
|
|
||||||
String contentType = editor.getViewer().getDocument().getContentType(offset);
|
String contentType = editor.getViewer().getDocument().getContentType(offset);
|
||||||
ContentAssistant assistant = new ContentAssistant();
|
ContentAssistant assistant = new ContentAssistant();
|
||||||
CContentAssistProcessor processor = new CContentAssistProcessor(editor, editor.getViewer(), assistant, contentType);
|
CContentAssistProcessor processor = new CContentAssistProcessor(editor, assistant, contentType);
|
||||||
return processor.computeCompletionProposals(editor.getViewer(), offset);
|
return processor.computeCompletionProposals(editor.getViewer(), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
|
||||||
ISourceViewer sourceViewer= EditorTestHelper.getSourceViewer((AbstractTextEditor)fEditor);
|
ISourceViewer sourceViewer= EditorTestHelper.getSourceViewer((AbstractTextEditor)fEditor);
|
||||||
String contentType = sourceViewer.getDocument().getContentType(offset);
|
String contentType = sourceViewer.getDocument().getContentType(offset);
|
||||||
ContentAssistant assistant = new ContentAssistant();
|
ContentAssistant assistant = new ContentAssistant();
|
||||||
CContentAssistProcessor processor = new CContentAssistProcessor(fEditor, sourceViewer, assistant, contentType);
|
CContentAssistProcessor processor = new CContentAssistProcessor(fEditor, assistant, contentType);
|
||||||
long startTime= System.currentTimeMillis();
|
long startTime= System.currentTimeMillis();
|
||||||
Object[] results = isCompletion
|
Object[] results = isCompletion
|
||||||
? (Object[]) processor.computeCompletionProposals(sourceViewer, offset)
|
? (Object[]) processor.computeCompletionProposals(sourceViewer, offset)
|
||||||
|
|
|
@ -365,25 +365,25 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
|
||||||
|
|
||||||
assistant.setRestoreCompletionProposalSize(getSettings("completion_proposal_size")); //$NON-NLS-1$
|
assistant.setRestoreCompletionProposalSize(getSettings("completion_proposal_size")); //$NON-NLS-1$
|
||||||
|
|
||||||
IContentAssistProcessor processor = new CContentAssistProcessor(getEditor(), sourceViewer, assistant, IDocument.DEFAULT_CONTENT_TYPE);
|
IContentAssistProcessor processor = new CContentAssistProcessor(getEditor(), assistant, IDocument.DEFAULT_CONTENT_TYPE);
|
||||||
assistant.setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
|
assistant.setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
|
||||||
|
|
||||||
processor = new CContentAssistProcessor(getEditor(), sourceViewer, assistant, ICPartitions.C_MULTI_LINE_COMMENT);
|
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_MULTI_LINE_COMMENT);
|
||||||
assistant.setContentAssistProcessor(processor, ICPartitions.C_MULTI_LINE_COMMENT);
|
assistant.setContentAssistProcessor(processor, ICPartitions.C_MULTI_LINE_COMMENT);
|
||||||
|
|
||||||
processor = new CContentAssistProcessor(getEditor(), sourceViewer, assistant, ICPartitions.C_SINGLE_LINE_COMMENT);
|
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_SINGLE_LINE_COMMENT);
|
||||||
assistant.setContentAssistProcessor(processor, ICPartitions.C_SINGLE_LINE_COMMENT);
|
assistant.setContentAssistProcessor(processor, ICPartitions.C_SINGLE_LINE_COMMENT);
|
||||||
|
|
||||||
processor = new CContentAssistProcessor(getEditor(), sourceViewer, assistant, ICPartitions.C_MULTI_LINE_DOC_COMMENT);
|
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_MULTI_LINE_DOC_COMMENT);
|
||||||
assistant.setContentAssistProcessor(processor, ICPartitions.C_MULTI_LINE_DOC_COMMENT);
|
assistant.setContentAssistProcessor(processor, ICPartitions.C_MULTI_LINE_DOC_COMMENT);
|
||||||
|
|
||||||
processor = new CContentAssistProcessor(getEditor(), sourceViewer, assistant, ICPartitions.C_SINGLE_LINE_DOC_COMMENT);
|
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_SINGLE_LINE_DOC_COMMENT);
|
||||||
assistant.setContentAssistProcessor(processor, ICPartitions.C_SINGLE_LINE_DOC_COMMENT);
|
assistant.setContentAssistProcessor(processor, ICPartitions.C_SINGLE_LINE_DOC_COMMENT);
|
||||||
|
|
||||||
processor = new CContentAssistProcessor(getEditor(), sourceViewer, assistant, ICPartitions.C_STRING);
|
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_STRING);
|
||||||
assistant.setContentAssistProcessor(processor, ICPartitions.C_STRING);
|
assistant.setContentAssistProcessor(processor, ICPartitions.C_STRING);
|
||||||
|
|
||||||
processor = new CContentAssistProcessor(getEditor(), sourceViewer, assistant, ICPartitions.C_PREPROCESSOR);
|
processor = new CContentAssistProcessor(getEditor(), assistant, ICPartitions.C_PREPROCESSOR);
|
||||||
assistant.setContentAssistProcessor(processor, ICPartitions.C_PREPROCESSOR);
|
assistant.setContentAssistProcessor(processor, ICPartitions.C_PREPROCESSOR);
|
||||||
|
|
||||||
ContentAssistPreference.configure(assistant, fPreferenceStore);
|
ContentAssistPreference.configure(assistant, fPreferenceStore);
|
||||||
|
|
|
@ -43,6 +43,7 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
|
||||||
|
|
||||||
private final IEditorPart fEditor;
|
private final IEditorPart fEditor;
|
||||||
private final boolean fIsCompletion;
|
private final boolean fIsCompletion;
|
||||||
|
private final boolean fIsAutoActivated;
|
||||||
|
|
||||||
private ITranslationUnit fTU= null;
|
private ITranslationUnit fTU= null;
|
||||||
private boolean fTUComputed= false;
|
private boolean fTUComputed= false;
|
||||||
|
@ -59,12 +60,14 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
|
||||||
* @param viewer the viewer used by the editor
|
* @param viewer the viewer used by the editor
|
||||||
* @param offset the invocation offset
|
* @param offset the invocation offset
|
||||||
* @param editor the editor that content assist is invoked in
|
* @param editor the editor that content assist is invoked in
|
||||||
|
* @param isAutoActivated inidicates whether content assist was auto-activated
|
||||||
*/
|
*/
|
||||||
public CContentAssistInvocationContext(ITextViewer viewer, int offset, IEditorPart editor, boolean isCompletion) {
|
public CContentAssistInvocationContext(ITextViewer viewer, int offset, IEditorPart editor, boolean isCompletion, boolean isAutoActivated) {
|
||||||
super(viewer, offset);
|
super(viewer, offset);
|
||||||
Assert.isNotNull(editor);
|
Assert.isNotNull(editor);
|
||||||
fEditor= editor;
|
fEditor= editor;
|
||||||
fIsCompletion= isCompletion;
|
fIsCompletion= isCompletion;
|
||||||
|
fIsAutoActivated= isAutoActivated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,6 +81,7 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
|
||||||
fTUComputed= true;
|
fTUComputed= true;
|
||||||
fEditor= null;
|
fEditor= null;
|
||||||
fIsCompletion= isCompletion;
|
fIsCompletion= isCompletion;
|
||||||
|
fIsAutoActivated= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -255,6 +259,10 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
|
||||||
return !fIsCompletion || (getParseOffset() != getInvocationOffset());
|
return !fIsCompletion || (getParseOffset() != getInvocationOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAutoActivated() {
|
||||||
|
return fIsAutoActivated;
|
||||||
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (fIndex != null) {
|
if (fIndex != null) {
|
||||||
fIndex.releaseReadLock();
|
fIndex.releaseReadLock();
|
||||||
|
|
|
@ -28,7 +28,6 @@ import org.eclipse.jface.text.contentassist.ContentAssistant;
|
||||||
import org.eclipse.jface.text.contentassist.ICompletionProposal;
|
import org.eclipse.jface.text.contentassist.ICompletionProposal;
|
||||||
import org.eclipse.jface.text.contentassist.IContextInformation;
|
import org.eclipse.jface.text.contentassist.IContextInformation;
|
||||||
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
|
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
|
||||||
import org.eclipse.jface.text.source.ISourceViewer;
|
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.graphics.Point;
|
import org.eclipse.swt.graphics.Point;
|
||||||
import org.eclipse.ui.IEditorPart;
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
@ -39,7 +38,9 @@ import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
|
||||||
import org.eclipse.cdt.ui.text.contentassist.IProposalFilter;
|
import org.eclipse.cdt.ui.text.contentassist.IProposalFilter;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil;
|
import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
|
||||||
import org.eclipse.cdt.internal.ui.text.CParameterListValidator;
|
import org.eclipse.cdt.internal.ui.text.CParameterListValidator;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.Symbols;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C/C++ content assist processor.
|
* C/C++ content assist processor.
|
||||||
|
@ -123,22 +124,12 @@ public class CContentAssistProcessor extends ContentAssistProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static final int IDX_AFTERDASH = 0;
|
|
||||||
private static final int IDX_AFTERCOLON = 1;
|
|
||||||
private static final int IDX_AFTEROTHER = 2;
|
|
||||||
private static final int IDX_ALL = 3;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private IContextInformationValidator fValidator;
|
private IContextInformationValidator fValidator;
|
||||||
private final IEditorPart fEditor;
|
private final IEditorPart fEditor;
|
||||||
private char[][] fCompletionAutoActivationCharacters;
|
|
||||||
private ISourceViewer fViewer;
|
|
||||||
|
|
||||||
public CContentAssistProcessor(IEditorPart editor, ISourceViewer viewer, ContentAssistant assistant, String partition) {
|
public CContentAssistProcessor(IEditorPart editor, ContentAssistant assistant, String partition) {
|
||||||
super(assistant, partition);
|
super(assistant, partition);
|
||||||
fEditor= editor;
|
fEditor= editor;
|
||||||
fViewer= viewer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -216,69 +207,41 @@ public class CContentAssistProcessor extends ContentAssistProcessor {
|
||||||
* @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#createContext(org.eclipse.jface.text.ITextViewer, int)
|
* @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#createContext(org.eclipse.jface.text.ITextViewer, int)
|
||||||
*/
|
*/
|
||||||
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset, boolean isCompletion) {
|
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset, boolean isCompletion) {
|
||||||
return new CContentAssistInvocationContext(viewer, offset, fEditor, isCompletion);
|
return new CContentAssistInvocationContext(viewer, offset, fEditor, isCompletion, isAutoActivated());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCompletionProposalAutoActivationCharacters(char[] activationSet) {
|
/*
|
||||||
if (activationSet == null) {
|
* @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#verifyAutoActivation(org.eclipse.jface.text.ITextViewer, int)
|
||||||
fCompletionAutoActivationCharacters= null;
|
*/
|
||||||
|
protected boolean verifyAutoActivation(ITextViewer viewer, int offset) {
|
||||||
|
IDocument doc= viewer.getDocument();
|
||||||
|
if (doc == null) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
if (offset <= 0) {
|
||||||
final int len= activationSet.length;
|
return false;
|
||||||
StringBuffer afterDash= new StringBuffer(len);
|
|
||||||
StringBuffer afterColon= new StringBuffer(len);
|
|
||||||
StringBuffer afterOther= new StringBuffer(len);
|
|
||||||
for (int i = 0; i < activationSet.length; i++) {
|
|
||||||
final char c = activationSet[i];
|
|
||||||
switch(c) {
|
|
||||||
case ':':
|
|
||||||
afterColon.append(c);
|
|
||||||
break;
|
|
||||||
case '>':
|
|
||||||
afterDash.append(c);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
afterDash.append(c);
|
|
||||||
afterColon.append(c);
|
|
||||||
afterOther.append(c);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
fCompletionAutoActivationCharacters= new char[4][];
|
|
||||||
fCompletionAutoActivationCharacters[IDX_AFTERDASH]= afterDash.toString().toCharArray();
|
|
||||||
fCompletionAutoActivationCharacters[IDX_AFTERCOLON]= afterColon.toString().toCharArray();
|
|
||||||
fCompletionAutoActivationCharacters[IDX_AFTEROTHER]= afterOther.toString().toCharArray();
|
|
||||||
fCompletionAutoActivationCharacters[IDX_ALL]= activationSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public char[] getCompletionProposalAutoActivationCharacters() {
|
|
||||||
if (fCompletionAutoActivationCharacters == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fViewer != null) {
|
|
||||||
char prevChar= 0;
|
|
||||||
try {
|
try {
|
||||||
final IDocument doc= fViewer.getDocument();
|
char activationChar= doc.getChar(--offset);
|
||||||
if (doc != null) {
|
switch (activationChar) {
|
||||||
prevChar= doc.getChar(fViewer.getSelectedRange().x-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (BadLocationException e) {
|
|
||||||
// beginning of document.
|
|
||||||
}
|
|
||||||
switch (prevChar) {
|
|
||||||
case ':':
|
case ':':
|
||||||
return fCompletionAutoActivationCharacters[IDX_AFTERCOLON];
|
return offset > 0 && doc.getChar(--offset) == ':';
|
||||||
case '-':
|
case '>':
|
||||||
return fCompletionAutoActivationCharacters[IDX_AFTERDASH];
|
return offset > 0 && doc.getChar(--offset) == '-';
|
||||||
default:
|
case '.':
|
||||||
return fCompletionAutoActivationCharacters[IDX_AFTEROTHER];
|
// avoid completion of float literals
|
||||||
|
CHeuristicScanner scanner= new CHeuristicScanner(doc);
|
||||||
|
int token= scanner.previousToken(--offset, Math.max(0, offset - 200));
|
||||||
|
// the scanner reports numbers as identifiers
|
||||||
|
if (token == Symbols.TokenIDENT && !Character.isJavaIdentifierStart(doc.getChar(scanner.getPosition() + 1))) {
|
||||||
|
// not a valid identifier
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return fCompletionAutoActivationCharacters[IDX_ALL];
|
} catch (BadLocationException exc) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,8 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final ICompletionProposal[] NO_PROPOSALS= {};
|
||||||
|
|
||||||
private final List fCategories;
|
private final List fCategories;
|
||||||
private final String fPartition;
|
private final String fPartition;
|
||||||
private final ContentAssistant fAssistant;
|
private final ContentAssistant fAssistant;
|
||||||
|
@ -115,6 +117,7 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
|
||||||
private String fIterationGesture= null;
|
private String fIterationGesture= null;
|
||||||
private int fNumberOfComputedResults= 0;
|
private int fNumberOfComputedResults= 0;
|
||||||
private String fErrorMessage;
|
private String fErrorMessage;
|
||||||
|
private boolean fIsAutoActivated;
|
||||||
|
|
||||||
public ContentAssistProcessor(ContentAssistant assistant, String partition) {
|
public ContentAssistProcessor(ContentAssistant assistant, String partition) {
|
||||||
Assert.isNotNull(partition);
|
Assert.isNotNull(partition);
|
||||||
|
@ -131,6 +134,7 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
|
||||||
if (event.processor != ContentAssistProcessor.this)
|
if (event.processor != ContentAssistProcessor.this)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
fIsAutoActivated= event.isAutoActivated;
|
||||||
fIterationGesture= getIterationGesture();
|
fIterationGesture= getIterationGesture();
|
||||||
KeySequence binding= getIterationBinding();
|
KeySequence binding= getIterationBinding();
|
||||||
|
|
||||||
|
@ -203,6 +207,10 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
|
||||||
public final ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
|
public final ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
|
||||||
long start= DEBUG ? System.currentTimeMillis() : 0;
|
long start= DEBUG ? System.currentTimeMillis() : 0;
|
||||||
|
|
||||||
|
if (isAutoActivated() && !verifyAutoActivation(viewer, offset)) {
|
||||||
|
return NO_PROPOSALS;
|
||||||
|
}
|
||||||
|
|
||||||
clearState();
|
clearState();
|
||||||
|
|
||||||
IProgressMonitor monitor= createProgressMonitor();
|
IProgressMonitor monitor= createProgressMonitor();
|
||||||
|
@ -238,6 +246,20 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that auto activation is allowed.
|
||||||
|
* <p>
|
||||||
|
* The default implementation always returns <code>true</code>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param viewer the text viewer
|
||||||
|
* @param offset the offset where content assist was invoked on
|
||||||
|
* @return <code>true</code> if auto activation is allowed
|
||||||
|
*/
|
||||||
|
protected boolean verifyAutoActivation(ITextViewer viewer, int offset) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void clearState() {
|
private void clearState() {
|
||||||
fErrorMessage=null;
|
fErrorMessage=null;
|
||||||
fNumberOfComputedResults= 0;
|
fNumberOfComputedResults= 0;
|
||||||
|
@ -396,6 +418,15 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
|
||||||
return new ContentAssistInvocationContext(viewer, offset);
|
return new ContentAssistInvocationContext(viewer, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the current session was auto-activated.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the current session was auto-activated.
|
||||||
|
*/
|
||||||
|
protected boolean isAutoActivated() {
|
||||||
|
return fIsAutoActivated;
|
||||||
|
}
|
||||||
|
|
||||||
private List getCategories() {
|
private List getCategories() {
|
||||||
if (fCategoryIteration == null)
|
if (fCategoryIteration == null)
|
||||||
return fCategories;
|
return fCategories;
|
||||||
|
|
Loading…
Add table
Reference in a new issue