1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +02:00

Fix for Bug 172723 - [Content Assist] Port DOMCompletionContributor to new extension point (patch by Bryan Wilkinson)

This commit is contained in:
Anton Leherbauer 2007-02-06 15:00:29 +00:00
parent 71355f9dc9
commit 4187ccb321
18 changed files with 546 additions and 909 deletions

View file

@ -1320,7 +1320,12 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (LT(1) != IToken.tRPAREN)
newInitializerExpressions = expression();
lastOffset = consume(IToken.tRPAREN).getEndOffset();
if (LT(1) == IToken.tEOC) {
lastOffset = consume().getEndOffset();
} else {
lastOffset = consume(IToken.tRPAREN).getEndOffset();
}
if (templateIdScopes.size() > 0) {
templateIdScopes.pop();
}

View file

@ -27,8 +27,8 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
@ -43,13 +43,12 @@ import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.ui.tests.text.EditorTestHelper;
import org.eclipse.cdt.ui.text.ICHelpInvocationContext;
import org.eclipse.cdt.internal.ui.CHelpProviderManager;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.text.CHelpBookDescriptor;
import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProcessor2;
import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistProcessor;
/**
* @author aniefer
@ -163,20 +162,20 @@ public class ContentAssistTests extends BaseUITestCase {
fail("Failed to get working copy"); //$NON-NLS-1$
}
// call the CompletionProcessor
// call the ContentAssistProcessor
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
FileEditorInput editorInput = new FileEditorInput(file);
IEditorPart editorPart = page.openEditor(editorInput, "org.eclipse.cdt.ui.editor.CEditor");
CEditor editor = (CEditor) editorPart ;
IAction completionAction = editor.getAction("ContentAssistProposal");
CCompletionProcessor2 completionProcessor = new CCompletionProcessor2(editorPart);
ISourceViewer viewer= EditorTestHelper.getSourceViewer(editor);
ICompletionProposal[] results = completionProcessor.computeCompletionProposals(viewer, offset); // (document, pos, wc, null);
return results ;
String contentType = editor.getViewer().getDocument().getContentType(offset);
ContentAssistant assistant = new ContentAssistant();
CContentAssistProcessor processor = new CContentAssistProcessor(editor, assistant, contentType);
return processor.computeCompletionProposals(editor.getViewer(), offset);
}
public void _testBug69334() throws Exception {
public void testBug69334() throws Exception {
importFile( "test.h", "class Test{ public : Test( int ); }; \n" ); //$NON-NLS-1$//$NON-NLS-2$
StringWriter writer = new StringWriter();
writer.write( "#include \"test.h\" \n"); //$NON-NLS-1$

View file

@ -19,6 +19,7 @@ import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.templates.TemplateProposal;
@ -26,7 +27,6 @@ import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.parser.KeywordSetKey;
import org.eclipse.cdt.core.parser.ParserFactory;
@ -37,7 +37,7 @@ import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.cdt.ui.tests.text.EditorTestHelper;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProcessor2;
import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistProcessor;
/**
*
@ -94,11 +94,13 @@ public abstract class AbstractCompletionTest extends BaseUITestCase {
System.out.println("\n\n\n\n\nTesting "+this.getClass().getName());
}
CCompletionProcessor2 completionProcessor = new CCompletionProcessor2(fEditor);
// call the CompletionProcessor
//Call the CContentAssistProcessor
ISourceViewer sourceViewer= EditorTestHelper.getSourceViewer((AbstractTextEditor)fEditor);
String contentType = sourceViewer.getDocument().getContentType(offset);
ContentAssistant assistant = new ContentAssistant();
CContentAssistProcessor processor = new CContentAssistProcessor(fEditor, assistant, contentType);
long startTime= System.currentTimeMillis();
ICompletionProposal[] results = completionProcessor.computeCompletionProposals(sourceViewer, offset);
ICompletionProposal[] results = processor.computeCompletionProposals(sourceViewer, offset);
long endTime= System.currentTimeMillis();
assertTrue(results != null);
@ -107,8 +109,6 @@ public abstract class AbstractCompletionTest extends BaseUITestCase {
Arrays.sort(expected);
Arrays.sort(resultStrings);
checkCompletionNode(completionProcessor.getCurrentCompletionNode());
if (CTestPlugin.getDefault().isDebugging()) {
System.out.println("Time (ms): " + (endTime-startTime));
for (int i = 0; i < resultStrings.length; i++) {
@ -147,15 +147,6 @@ public abstract class AbstractCompletionTest extends BaseUITestCase {
}
/**
* Perform additional checks on the ASTCompletionNode.
*
* @param currentCompletionNode
*/
protected void checkCompletionNode(ASTCompletionNode currentCompletionNode) {
// no-op by default
}
private String toString(String[] strings) {
StringBuffer buf= new StringBuffer();
for(int i=0; i< strings.length; i++){

View file

@ -27,7 +27,6 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
public abstract class CompletionProposalsBaseTest extends AbstractCompletionTest {
@ -95,15 +94,4 @@ public abstract class CompletionProposalsBaseTest extends AbstractCompletionTest
assertCompletionResults(getCompletionPosition(), expected, false);
}
/*
* @see org.eclipse.cdt.ui.tests.text.contentassist2.AbstractCompletionTest#checkCompletionNode(org.eclipse.cdt.core.dom.ast.ASTCompletionNode)
*/
protected void checkCompletionNode(ASTCompletionNode currentCompletionNode) {
assertNotNull("null completion node!", currentCompletionNode);
// check the completion node
String prefix = currentCompletionNode.getPrefix();
assertEquals(getExpectedPrefix(), prefix);
}
}

View file

@ -1,101 +0,0 @@
/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
* Bryan Wilkinson (QNX)
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text.contentassist2;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* @author hamer
*
* Testing Argument_Type completion kind , with No prefix
* Bug#50642 : Wrong completion kind when declaring an argument type
*
*/
public class CompletionTest_ArgumentType_NoPrefix extends CompletionProposalsBaseTest{
private final String fileName = "CompletionTestStart17.cpp";
private final String fileFullPath ="resources/contentassist/" + fileName;
private final String headerFileName = "CompletionTestStart.h";
private final String headerFileFullPath ="resources/contentassist/" + headerFileName;
private final String expectedPrefix = "";
private final String[] expectedResults = {
"aClass",
"anotherClass",
"aNamespace",
"anEnumeration",
"AStruct",
"xOtherClass",
"xNamespace",
"xEnumeration",
"XStruct"
};
public CompletionTest_ArgumentType_NoPrefix(String name) {
super(name);
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=169860
}
public static Test suite() {
TestSuite suite= new TestSuite(CompletionTest_ArgumentType_NoPrefix.class.getName());
suite.addTest(new CompletionTest_ArgumentType_NoPrefix("testCompletionProposals"));
return suite;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getCompletionPosition()
*/
protected int getCompletionPosition() {
return getBuffer().indexOf(" ") + 2;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getExpectedPrefix()
*/
protected String getExpectedPrefix() {
return expectedPrefix;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getExpectedResultsValues()
*/
protected String[] getExpectedResultsValues() {
return expectedResults;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getFileName()
*/
protected String getFileName() {
return fileName;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getFileFullPath()
*/
protected String getFileFullPath() {
return fileFullPath;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getHeaderFileFullPath()
*/
protected String getHeaderFileFullPath() {
return headerFileFullPath;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getHeaderFileName()
*/
protected String getHeaderFileName() {
return headerFileName;
}
}

View file

@ -1,101 +0,0 @@
/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
* Bryan Wilkinson (QNX)
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text.contentassist2;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* @author hamer
*
* Testing Argument_Type completion kind , with No prefix
* Bug#50642 : Wrong completion kind when declaring an argument type
*
*/
public class CompletionTest_ArgumentType_NoPrefix2 extends CompletionProposalsBaseTest{
private final String fileName = "CompletionTestStart19.cpp";
private final String fileFullPath ="resources/contentassist/" + fileName;
private final String headerFileName = "CompletionTestStart.h";
private final String headerFileFullPath ="resources/contentassist/" + headerFileName;
private final String expectedPrefix = "";
private final String[] expectedResults = {
"aClass",
"anotherClass",
"aNamespace",
"anEnumeration",
"AStruct",
"xOtherClass",
"xNamespace",
"xEnumeration",
"XStruct",
"ClassA"
};
public CompletionTest_ArgumentType_NoPrefix2(String name) {
super(name);
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=169860
}
public static Test suite() {
TestSuite suite= new TestSuite(CompletionTest_ArgumentType_NoPrefix2.class.getName());
suite.addTest(new CompletionTest_ArgumentType_NoPrefix2("testCompletionProposals"));
return suite;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getCompletionPosition()
*/
protected int getCompletionPosition() {
return getBuffer().indexOf(" ") + 2;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getExpectedPrefix()
*/
protected String getExpectedPrefix() {
return expectedPrefix;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getExpectedResultsValues()
*/
protected String[] getExpectedResultsValues() {
return expectedResults;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getFileName()
*/
protected String getFileName() {
return fileName;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getFileFullPath()
*/
protected String getFileFullPath() {
return fileFullPath;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getHeaderFileFullPath()
*/
protected String getHeaderFileFullPath() {
return headerFileFullPath;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getHeaderFileName()
*/
protected String getHeaderFileName() {
return headerFileName;
}
}

View file

@ -26,8 +26,6 @@ public class ContentAssist2TestSuite extends TestSuite {
super("Tests in package org.eclipse.cdt.ui.tests.text.contentassist2");
addTest(CompletionTest_MemberReference_Arrow_Prefix2.suite());
addTest(CompletionTest_ArgumentType_NoPrefix.suite());
addTest(CompletionTest_ArgumentType_NoPrefix2.suite());
addTest(CompletionTest_ArgumentType_Prefix.suite());
addTest(CompletionTest_ArgumentType_Prefix2.suite());
addTest(CompletionTest_ClassReference_NoPrefix.suite());

View file

@ -1478,10 +1478,6 @@
</extension>
<extension
point="org.eclipse.cdt.ui.completionContributors">
<contributor
class="org.eclipse.cdt.internal.ui.text.contentassist.DOMCompletionContributor"
id="DOM"
priority="1"/>
<contributor
class="org.eclipse.cdt.internal.ui.text.contentassist.KeywordCompletionContributor"
id="Keywords"
@ -1523,6 +1519,20 @@
<proposalCategory
icon="$nl$/icons/elcl16/wordassist_co.gif"/>
</extension>
<extension
id="DOMCompletionProposalComputer"
point="org.eclipse.cdt.ui.completionProposalComputer">
<completionProposalComputer
categoryId="org.eclipse.cdt.ui.parserProposalCategory"
class="org.eclipse.cdt.internal.ui.text.contentassist.DOMCompletionProposalComputer">
<partition
type="__dftl_partition_content_type">
</partition>
<partition
type="__c_preprocessor">
</partition>
</completionProposalComputer>
</extension>
<!-- legacy completions (completionContributors) -->
<extension
@ -1808,4 +1818,5 @@
class="org.eclipse.cdt.internal.ui.navigator.CNavigatorDragAdapterAssistant"
viewerId="org.eclipse.ui.navigator.ProjectExplorer"/>
</extension>
</plugin>

View file

@ -1,216 +0,0 @@
/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Bryan Wilkinson (QNX)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
import org.eclipse.cdt.ui.text.contentassist.ICompletionContributor;
import org.eclipse.cdt.ui.text.contentassist.IProposalFilter;
import org.eclipse.cdt.internal.ui.CUIMessages;
import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil;
import org.eclipse.cdt.internal.ui.text.CParameterListValidator;
/**
* @author Doug Schaefer
*/
public class CCompletionProcessor2 implements IContentAssistProcessor {
private IEditorPart editor;
private String errorMessage;
private char[] autoActivationChars;
// Property names
private String assistPrefix = "CEditor.contentassist"; //$NON-NLS-1$
private String noCompletions = assistPrefix + ".noCompletions"; //$NON-NLS-1$
private ASTCompletionNode fCurrentCompletionNode;
public CCompletionProcessor2(IEditorPart editor) {
this.editor = editor;
fCurrentCompletionNode = null;
}
public ICompletionProposal[] computeCompletionProposals(final ITextViewer viewer, int offset) {
try {
IWorkingCopy workingCopy = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
IIndex index = CCorePlugin.getIndexManager().getIndex(workingCopy.getCProject(),
IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_DEPENDENT);
try {
index.acquireReadLock();
} catch (InterruptedException e) {
return null;
}
try {
String prefix = null;
if (workingCopy != null) {
IPDOMManager manager = CCorePlugin.getPDOMManager();
String indexerId = manager.getIndexerId(workingCopy.getCProject());
int flags = ITranslationUnit.AST_SKIP_ALL_HEADERS;
if (IPDOMManager.ID_NO_INDEXER.equals(indexerId)) {
flags = 0;
}
fCurrentCompletionNode = workingCopy.getCompletionNode(index, flags, offset);
if (fCurrentCompletionNode != null)
prefix = fCurrentCompletionNode.getPrefix();
}
if (prefix == null)
prefix = scanPrefix(viewer.getDocument(), offset);
errorMessage = CUIMessages.getString(noCompletions);
List proposals = new ArrayList();
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CUIPlugin.PLUGIN_ID, "completionContributors"); //$NON-NLS-1$
if (point == null)
return null;
IExtension[] extensions = point.getExtensions();
for (int i = 0; i < extensions.length; ++i) {
IConfigurationElement[] elements = extensions[i].getConfigurationElements();
for (int j = 0; j < elements.length; ++j) {
IConfigurationElement element = elements[j];
if (!"contributor".equals(element.getName())) //$NON-NLS-1$
continue;
Object contribObject = element.createExecutableExtension("class"); //$NON-NLS-1$
if (!(contribObject instanceof ICompletionContributor))
continue;
ICompletionContributor contributor = (ICompletionContributor)contribObject;
contributor.contributeCompletionProposals(viewer, offset, workingCopy, fCurrentCompletionNode, prefix, proposals);
}
}
IProposalFilter filter = getCompletionFilter();
ICCompletionProposal[] proposalsInput = (ICCompletionProposal[]) proposals.toArray(new ICCompletionProposal[proposals.size()]) ;
ICCompletionProposal[] proposalsFiltered = filter.filterProposals(proposalsInput);
return proposalsFiltered;
} finally {
index.releaseReadLock();
}
} catch (Throwable e) {
errorMessage = e.toString();
}
return null;
}
private IProposalFilter getCompletionFilter() {
IProposalFilter filter = null;
try {
IConfigurationElement filterElement = ProposalFilterPreferencesUtil.getPreferredFilterElement();
if (null != filterElement) {
Object contribObject = filterElement
.createExecutableExtension("class"); //$NON-NLS-1$
if ((contribObject instanceof IProposalFilter)) {
filter = (IProposalFilter) contribObject;
}
}
} catch (InvalidRegistryObjectException e) {
// No action required since we will be using the fail-safe default filter
CUIPlugin.getDefault().log(e);
} catch (CoreException e) {
// No action required since we will be using the fail-safe default filter
CUIPlugin.getDefault().log(e);
}
if (null == filter) {
// fail-safe default implementation
filter = new DefaultProposalFilter();
}
return filter;
}
private String scanPrefix(IDocument document, int end) {
try {
int start = end;
while ((start != 0) && Character.isUnicodeIdentifierPart(document.getChar(start - 1)))
start--;
if ((start != 0) && Character.isUnicodeIdentifierStart(document.getChar(start - 1)))
start--;
return document.get(start, end - start);
} catch (BadLocationException e) {
return null;
}
}
public IContextInformation[] computeContextInformation(ITextViewer viewer,
int offset) {
// TODO Auto-generated method stub
return null;
}
public char[] getCompletionProposalAutoActivationCharacters() {
return autoActivationChars;
}
public void setCompletionProposalAutoActivationCharacters(char[] autoActivationChars) {
this.autoActivationChars = autoActivationChars;
}
public char[] getContextInformationAutoActivationCharacters() {
return null; // none
}
public String getErrorMessage() {
return errorMessage;
}
public IContextInformationValidator getContextInformationValidator() {
return new CParameterListValidator();
}
public void orderProposalsAlphabetically(boolean order) {
}
public void allowAddingIncludes(boolean allowAddingIncludes) {
}
/**
* @return the fCurrentCompletionNode
*/
public ASTCompletionNode getCurrentCompletionNode() {
return fCurrentCompletionNode;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2006 IBM Corporation and others.
* Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -667,29 +667,20 @@ public class CCompletionProposal implements ICCompletionProposal, ICompletionPro
setReplacementLength(length);
}
/* (non-Javadoc)
/*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return fDisplayString.hashCode()
+ fReplacementString.hashCode()
+ ((fContextInformation == null) ? 0 : fContextInformation.hashCode());
return fIdString.hashCode();
}
/* (non-Javadoc)
/*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object other) {
if(!(other instanceof CCompletionProposal))
if(!(other instanceof ICCompletionProposal))
return false;
if(!(fDisplayString.equals(((CCompletionProposal)other).fDisplayString)))
return false;
if(!(fReplacementString.equals(((CCompletionProposal)other).fReplacementString)))
return false;
if((fContextInformation != null) && (((CCompletionProposal)other).fContextInformation != null) && (!(fContextInformation.equals(((CCompletionProposal)other).fContextInformation))))
return false;
return true;
return fIdString.equalsIgnoreCase(((ICCompletionProposal)other).getIdString());
}
}

View file

@ -8,18 +8,28 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Bryan Wilkinson (QNX)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexManager;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
import org.eclipse.cdt.internal.ui.text.Symbols;
/**
* Describes the context of a content assist invocation in a C/C++ editor.
@ -32,9 +42,16 @@ import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
public class CContentAssistInvocationContext extends ContentAssistInvocationContext {
private final IEditorPart fEditor;
private final boolean fIsCompletion;
private ITranslationUnit fTU= null;
private boolean fTUComputed= false;
private int fParseOffset= -1;
private boolean fParseOffsetComputed= false;
private ASTCompletionNode fCN= null;
private boolean fCNComputed= false;
private IIndex fIndex = null;
/**
* Creates a new context.
*
@ -42,10 +59,11 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
* @param offset the invocation offset
* @param editor the editor that content assist is invoked in
*/
public CContentAssistInvocationContext(ITextViewer viewer, int offset, IEditorPart editor) {
public CContentAssistInvocationContext(ITextViewer viewer, int offset, IEditorPart editor, boolean isCompletion) {
super(viewer, offset);
Assert.isNotNull(editor);
fEditor= editor;
fIsCompletion= isCompletion;
}
/**
@ -53,11 +71,12 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
*
* @param unit the translation unit in <code>document</code>
*/
public CContentAssistInvocationContext(ITranslationUnit unit) {
public CContentAssistInvocationContext(ITranslationUnit unit, boolean isCompletion) {
super();
fTU= unit;
fTUComputed= true;
fEditor= null;
fIsCompletion= isCompletion;
}
/**
@ -84,6 +103,111 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
ITranslationUnit unit= getTranslationUnit();
return unit == null ? null : unit.getCProject();
}
public ASTCompletionNode getCompletionNode() {
if (fCNComputed) return fCN;
fCNComputed = true;
ICProject proj= getProject();
if (proj == null) return null;
try{
fIndex = CCorePlugin.getIndexManager().getIndex(proj,
IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_DEPENDENT);
try {
fIndex.acquireReadLock();
} catch (InterruptedException e) {
fIndex = null;
}
IPDOMManager manager = CCorePlugin.getPDOMManager();
String indexerId = manager.getIndexerId(proj);
int flags = ITranslationUnit.AST_SKIP_ALL_HEADERS;
if (fIndex == null || IPDOMManager.ID_NO_INDEXER.equals(indexerId)) {
flags = 0;
}
fCN = fTU.getCompletionNode(fIndex, flags, getParseOffset());
} catch (CoreException e) {
}
return fCN;
}
public int getParseOffset() {
if (!fParseOffsetComputed) {
fParseOffsetComputed= true;
if (fIsCompletion) {
fParseOffset = guessCompletionPosition();
} else {
fParseOffset = guessContextInformationPosition();
}
}
return fParseOffset;
}
protected int guessCompletionPosition() {
final int contextPosition= getInvocationOffset();
CHeuristicScanner scanner= new CHeuristicScanner(getDocument());
int bound= Math.max(-1, contextPosition - 200);
int pos= scanner.findNonWhitespaceBackward(contextPosition - 1, bound);
if (pos == CHeuristicScanner.NOT_FOUND) return contextPosition;
int token= scanner.previousToken(pos, bound);
if (token == Symbols.TokenCOMMA) {
pos= scanner.findOpeningPeer(pos, bound, '(', ')');
if (pos == CHeuristicScanner.NOT_FOUND) return contextPosition;
token = scanner.previousToken(pos, bound);
}
if (token == Symbols.TokenLPAREN) {
pos= scanner.findNonWhitespaceBackward(pos - 1, bound);
if (pos == CHeuristicScanner.NOT_FOUND) return contextPosition;
token= scanner.previousToken(pos, bound);
if (token == Symbols.TokenIDENT || token == Symbols.TokenGREATERTHAN) {
return pos + 1;
}
}
return contextPosition;
}
protected int guessContextInformationPosition() {
final int contextPosition= getInvocationOffset();
CHeuristicScanner scanner= new CHeuristicScanner(getDocument());
int bound= Math.max(-1, contextPosition - 200);
// try the innermost scope of parentheses that looks like a method call
int pos= contextPosition - 1;
do {
int paren= scanner.findOpeningPeer(pos, bound, '(', ')');
if (paren == CHeuristicScanner.NOT_FOUND)
break;
paren= scanner.findNonWhitespaceBackward(paren - 1, bound);
if (paren == CHeuristicScanner.NOT_FOUND) {
break;
}
int token= scanner.previousToken(paren, bound);
// next token must be a method name (identifier) or the closing angle of a
// constructor call of a template type.
if (token == Symbols.TokenIDENT || token == Symbols.TokenGREATERTHAN) {
return paren + 1;
}
pos= paren;
} while (true);
return contextPosition;
}
/**
* Get the editor content assist is invoked in.
@ -93,4 +217,15 @@ public class CContentAssistInvocationContext extends ContentAssistInvocationCont
public IEditorPart getEditor() {
return fEditor;
}
public boolean isContextInformationStyle() {
return !fIsCompletion || (getParseOffset() != getInvocationOffset());
}
public void dispose() {
if (fIndex != null) {
fIndex.releaseReadLock();
}
super.dispose();
}
}

View file

@ -8,19 +8,28 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Bryan Wilkinson (QNX)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.ui.IEditorPart;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
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.CParameterListValidator;
/**
@ -50,14 +59,49 @@ public class CContentAssistProcessor extends ContentAssistProcessor {
* @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#filterAndSort(java.util.List, org.eclipse.core.runtime.IProgressMonitor)
*/
protected List filterAndSortProposals(List proposals, IProgressMonitor monitor, ContentAssistInvocationContext context) {
return proposals;
IProposalFilter filter = getCompletionFilter();
ICCompletionProposal[] proposalsInput = (ICCompletionProposal[]) proposals.toArray(new ICCompletionProposal[proposals.size()]) ;
ICCompletionProposal[] proposalsFiltered = filter.filterProposals(proposalsInput);
return Arrays.asList(proposalsFiltered);
}
private IProposalFilter getCompletionFilter() {
IProposalFilter filter = null;
try {
IConfigurationElement filterElement = ProposalFilterPreferencesUtil.getPreferredFilterElement();
if (null != filterElement) {
Object contribObject = filterElement
.createExecutableExtension("class"); //$NON-NLS-1$
if ((contribObject instanceof IProposalFilter)) {
filter = (IProposalFilter) contribObject;
}
}
} catch (InvalidRegistryObjectException e) {
// No action required since we will be using the fail-safe default filter
CUIPlugin.getDefault().log(e);
} catch (CoreException e) {
// No action required since we will be using the fail-safe default filter
CUIPlugin.getDefault().log(e);
}
if (null == filter) {
// fail-safe default implementation
filter = new DefaultProposalFilter();
}
return filter;
}
protected List filterAndSortContextInformation(List contexts,
IProgressMonitor monitor) {
return contexts;
}
/*
* @see org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistProcessor#createContext(org.eclipse.jface.text.ITextViewer, int)
*/
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset) {
return new CContentAssistInvocationContext(viewer, offset, fEditor);
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset, boolean isCompletion) {
return new CContentAssistInvocationContext(viewer, offset, fEditor, isCompletion);
}
}

View file

@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Bryan Wilkinson (QNX)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
@ -206,29 +207,34 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
IProgressMonitor monitor= createProgressMonitor();
monitor.beginTask(ContentAssistMessages.ContentAssistProcessor_computing_proposals, fCategories.size() + 1);
ContentAssistInvocationContext context= createContext(viewer, offset);
long setup= DEBUG ? System.currentTimeMillis() : 0;
ContentAssistInvocationContext context= createContext(viewer, offset, true);
monitor.subTask(ContentAssistMessages.ContentAssistProcessor_collecting_proposals);
List proposals= collectProposals(viewer, offset, monitor, context);
long collect= DEBUG ? System.currentTimeMillis() : 0;
try {
long setup= DEBUG ? System.currentTimeMillis() : 0;
monitor.subTask(ContentAssistMessages.ContentAssistProcessor_collecting_proposals);
List proposals= collectProposals(viewer, offset, monitor, context);
long collect= DEBUG ? System.currentTimeMillis() : 0;
monitor.subTask(ContentAssistMessages.ContentAssistProcessor_sorting_proposals);
List filtered= filterAndSortProposals(proposals, monitor, context);
fNumberOfComputedResults= filtered.size();
long filter= DEBUG ? System.currentTimeMillis() : 0;
ICompletionProposal[] result= (ICompletionProposal[]) filtered.toArray(new ICompletionProposal[filtered.size()]);
monitor.done();
if (DEBUG) {
System.err.println("Code Assist Stats (" + result.length + " proposals)"); //$NON-NLS-1$ //$NON-NLS-2$
System.err.println("Code Assist (setup):\t" + (setup - start) ); //$NON-NLS-1$
System.err.println("Code Assist (collect):\t" + (collect - setup) ); //$NON-NLS-1$
System.err.println("Code Assist (sort):\t" + (filter - collect) ); //$NON-NLS-1$
monitor.subTask(ContentAssistMessages.ContentAssistProcessor_sorting_proposals);
List filtered= filterAndSortProposals(proposals, monitor, context);
fNumberOfComputedResults= filtered.size();
long filter= DEBUG ? System.currentTimeMillis() : 0;
ICompletionProposal[] result= (ICompletionProposal[]) filtered.toArray(new ICompletionProposal[filtered.size()]);
monitor.done();
if (DEBUG) {
System.err.println("Code Assist Stats (" + result.length + " proposals)"); //$NON-NLS-1$ //$NON-NLS-2$
System.err.println("Code Assist (setup):\t" + (setup - start) ); //$NON-NLS-1$
System.err.println("Code Assist (collect):\t" + (collect - setup) ); //$NON-NLS-1$
System.err.println("Code Assist (sort):\t" + (filter - collect) ); //$NON-NLS-1$
}
return result;
} finally {
context.dispose();
}
return result;
}
private void clearState() {
@ -288,18 +294,22 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
private List collectContextInformation(ITextViewer viewer, int offset, IProgressMonitor monitor) {
List proposals= new ArrayList();
ContentAssistInvocationContext context= createContext(viewer, offset);
ContentAssistInvocationContext context= createContext(viewer, offset, false);
List providers= getCategories();
for (Iterator it= providers.iterator(); it.hasNext();) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
List computed= cat.computeContextInformation(context, fPartition, new SubProgressMonitor(monitor, 1));
proposals.addAll(computed);
if (fErrorMessage == null)
fErrorMessage= cat.getErrorMessage();
try {
List providers= getCategories();
for (Iterator it= providers.iterator(); it.hasNext();) {
CompletionProposalCategory cat= (CompletionProposalCategory) it.next();
List computed= cat.computeContextInformation(context, fPartition, new SubProgressMonitor(monitor, 1));
proposals.addAll(computed);
if (fErrorMessage == null)
fErrorMessage= cat.getErrorMessage();
}
return proposals;
} finally {
context.dispose();
}
return proposals;
}
/**
@ -381,7 +391,7 @@ public class ContentAssistProcessor implements IContentAssistProcessor {
* @param offset the content assist offset
* @return the context to be passed to the computers
*/
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset) {
protected ContentAssistInvocationContext createContext(ITextViewer viewer, int offset, boolean isCompletion) {
return new ContentAssistInvocationContext(viewer, offset);
}

View file

@ -1,26 +1,23 @@
/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and others.
* Copyright (c) 2007 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:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Bryan Wilkinson (QNX)
* Markus Schorn (Wind River Systems)
* QNX - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.swt.graphics.Image;
@ -45,6 +42,7 @@ import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPDelegate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
@ -52,36 +50,41 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.ui.text.contentassist.ICompletionContributor;
import org.eclipse.cdt.internal.ui.viewsupport.CElementImageProvider;
public class DOMCompletionContributor implements ICompletionContributor {
/**
* Searches the DOM (both the AST and the index) for completion proposals.
*
* @author Bryan Wilkinson
*/
public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer {
public void contributeCompletionProposals(ITextViewer viewer,
int offset,
IWorkingCopy workingCopy,
ASTCompletionNode completionNode,
String prefix,
List proposals) {
/**
* Default constructor is required (executable extension).
*/
public DOMCompletionProposalComputer() {
}
protected List computeCompletionProposals(
CContentAssistInvocationContext context,
ASTCompletionNode completionNode, String prefix) {
List proposals = new ArrayList();
if (completionNode == null) {
return;
}
if(inPreprocessorDirective(viewer.getDocument(), offset)) {
if(inPreprocessorDirective(context)) {
// add only macros
addMacroProposals(viewer, offset, completionNode, prefix, proposals);
addMacroProposals(context, prefix, proposals);
} else {
boolean handleMacros= false;
IASTName[] names = completionNode.getNames();
if (names == null || names.length == 0)
// No names, not much we can do here
return;
return Collections.EMPTY_LIST;
// Find all bindings
List allBindings = new ArrayList();
@ -107,28 +110,15 @@ public class DOMCompletionContributor implements ICompletionContributor {
Iterator iBinding = allBindings.iterator();
while (iBinding.hasNext()) {
IBinding binding = (IBinding)iBinding.next();
handleBinding(binding, completionNode, offset, viewer, proposals);
handleBinding(binding, context, proposals);
}
if (handleMacros) {
addMacroProposals(viewer, offset, completionNode, prefix, proposals);
addMacroProposals(context, prefix, proposals);
}
}
}
private void addMacroProposals(ITextViewer viewer, int offset,
ASTCompletionNode completionNode, String prefix, List proposals) {
char[] prefixChars= prefix.toCharArray();
IASTPreprocessorMacroDefinition[] macros = completionNode.getTranslationUnit().getMacroDefinitions();
if (macros != null)
for (int i = 0; i < macros.length; ++i)
if (CharArrayUtils.equals(macros[i].getName().toCharArray(), 0, prefixChars.length, prefixChars, false))
handleMacro(macros[i], completionNode, offset, viewer, proposals);
macros = completionNode.getTranslationUnit().getBuiltinMacroDefinitions();
if (macros != null)
for (int i = 0; i < macros.length; ++i)
if (CharArrayUtils.equals(macros[i].getName().toCharArray(), 0, prefixChars.length, prefixChars, false))
handleMacro(macros[i], completionNode, offset, viewer, proposals);
return proposals;
}
/**
@ -138,7 +128,10 @@ public class DOMCompletionContributor implements ICompletionContributor {
* @param offset the offset to check
* @return <code>true</code> if offset is inside a preprocessor directive
*/
private boolean inPreprocessorDirective(IDocument doc, int offset) {
private boolean inPreprocessorDirective(CContentAssistInvocationContext context) {
IDocument doc = context.getViewer().getDocument();
int offset = context.getParseOffset();
if (offset > 0 && offset == doc.getLength()) {
--offset;
}
@ -150,17 +143,94 @@ public class DOMCompletionContributor implements ICompletionContributor {
return false;
}
protected void handleBinding(IBinding binding, ASTCompletionNode completionNode, int offset, ITextViewer viewer, List proposals) {
if (binding instanceof IFunction) {
handleFunction((IFunction)binding, completionNode, offset, viewer, proposals);
} else if (binding instanceof IVariable) {
handleVariable((IVariable) binding, completionNode, offset, viewer, proposals);
}
else
proposals.add(createProposal(binding.getName(), binding.getName(), getImage(binding), completionNode, offset, viewer));
private void addMacroProposals(CContentAssistInvocationContext context, String prefix, List proposals) {
char[] prefixChars= prefix.toCharArray();
ASTCompletionNode completionNode = context.getCompletionNode();
IASTPreprocessorMacroDefinition[] macros = completionNode.getTranslationUnit().getMacroDefinitions();
if (macros != null)
for (int i = 0; i < macros.length; ++i)
if (CharArrayUtils.equals(macros[i].getName().toCharArray(), 0, prefixChars.length, prefixChars, false))
handleMacro(macros[i], context, proposals);
macros = completionNode.getTranslationUnit().getBuiltinMacroDefinitions();
if (macros != null)
for (int i = 0; i < macros.length; ++i)
if (CharArrayUtils.equals(macros[i].getName().toCharArray(), 0, prefixChars.length, prefixChars, false))
handleMacro(macros[i], context, proposals);
}
private void handleFunction(IFunction function, ASTCompletionNode completionNode, int offset, ITextViewer viewer, List proposals) {
private void handleMacro(IASTPreprocessorMacroDefinition macro, CContentAssistInvocationContext context, List proposals) {
String macroName = macro.getName().toString();
Image image = getImage(CElementImageProvider.getMacroImageDescriptor());
if (macro instanceof IASTPreprocessorFunctionStyleMacroDefinition) {
IASTPreprocessorFunctionStyleMacroDefinition functionMacro = (IASTPreprocessorFunctionStyleMacroDefinition)macro;
StringBuffer repStringBuff = new StringBuffer();
repStringBuff.append(macroName);
repStringBuff.append('(');
StringBuffer args = new StringBuffer();
IASTFunctionStyleMacroParameter[] params = functionMacro.getParameters();
if (params != null)
for (int i = 0; i < params.length; ++i) {
if (i > 0)
args.append(", "); //$NON-NLS-1$
args.append(params[i].getParameter());
}
String argString = args.toString();
StringBuffer descStringBuff = new StringBuffer(repStringBuff.toString());
descStringBuff.append(argString);
descStringBuff.append(')');
repStringBuff.append(')');
String repString = repStringBuff.toString();
String descString = descStringBuff.toString();
CCompletionProposal proposal = createProposal(repString, descString, image, context);
if (!context.isContextInformationStyle()) {
proposal.setCursorPosition(repString.length() - 1);
}
if (argString.length() > 0) {
CProposalContextInformation info = new CProposalContextInformation(image, descString, argString);
info.setContextInformationPosition(context.getParseOffset());
proposal.setContextInformation(info);
}
proposals.add(proposal);
} else
proposals.add(createProposal(macroName, macroName, image, context));
}
protected void handleBinding(IBinding binding, CContentAssistInvocationContext context, List proposals) {
if (binding instanceof ICPPClassType) {
handleClass((ICPPClassType) binding, context, proposals);
} else if (binding instanceof IFunction) {
handleFunction((IFunction)binding, context, proposals);
} else if (binding instanceof IVariable) {
handleVariable((IVariable) binding, context, proposals);
} else {
proposals.add(createProposal(binding.getName(), binding.getName(), getImage(binding), context));
}
}
private void handleClass(ICPPClassType classType, CContentAssistInvocationContext context, List proposals) {
if (context.isContextInformationStyle()) {
try {
ICPPConstructor[] constructors = classType.getConstructors();
for (int i = 0; i < constructors.length; i++) {
handleFunction(constructors[i], context, proposals);
}
} catch (DOMException e) {
}
} else {
proposals.add(createProposal(classType.getName(), classType.getName(), getImage(classType), context));
}
}
private void handleFunction(IFunction function, CContentAssistInvocationContext context, List proposals) {
Image image = getImage(function);
StringBuffer repStringBuff = new StringBuffer();
@ -230,22 +300,21 @@ public class DOMCompletionContributor implements ICompletionContributor {
repStringBuff.append(')');
String repString = repStringBuff.toString();
int repLength = completionNode.getLength();
int repOffset = offset - repLength;
CCompletionProposal proposal = new CCompletionProposal(repString, repOffset, repLength, image, dispString, idString, 1, viewer);
proposal.setCursorPosition(repString.length() - 1);
CCompletionProposal proposal = createProposal(repString, dispString, idString, image, context);
if (!context.isContextInformationStyle()) {
proposal.setCursorPosition(repString.length() - 1);
}
if (dispargString.length() > 0) {
CProposalContextInformation info = new CProposalContextInformation(image, dispString, dispargString);
info.setContextInformationPosition(offset);
info.setContextInformationPosition(context.getParseOffset());
proposal.setContextInformation(info);
}
proposals.add(proposal);
}
private void handleVariable(IVariable variable, ASTCompletionNode completionNode, int offset, ITextViewer viewer, List proposals) {
private void handleVariable(IVariable variable, CContentAssistInvocationContext context, List proposals) {
StringBuffer repStringBuff = new StringBuffer();
repStringBuff.append(variable.getName());
@ -269,61 +338,25 @@ public class DOMCompletionContributor implements ICompletionContributor {
String repString = repStringBuff.toString();
int repLength = completionNode.getLength();
int repOffset = offset - repLength;
Image image = getImage(variable);
CCompletionProposal proposal = new CCompletionProposal(repString, repOffset, repLength, image, dispString, idString, 1, viewer);
CCompletionProposal proposal = createProposal(repString, dispString, idString, image, context);
proposals.add(proposal);
}
private void handleMacro(IASTPreprocessorMacroDefinition macro, ASTCompletionNode completionNode, int offset, ITextViewer viewer, List proposals) {
String macroName = macro.getName().toString();
Image image = getImage(CElementImageProvider.getMacroImageDescriptor());
if (macro instanceof IASTPreprocessorFunctionStyleMacroDefinition) {
IASTPreprocessorFunctionStyleMacroDefinition functionMacro = (IASTPreprocessorFunctionStyleMacroDefinition)macro;
StringBuffer repStringBuff = new StringBuffer();
repStringBuff.append(macroName);
repStringBuff.append('(');
StringBuffer args = new StringBuffer();
IASTFunctionStyleMacroParameter[] params = functionMacro.getParameters();
if (params != null)
for (int i = 0; i < params.length; ++i) {
if (i > 0)
args.append(", "); //$NON-NLS-1$
args.append(params[i].getParameter());
}
String argString = args.toString();
StringBuffer descStringBuff = new StringBuffer(repStringBuff.toString());
descStringBuff.append(argString);
descStringBuff.append(')');
repStringBuff.append(')');
String repString = repStringBuff.toString();
String descString = descStringBuff.toString();
CCompletionProposal proposal = createProposal(repString, descString, image, completionNode, offset, viewer);
proposal.setCursorPosition(repString.length() - 1);
if (argString.length() > 0) {
CProposalContextInformation info = new CProposalContextInformation(image, descString, argString);
info.setContextInformationPosition(offset);
proposal.setContextInformation(info);
}
proposals.add(proposal);
} else
proposals.add(createProposal(macroName, macroName, image, completionNode, offset, viewer));
private CCompletionProposal createProposal(String repString, String dispString, Image image, CContentAssistInvocationContext context) {
return createProposal(repString, dispString, null, image, context);
}
private CCompletionProposal createProposal(String repString, String dispString, Image image, ASTCompletionNode completionNode, int offset, ITextViewer viewer) {
int repLength = completionNode.getLength();
int repOffset = offset - repLength;
return new CCompletionProposal(repString, repOffset, repLength, image, dispString, 1, viewer);
private CCompletionProposal createProposal(String repString, String dispString, String idString, Image image, CContentAssistInvocationContext context) {
int parseOffset = context.getParseOffset();
int invocationOffset = context.getInvocationOffset();
boolean doReplacement = !context.isContextInformationStyle();
int repLength = doReplacement ? context.getCompletionNode().getLength() : 0;
int repOffset = doReplacement ? parseOffset - repLength : invocationOffset;
repString = doReplacement ? repString : ""; //$NON-NLS-1$
return new CCompletionProposal(repString, repOffset, repLength, image, dispString, idString, 1, context.getViewer());
}
private Image getImage(ImageDescriptor desc) {
@ -393,5 +426,4 @@ public class DOMCompletionContributor implements ICompletionContributor {
? CUIPlugin.getImageDescriptorRegistry().get( imageDescriptor )
: null;
}
}

View file

@ -13,85 +13,27 @@
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationExtension;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorPart;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
import org.eclipse.cdt.internal.ui.text.Symbols;
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.contentassist.ICompletionContributor;
/**
* A proposal computer wrapping the legacy {@link CCompletionProcessor2}.
*
* A proposal computer for handling the legacy extension from the
* completionContributors extension point.
*
* @since 4.0
*/
public class LegacyCompletionProposalComputer implements ICompletionProposalComputer {
private static final class ContextInformationWrapper implements IContextInformation, IContextInformationExtension {
private final IContextInformation fContextInformation;
private int fPosition;
public ContextInformationWrapper(IContextInformation contextInformation) {
fContextInformation= contextInformation;
}
/*
* @see IContextInformation#getContextDisplayString()
*/
public String getContextDisplayString() {
return fContextInformation.getContextDisplayString();
}
/*
* @see IContextInformation#getImage()
*/
public Image getImage() {
return fContextInformation.getImage();
}
/*
* @see IContextInformation#getInformationDisplayString()
*/
public String getInformationDisplayString() {
return fContextInformation.getInformationDisplayString();
}
/*
* @see IContextInformationExtension#getContextInformationPosition()
*/
public int getContextInformationPosition() {
return fPosition;
}
public void setContextInformationPosition(int position) {
fPosition= position;
}
/*
* @see org.eclipse.jface.text.contentassist.IContextInformation#equals(java.lang.Object)
*/
public boolean equals(Object object) {
if (object instanceof ContextInformationWrapper)
return fContextInformation.equals(((ContextInformationWrapper) object).fContextInformation);
else
return fContextInformation.equals(object);
}
}
private CCompletionProcessor2 fCompletionProcessor;
public class LegacyCompletionProposalComputer extends ParsingBasedProposalComputer {
/**
* Default constructor is required (executable extension).
@ -99,110 +41,34 @@ public class LegacyCompletionProposalComputer implements ICompletionProposalComp
public LegacyCompletionProposalComputer() {
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeCompletionProposals(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) {
if (context instanceof CContentAssistInvocationContext) {
CContentAssistInvocationContext cContext= (CContentAssistInvocationContext)context;
return internalComputeCompletionProposals(context.getInvocationOffset(), cContext, monitor);
}
return Collections.EMPTY_LIST;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#computeContextInformation(org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext, org.eclipse.core.runtime.IProgressMonitor)
*/
public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) {
if (context instanceof CContentAssistInvocationContext) {
CContentAssistInvocationContext cContext= (CContentAssistInvocationContext)context;
int contextInformationPosition= guessContextInformationPosition(cContext);
if (contextInformationPosition >= 0) {
List result= addContextInformations(cContext, contextInformationPosition, monitor);
return result;
}
}
return Collections.EMPTY_LIST;
}
protected int guessContextInformationPosition(ContentAssistInvocationContext context) {
final int contextPosition= context.getInvocationOffset();
protected List computeCompletionProposals(
CContentAssistInvocationContext context,
ASTCompletionNode completionNode, String prefix) throws CoreException {
IDocument document= context.getDocument();
CHeuristicScanner scanner= new CHeuristicScanner(document);
int bound= Math.max(-1, contextPosition - 200);
ITextViewer viewer = context.getViewer();
int offset = context.getInvocationOffset();
IWorkingCopy workingCopy = context.getTranslationUnit().getWorkingCopy();
// try the innermost scope of parentheses that looks like a method call
int pos= contextPosition - 1;
do {
int paren= scanner.findOpeningPeer(pos, bound, '(', ')');
if (paren == CHeuristicScanner.NOT_FOUND)
break;
paren= scanner.findNonWhitespaceBackward(paren - 1, bound);
if (paren == CHeuristicScanner.NOT_FOUND) {
break;
}
int token= scanner.previousToken(paren, bound);
// next token must be a method name (identifier) or the closing angle of a
// constructor call of a template type.
if (token == Symbols.TokenIDENT || token == Symbols.TokenGREATERTHAN) {
return paren + 1;
}
pos= paren;
} while (true);
List proposals = new ArrayList();
return context.getInvocationOffset();
}
private List addContextInformations(CContentAssistInvocationContext context, int offset, IProgressMonitor monitor) {
List proposals= internalComputeCompletionProposals(offset, context, monitor);
List result= new ArrayList(proposals.size());
for (Iterator it= proposals.iterator(); it.hasNext();) {
ICompletionProposal proposal= (ICompletionProposal) it.next();
IContextInformation contextInformation= proposal.getContextInformation();
if (contextInformation != null) {
ContextInformationWrapper wrapper= new ContextInformationWrapper(contextInformation);
wrapper.setContextInformationPosition(offset);
result.add(wrapper);
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CUIPlugin.PLUGIN_ID, "completionContributors"); //$NON-NLS-1$
if (point == null)
return null;
IExtension[] extensions = point.getExtensions();
for (int i = 0; i < extensions.length; ++i) {
IConfigurationElement[] elements = extensions[i].getConfigurationElements();
for (int j = 0; j < elements.length; ++j) {
IConfigurationElement element = elements[j];
if (!"contributor".equals(element.getName())) //$NON-NLS-1$
continue;
Object contribObject = element.createExecutableExtension("class"); //$NON-NLS-1$
if (!(contribObject instanceof ICompletionContributor))
continue;
ICompletionContributor contributor = (ICompletionContributor)contribObject;
contributor.contributeCompletionProposals(viewer, offset, workingCopy, completionNode, prefix, proposals);
}
}
return result;
return proposals;
}
private List internalComputeCompletionProposals(int offset, CContentAssistInvocationContext context, IProgressMonitor monitor) {
IEditorPart editor= context.getEditor();
if (editor != null) {
fCompletionProcessor= new CCompletionProcessor2(editor);
ICompletionProposal[] proposals= fCompletionProcessor.computeCompletionProposals(context.getViewer(), offset);
if (proposals != null) {
return Arrays.asList(proposals);
}
}
return Collections.EMPTY_LIST;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#getErrorMessage()
*/
public String getErrorMessage() {
if (fCompletionProcessor != null) {
return fCompletionProcessor.getErrorMessage();
}
return null;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionEnded()
*/
public void sessionEnded() {
fCompletionProcessor= null;
}
/*
* @see org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer#sessionStarted()
*/
public void sessionStarted() {
}
}

View file

@ -1,117 +0,0 @@
/*******************************************************************************
* Copyright (c) 2006 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 - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.cdt.core.dom.IPDOMNode;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.contentassist.ICompletionContributor;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
/**
* @author Doug Schaefer
*
* Completion contributor that looks up prefixes in the PDOM.
*/
public class PDOMCompletionContributor extends DOMCompletionContributor implements ICompletionContributor {
public void contributeCompletionProposals(
final ITextViewer viewer,
final int offset,
final IWorkingCopy workingCopy,
final ASTCompletionNode completionNode,
final String prefix,
final List proposals) {
if (completionNode == null)
return;
// Return anyway
if (completionNode != null)
return;
try {
PDOM pdom = (PDOM) CCoreInternals.getPDOMManager().getPDOM(workingCopy.getCProject());
IASTName[] names = completionNode.getNames();
for (int i = 0; i < names.length; ++i) {
IASTName name = names[i];
IASTNode parent = name.getParent();
if (parent instanceof IASTIdExpression || parent instanceof IASTNamedTypeSpecifier) {
pdom.accept(new IPDOMVisitor() {
public boolean visit(IPDOMNode node) throws CoreException {
if (node instanceof PDOMLinkage)
return true;
if (node instanceof PDOMBinding) {
PDOMBinding binding = (PDOMBinding)node;
if (binding.getName().startsWith(prefix)) {
handleBinding(binding, completionNode, offset, viewer, proposals);
}
}
return false;
}
public void leave(IPDOMNode node) throws CoreException {
}
});
} else if (parent instanceof IASTFieldReference) {
// Find the type the look at the fields
IASTFieldReference fieldRef = (IASTFieldReference)parent;
IASTExpression expression = fieldRef.getFieldOwner();
IType type = expression.getExpressionType();
if (type != null && type instanceof IBinding) {
IBinding binding = (IBinding)type;
PDOMLinkage linkage = pdom.getLinkage(name.getLinkage().getID());
PDOMBinding pdomBinding = linkage.adaptBinding(binding);
if (pdomBinding != null) {
pdomBinding.accept(new IPDOMVisitor() {
public boolean visit(IPDOMNode node) throws CoreException {
if (node instanceof IField) {
PDOMBinding binding = (PDOMBinding)node;
if (binding.getName().startsWith(prefix))
handleBinding(binding, completionNode, offset, viewer, proposals);
}
return false;
}
public void leave(IPDOMNode node) throws CoreException {
}
});
}
}
}
}
} catch (CoreException e) {
CUIPlugin.getDefault().log(e);
}
}
}

View file

@ -0,0 +1,94 @@
/*******************************************************************************
* Copyright (c) 2007 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 - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
import org.eclipse.cdt.ui.text.contentassist.ICompletionProposalComputer;
/**
* The base class for any proposal computers that require a completion node in
* order to determine its completion proposals.
*
* @author Bryan Wilkinson
*/
public abstract class ParsingBasedProposalComputer implements ICompletionProposalComputer {
private String fErrorMessage = null;
public List computeCompletionProposals(
ContentAssistInvocationContext context, IProgressMonitor monitor) {
try {
if (context instanceof CContentAssistInvocationContext) {
CContentAssistInvocationContext cContext = (CContentAssistInvocationContext) context;
ASTCompletionNode completionNode = cContext.getCompletionNode();
if (completionNode == null) return Collections.EMPTY_LIST;
String prefix = completionNode.getPrefix();
if (prefix == null) {
prefix = cContext.computeIdentifierPrefix().toString();
}
return computeCompletionProposals(cContext, completionNode, prefix);
}
} catch (Throwable e) {
fErrorMessage = e.toString();
}
return Collections.EMPTY_LIST;
}
protected abstract List computeCompletionProposals(
CContentAssistInvocationContext context,
ASTCompletionNode completionNode,
String prefix) throws CoreException;
public List computeContextInformation(
ContentAssistInvocationContext context, IProgressMonitor monitor) {
List proposals= computeCompletionProposals(context, monitor);
// remove duplicates
proposals= new ArrayList(new LinkedHashSet(proposals));
List result= new ArrayList();
for (Iterator it= proposals.iterator(); it.hasNext();) {
ICompletionProposal proposal= (ICompletionProposal) it.next();
IContextInformation contextInformation= proposal.getContextInformation();
if (contextInformation != null) {
result.add(contextInformation);
}
}
return result;
}
public String getErrorMessage() {
return fErrorMessage;
}
public void sessionEnded() {
}
public void sessionStarted() {
fErrorMessage = null;
}
}

View file

@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Anton Leherbauer (Wind River Systems)
* Bryan Wilkinson (QNX)
*******************************************************************************/
package org.eclipse.cdt.ui.text.contentassist;
@ -145,6 +146,13 @@ public class ContentAssistInvocationContext {
return fPrefix;
}
/**
* Called upon completion of the content assist. Used to free any resources
* used by the context.
*/
public void dispose() {
}
/**
* Invocation contexts are equal if they describe the same context and are of the same type.
* This implementation checks for <code>null</code> values and class equality. Subclasses