From 4187ccb321cbea7262387cec985011903e0c9493 Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Tue, 6 Feb 2007 15:00:29 +0000 Subject: [PATCH] Fix for Bug 172723 - [Content Assist] Port DOMCompletionContributor to new extension point (patch by Bryan Wilkinson) --- .../dom/parser/cpp/GNUCPPSourceParser.java | 7 +- .../contentassist/ContentAssistTests.java | 17 +- .../AbstractCompletionTest.java | 23 +- .../CompletionProposalsBaseTest.java | 12 - .../CompletionTest_ArgumentType_NoPrefix.java | 101 -------- ...CompletionTest_ArgumentType_NoPrefix2.java | 101 -------- .../ContentAssist2TestSuite.java | 2 - core/org.eclipse.cdt.ui/plugin.xml | 19 +- .../contentassist/CCompletionProcessor2.java | 216 ---------------- .../contentassist/CCompletionProposal.java | 23 +- .../CContentAssistInvocationContext.java | 141 +++++++++- .../CContentAssistProcessor.java | 50 +++- .../contentassist/ContentAssistProcessor.java | 72 +++--- ...ava => DOMCompletionProposalComputer.java} | 242 ++++++++++-------- .../LegacyCompletionProposalComputer.java | 210 +++------------ .../PDOMCompletionContributor.java | 117 --------- .../ParsingBasedProposalComputer.java | 94 +++++++ .../ContentAssistInvocationContext.java | 8 + 18 files changed, 546 insertions(+), 909 deletions(-) delete mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_ArgumentType_NoPrefix.java delete mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_ArgumentType_NoPrefix2.java delete mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProcessor2.java rename core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/{DOMCompletionContributor.java => DOMCompletionProposalComputer.java} (77%) delete mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/PDOMCompletionContributor.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ParsingBasedProposalComputer.java diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index f51579b1f7b..1800607c314 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -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(); } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist/ContentAssistTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist/ContentAssistTests.java index 379c843f552..5d331feb71b 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist/ContentAssistTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist/ContentAssistTests.java @@ -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$ diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/AbstractCompletionTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/AbstractCompletionTest.java index 673bbeca125..c5e0c88c03e 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/AbstractCompletionTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/AbstractCompletionTest.java @@ -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++){ diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionProposalsBaseTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionProposalsBaseTest.java index 710ceb2944e..58bd806fe17 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionProposalsBaseTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionProposalsBaseTest.java @@ -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); - } - } \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_ArgumentType_NoPrefix.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_ArgumentType_NoPrefix.java deleted file mode 100644 index c6c261110d7..00000000000 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_ArgumentType_NoPrefix.java +++ /dev/null @@ -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; - } - -} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_ArgumentType_NoPrefix2.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_ArgumentType_NoPrefix2.java deleted file mode 100644 index 8df6b0fea1b..00000000000 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_ArgumentType_NoPrefix2.java +++ /dev/null @@ -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; - } - -} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/ContentAssist2TestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/ContentAssist2TestSuite.java index b380118fc61..3db1b3f65e0 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/ContentAssist2TestSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/ContentAssist2TestSuite.java @@ -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()); diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index 17c11a1030f..174ebbf0a7c 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -1478,10 +1478,6 @@ - + + + + + + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProcessor2.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProcessor2.java deleted file mode 100644 index 16b951b9158..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProcessor2.java +++ /dev/null @@ -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; - } - -} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProposal.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProposal.java index f62b2376380..5a2d2c3d947 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProposal.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CCompletionProposal.java @@ -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()); } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistInvocationContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistInvocationContext.java index 9f5de95c1d7..a6053593501 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistInvocationContext.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistInvocationContext.java @@ -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 document */ - 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(); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java index ed32238f6d4..b27cf437324 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java @@ -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); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistProcessor.java index c3ab20d9597..250791ab98d 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistProcessor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ContentAssistProcessor.java @@ -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); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionContributor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java similarity index 77% rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionContributor.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java index 8c29be5dce8..180daf01430 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionContributor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/DOMCompletionProposalComputer.java @@ -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 true 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; } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/LegacyCompletionProposalComputer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/LegacyCompletionProposalComputer.java index 008d608e62b..1c65d7d054e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/LegacyCompletionProposalComputer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/LegacyCompletionProposalComputer.java @@ -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() { - } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/PDOMCompletionContributor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/PDOMCompletionContributor.java deleted file mode 100644 index 97fe73a7a3b..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/PDOMCompletionContributor.java +++ /dev/null @@ -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); - } - } - -} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ParsingBasedProposalComputer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ParsingBasedProposalComputer.java new file mode 100644 index 00000000000..ac70af4cfff --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ParsingBasedProposalComputer.java @@ -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; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ContentAssistInvocationContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ContentAssistInvocationContext.java index a12dd887f96..d8efac84bc9 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ContentAssistInvocationContext.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/text/contentassist/ContentAssistInvocationContext.java @@ -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 null values and class equality. Subclasses