1
0
Fork 0
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:
Anton Leherbauer 2008-02-11 14:22:31 +00:00
parent 39053ae062
commit d12b37a95c
6 changed files with 83 additions and 81 deletions

View file

@ -175,7 +175,7 @@ public class ContentAssistTests extends BaseUITestCase {
String contentType = editor.getViewer().getDocument().getContentType(offset);
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);
}

View file

@ -113,7 +113,7 @@ public abstract class AbstractContentAssistTest extends BaseUITestCase {
ISourceViewer sourceViewer= EditorTestHelper.getSourceViewer((AbstractTextEditor)fEditor);
String contentType = sourceViewer.getDocument().getContentType(offset);
ContentAssistant assistant = new ContentAssistant();
CContentAssistProcessor processor = new CContentAssistProcessor(fEditor, sourceViewer, assistant, contentType);
CContentAssistProcessor processor = new CContentAssistProcessor(fEditor, assistant, contentType);
long startTime= System.currentTimeMillis();
Object[] results = isCompletion
? (Object[]) processor.computeCompletionProposals(sourceViewer, offset)

View file

@ -365,25 +365,25 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
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);
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);
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);
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);
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);
processor = new CContentAssistProcessor(getEditor(), sourceViewer, assistant, ICPartitions.C_STRING);
processor = new CContentAssistProcessor(getEditor(), assistant, 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);
ContentAssistPreference.configure(assistant, fPreferenceStore);

View file

@ -43,6 +43,7 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
private final IEditorPart fEditor;
private final boolean fIsCompletion;
private final boolean fIsAutoActivated;
private ITranslationUnit fTU= null;
private boolean fTUComputed= false;
@ -59,12 +60,14 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
* @param viewer the viewer used by the editor
* @param offset the invocation offset
* @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);
Assert.isNotNull(editor);
fEditor= editor;
fIsCompletion= isCompletion;
fIsAutoActivated= isAutoActivated;
}
/**
@ -78,6 +81,7 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
fTUComputed= true;
fEditor= null;
fIsCompletion= isCompletion;
fIsAutoActivated= false;
}
/**
@ -109,7 +113,7 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
if (fCNComputed) return fCN;
fCNComputed = true;
int offset = getParseOffset();
if (offset < 0) return null;
@ -255,6 +259,10 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
return !fIsCompletion || (getParseOffset() != getInvocationOffset());
}
public boolean isAutoActivated() {
return fIsAutoActivated;
}
public void dispose() {
if (fIndex != null) {
fIndex.releaseReadLock();

View file

@ -28,7 +28,6 @@ import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
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.Point;
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.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.Symbols;
/**
* 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 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);
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)
*/
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset, boolean isCompletion) {
return new CContentAssistInvocationContext(viewer, offset, fEditor, isCompletion);
}
public void setCompletionProposalAutoActivationCharacters(char[] activationSet) {
if (activationSet == null) {
fCompletionAutoActivationCharacters= null;
}
else {
final int len= activationSet.length;
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;
}
return new CContentAssistInvocationContext(viewer, offset, fEditor, isCompletion, isAutoActivated());
}
public char[] getCompletionProposalAutoActivationCharacters() {
if (fCompletionAutoActivationCharacters == null) {
return null;
/*
* @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#verifyAutoActivation(org.eclipse.jface.text.ITextViewer, int)
*/
protected boolean verifyAutoActivation(ITextViewer viewer, int offset) {
IDocument doc= viewer.getDocument();
if (doc == null) {
return false;
}
if (fViewer != null) {
char prevChar= 0;
try {
final IDocument doc= fViewer.getDocument();
if (doc != null) {
prevChar= doc.getChar(fViewer.getSelectedRange().x-1);
if (offset <= 0) {
return false;
}
try {
char activationChar= doc.getChar(--offset);
switch (activationChar) {
case ':':
return offset > 0 && doc.getChar(--offset) == ':';
case '>':
return offset > 0 && doc.getChar(--offset) == '-';
case '.':
// 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;
}
}
catch (BadLocationException e) {
// beginning of document.
}
switch (prevChar) {
case ':':
return fCompletionAutoActivationCharacters[IDX_AFTERCOLON];
case '-':
return fCompletionAutoActivationCharacters[IDX_AFTERDASH];
default:
return fCompletionAutoActivationCharacters[IDX_AFTEROTHER];
return true;
}
} catch (BadLocationException exc) {
}
return fCompletionAutoActivationCharacters[IDX_ALL];
return false;
}
}

View file

@ -102,6 +102,8 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
}
};
private static final ICompletionProposal[] NO_PROPOSALS= {};
private final List fCategories;
private final String fPartition;
@ -115,7 +117,8 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
private String fIterationGesture= null;
private int fNumberOfComputedResults= 0;
private String fErrorMessage;
private boolean fIsAutoActivated;
public ContentAssistProcessor(ContentAssistant assistant, String partition) {
Assert.isNotNull(partition);
Assert.isNotNull(assistant);
@ -131,6 +134,7 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
if (event.processor != ContentAssistProcessor.this)
return;
fIsAutoActivated= event.isAutoActivated;
fIterationGesture= getIterationGesture();
KeySequence binding= getIterationBinding();
@ -203,6 +207,10 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
public final ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
long start= DEBUG ? System.currentTimeMillis() : 0;
if (isAutoActivated() && !verifyAutoActivation(viewer, offset)) {
return NO_PROPOSALS;
}
clearState();
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() {
fErrorMessage=null;
fNumberOfComputedResults= 0;
@ -396,6 +418,15 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
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() {
if (fCategoryIteration == null)
return fCategories;