1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 173458: Camel case based content assist, by Jens Elmenthaler.

This commit is contained in:
Markus Schorn 2011-02-23 16:08:53 +00:00
parent 7b8eb1ed1a
commit df420139a3
39 changed files with 1212 additions and 127 deletions

View file

@ -0,0 +1,75 @@
/*******************************************************************************
* Copyright (c) 2011 Tomasz Wesolowski 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:
* Jens Elmenthaler - initial implementation
* http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests;
import junit.framework.TestCase;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.core.runtime.preferences.InstanceScope;
public class ContentAssistMatcherFactoryTest extends TestCase {
@Override
protected void tearDown() throws Exception {
InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID).remove(
CCorePreferenceConstants.SHOW_CAMEL_CASE_MATCHES);
super.tearDown();
}
public void testCamelCasePreference() {
// Default is show camel case matches on
assertTrue(match("foo", "fooBar"));
assertTrue(match("fB", "fooBar"));
setShowCamelCaseMatches(false);
assertTrue(match("foo", "fooBar"));
assertFalse(match("fB", "fooBar"));
setShowCamelCaseMatches(true);
assertTrue(match("foo", "fooBar"));
assertTrue(match("fB", "fooBar"));
}
public void testCamelCaseMatcher() {
setShowCamelCaseMatches(true);
IContentAssistMatcher matcher = ContentAssistMatcherFactory
.getInstance().createMatcher("fB");
assertEquals("f", String.valueOf(matcher.getPrefixForBinarySearch()));
assertTrue(matcher.matchRequiredAfterBinarySearch());
}
public void testPrefixMatcher() {
setShowCamelCaseMatches(true);
IContentAssistMatcher matcher = ContentAssistMatcherFactory
.getInstance().createMatcher("foo");
assertEquals("foo", String.valueOf(matcher.getPrefixForBinarySearch()));
assertFalse(matcher.matchRequiredAfterBinarySearch());
}
private void setShowCamelCaseMatches(boolean enabled) {
InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID).putBoolean(
CCorePreferenceConstants.SHOW_CAMEL_CASE_MATCHES, enabled);
}
private boolean match(String pattern, String name) {
return ContentAssistMatcherFactory.getInstance().match(
pattern.toCharArray(), name.toCharArray());
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2008 IBM Corporation and others.
* Copyright (c) 2002, 2011 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
@ -7,6 +7,7 @@
*
* Contributors:
* IBM Rational Software - Initial API and implementation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests;
@ -29,6 +30,8 @@ public class ParserTestSuite extends TestCase {
TestSuite suite= new TestSuite(ParserTestSuite.class.getName());
suite.addTestSuite(ArrayUtilsTest.class);
suite.addTestSuite(CharArrayUtilsTest.class);
suite.addTestSuite(SegmentMatcherTest.class);
suite.addTestSuite(ContentAssistMatcherFactoryTest.class);
suite.addTestSuite(CModelElementsTests.class);
suite.addTestSuite(StructuralCModelElementsTests.class);
suite.addTestSuite(ObjectMapTest.class);

View file

@ -0,0 +1,167 @@
/*******************************************************************************
* Copyright (c) 2011 Tomasz Wesolowski 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:
* Tomasz Wesolowski - initial API and implementation
* Jens Elmenthaler - further tweaking
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests;
import junit.framework.TestCase;
import org.eclipse.cdt.core.parser.util.SegmentMatcher;
public class SegmentMatcherTest extends TestCase {
public void testSimple() {
assertTrue(matchSegments("", "fooBarBaz"));
assertTrue(matchSegments("fBB", "fooBarBaz"));
assertTrue(matchSegments("fooBB", "fooBarBaz"));
assertTrue(matchSegments("foBaBaz", "fooBarBaz"));
assertTrue(matchSegments("fBBaz", "fooBarBaz"));
assertTrue(matchSegments("fooBarBaz", "fooBarBaz"));
assertTrue(matchSegments("foo", "fooBarBaz"));
assertTrue(matchSegments("fooB", "fooBarBaz"));
assertTrue(matchSegments("fBBaz", "fooBarBaz"));
assertTrue(matchSegments("fooB", "fooBarBaz"));
assertTrue(matchSegments("fBBaz", "fooBarBaz"));
// Improvement compared to JDT: an all upper case abbreviation should
// also match as a single segment.
assertTrue(matchSegments("fBBaz", "fooBARBaz"));
// Improvement compared to JDT: you don't need to specify all segments
// in between.
assertTrue(matchSegments("fBaz", "fooBARBaz"));
assertFalse(matchSegments("FooBarBaz", "fooBarBaz"));
assertFalse(matchSegments("fooBARBaz", "fooBarBaz"));
assertTrue(matchSegments("fooBarbaz", "fooBarBaz"));
assertFalse(matchSegments("barBaz", "fooBarBaz"));
assertFalse(matchSegments("BarBaz", "fooBarBaz"));
assertTrue(matchSegments("fBaz", "fooBarBaz"));
assertFalse(matchSegments("fBaBar", "fooBarBaz"));
assertFalse(matchSegments("fBBB", "fooBarBaz"));
assertFalse(matchSegments("fBBBarBaz", "fooBarBaz"));
assertFalse(matchSegments("foooBarBaz", "fooBarBaz"));
assertFalse(matchSegments("foBrBaz", "fooBarBaz"));
}
public void testSuffix() {
assertTrue(matchSegments("fooBar", "fooBar123"));
assertTrue(matchSegments("fooBar", "fooBarrr"));
assertTrue(matchSegments("fooBar", "fooBarr__"));
}
public void testNumeric() {
assertTrue(matchSegments("fBBaz", "foo29BarBaz"));
assertTrue(matchSegments("fBBaz", "fooBar100Baz10"));
assertTrue(matchSegments("fB100Baz1", "fooBar100Baz10"));
assertTrue(matchSegments("fB100Baz10", "fooBar100Baz10"));
assertTrue(matchSegments("fooBar100Baz10", "fooBar100Baz10"));
assertFalse(matchSegments("fBar100Ba", "fooBarBaz"));
assertTrue(matchSegments("f100Baz", "fooBar100Baz10"));
assertFalse(matchSegments("fB1000Baz", "fooBar100Baz"));
assertFalse(matchSegments("sV", "seed48"));
}
public void testSeparator() {
assertTrue(matchSegments("fBB", "foo_Bar_Baz"));
assertTrue(matchSegments("fBB", "foo_BarBaz"));
assertTrue(matchSegments("fBB", "foo_bar_baz"));
// Improvement compared to JDT:
assertTrue(matchSegments("FBB", "FOO_BAR_BAZ"));
assertTrue(matchSegments("fBB", "foo__barBaz"));
assertTrue(matchSegments("fBB", "foo__bar__baz"));
assertTrue(matchSegments("fB_B", "foo__bar__Baz"));
assertTrue(matchSegments("f__b", "foo__bar"));
assertFalse(matchSegments("fB_B", "foo__bar__baz"));
assertFalse(matchSegments("f___b", "foo__bar"));
assertFalse(matchSegments("f__bb", "foo__bar__baz"));
assertFalse(matchSegments("f_B_B", "fooBarBaz"));
assertFalse(matchSegments("f_B", "foo_bar"));
assertFalse(matchSegments("foo_B", "foo_bar"));
assertFalse(matchSegments("foo_Bar", "foo_bar"));
assertFalse(matchSegments("fO_bar", "foo_bar"));
assertFalse(matchSegments("f__b", "foo_bar"));
}
public void testPrefixChars() {
assertFalse(matchSegments("$asd","_asd"));
assertFalse(matchSegments("_$$","__"));
assertFalse(matchSegments("__$","__"));
// require everything to be exactly the same from start up until the first section
assertTrue(matchSegments("__f", "__fooBar"));
assertTrue(matchSegments("__fooB", "__fooBar"));
assertFalse(matchSegments("_fooB", "__fooBar"));
assertFalse(matchSegments("_FooB", "__fooBar"));
assertFalse(matchSegments("_$fooB", "__fooBar"));
assertTrue(matchSegments("___", "___"));
assertFalse(matchSegments("$__", "___"));
assertFalse(matchSegments("__$", "___"));
assertTrue(matchSegments("__", "___"));
assertFalse(matchSegments("____", "___"));
}
public void testAbbreviations() {
assertTrue(matchSegments("IFB", "IFooBar"));
assertTrue(matchSegments("IFoB", "IFooBar"));
assertTrue(matchSegments("XYZ", "XYZFooBar"));
}
public void testSingleSegment() {
assertTrue(matchSegments("foo", "fooBar"));
assertFalse(matchSegments("bar", "fooBar"));
}
public void testGetPrefixForBinarySearch() {
// Segments can be skipped, because of that the first letter as well
// as the leading separator must not be added to the binary search prefix.
assertEquals("foo", getPrefixForBinarySearch("fooBar"));
assertEquals("foo", getPrefixForBinarySearch("foo6"));
assertEquals("foo", getPrefixForBinarySearch("foo_"));
assertEquals("foo", getPrefixForBinarySearch("foo$"));
assertEquals("___", getPrefixForBinarySearch("___"));
assertEquals("___foo", getPrefixForBinarySearch("___fooBar"));
assertEquals("___foo", getPrefixForBinarySearch("___foo3"));
assertEquals("___foo", getPrefixForBinarySearch("___foo_"));
assertEquals("___foo", getPrefixForBinarySearch("___foo$"));
assertEquals("$__", getPrefixForBinarySearch("$__"));
assertEquals("$__foo", getPrefixForBinarySearch("$__fooBar"));
assertEquals("$__foo", getPrefixForBinarySearch("$__foo3"));
assertEquals("$__foo", getPrefixForBinarySearch("$__foo_"));
}
/**
* Only checks segment matching (i.e. without case-insensitive prefix matching)
*/
private boolean matchSegments(String pattern, String name) {
SegmentMatcher matcher = new SegmentMatcher(pattern.toCharArray());
return matcher.matchSegments(name.toCharArray());
}
private String getPrefixForBinarySearch(String pattern) {
SegmentMatcher matcher = new SegmentMatcher(pattern.toCharArray());
return String.valueOf(matcher.getPrefixForBinarySearch());
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* Copyright (c) 2004, 2011 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
@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Bryan Wilkinson (QNX)
* Markus Schorn (Wind River Systems)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.prefix;
@ -296,4 +297,44 @@ public class BasicCompletionTest extends CompletionTestBase {
checkNonPrefixCompletion(code, true, expected);
}
// typedef int FooBar;
// typedef int Foo_Bar;
// FB
public void testCamelCaseCompletion_CScope() throws Exception {
String code = getAboveComment();
String[] expected= {"FooBar", "Foo_Bar"};
checkCompletion(code, false, expected);
}
// typedef int FooBar;
// typedef int Foo_Bar;
// FB
public void testCamelCaseCompletion_CPPScope() throws Exception {
String code = getAboveComment();
String[] expected= {"FooBar", "Foo_Bar"};
checkCompletion(code, true, expected);
}
// class FooBar {
// FooBar();
// }
// FooBar::FB
public void testCamelCaseCompletion_CPPASTQualifiedName_CPPClassScope() throws Exception {
String code = getAboveComment();
String[] expected= {"FooBar", "FooBar"};
checkCompletion(code, true, expected);
}
// struct s1 {
// int fooBar;
// int foo_bar;
// };
// void test() {
// struct s1 s;
// s.
public void testCamelCaseCompletion_CVisitor() throws Exception {
String code = getAboveComment();
String[] expected= {"fooBar", "foo_bar"};
checkCompletion(code, false, expected);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Symbian Software Ltd. and others.
* Copyright (c) 2007, 2011 Symbian Software Ltd. 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
@ -9,6 +9,7 @@
* Andrew Ferguson (Symbian) - initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.index.tests;
@ -68,6 +69,12 @@ public class EmptyIndexFragment implements IIndexFragment {
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
public IIndexFragmentBinding[] findBindingsForContentAssist(char[] prefix,
boolean filescope, IndexFilter filter, IProgressMonitor monitor)
throws CoreException {
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
public IIndexMacro[] findMacros(char[] name, boolean isPrefix, boolean caseSensitive, IndexFilter filter, IProgressMonitor monitor) {
return IIndexMacro.EMPTY_INDEX_MACRO_ARRAY;
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 Wind River Systems, Inc. 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
@ -10,6 +10,7 @@
* Andrew Ferguson (Symbian)
* Bryan Wilkinson (QNX)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.core.index;
@ -327,6 +328,18 @@ public interface IIndex {
*/
public IIndexBinding[] findBindingsForPrefix(char[] prefix, boolean fileScopeOnly, IndexFilter filter, IProgressMonitor monitor) throws CoreException;
/**
* Searches for all bindings that are valid completions to the given prefix.
* @param prefix the text to be completed.
* @param fileScopeOnly if true, only bindings at file scope are returned
* @param filter a filter that allows for skipping parts of the index
* @param monitor a monitor for progress reporting and cancellation, may be <code>null</code>
* @return an array of bindings that complete the given text
* @throws CoreException
* @since 5.3
*/
public IIndexBinding[] findBindingsForContentAssist(char[] prefix, boolean fileScopeOnly, IndexFilter filter, IProgressMonitor monitor) throws CoreException;
/**
* Searches for all names that resolve to the given binding. You can limit the result to references, declarations
* or definitions, or a combination of those.

View file

@ -0,0 +1,158 @@
/*******************************************************************************
* Copyright (c) 2011 Jens Elmenthaler 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:
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.core.parser.util;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.core.runtime.preferences.InstanceScope;
/**
* The facade to the pattern matching algorithms of content assist.
*
* @author Jens Elmenthaler
*
* @noextend This class is not intended to be subclassed by clients.
* @since 5.3
*/
public class ContentAssistMatcherFactory {
private static ContentAssistMatcherFactory instance = null;
private boolean showCamelCaseMatches;
private final IPreferenceChangeListener preferencesListener = new IPreferenceChangeListener() {
public void preferenceChange(PreferenceChangeEvent event) {
String prop = event.getKey();
if (prop.equals(CCorePreferenceConstants.SHOW_CAMEL_CASE_MATCHES)) {
updateOnPreferences();
}
}
};
private static class CamelCaseMatcher implements IContentAssistMatcher {
private final SegmentMatcher matcher;
public CamelCaseMatcher(char[] pattern) {
matcher = new SegmentMatcher(pattern);
}
public char[] getPrefixForBinarySearch() {
return matcher.getPrefixForBinarySearch();
}
public boolean matchRequiredAfterBinarySearch() {
return matcher.matchRequiredAfterBinarySearch();
}
public boolean match(char[] name) {
return matcher.match(name);
}
}
private static class PrefixMatcher implements IContentAssistMatcher {
private final char[] prefix;
public PrefixMatcher(char[] prefix) {
this.prefix = prefix;
}
public char[] getPrefixForBinarySearch() {
return prefix;
}
public boolean matchRequiredAfterBinarySearch() {
return false;
}
public boolean match(char[] name) {
return CharArrayUtils.equals(name, 0, prefix.length, prefix, true);
}
}
private ContentAssistMatcherFactory() {
getPreferences().addPreferenceChangeListener(
preferencesListener);
updateOnPreferences();
}
public static synchronized ContentAssistMatcherFactory getInstance() {
if (instance == null) {
instance = new ContentAssistMatcherFactory();
}
return instance;
}
private void shutdownInternal() {
getPreferences().removePreferenceChangeListener(
preferencesListener);
}
/**
* @noreference This method is not intended to be referenced by clients.
*/
public static synchronized void shutdown() {
if (instance != null) {
instance.shutdownInternal();
}
}
private static IEclipsePreferences getPreferences() {
return InstanceScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID);
}
private synchronized void updateOnPreferences() {
IPreferencesService prefs = Platform.getPreferencesService();
showCamelCaseMatches = prefs.getBoolean(CCorePlugin.PLUGIN_ID,
CCorePreferenceConstants.SHOW_CAMEL_CASE_MATCHES, true, null);
}
/**
* @param pattern The pattern for which to create a matcher.
* @return A suitable matcher.
*/
public synchronized IContentAssistMatcher createMatcher(char[] pattern) {
return showCamelCaseMatches ? new CamelCaseMatcher(pattern) : new PrefixMatcher(pattern);
}
/**
* @param pattern The pattern for which to create a matcher.
* @return A suitable matcher.
*/
public IContentAssistMatcher createMatcher(String pattern) {
return createMatcher(pattern.toCharArray());
}
/**
* A helper method to match a name against the pattern typed by the user.
* If you need to match many names at once against the same pattern, use
* {@link #createMatcher(char[])} and re-use the returned matcher instead.
*
* @param pattern The user provided pattern.
* @param name The name to match against the pattern.
*
* @return <code>true</code> if the name matches the given pattern.
*/
public boolean match(char[] pattern, char[] name) {
return createMatcher(pattern).match(name);
}
}

View file

@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2011 Jens Elmenthaler 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:
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.core.parser.util;
/**
* A matcher for content assist-like application to determine whether names
* match the user provided text.
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
* @since 5.3
*/
public interface IContentAssistMatcher {
/**
* The user provided text normally represents some kind of pattern. This pattern
* may not be suitable for binary searches (e.g. within the index).
* For each content assist pattern, however, there is a string that can be
* calculated and used for binary searches.
* In the compare method used by your binary search, return 0 for any string
* that starts with the returned string.
*
* @return Such a string.
*/
char[] getPrefixForBinarySearch();
/**
* @return If false, calling @{@link #match(char[])} can be skipped if a
* name survived a binary search using the prefix returned by
* @{@link #getPrefixForBinarySearch()} as key.
*/
boolean matchRequiredAfterBinarySearch();
/**
* Matches the given name following the rules of content assist.
*
* @param name
*
* @return True if the name matches.
*/
boolean match(char[] name);
}

View file

@ -0,0 +1,236 @@
/*******************************************************************************
* Copyright (c) 2011 Tomasz Wesolowski 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:
* Tomasz Wesolowski - initial API and implementation
* Jens Elmenthaler - further tweaking
*******************************************************************************/
package org.eclipse.cdt.core.parser.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A matcher for camel case matching supporting both the camel case as well as
* he underscore notation.
*
* @noextend This class is not intended to be subclassed by clients.
* @since 5.3
*/
public class SegmentMatcher {
private final char[] prefixForBinarySearch;
/** The string the any prefix match has to start with. */
private final char[] prefixForMatching;
/** The regular expression for a segment match. */
private final Pattern regexp;
/** The minimum length any name must have in order to match. */
private final int minNameLength;
private final boolean singleSegment;
/**
* @param pattern
* The camel case or underscore pattern.
*/
public SegmentMatcher(char[] pattern) {
if (pattern == null || pattern.length == 0) {
prefixForMatching = CharArrayUtils.EMPTY;
prefixForBinarySearch = CharArrayUtils.EMPTY;
regexp = null;
minNameLength = 0;
singleSegment = true;
} else {
StringBuffer regexpBuffer = new StringBuffer("^"); //$NON-NLS-1$
int i = 0;
int lengthOfFirstSegment = 0;
char currentChar;
int segmentCount = 0;
// Translate each segment
while (i < pattern.length) {
boolean separatorSpecified = false;
// Handle prefix, i.e. anything before the first letter or digit
for (; i < pattern.length; ++i) {
currentChar = pattern[i];
if (Character.isLetterOrDigit(currentChar)) {
break;
} else {
// Quote those characters.
regexpBuffer.append(Pattern.quote(String.valueOf(currentChar)));
separatorSpecified = true;
}
}
if (i < pattern.length) {
// The character here is always a letter or digit.
currentChar = pattern[i];
if (Character.isDigit(currentChar)) {
// Handle number segment
regexpBuffer.append(currentChar);
for (++i; i < pattern.length; ++i) {
currentChar = pattern[i];
if (Character.isDigit(currentChar)) {
regexpBuffer.append(currentChar);
} else {
break;
}
}
} else {
// Handle text segment
char lower = Character.toLowerCase(currentChar);
char upper = Character.toUpperCase(currentChar);
if ((segmentCount == 0) || separatorSpecified) {
regexpBuffer.append(currentChar);
} else {
regexpBuffer.append("(_["); //$NON-NLS-1$
regexpBuffer.append(lower);
regexpBuffer.append(upper);
regexpBuffer.append("]|"); //$NON-NLS-1$
regexpBuffer.append(upper);
regexpBuffer.append(')');
}
// Remaining letters of the segment
for (++i; i < pattern.length; ++i) {
currentChar = pattern[i];
if (Character.isLetter(currentChar)) {
if (Character.isUpperCase(currentChar)) {
break;
} else {
lower = currentChar;
upper = Character.toUpperCase(currentChar);
regexpBuffer.append('[');
regexpBuffer.append(lower);
regexpBuffer.append(upper);
regexpBuffer.append(']');
}
} else {
break;
}
}
}
}
regexpBuffer.append(".*"); //$NON-NLS-1$
if (segmentCount == 0) {
lengthOfFirstSegment = i;
}
++segmentCount;
}
regexp = Pattern.compile(regexpBuffer.toString());
singleSegment = (segmentCount == 1);
prefixForMatching = pattern;
// The first segment is also the binary search prefix
prefixForBinarySearch = CharArrayUtils.extract(pattern, 0, lengthOfFirstSegment);
minNameLength = pattern.length;
}
}
/**
* Matches the given name by prefix and segment matching.
*
* @return true if the associated pattern is a prefix-based or segment-based abbreviation of name.
*/
public boolean match(char[] name) {
if (matchPrefix(name)) {
return true;
}
// If there is only a single segment given and prefix match failed,
// the segment match cannot pass either. So skip it.
if (singleSegment) {
return false;
}
return matchSegments(name);
}
/**
* Matches the given name by prefix matching.
*
* @return true if the associated pattern is a prefix-based abbreviation of name.
*/
public boolean matchPrefix(char[] name) {
return (CharArrayUtils.equals(name, 0, prefixForMatching.length, prefixForMatching, true));
}
/**
* Matches the given name by segment matching.
*
* @return true if the associated pattern is a segment-based abbreviation of name.
*/
public boolean matchSegments(char[] name) {
if (name == null) {
return false;
}
if (name.length < minNameLength) {
return false;
}
if (regexp == null) {
return true;
}
Matcher matcher = regexp.matcher(String.valueOf(name));
return matcher.find();
}
/**
* Matches pattern to name by prefix and segment matching. If you have to match
* against the same pattern repeatedly, create a {@link SegmentMatcher} instead
* and re-use it all the time, because this is much faster.
*
* @return true if pattern is a prefix-based or segment-based abbreviation of name
*/
public static boolean match(char[] pattern, char[] name) {
return (new SegmentMatcher(pattern)).match(name);
}
/**
* The pattern used by this matcher is not suitable for binary searches
* (e.g. within the index).
* However, there can be calculated a string that can be used in the
* context of binary searches.
* In the compare method used by your binary search, return 0 for any string
* that starts with the returned string.
*
* @return Such a string.
*/
public char[] getPrefixForBinarySearch() {
return prefixForBinarySearch;
}
/**
* @return If false, calling @{@link #match(char[])} can be skipped if a
* name survived a binary search using the prefix returned by
* @{@link #getPrefixForBinarySearch()} as key.
*/
boolean matchRequiredAfterBinarySearch() {
return !singleSegment;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* Copyright (c) 2004, 2011 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
@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c;
@ -56,6 +57,8 @@ import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousParameterDeclaration;
@ -327,10 +330,11 @@ public class CScope implements ICScope, IASTInternalScope {
populateCache();
for (CharArrayObjectMap map : mapsToNameOrBinding) {
if (prefixLookup) {
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(c);
Object[] keys = map.keyArray();
for (Object key2 : keys) {
char[] key = (char[]) key2;
if (CharArrayUtils.equals(key, 0, c.length, c, true)) {
if (matcher.match(key)) {
obj = ArrayUtil.append(obj, map.get(key));
}
}
@ -344,7 +348,7 @@ public class CScope implements ICScope, IASTInternalScope {
IIndex index = tu.getIndex();
if (index != null) {
try {
IBinding[] bindings = prefixLookup ? index.findBindingsForPrefix(name.toCharArray(), true, INDEX_FILTERS[NAMESPACE_TYPE_BOTH], null)
IBinding[] bindings = prefixLookup ? index.findBindingsForContentAssist(name.toCharArray(), true, INDEX_FILTERS[NAMESPACE_TYPE_BOTH], null)
: index.findBindings(name.toCharArray(), INDEX_FILTERS[NAMESPACE_TYPE_BOTH], null);
if (fileSet != null) {
bindings = fileSet.filterFileLocalBindings(bindings);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* Copyright (c) 2005, 2011 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
@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c;
@ -89,6 +90,8 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArraySet;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
@ -609,9 +612,10 @@ public class CVisitor extends ASTQueries {
if (prefix) {
IBinding[] result = null;
char[] p = fieldReference.getFieldName().toCharArray();
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(p);
IField[] fields = ((ICompositeType) type).getFields();
for (IField field : fields) {
if (CharArrayUtils.equals(field.getNameCharArray(), 0, p.length, p, true)) {
if (matcher.match(field.getNameCharArray())) {
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, field);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* Copyright (c) 2004, 2011 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
@ -9,6 +9,7 @@
* John Camelon (IBM) - Initial API and implementation
* Bryan Wilkinson (QNX)
* Markus Schorn (Wind River Systems)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -41,6 +42,7 @@ import org.eclipse.cdt.core.model.IEnumeration;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalNameOwner;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
@ -329,7 +331,7 @@ public class CPPASTQualifiedName extends CPPASTNameBase
private boolean nameMatches(char[] potential, char[] name, boolean isPrefix) {
if (isPrefix)
return CharArrayUtils.equals(potential, 0, name.length, name, true);
return ContentAssistMatcherFactory.getInstance().match(name, potential);
return CharArrayUtils.equals(potential, name);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* Copyright (c) 2004, 2011 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
@ -11,6 +11,7 @@
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -54,6 +55,7 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
@ -240,7 +242,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
}
IBinding[] result = null;
if ((!prefixLookup && CharArrayUtils.equals(c, compName.getLookupKey()))
|| (prefixLookup && CharArrayUtils.equals(compName.getLookupKey(), 0, c.length, c, true))) {
|| (prefixLookup && ContentAssistMatcherFactory.getInstance().match(c, compName.getLookupKey()))) {
if (shallReturnConstructors(name, prefixLookup)) {
result = (IBinding[]) ArrayUtil.addAll(IBinding.class, result, getConstructors(name, resolve));
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2010, 2011 Wind River Systems, Inc. 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
@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn (Wind River Systems) - initial API and implementation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -45,6 +46,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
@ -342,9 +345,10 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
private IBinding[] getPrefixBindings(char[] name) {
List<IBinding> result= new ArrayList<IBinding>();
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(name);
for (ICPPMethod m : getMethods()) {
if (!(m instanceof ICPPConstructor)) {
if (CharArrayUtils.equals(name, 0, name.length, m.getNameCharArray(), true)) {
if (matcher.match(m.getNameCharArray())) {
result.add(m);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* Copyright (c) 2004, 2011 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
@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -37,6 +38,8 @@ import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
@ -211,7 +214,7 @@ abstract public class CPPScope implements ICPPASTInternalScope {
IndexFilter filter = IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE;
final char[] nchars = name.getLookupKey();
IBinding[] bindings = prefixLookup ?
index.findBindingsForPrefix(nchars, true, filter, null) :
index.findBindingsForContentAssist(nchars, true, filter, null) :
index.findBindings(nchars, filter, null);
if (fileSet != null) {
bindings= fileSet.filterFileLocalBindings(bindings);
@ -253,9 +256,10 @@ abstract public class CPPScope implements ICPPASTInternalScope {
if (prefixLookup) {
Object[] keys = bindings != null ? bindings.keyArray() : new Object[0];
ObjectSet<Object> all= new ObjectSet<Object>(16);
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(c);
for (Object key2 : keys) {
final char[] key = (char[]) key2;
if (key != CONSTRUCTOR_KEY && CharArrayUtils.equals(key, 0, c.length, c, true)) {
if (key != CONSTRUCTOR_KEY && matcher.match(key)) {
obj= bindings.get(key);
if (obj instanceof ObjectSet<?>) {
all.addAll((ObjectSet<?>) obj);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 Wind River Systems, Inc. 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
@ -11,6 +11,7 @@
* Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
@ -531,6 +532,34 @@ public class CIndex implements IIndex {
}
}
public IIndexBinding[] findBindingsForContentAssist(char[] prefix, boolean filescope,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].findBindingsForContentAssist(prefix, filescope, filter, monitor);
} else {
List<IIndexBinding[]> result = new ArrayList<IIndexBinding[]>();
ILinkage[] linkages = Linkage.getIndexerLinkages();
for (ILinkage linkage : linkages) {
if (filter.acceptLinkage(linkage)) {
IIndexFragmentBinding[][] fragmentBindings = new IIndexFragmentBinding[fPrimaryFragmentCount][];
for (int i = 0; i < fPrimaryFragmentCount; i++) {
try {
IBinding[] part = fFragments[i].findBindingsForContentAssist(prefix, filescope, retargetFilter(linkage, filter), monitor);
fragmentBindings[i] = new IIndexFragmentBinding[part.length];
System.arraycopy(part, 0, fragmentBindings[i], 0, part.length);
} catch (CoreException e) {
CCorePlugin.log(e);
fragmentBindings[i] = IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
}
ICompositesFactory factory = getCompositesFactory(linkage.getLinkageID());
result.add(factory.getCompositeBindings(fragmentBindings));
}
}
return flatten(result);
}
}
public IIndexBinding[] findBindings(char[] name, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (SPECIALCASE_SINGLES && fFragments.length == 1) {
return fFragments[0].findBindings(name, filescope, filter, monitor);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 Wind River Systems, Inc. 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
@ -10,6 +10,7 @@
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
@ -115,6 +116,10 @@ final public class EmptyCIndex implements IIndex {
return IIndexBinding.EMPTY_INDEX_BINDING_ARRAY;
}
public IIndexBinding[] findBindingsForContentAssist(char[] prefix, boolean filescope, IndexFilter filter, IProgressMonitor monitor) {
return IIndexBinding.EMPTY_INDEX_BINDING_ARRAY;
}
public IIndexBinding[] findBindings(char[][] names, IndexFilter filter,
IProgressMonitor monitor) {
return IIndexBinding.EMPTY_INDEX_BINDING_ARRAY;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 Wind River Systems, Inc. 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
@ -10,6 +10,7 @@
* Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
@ -213,6 +214,12 @@ public interface IIndexFragment {
*/
IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException;
/**
* Returns all bindings that would be a valid completion for the given text.
* @param monitor to report progress, may be <code>null</code>
*/
IIndexFragmentBinding[] findBindingsForContentAssist(char[] prefix, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException;
/**
* Returns all macros with the given prefix or name, accepted by the given filter
* @param monitor to report progress, may be <code>null</code>

View file

@ -12,6 +12,7 @@
* Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
@ -695,6 +696,7 @@ public class PDOM extends PlatformObject implements IPDOM {
if (simpleNames != null && simpleNames.length == 1) {
return findMacroContainers(simpleNames[0], false, caseSensitive, filter, monitor);
}
char[] prefix= extractPrefix(patterns);
if (prefix != null) {
return findMacroContainers(prefix, true, caseSensitive, filter, monitor);
@ -734,7 +736,7 @@ public class PDOM extends PlatformObject implements IPDOM {
nodes.add(linkage);
for (int i=0; i < names.length-1; i++) {
char[] name= names[i];
NamedNodeCollector collector= new NamedNodeCollector(linkage, name, false, caseSensitive);
NamedNodeCollector collector= new NamedNodeCollector(linkage, name, false, false, caseSensitive);
for (Iterator<PDOMNamedNode> in = nodes.iterator(); in.hasNext();) {
PDOMNode node= in.next();
node.accept(collector);
@ -743,7 +745,7 @@ public class PDOM extends PlatformObject implements IPDOM {
nodes.addAll(Arrays.asList(collector.getNodes()));
}
char[] name= names[names.length-1];
BindingCollector collector= new BindingCollector(linkage, name, filter, false, caseSensitive);
BindingCollector collector= new BindingCollector(linkage, name, filter, false, false, caseSensitive);
for (Iterator<PDOMNamedNode> in = nodes.iterator(); in.hasNext();) {
PDOMNode node= in.next();
node.accept(collector);
@ -1073,11 +1075,19 @@ public class PDOM extends PlatformObject implements IPDOM {
}
public IIndexFragmentBinding[] findBindingsForPrefix(char[] prefix, boolean filescope, boolean caseSensitive, IndexFilter filter, IProgressMonitor monitor) throws CoreException {
return findBindingsForPrefixOrContentAssist(prefix, filescope, false, caseSensitive, filter, monitor);
}
public IIndexFragmentBinding[] findBindingsForContentAssist(char[] prefix, boolean filescope, IndexFilter filter, IProgressMonitor monitor) throws CoreException {
return findBindingsForPrefixOrContentAssist(prefix, filescope, true, false, filter, monitor);
}
private IIndexFragmentBinding[] findBindingsForPrefixOrContentAssist(char[] prefix, boolean filescope, boolean isContentAssist, boolean caseSensitive, IndexFilter filter, IProgressMonitor monitor) throws CoreException {
ArrayList<IIndexFragmentBinding> result= new ArrayList<IIndexFragmentBinding>();
for (PDOMLinkage linkage : getLinkageList()) {
if (filter.acceptLinkage(linkage)) {
PDOMBinding[] bindings;
BindingCollector visitor = new BindingCollector(linkage, prefix, filter, true, caseSensitive);
BindingCollector visitor = new BindingCollector(linkage, prefix, filter, !isContentAssist, isContentAssist, caseSensitive);
visitor.setMonitor(monitor);
try {
linkage.accept(visitor);
@ -1117,7 +1127,7 @@ public class PDOM extends PlatformObject implements IPDOM {
}
if (!isCaseSensitive || !filescope) {
BindingCollector visitor= new BindingCollector(linkage, name, filter, false, isCaseSensitive);
BindingCollector visitor= new BindingCollector(linkage, name, filter, false, false, isCaseSensitive);
visitor.setMonitor(monitor);
if (!isCaseSensitive)
@ -1146,7 +1156,7 @@ public class PDOM extends PlatformObject implements IPDOM {
try {
for (PDOMLinkage linkage : getLinkageList()) {
if (filter.acceptLinkage(linkage)) {
MacroContainerCollector visitor = new MacroContainerCollector(linkage, prefix, isPrefix, isCaseSensitive);
MacroContainerCollector visitor = new MacroContainerCollector(linkage, prefix, isPrefix, false, isCaseSensitive);
visitor.setMonitor(monitor);
linkage.getMacroIndex().accept(visitor);
result.addAll(visitor.getMacroList());
@ -1163,7 +1173,7 @@ public class PDOM extends PlatformObject implements IPDOM {
try {
for (PDOMLinkage linkage : getLinkageList()) {
if (filter.acceptLinkage(linkage)) {
MacroContainerCollector visitor = new MacroContainerCollector(linkage, prefix, isPrefix, isCaseSensitive);
MacroContainerCollector visitor = new MacroContainerCollector(linkage, prefix, isPrefix, false, isCaseSensitive);
visitor.setMonitor(monitor);
linkage.getMacroIndex().accept(visitor);
for (PDOMMacroContainer mcont : visitor.getMacroList()) {
@ -1393,7 +1403,7 @@ public class PDOM extends PlatformObject implements IPDOM {
};
}
if (filter != null) {
BindingCollector collector= new BindingCollector(cpp, binding.getNameCharArray(), filter, false, true);
BindingCollector collector= new BindingCollector(cpp, binding.getNameCharArray(), filter, false, false, true);
cpp.accept(collector);
return collector.getBindings();
}

View file

@ -8,6 +8,7 @@
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
@ -114,6 +115,14 @@ public class PDOMProxy implements IPDOM {
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
public synchronized IIndexFragmentBinding[] findBindingsForContentAssist(char[] prefix, boolean filescope,
IndexFilter filter, IProgressMonitor monitor) throws CoreException {
if (fDelegate != null)
return fDelegate.findBindingsForContentAssist(prefix, filescope, filter, monitor);
return IIndexFragmentBinding.EMPTY_INDEX_BINDING_ARRAY;
}
public synchronized IIndexFragmentInclude[] findIncludedBy(IIndexFragmentFile file) throws CoreException {
if (fDelegate != null)
return fDelegate.findIncludedBy(file);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 QNX Software Systems and others.
* Copyright (c) 2006, 2011 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
@ -9,6 +9,7 @@
* QNX - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;
@ -32,15 +33,28 @@ public final class BindingCollector extends NamedNodeCollector {
* Collects all bindings with given name.
*/
public BindingCollector(PDOMLinkage linkage, char[] name) {
this(linkage, name, null, false, true);
this(linkage, name, null, false, false, true);
}
/**
* Collects all bindings with given name, passing the filter. If prefixLookup is set to
* <code>true</code> a binding is considered if its name starts with the given prefix.
* Collects all bindings with given name, passing the filter.
*
* @param linkage
* @param name
* @param filter
* @param prefixLookup
* If set to <code>true</code> a binding is considered if its name starts with the given prefix
* Otherwise, the binding will only be considered if its name matches exactly. This parameter
* is ignored if <code>contentAssistLookup</code> is true.
* @param contentAssistLookup
* If set to <code>true</code> a binding is considered if its names matches according to the
* current content assist matching rules.
* @param caseSensitive
* Ignored if <code>contentAssistLookup</code> is true.
*/
public BindingCollector(PDOMLinkage linkage, char[] name, IndexFilter filter, boolean prefixLookup, boolean caseSensitive) {
super(linkage, name, prefixLookup, caseSensitive);
public BindingCollector(PDOMLinkage linkage, char[] name, IndexFilter filter, boolean prefixLookup,
boolean contentAssistLookup, boolean caseSensitive) {
super(linkage, name, prefixLookup, contentAssistLookup, caseSensitive);
this.filter= filter;
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 Wind River Systems, Inc. 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
@ -7,12 +7,15 @@
*
* Contributors:
* Markus Schorn (Wind River Systems)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
import org.eclipse.cdt.internal.core.pdom.db.IString;
import org.eclipse.core.runtime.CoreException;
@ -25,8 +28,9 @@ import org.eclipse.core.runtime.OperationCanceledException;
*/
public final class MacroContainerCollector implements IBTreeVisitor {
private final PDOMLinkage linkage;
private final char[] name;
private final char[] matchChars;
private final boolean prefixLookup;
private final IContentAssistMatcher contentAssistMatcher;
private final boolean caseSensitive;
private IProgressMonitor monitor= null;
private int monitorCheckCounter= 0;
@ -37,13 +41,35 @@ public final class MacroContainerCollector implements IBTreeVisitor {
/**
* Collects all nodes with given name, passing the filter. If prefixLookup is set to
* <code>true</code> a binding is considered if its name starts with the given prefix.
*
* @param linkage
* @param name
* @param prefixLookup
* If set to <code>true</code> a binding is considered if its name starts with the given prefix
* Otherwise, the binding will only be considered if its name matches exactly. This parameter
* is ignored if <code>contentAssistLookup</code> is true.
* @param contentAssistLookup
* If set to <code>true</code> a binding is considered if its names matches according to the
* current content assist matching rules.
* @param caseSensitive
* Ignored if <code>contentAssistLookup</code> is true.
*/
public MacroContainerCollector(PDOMLinkage linkage, char[] name, boolean prefixLookup, boolean caseSensitive) {
this.name= name;
this.linkage= linkage;
public MacroContainerCollector(PDOMLinkage linkage, char[] name, boolean prefixLookup,
boolean contentAssistLookup, boolean caseSensitive) {
if (contentAssistLookup) {
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(name);
this.contentAssistMatcher = matcher.matchRequiredAfterBinarySearch() ? matcher : null;
this.matchChars = matcher.getPrefixForBinarySearch();
this.prefixLookup= true;
this.caseSensitive= false;
} else {
this.contentAssistMatcher = null;
this.matchChars = name;
this.prefixLookup= prefixLookup;
this.caseSensitive= caseSensitive;
}
this.linkage= linkage;
}
/**
* Allows to cancel a visit. If set a visit may throw an OperationCancelledException.
@ -63,17 +89,16 @@ public final class MacroContainerCollector implements IBTreeVisitor {
private int compare(IString rhsName) throws CoreException {
int cmp;
if (prefixLookup) {
cmp= rhsName.comparePrefix(name, false);
cmp= rhsName.comparePrefix(matchChars, false);
if(caseSensitive) {
cmp= cmp==0 ? rhsName.comparePrefix(name, true) : cmp;
cmp= cmp==0 ? rhsName.comparePrefix(matchChars, true) : cmp;
}
return cmp;
} else {
if(caseSensitive) {
cmp= rhsName.compareCompatibleWithIgnoreCase(name);
cmp= rhsName.compareCompatibleWithIgnoreCase(matchChars);
}
else {
cmp= rhsName.compare(name, false);
cmp= rhsName.compare(matchChars, false);
}
}
return cmp;
@ -86,7 +111,15 @@ public final class MacroContainerCollector implements IBTreeVisitor {
if (record == 0)
return true;
if (contentAssistMatcher != null) {
char[] nodeName = PDOMNamedNode.getDBName(linkage.getDB(), record).getChars();
if (contentAssistMatcher.match(nodeName)) {
macros.add(new PDOMMacroContainer(linkage, record));
}
} else {
macros.add(new PDOMMacroContainer(linkage, record));
}
return true; // look for more
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 Wind River Systems, Inc. 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
@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;
@ -15,6 +16,8 @@ import java.util.List;
import org.eclipse.cdt.core.dom.IPDOMNode;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
import org.eclipse.cdt.internal.core.pdom.db.IString;
import org.eclipse.core.runtime.CoreException;
@ -26,9 +29,11 @@ import org.eclipse.core.runtime.OperationCanceledException;
* @since 4.0
*/
public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
private final PDOMLinkage linkage;
private final char[] name;
private final char[] matchChars;
private final boolean prefixLookup;
private final IContentAssistMatcher contentAssistMatcher;
private final boolean caseSensitive;
private IProgressMonitor monitor= null;
private int monitorCheckCounter= 0;
@ -39,19 +44,40 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
* Collects all nodes with given name.
*/
public NamedNodeCollector(PDOMLinkage linkage, char[] name) {
this(linkage, name, false, true);
this(linkage, name, false, false, true);
}
/**
* Collects all nodes with given name, passing the filter. If prefixLookup is set to
* <code>true</code> a binding is considered if its name starts with the given prefix.
* Collects all nodes with given name, passing the filter.
*
* @param linkage
* @param name
* @param prefixLookup
* If set to <code>true</code> a binding is considered if its name starts with the given prefix
* Otherwise, the binding will only be considered if its name matches exactly. This parameter
* is ignored if <code>contentAssistLookup</code> is true.
* @param contentAssistLookup
* If set to <code>true</code> a binding is considered if its names matches according to the
* current content assist matching rules.
* @param caseSensitive
* Ignored if <code>contentAssistLookup</code> is true.
*/
public NamedNodeCollector(PDOMLinkage linkage, char[] name, boolean prefixLookup, boolean caseSensitive) {
this.name= name;
public NamedNodeCollector(PDOMLinkage linkage, char[] name, boolean prefixLookup,
boolean contentAssistLookup, boolean caseSensitive) {
this.linkage= linkage;
if (contentAssistLookup) {
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(name);
this.contentAssistMatcher = matcher.matchRequiredAfterBinarySearch() ? matcher : null;
this.matchChars = matcher.getPrefixForBinarySearch();
this.prefixLookup= true;
this.caseSensitive= false;
} else {
this.contentAssistMatcher = null;
this.matchChars = name;
this.prefixLookup= prefixLookup;
this.caseSensitive= caseSensitive;
}
}
/**
* Allows to cancel a visit. If set a visit may throw an OperationCancelledException.
@ -71,17 +97,16 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
private int compare(IString rhsName) throws CoreException {
int cmp;
if (prefixLookup) {
cmp= rhsName.comparePrefix(name, false);
cmp= rhsName.comparePrefix(matchChars, false);
if(caseSensitive) {
cmp= cmp==0 ? rhsName.comparePrefix(name, true) : cmp;
cmp= cmp==0 ? rhsName.comparePrefix(matchChars, true) : cmp;
}
return cmp;
} else {
if(caseSensitive) {
cmp= rhsName.compareCompatibleWithIgnoreCase(name);
cmp= rhsName.compareCompatibleWithIgnoreCase(matchChars);
}
else {
cmp= rhsName.compare(name, false);
cmp= rhsName.compare(matchChars, false);
}
}
return cmp;
@ -106,7 +131,9 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
* @throws CoreException
*/
protected boolean addNode(PDOMNamedNode node) throws CoreException {
if ((contentAssistMatcher == null) || contentAssistMatcher.match(node.getDBName().getChars())) {
nodes.add(node);
}
return true; // look for more
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 QNX Software Systems and others.
* Copyright (c) 2005, 2011 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
@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* IBM Corporation
* Andrew Ferguson (Symbian)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;
@ -399,7 +400,7 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
return result;
}
BindingCollector visitor = new BindingCollector(this, name, null, false, true);
BindingCollector visitor = new BindingCollector(this, name, null, false, false, true);
visitor.setMonitor(monitor);
getIndex().accept(visitor);
PDOMBinding[] result= visitor.getBindings();

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 QNX Software Systems and others.
* Copyright (c) 2005, 2011 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
@ -11,6 +11,7 @@
* Andrew Ferguson (Symbian)
* Bryan Wilkinson (QNX)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
@ -41,6 +42,7 @@ import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.util.CharArrayMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
@ -140,7 +142,7 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope {
public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) {
try {
if (name instanceof ICPPASTConversionName) {
BindingCollector visitor = new BindingCollector(fBinding.getLinkage(), Keywords.cOPERATOR, CONVERSION_FILTER, true, true);
BindingCollector visitor = new BindingCollector(fBinding.getLinkage(), Keywords.cOPERATOR, CONVERSION_FILTER, true, false, true);
acceptViaCache(fBinding, visitor, true);
return visitor.getBindings();
}
@ -157,8 +159,8 @@ class PDOMCPPClassScope implements ICPPClassScope, IIndexScope {
}
// prefix lookup
BindingCollector visitor = new BindingCollector(fBinding.getLinkage(), nameChars, IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE, prefixLookup, !prefixLookup);
if (CharArrayUtils.equals(fBinding.getNameCharArray(), 0, nameChars.length, nameChars, true)) {
BindingCollector visitor = new BindingCollector(fBinding.getLinkage(), nameChars, IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE, prefixLookup, prefixLookup, !prefixLookup);
if (ContentAssistMatcherFactory.getInstance().match(nameChars, fBinding.getNameCharArray())) {
// add the class itself, constructors will be found during the visit
visitor.visit((IPDOMNode) getClassNameBinding());
}

View file

@ -7,6 +7,7 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
@ -28,7 +29,8 @@ import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.util.CharArrayMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.index.IIndexScope;
import org.eclipse.cdt.internal.core.pdom.PDOM;
@ -72,8 +74,9 @@ class PDOMCPPEnumScope implements ICPPScope, IIndexScope {
if (prefixLookup) {
final List<IBinding> result= new ArrayList<IBinding>();
final char[] nc= name.toCharArray();
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(nc);
for (char[] key : map.keys()) {
if (CharArrayUtils.equals(key, 0, nc.length, nc, true)) {
if (matcher.match(key)) {
result.add(map.get(key));
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 QNX Software Systems and others.
* Copyright (c) 2006, 2011 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
@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
* Bryan Wilkinson (QNX)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
@ -151,7 +152,7 @@ class PDOMCPPNamespace extends PDOMCPPBinding
public IBinding[] find(String name) {
try {
BindingCollector visitor = new BindingCollector(getLinkage(), name.toCharArray(),
IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE, false, true);
IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE, false, false, true);
getIndex().accept(visitor);
return visitor.getBindings();
} catch (CoreException e) {
@ -182,7 +183,7 @@ class PDOMCPPNamespace extends PDOMCPPBinding
result= getBindingsViaCache(name.getLookupKey());
} else {
BindingCollector visitor= new BindingCollector(getLinkage(), name.getLookupKey(),
IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE, prefixLookup, !prefixLookup);
IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE, prefixLookup, prefixLookup, !prefixLookup);
getIndex().accept(visitor);
result = visitor.getBindings();
}
@ -203,7 +204,7 @@ class PDOMCPPNamespace extends PDOMCPPBinding
return result;
}
BindingCollector visitor = new BindingCollector(getLinkage(), name,
IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE, false, true);
IndexFilter.CPP_DECLARED_OR_IMPLICIT_NO_INSTANCE, false, false, true);
getIndex().accept(visitor);
result = visitor.getBindings();
pdom.putCachedResult(key, result);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* Copyright (c) 2000, 2011 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
@ -11,6 +11,7 @@
* Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems)
* oyvind.harboe@zylin.com - http://bugs.eclipse.org/250638
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.core;
@ -32,6 +33,7 @@ import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.resources.IConsole;
import org.eclipse.cdt.core.resources.IPathEntryVariableManager;
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
@ -295,6 +297,8 @@ public class CCorePlugin extends Plugin {
fNewCProjectDescriptionManager.shutdown();
ResourceLookup.shutdown();
ContentAssistMatcherFactory.shutdown();
savePluginPreferences();
} finally {
super.stop(context);

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 QNX Software Systems and others.
* Copyright (c) 2000, 2011 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
@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
* IBM Corporation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.core;
@ -163,4 +164,11 @@ public class CCorePreferenceConstants {
* @since 5.3
*/
public static final String PREF_BUILD_CONFIGS_RESOURCE_CHANGES = "build.proj.ref.configs.enabled"; //$NON-NLS-1$
/**
* Key for boolean preference telling whether camel case/underscore matches are to be shown by content assist features or not.
*
* @since 5.3
*/
public static final String SHOW_CAMEL_CASE_MATCHES = "contentAssist.showCamelCaseMatches"; //$NON-NLS-1$
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 QNX Software Systems and others.
* Copyright (c) 2000, 2011 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
@ -10,6 +10,7 @@
* Sergey Prigogin (Google)
* Markus Schorn (Wind River Systems)
* IBM Corporation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.core;
@ -69,5 +70,8 @@ public class CCorePreferenceInitializer extends AbstractPreferenceInitializer {
// indexer defaults
IndexerPreferences.initializeDefaultPreferences(defaultPreferences);
// content assist defaults
defaultPreferences.putBoolean(CCorePreferenceConstants.SHOW_CAMEL_CASE_MATCHES, true);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 Wind River Systems, Inc. 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
@ -11,6 +11,7 @@
* Markus Schorn (Wind River Systems)
* IBM Corporation
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text.contentassist2;
@ -300,7 +301,7 @@ public class CompletionTests extends AbstractContentAssistTest {
//void f() {gC/*cursor*/
public void testGlobalVariables_GlobalScope() throws Exception {
final String[] expected= {
"gC1", "gC2"
"gC1", "gC2", "gfC1(void)", "gfC2(void)"
};
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
}
@ -308,7 +309,7 @@ public class CompletionTests extends AbstractContentAssistTest {
//void C1::f() {gC/*cursor*/
public void testGlobalVariables_MethodScope() throws Exception {
final String[] expected= {
"gC1", "gC2"
"gC1", "gC2", "gfC1(void)", "gfC2(void)"
};
assertCompletionResults(fCursorOffset, expected, AbstractContentAssistTest.COMPARE_ID_STRINGS);
}
@ -1353,4 +1354,18 @@ public class CompletionTests extends AbstractContentAssistTest {
final String[] expected= { "BaseMethod(void)" };
assertCompletionResults(fCursorOffset, expected, COMPARE_ID_STRINGS);
}
// #define fooBar
// #define foo_bar
// fB/*cursor*/
public void testUserMacroSegmentMatch() throws Exception {
final String[] expected= { "fooBar", "foo_bar" };
assertCompletionResults(fCursorOffset, expected, COMPARE_ID_STRINGS);
}
// __bVA/*cursor*/
public void testBuiltinMacroSegmentMatch() throws Exception {
final String[] expected= { "__builtin_va_arg(ap, type)" };
assertCompletionResults(fCursorOffset, expected, COMPARE_ID_STRINGS);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 Wind River Systems, Inc. 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
@ -9,6 +9,7 @@
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM Corporation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.ui.tests.text.contentassist2;
@ -594,7 +595,7 @@ public class CompletionTests_PlainC extends AbstractContentAssistTest {
//void f() {gC/*cursor*/
public void testGlobalVariables_GlobalScope() throws Exception {
final String[] expected= {
"gC1", "gC2"
"gC1", "gC2", "gfC1(void)", "gfC2(void)"
};
assertCompletionResults(expected);
}
@ -604,7 +605,7 @@ public class CompletionTests_PlainC extends AbstractContentAssistTest {
//void foo() {gC/*cursor*/
public void testGlobalVariables_FunctionScope() throws Exception {
final String[] expected= {
"gC1", "gC2"
"gC1", "gC2", "gfC1(void)", "gfC2(void)"
};
assertCompletionResults(expected);
}

View file

@ -0,0 +1,103 @@
/*******************************************************************************
* Copyright (c) 2011 Jens Elmenthaler 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:
* Jens Elmenthaler - initial API and implementation
* (http://bugs.eclipse.org/173458, camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.eclipse.cdt.core.CCorePlugin;
/**
* A preference that on preference from the UI plugin, as well the CDT core.
*
* Currently only supporting boolean preferences.
*/
public abstract class AbstractMixedPreferencePage extends AbstractPreferencePage {
protected OverlayPreferenceStore corePrefsOverlayStore;
private Map<Button, String> corePrefsCheckBoxes = new HashMap<Button, String>();
private SelectionListener corePrefsCheckBoxListener = new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
Button button = (Button) e.widget;
corePrefsOverlayStore.setValue(corePrefsCheckBoxes.get(button), button.getSelection());
}
};
public AbstractMixedPreferencePage() {
corePrefsOverlayStore = new OverlayPreferenceStore(new ScopedPreferenceStore(InstanceScope.INSTANCE,
CCorePlugin.PLUGIN_ID), createCorePrefsOverlayStoreKeys());
}
protected Button addCorePrefsCheckBox(Composite parent, String label, String key, int indentation) {
Button checkBox = new Button(parent, SWT.CHECK);
checkBox.setText(label);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalIndent = indentation;
gd.horizontalSpan = 2;
checkBox.setLayoutData(gd);
checkBox.addSelectionListener(corePrefsCheckBoxListener);
corePrefsCheckBoxes.put(checkBox, key);
return checkBox;
}
protected abstract OverlayPreferenceStore.OverlayKey[] createCorePrefsOverlayStoreKeys();
@Override
protected void initializeFields() {
super.initializeFields();
Iterator<Button> e = corePrefsCheckBoxes.keySet().iterator();
while (e.hasNext()) {
Button b = e.next();
String key = corePrefsCheckBoxes.get(b);
b.setSelection(corePrefsOverlayStore.getBoolean(key));
}
}
@Override
public boolean performOk() {
corePrefsOverlayStore.propagate();
return super.performOk();
}
@Override
protected void performDefaults() {
corePrefsOverlayStore.loadDefaults();
super.performDefaults();
}
@Override
public void dispose() {
if (corePrefsOverlayStore != null) {
corePrefsOverlayStore.stop();
corePrefsOverlayStore = null;
}
super.dispose();
}
}

View file

@ -10,6 +10,7 @@
* Anton Leherbauer (Wind River Systems)
* IBM Corporation
* Kirk Beitz (Nokia)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
@ -25,6 +26,8 @@ import org.eclipse.swt.widgets.Group;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.preferences.OverlayPreferenceStore.OverlayKey;
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
@ -32,7 +35,7 @@ import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
/**
* CodeAssistPreferencePage
*/
public class CodeAssistPreferencePage extends AbstractPreferencePage {
public class CodeAssistPreferencePage extends AbstractMixedPreferencePage {
/**
*
@ -67,6 +70,17 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
}
@Override
protected OverlayPreferenceStore.OverlayKey[] createCorePrefsOverlayStoreKeys() {
ArrayList<OverlayKey> overlayKeys = new ArrayList<OverlayKey>();
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CCorePreferenceConstants.SHOW_CAMEL_CASE_MATCHES));
OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
overlayKeys.toArray(keys);
return keys;
}
/*
* @see PreferencePage#createControl(Composite)
*/
@ -83,6 +97,8 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
protected Control createContents(Composite parent) {
fOverlayStore.load();
fOverlayStore.start();
corePrefsOverlayStore.load();
corePrefsOverlayStore.start();
Composite contentAssistComposite = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
@ -123,6 +139,9 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
label = PreferencesMessages.CEditorPreferencePage_ContentAssistPage_proposalFilterSelect ;
addComboBox(sortingGroup, label, ContentAssistPreference.PROPOSALS_FILTER, NO_TEXT_LIMIT, 0);
label= PreferencesMessages.CEditorPreferencePage_ContentAssistPage_showCamelCaseMatches;
addCorePrefsCheckBox(sortingGroup, label, CCorePreferenceConstants.SHOW_CAMEL_CASE_MATCHES, 0);
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
// The following items are grouped for Auto Activation
label = PreferencesMessages.CEditorPreferencePage_ContentAssistPage_autoActivationGroupTitle;
@ -153,7 +172,7 @@ public class CodeAssistPreferencePage extends AbstractPreferencePage {
*/
@Override
public void init(IWorkbench workbench) {
// TODO Auto-generated method stub
// Nothing to do.
}
public static void initDefaults(IPreferenceStore store) {

View file

@ -13,6 +13,7 @@
* Andrew Ferguson (Symbian)
* Kirk Beitz (Nokia)
* James Blackburn (Broadcom Corp.)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.preferences;
@ -48,6 +49,7 @@ public final class PreferencesMessages extends NLS {
public static String CEditorPreferencePage_ContentAssistPage_insertSingleProposalAutomatically;
public static String CEditorPreferencePage_ContentAssistPage_insertCommonProposalAutomatically;
public static String CEditorPreferencePage_ContentAssistPage_showProposalsInAlphabeticalOrder;
public static String CEditorPreferencePage_ContentAssistPage_showCamelCaseMatches;
public static String CEditorPreferencePage_ContentAssistPage_autoActivationGroupTitle;
public static String CEditorPreferencePage_ContentAssistPage_autoActivationEnableDot;
public static String CEditorPreferencePage_ContentAssistPage_autoActivationEnableArrow;

View file

@ -13,6 +13,7 @@
# Andrew Ferguson (Symbian)
# Kirk Beitz (Nokia)
# James Blackburn (Broadcom Corp.)
# Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
###############################################################################
CEditorPreferencePage_link=C/C++ Editor Preferences. General preferences may be set via <a href="org.eclipse.ui.preferencePages.GeneralTextEditor">Text Editors</a>.
@ -27,6 +28,7 @@ CEditorPreferencePage_ContentAssistPage_insertionGroupTitle=Insertion
CEditorPreferencePage_ContentAssistPage_insertSingleProposalAutomatically=&Insert single proposals automatically
CEditorPreferencePage_ContentAssistPage_insertCommonProposalAutomatically=I&nsert common prefixes automatically
CEditorPreferencePage_ContentAssistPage_showProposalsInAlphabeticalOrder=Present proposals in a&lphabetical order
CEditorPreferencePage_ContentAssistPage_showCamelCaseMatches=Show ca&mel case matches
CEditorPreferencePage_ContentAssistPage_autoActivationGroupTitle=Auto-Activation
CEditorPreferencePage_ContentAssistPage_autoActivationEnableDot=Enable "." as &trigger
CEditorPreferencePage_ContentAssistPage_autoActivationEnableArrow=Enable "->" as tri&gger

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others.
* Copyright (c) 2004, 2011 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
@ -7,6 +7,7 @@
*
* Contributors:
* IBM Rational Software - Initial API and implementation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
@ -35,10 +36,10 @@ import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.link.ILinkedModeListener;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedModeUI;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.jface.text.link.LinkedModeUI.ExitFlags;
import org.eclipse.jface.text.link.LinkedModeUI.IExitPolicy;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
@ -49,6 +50,7 @@ import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICCompletionProposal;
@ -481,7 +483,7 @@ public class CCompletionProposal implements ICCompletionProposal, ICompletionPro
if (offset < fReplacementOffset)
return false;
boolean validated= startsWith(document, offset, fReplacementString);
boolean validated= match(document, offset, fReplacementString);
if (validated && event != null) {
// adapt replacement range to document change
@ -509,10 +511,10 @@ public class CCompletionProposal implements ICCompletionProposal, ICompletionPro
}
/**
* Returns <code>true</code> if a words starts with the code completion prefix in the document,
* Returns <code>true</code> if a words matches the code completion prefix in the document,
* <code>false</code> otherwise.
*/
protected boolean startsWith(IDocument document, int offset, String word) {
protected boolean match(IDocument document, int offset, String word) {
if (word == null)
return false;
@ -522,8 +524,8 @@ public class CCompletionProposal implements ICCompletionProposal, ICompletionPro
try {
int length= offset - fReplacementOffset;
String start= document.get(fReplacementOffset, length);
return word.substring(0, length).equalsIgnoreCase(start);
String pattern= document.get(fReplacementOffset, length);
return ContentAssistMatcherFactory.getInstance().match(pattern.toCharArray(), word.toCharArray());
} catch (BadLocationException x) {
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 QNX Software Systems and others.
* Copyright (c) 2007, 2011 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
@ -10,6 +10,7 @@
* Markus Schorn (Wind River Systems)
* Anton Leherbauer (Wind River Systems)
* Sergey Prigogin (Google)
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
@ -64,6 +65,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions;
@ -198,30 +201,36 @@ public class DOMCompletionProposalComputer extends ParsingBasedProposalComputer
private void addMacroProposals(CContentAssistInvocationContext context, String prefix,
List<ICompletionProposal> proposals) {
IASTCompletionNode completionNode = context.getCompletionNode();
addMacroProposals(context, prefix, proposals, completionNode.getTranslationUnit()
.getMacroDefinitions());
addMacroProposals(context, prefix, proposals, completionNode.getTranslationUnit()
.getBuiltinMacroDefinitions());
}
private void addMacroProposals(CContentAssistInvocationContext context, String prefix,
List<ICompletionProposal> proposals, IASTPreprocessorMacroDefinition[] macros) {
if (macros != null) {
char[] prefixChars= prefix.toCharArray();
final boolean matchPrefix= !context.isContextInformationStyle();
IASTCompletionNode completionNode = context.getCompletionNode();
IASTPreprocessorMacroDefinition[] macros = completionNode.getTranslationUnit().getMacroDefinitions();
if (macros != null) {
if (matchPrefix) {
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(prefixChars);
for (int i = 0; i < macros.length; ++i) {
final char[] macroName= macros[i].getName().toCharArray();
if (CharArrayUtils.equals(macroName, 0, matchPrefix ? prefixChars.length : macroName.length,
prefixChars, true)) {
if (matcher.match(macroName)) {
handleMacro(macros[i], context, prefix, proposals);
}
}
}
macros = completionNode.getTranslationUnit().getBuiltinMacroDefinitions();
if (macros != null) {
} else {
for (int i = 0; i < macros.length; ++i) {
final char[] macroName= macros[i].getName().toCharArray();
if (CharArrayUtils.equals(macroName, 0, matchPrefix ? prefixChars.length : macroName.length,
prefixChars, true)) {
if (CharArrayUtils.equals(macroName, 0, macroName.length, prefixChars, true)) {
handleMacro(macros[i], context, prefix, proposals);
}
}
}
}
}
private void handleMacro(IASTPreprocessorMacroDefinition macro, CContentAssistInvocationContext context,
String prefix, List<ICompletionProposal> proposals) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2008, 2011 Wind River Systems, Inc. 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
@ -7,6 +7,7 @@
*
* Contributors:
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* Jens Elmenthaler - http://bugs.eclipse.org/173458 (camel case completion)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.contentassist;
@ -40,6 +41,8 @@ import org.eclipse.cdt.core.model.IInclude;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.util.ContentAssistMatcherFactory;
import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.text.ICPartitions;
import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
@ -249,9 +252,10 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
final int prefixLength = namePrefix.length();
final IProject project= tu.getCProject().getProject();
File[] files= fileDir.listFiles();
IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(namePrefix);
for (File file : files) {
final String name= file.getName();
if (name.length() >= prefixLength && namePrefix.equalsIgnoreCase(name.substring(0, prefixLength))) {
if (name.length() >= prefixLength && matcher.match(name.toCharArray())) {
if (file.isFile()) {
if (CoreModel.isValidCXXHeaderUnitName(project, name) || CoreModel.isValidCHeaderUnitName(project, name)) {
includeFiles.add(prefixPath.append(name).toString());
@ -296,6 +300,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
}
final IPath cPrefixPath= prefixPath;
final int prefixLength = namePrefix.length();
final IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(namePrefix);
final IProject project= tu.getCProject().getProject();
parent.accept(new IResourceProxyVisitor() {
boolean fFirstVisit= true;
@ -306,7 +311,7 @@ public class InclusionProposalComputer implements ICompletionProposalComputer {
fFirstVisit= false;
return true;
}
if (name.length() >= prefixLength && namePrefix.equalsIgnoreCase(name.substring(0, prefixLength))) {
if (name.length() >= prefixLength && matcher.match(name.toCharArray())) {
if (type == IResource.FILE) {
if (CoreModel.isValidCXXHeaderUnitName(project, name) || CoreModel.isValidCHeaderUnitName(project, name)) {
includeFiles.add(cPrefixPath.append(name).toString());