mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +02:00
Merge remote-tracking branch 'cdt/master' into sd90
This commit is contained in:
commit
0142bde6ea
89 changed files with 3439 additions and 272 deletions
|
@ -186,6 +186,7 @@ public class Messages extends NLS {
|
|||
public static String NewMakeProjFromExistingPage_7;
|
||||
public static String NewMakeProjFromExistingPage_8;
|
||||
public static String NewMakeProjFromExistingPage_9;
|
||||
public static String NewMakeProjFromExistingPage_DirReadOnlyError;
|
||||
public static String NewVarDialog_0;
|
||||
public static String NewVarDialog_1;
|
||||
public static String PreferredToolchainsTab_0;
|
||||
|
|
|
@ -152,6 +152,8 @@ NewMakeProjFromExistingPage_6=Browse...
|
|||
NewMakeProjFromExistingPage_7=Select root directory of existing code
|
||||
NewMakeProjFromExistingPage_8=Not a valid directory
|
||||
NewMakeProjFromExistingPage_9=Languages
|
||||
NewMakeProjFromExistingPage_DirReadOnlyError=Directory is read-only
|
||||
|
||||
|
||||
# ----------- Configuration Selection Page -----------
|
||||
BuildPropertyPage_error_Unknown_tree_element=Unknown type of element in tree of type {0}
|
||||
|
|
|
@ -155,10 +155,13 @@ public class NewMakeProjFromExistingPage extends WizardPage {
|
|||
else {
|
||||
final File file= new File(loc);
|
||||
if (file.isDirectory()) {
|
||||
// Ensure we can create files in the directory.
|
||||
if (!file.canWrite())
|
||||
msg = Messages.NewMakeProjFromExistingPage_DirReadOnlyError;
|
||||
// Set the project name to the directory name but not if the user has supplied a name
|
||||
// (bugzilla 368987). Use a job to ensure proper sequence of activity, as setting the Text
|
||||
// will invoke the listener, which will invoke this method.
|
||||
if (!projectNameSetByUser && !name.equals(file.getName())) {
|
||||
else if (!projectNameSetByUser && !name.equals(file.getName())) {
|
||||
WorkbenchJob wjob = new WorkbenchJob("update project name") { //$NON-NLS-1$
|
||||
@Override
|
||||
public IStatus runInUIThread(IProgressMonitor monitor) {
|
||||
|
|
|
@ -4509,25 +4509,25 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
parseAndCheckBindings(code);
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, CPP);
|
||||
ICPPFunctionTemplate f= bh.assertNonProblem("f1", 2);
|
||||
assertEquals("void (int (*)(#0 ...))", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertEquals("void (int (*)(#0(...) ...))", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertFalse(f.getParameters()[0].isParameterPack());
|
||||
f= bh.assertNonProblem("f2", 2);
|
||||
assertEquals("void (int (* ...)(#0, int))", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertEquals("void (int (* ...)(#0(...), int))", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertTrue(f.getParameters()[0].isParameterPack());
|
||||
f= bh.assertNonProblem("f3", 2);
|
||||
assertEquals("void (#0 (* ...)())", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertEquals("void (#0(...) (* ...)())", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertTrue(f.getParameters()[0].isParameterPack());
|
||||
f= bh.assertNonProblem("f4", 2);
|
||||
assertEquals("void (int (& ...)[3 *0 0])", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertTrue(f.getParameters()[0].isParameterPack());
|
||||
f= bh.assertNonProblem("f5", 2);
|
||||
assertEquals("void (#0 ...)", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertEquals("void (#0(...) ...)", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertTrue(f.getParameters()[0].isParameterPack());
|
||||
f= bh.assertNonProblem("f6", 2);
|
||||
assertEquals("void (#0, ...)", ASTTypeUtil.getType(f.getType(), true));
|
||||
assertFalse(f.getParameters()[0].isParameterPack());
|
||||
f= bh.assertNonProblem("f7", 2);
|
||||
assertEquals("#0 ...", ASTTypeUtil.getType(f.getExceptionSpecification()[0], true));
|
||||
assertEquals("#0(...) ...", ASTTypeUtil.getType(f.getExceptionSpecification()[0], true));
|
||||
}
|
||||
|
||||
// template<typename... Pack> class C1 {};
|
||||
|
@ -7165,4 +7165,151 @@ public class AST2TemplateTests extends AST2TestBase {
|
|||
public void testDependentExpressionInvolvingFieldInNestedClass_399362() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <typename _Tp>
|
||||
// struct remove_reference {
|
||||
// typedef _Tp type;
|
||||
// };
|
||||
// template <typename>
|
||||
// struct A {};
|
||||
// template <typename From, typename To>
|
||||
// struct waldo {
|
||||
// typedef typename remove_reference<From>::type src_t;
|
||||
// typedef A<src_t> type;
|
||||
// };
|
||||
// template <bool First>
|
||||
// struct ice_or {
|
||||
// static const bool value = First;
|
||||
// };
|
||||
// template <typename T>
|
||||
// struct is_waldo {
|
||||
// static const bool value = false;
|
||||
// };
|
||||
// template <typename... Args>
|
||||
// struct contains_waldo {
|
||||
// static const bool value = ice_or<is_waldo<typename remove_reference<Args>::type>::value...>::value;
|
||||
// };
|
||||
// template <bool>
|
||||
// struct S {};
|
||||
// struct Cat {
|
||||
// void meow();
|
||||
// };
|
||||
// template <>
|
||||
// struct S<false> {
|
||||
// typedef Cat type;
|
||||
// };
|
||||
// int main() {
|
||||
// S<contains_waldo<int>::value>::type t;
|
||||
// }
|
||||
public void testVariadicTemplates_401024() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// struct S {
|
||||
// void kind();
|
||||
// };
|
||||
// struct T {};
|
||||
// namespace N {
|
||||
// S operator++(T);
|
||||
// template <class T>
|
||||
// struct impl {
|
||||
// static T x;
|
||||
// typedef decltype(++x) type;
|
||||
// };
|
||||
// }
|
||||
// void test() {
|
||||
// N::impl<T>::type operand;
|
||||
// operand.kind(); // ERROR HERE: Method 'kind' could not be resolved
|
||||
// }
|
||||
public void testNameLookupInDependentExpression_399829a() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// struct S {
|
||||
// void kind();
|
||||
// };
|
||||
// namespace N {
|
||||
// struct tag {};
|
||||
// struct any { template <class T> any(T); };
|
||||
// tag operator++(any);
|
||||
// tag operator,(tag,int);
|
||||
// S check(tag);
|
||||
// int check(int);
|
||||
// template <class T>
|
||||
// struct impl {
|
||||
// static T& x;
|
||||
// typedef decltype(N::check((++x,0))) type;
|
||||
// };
|
||||
// }
|
||||
// void test() {
|
||||
// N::impl<S>::type operand;
|
||||
// operand.kind(); // ERROR HERE: Method 'kind' could not be resolved
|
||||
// }
|
||||
public void testNameLookupInDependentExpression_399829b() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <bool> int assertion_failed(void*);
|
||||
// struct assert_ {};
|
||||
// assert_ arg;
|
||||
// char operator==(assert_, assert_);
|
||||
// template <unsigned> struct assert_relation {};
|
||||
// template<class>
|
||||
// struct concept {
|
||||
// typedef decltype(assertion_failed<true>((assert_relation<sizeof(arg == arg) >*)0)) type;
|
||||
// };
|
||||
// template <bool> struct S {};
|
||||
// template <typename>
|
||||
// struct is_int
|
||||
// {
|
||||
// static const bool value = false;
|
||||
// };
|
||||
// template<typename T>
|
||||
// S<true> operator==(T, T*);
|
||||
// template<typename T>
|
||||
// S<(is_int<T>::value)> operator==(T, T);
|
||||
public void testRegression_399829() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <typename>
|
||||
// struct Bind {};
|
||||
// template <typename Func, typename ... BoundArgs>
|
||||
// struct Bind_helper {
|
||||
// typedef Bind<Func(BoundArgs...)> type;
|
||||
// };
|
||||
// template <typename Func, typename ... BoundArgs>
|
||||
// typename Bind_helper<Func, BoundArgs...>::type
|
||||
// bind(Func, BoundArgs...);
|
||||
// struct S {
|
||||
// template <typename T, typename U>
|
||||
// void operator()(T, U);
|
||||
// };
|
||||
// int main() {
|
||||
// S s;
|
||||
// bind(s, 0, foo);
|
||||
// }
|
||||
public void testNPE_401140() throws Exception {
|
||||
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
|
||||
helper.assertProblem("bind(s, 0, foo)", "bind");
|
||||
}
|
||||
|
||||
// template <bool... Args>
|
||||
// struct ice_or;
|
||||
// template <bool First>
|
||||
// struct ice_or<First> {
|
||||
// static const bool value = First;
|
||||
// };
|
||||
// template <bool>
|
||||
// struct S {};
|
||||
// template <>
|
||||
// struct S<false> {
|
||||
// typedef int type;
|
||||
// };
|
||||
// int main() {
|
||||
// S<ice_or<false>::value>::type t;
|
||||
// }
|
||||
public void testVariadicNonTypeTemplateParameter_401142() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7314,7 +7314,7 @@ public class AST2Tests extends AST2TestBase {
|
|||
parseAndCheckBindings(code, C, true);
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, false);
|
||||
ITypedef td= bh.assertNonProblem("ptrdiff_t", 0);
|
||||
assertEquals("int", ASTTypeUtil.getType(td.getType()));
|
||||
assertEquals("long int", ASTTypeUtil.getType(td.getType()));
|
||||
td= bh.assertNonProblem("size_t", 0);
|
||||
assertEquals("unsigned long int", ASTTypeUtil.getType(td.getType()));
|
||||
|
||||
|
@ -7322,7 +7322,7 @@ public class AST2Tests extends AST2TestBase {
|
|||
parseAndCheckBindings(code, CPP, true);
|
||||
bh= new BindingAssertionHelper(code, true);
|
||||
td= bh.assertNonProblem("ptrdiff_t", 0);
|
||||
assertEquals("int", ASTTypeUtil.getType(td.getType()));
|
||||
assertEquals("long int", ASTTypeUtil.getType(td.getType()));
|
||||
td= bh.assertNonProblem("size_t", 0);
|
||||
assertEquals("unsigned long int", ASTTypeUtil.getType(td.getType()));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.pdom.tests;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.ChunkCache;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.PDOMStringSet;
|
||||
|
||||
// copy/pasted from BTreeTests
|
||||
public class PDOMStringSetTests extends BaseTestCase
|
||||
{
|
||||
protected File dbFile;
|
||||
protected Database db;
|
||||
protected PDOMStringSet stringSet;
|
||||
protected int rootRecord;
|
||||
|
||||
public static Test suite()
|
||||
{
|
||||
return suite( PDOMStringSetTests.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
dbFile = File.createTempFile( "pdomstringsettest", "db" );
|
||||
db = new Database( dbFile, new ChunkCache(), 0, false );
|
||||
db.setExclusiveLock();
|
||||
rootRecord = Database.DATA_AREA;
|
||||
stringSet = new PDOMStringSet( db, rootRecord );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
db.close();
|
||||
dbFile.deleteOnExit();
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
// Quick tests to exercise the basic functionality.
|
||||
public void testInterface() throws Exception
|
||||
{
|
||||
long val1_rec_a = stringSet.add( "val1" );
|
||||
long val2_rec_a = stringSet.add( "val2" );
|
||||
long val1_rec_b = stringSet.add( "val1" );
|
||||
assertTrue( val1_rec_a != 0 );
|
||||
assertTrue( val2_rec_a != 0 );
|
||||
assertEquals( val1_rec_a, val1_rec_b );
|
||||
|
||||
long val1_find = stringSet.find( "val1" );
|
||||
long val2_find = stringSet.find( "val2" );
|
||||
assertEquals( val1_rec_a, val1_find );
|
||||
assertEquals( val2_rec_a, val2_find );
|
||||
|
||||
long val1_rm = stringSet.remove( "val1" );
|
||||
assertEquals( val1_rec_a, val1_rm );
|
||||
assertEquals( 0, stringSet.find( "val1" ) );
|
||||
assertEquals( val2_rec_a, stringSet.find( "val2" ) );
|
||||
|
||||
stringSet.clearCaches();
|
||||
assertEquals( val2_rec_a, stringSet.find( "val2" ) );
|
||||
assertEquals( 0, stringSet.find( "val1" ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.pdom.tests;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.index.IIndexFileLocation;
|
||||
import org.eclipse.cdt.core.index.IIndexLocationConverter;
|
||||
import org.eclipse.cdt.core.model.LanguageManager;
|
||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||
import org.eclipse.cdt.internal.core.dom.ast.tag.Tag;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||
import org.eclipse.cdt.internal.core.pdom.WritablePDOM;
|
||||
import org.eclipse.cdt.internal.core.pdom.tag.PDOMTag;
|
||||
import org.eclipse.cdt.internal.core.pdom.tag.PDOMTagIndex;
|
||||
|
||||
// copy/pasted from BTreeTests
|
||||
public class PDOMTagIndexTests extends BaseTestCase
|
||||
{
|
||||
private PDOM pdom;
|
||||
|
||||
public static Test suite()
|
||||
{
|
||||
return suite( PDOMTagIndexTests.class );
|
||||
}
|
||||
|
||||
private static class MockIndexLocationConverter implements IIndexLocationConverter
|
||||
{
|
||||
@Override public IIndexFileLocation fromInternalFormat( String raw ) { return null; }
|
||||
@Override public String toInternalFormat( IIndexFileLocation location ) { return null; }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
File tmpFile = File.createTempFile( getClass().getSimpleName() + '.' + Double.toString( Math.random() ).substring( 2 ), null );
|
||||
pdom = new WritablePDOM( tmpFile, new MockIndexLocationConverter(), LanguageManager.getInstance().getPDOMLinkageFactoryMappings() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception
|
||||
{
|
||||
pdom.close();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
// return the nearest valid record that is less than the specified base
|
||||
private static long lastRecordBase = 1000;
|
||||
private static long computeValidRecord()
|
||||
{
|
||||
lastRecordBase += 1000;
|
||||
return ( lastRecordBase & ~7L ) | 2;
|
||||
}
|
||||
|
||||
// A quick sanity test to confirm basic functionality.
|
||||
public void testSimple() throws Exception
|
||||
{
|
||||
String tagger = "tagger_a";
|
||||
long rec = computeValidRecord();
|
||||
|
||||
assertNotNull( PDOMTagIndex.createTag( pdom, rec, tagger, 1 ) );
|
||||
assertNotNull( PDOMTagIndex.getTag( pdom, rec, tagger ) );
|
||||
}
|
||||
|
||||
public void testMultipleTaggers() throws Exception
|
||||
{
|
||||
String tagger_a = "tagger_a";
|
||||
String tagger_b = "tagger_b";
|
||||
long rec1 = computeValidRecord();
|
||||
long rec2 = computeValidRecord();
|
||||
|
||||
assertNotNull( PDOMTagIndex.createTag( pdom, rec1, tagger_a, 1 ) );
|
||||
assertNotNull( PDOMTagIndex.createTag( pdom, rec1, tagger_b, 1 ) );
|
||||
assertNotNull( PDOMTagIndex.createTag( pdom, rec2, tagger_a, 1 ) );
|
||||
|
||||
assertNotNull( PDOMTagIndex.getTag( pdom, rec2, tagger_a ) );
|
||||
assertNull( PDOMTagIndex.getTag( pdom, rec2, tagger_b ) );
|
||||
|
||||
Iterable<ITag> tags1 = PDOMTagIndex.getTags( pdom, rec1 );
|
||||
int tag_count = 0;
|
||||
for( ITag tag : tags1 )
|
||||
{
|
||||
++tag_count;
|
||||
assertTrue( tag.getTaggerId().equals( tagger_a ) || tag.getTaggerId().equals( tagger_b ) );
|
||||
assertEquals( 1, tag.getDataLen() );
|
||||
}
|
||||
assertEquals( 2, tag_count );
|
||||
}
|
||||
|
||||
public void testReplaceTags() throws Exception
|
||||
{
|
||||
String tagger_a = "tagger_a";
|
||||
String tagger_b = "tagger_b";
|
||||
long rec = computeValidRecord();
|
||||
|
||||
ITag taga = PDOMTagIndex.createTag( pdom, rec, tagger_a, 2 );
|
||||
assertNotNull( taga );
|
||||
assertTrue( taga instanceof PDOMTag );
|
||||
PDOMTag taga_pdom = (PDOMTag)taga;
|
||||
ITag tagb = PDOMTagIndex.createTag( pdom, rec, tagger_a, 2 );
|
||||
assertNotNull( tagb );
|
||||
|
||||
// replacement should delete tags for taggers that are no longer present and shorter tags
|
||||
// should be modified in place
|
||||
PDOMTagIndex.setTags( pdom, rec, Arrays.<ITag>asList( new Tag( tagger_a, 1 ) ) );
|
||||
assertNull( PDOMTagIndex.getTag( pdom, rec, tagger_b ) );
|
||||
ITag shorter_ = PDOMTagIndex.getTag( pdom, rec, tagger_a );
|
||||
assertNotNull( shorter_ );
|
||||
assertTrue( shorter_ instanceof PDOMTag );
|
||||
PDOMTag shorter_pdom = (PDOMTag)shorter_;
|
||||
assertEquals( taga_pdom.getRecord(), shorter_pdom.getRecord() );
|
||||
|
||||
// longer tags should create a new record
|
||||
PDOMTagIndex.setTags( pdom, rec, Arrays.<ITag>asList( new Tag( tagger_a, 4 ) ) );
|
||||
ITag longer_ = PDOMTagIndex.getTag( pdom, rec, tagger_a );
|
||||
assertNotNull( longer_ );
|
||||
assertTrue( longer_ instanceof PDOMTag );
|
||||
PDOMTag longer_pdom = (PDOMTag)longer_;
|
||||
assertTrue( taga_pdom.getRecord() != longer_pdom.getRecord() );
|
||||
|
||||
// TODO figure out how to confirm that the original tag was free'd
|
||||
}
|
||||
}
|
|
@ -38,7 +38,9 @@ public class PDOMTests extends TestSuite {
|
|||
suite.addTest(OverloadsWithinSingleTUTests.suite());
|
||||
suite.addTest(OverloadsWithinCommonHeaderTests.suite());
|
||||
suite.addTest(BTreeTests.suite());
|
||||
suite.addTest(FilesOnReindexTests.suite());
|
||||
suite.addTest(PDOMStringSetTests.suite());
|
||||
suite.addTest(PDOMTagIndexTests.suite());
|
||||
suite.addTest(FilesOnReindexTests.suite());
|
||||
suite.addTest(GeneratePDOMApplicationTest.suite());
|
||||
|
||||
suite.addTest(CPPFieldTests.suite());
|
||||
|
|
|
@ -16,6 +16,7 @@ Export-Package: org.eclipse.cdt.core,
|
|||
org.eclipse.cdt.core.dom.ast.gnu,
|
||||
org.eclipse.cdt.core.dom.ast.gnu.c,
|
||||
org.eclipse.cdt.core.dom.ast.gnu.cpp,
|
||||
org.eclipse.cdt.core.dom.ast.tag,
|
||||
org.eclipse.cdt.core.dom.parser,
|
||||
org.eclipse.cdt.core.dom.parser.c,
|
||||
org.eclipse.cdt.core.dom.parser.cpp,
|
||||
|
@ -52,6 +53,7 @@ Export-Package: org.eclipse.cdt.core,
|
|||
org.eclipse.cdt.internal.core.browser;x-friends:="org.eclipse.cdt.ui",
|
||||
org.eclipse.cdt.internal.core.cdtvariables;x-internal:=true,
|
||||
org.eclipse.cdt.internal.core.dom;x-internal:=true,
|
||||
org.eclipse.cdt.internal.core.dom.ast.tag;x-internal:=true,
|
||||
org.eclipse.cdt.internal.core.dom.parser;x-friends:="org.eclipse.cdt.ui",
|
||||
org.eclipse.cdt.internal.core.dom.parser.c;x-friends:="org.eclipse.cdt.ui",
|
||||
org.eclipse.cdt.internal.core.dom.parser.cpp;x-friends:="org.eclipse.cdt.ui",
|
||||
|
@ -84,6 +86,7 @@ Export-Package: org.eclipse.cdt.core,
|
|||
org.eclipse.cdt.internal.core.pdom.dom.cpp;x-internal:=true,
|
||||
org.eclipse.cdt.internal.core.pdom.export;x-internal:=true,
|
||||
org.eclipse.cdt.internal.core.pdom.indexer;x-friends:="org.eclipse.cdt.ui",
|
||||
org.eclipse.cdt.internal.core.pdom.tag;x-internal:=true,
|
||||
org.eclipse.cdt.internal.core.resources;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.make.core,org.eclipse.cdt.codan.ui.cxx",
|
||||
org.eclipse.cdt.internal.core.settings.model;x-internal:=true,
|
||||
org.eclipse.cdt.internal.core.util;x-internal:=true,
|
||||
|
@ -111,6 +114,7 @@ Export-Package: org.eclipse.cdt.core,
|
|||
org.eclipse.cdt.utils.xcoff,
|
||||
org.eclipse.cdt.utils.xcoff.parser
|
||||
Require-Bundle: org.eclipse.core.contenttype;bundle-version="[3.3.0,4.0.0)",
|
||||
org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
|
||||
org.eclipse.core.filebuffers;bundle-version="[3.2.0,4.0.0)",
|
||||
org.eclipse.core.filesystem;bundle-version="[1.1.0,2.0.0)",
|
||||
org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
|
||||
|
|
|
@ -424,6 +424,8 @@ public class ASTTypeUtil {
|
|||
if (normalize) {
|
||||
result.append('#');
|
||||
result.append(Integer.toString(type.getParameterID(), 16));
|
||||
if (type.isParameterPack())
|
||||
result.append("(...)"); //$NON-NLS-1$
|
||||
} else {
|
||||
result.append(type.getName());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.core.dom.ast.tag;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
||||
/**
|
||||
* Implementations are contributed with the org.eclipse.cdt.core.tagger extension-point. The implementation
|
||||
* is responsible for populating the tag's data using a given input binding.
|
||||
*
|
||||
* @see #process(ITagWriter, IBinding, IASTName)
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface IBindingTagger
|
||||
{
|
||||
/**
|
||||
* Examine the given input binding to decide if a tag should be created. Use the given tagWriter
|
||||
* to create data if needed. Return the tag if one was created and null otherwise. A tagger (as
|
||||
* identified by it's unique id string) is allowed to create only one tag for each binding.
|
||||
*
|
||||
* @param tagWriter the writer to use for creating new tags
|
||||
* @param binding the binding to examine when populating the tag (if needed)
|
||||
* @param ast the AST name from which the binding was created
|
||||
* @return the tag if one was created and null otherwise
|
||||
*/
|
||||
public ITag process( ITagWriter tagWriter, IBinding binding, IASTName ast );
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.core.dom.ast.tag;
|
||||
|
||||
/**
|
||||
* Tags are used to annotate {@link ITagReader}'s with extra information. They are created
|
||||
* by implementations of {@link IBindingTagger} which are contributed using the
|
||||
* org.eclipse.cdt.core.tagger extension point. The base tag interface is read-only, it
|
||||
* is extended by the writable {@link IWritableTag}.
|
||||
*
|
||||
* @see IBindingTagger
|
||||
* @see ITagReader
|
||||
* @see IWritableTag
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface ITag
|
||||
{
|
||||
/** A constant that is returned to indicate a read failure. */
|
||||
public static final int Fail = -1;
|
||||
|
||||
/** Return the number of bytes in the tag's data payload. */
|
||||
public int getDataLen();
|
||||
|
||||
/** Return the globally unique id of the tagger that created the receiver. */
|
||||
public String getTaggerId();
|
||||
|
||||
/** Return the byte from the specified offset or {@link #Fail} on failure. */
|
||||
public int getByte( int offset );
|
||||
|
||||
/** Return the specified number of bytes from the specified offset. Specify len of -1 to read all
|
||||
* bytes from the specified offset to the end of the payload. Return null on failure. */
|
||||
public byte[] getBytes( int offset, int len );
|
||||
|
||||
// TODO read methods for all the other types
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.core.dom.ast.tag;
|
||||
|
||||
|
||||
/**
|
||||
* An interface that provides read-only access to the tags associated with a particular binding.
|
||||
*
|
||||
* @see ITag
|
||||
* @see ITagService
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface ITagReader
|
||||
{
|
||||
/**
|
||||
* Look for a tag for the receiver, returns null if there is no such tag.
|
||||
*
|
||||
* @param id A string that uniquely identifies the tag to be returned. This value was provided by the contributor
|
||||
* when the tag was created (see {@link ITagWriter#createTag(String, int)}).
|
||||
*/
|
||||
public ITag getTag( String id );
|
||||
|
||||
/**
|
||||
* Return all tags known to the receiver. Does not return null.
|
||||
*/
|
||||
public Iterable<ITag> getTags();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.core.dom.ast.tag;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
||||
/**
|
||||
* Provides ITagReaders for specific bindings. The kind of the reader will vary based on
|
||||
* the kind of the input binding.
|
||||
*
|
||||
* @see ITag
|
||||
* @see ITagReader
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface ITagService
|
||||
{
|
||||
/**
|
||||
* Finds or creates a tag reader for the specified binding or null if a reader cannot
|
||||
* be associated with this binding.
|
||||
*
|
||||
* @param binding could be null
|
||||
*/
|
||||
public ITagReader findTagReader( IBinding binding );
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.core.dom.ast.tag;
|
||||
|
||||
/**
|
||||
* An interface that allows tag creation and modification.
|
||||
*
|
||||
* @see ITag
|
||||
* @see ITagService
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface ITagWriter
|
||||
{
|
||||
/**
|
||||
* Create and return a new tag for the receiver. E.g., if this writer is associated with a persistent binding,
|
||||
* then returned tag will read and write from the PDOM database.
|
||||
*
|
||||
* @param id A string that uniquely identifies the tag to be returned. This value will be used by the contributor
|
||||
* when to find the tag (see {@link ITagReader#getTag(String)}).
|
||||
* @param len The number of bytes that should be allocated to store the tag's data.
|
||||
*/
|
||||
public IWritableTag createTag( String id, int len );
|
||||
|
||||
/**
|
||||
* Sets the receiver's tags to only the ones provided. Deletes existing tags that are not in the argument list.
|
||||
*/
|
||||
public boolean setTags( Iterable<ITag> tags );
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.core.dom.ast.tag;
|
||||
|
||||
/**
|
||||
* Tags are used to annotate {@link ITagWriter}'s with extra information. They are created
|
||||
* by implementations of {@link IBindingTagger} which are contributed using the
|
||||
* org.eclipse.cdt.core.tagger extension point.
|
||||
*
|
||||
* @see IBindingTagger
|
||||
* @see ITagReader
|
||||
* @see ITagWriter
|
||||
* @since 5.5
|
||||
*/
|
||||
public interface IWritableTag extends ITag
|
||||
{
|
||||
/** Write the given byte to the given offset in the tag. Return true if successful and false otherwise. */
|
||||
public boolean putByte( int offset, byte data );
|
||||
|
||||
/** Write the argument buffer into the receiver's payload starting at the specified offset. Write the specified
|
||||
* number of bytes or the full buffer when len is -1. Return true if successful and false otherwise. */
|
||||
public boolean putBytes( int offset, byte data[], int len );
|
||||
|
||||
// TODO write for all types
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.dom.ast.tag;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagReader;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagWriter;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IWritableTag;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
|
||||
|
||||
public class NonCachedTaggable implements ITagReader, ITagWriter
|
||||
{
|
||||
private final IBinding binding;
|
||||
private IASTName ast;
|
||||
|
||||
public NonCachedTaggable( IBinding binding )
|
||||
{
|
||||
this.binding = binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWritableTag createTag( String id, int len )
|
||||
{
|
||||
return new Tag( id, len );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITag getTag( String id )
|
||||
{
|
||||
return TagManager.getInstance().process( id, this, binding, getAST() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ITag> getTags()
|
||||
{
|
||||
return TagManager.getInstance().process( this, binding, getAST() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setTags( Iterable<ITag> tags )
|
||||
{
|
||||
// this non-caching implementation has nothing to set, the tags will be regenerated
|
||||
// when they are queried
|
||||
return true;
|
||||
}
|
||||
|
||||
private IASTName getAST()
|
||||
{
|
||||
if( ast != null )
|
||||
return ast;
|
||||
|
||||
if( ! ( binding instanceof ICPPInternalBinding ) )
|
||||
return null;
|
||||
|
||||
IASTNode node = getPhysicalNode( (ICPPInternalBinding)binding );
|
||||
if( node == null )
|
||||
return null;
|
||||
|
||||
return ast = getName( node );
|
||||
}
|
||||
|
||||
private static IASTNode getPhysicalNode( ICPPInternalBinding binding )
|
||||
{
|
||||
IASTNode node = binding.getDefinition();
|
||||
if( node != null )
|
||||
return node;
|
||||
|
||||
IASTNode[] nodes = binding.getDeclarations();
|
||||
if( nodes == null
|
||||
|| nodes.length <= 0 )
|
||||
return null;
|
||||
return nodes[0];
|
||||
}
|
||||
|
||||
private static IASTName getName( IASTNode node )
|
||||
{
|
||||
if( node instanceof IASTName )
|
||||
return (IASTName)node;
|
||||
if( node instanceof ICPPASTCompositeTypeSpecifier )
|
||||
return ( (ICPPASTCompositeTypeSpecifier)node ).getName();
|
||||
if( node instanceof IASTDeclarator )
|
||||
return ( (IASTDeclarator)node ).getName();
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.dom.ast.tag;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IWritableTag;
|
||||
|
||||
/**
|
||||
* A trivial implementation that stores all data in memory.
|
||||
*
|
||||
* @see NonCachedTaggable
|
||||
*/
|
||||
public class Tag implements IWritableTag
|
||||
{
|
||||
private final String taggerId;
|
||||
private final byte[] buff;
|
||||
|
||||
public Tag( String taggerId, int dataLen )
|
||||
{
|
||||
this.taggerId = taggerId;
|
||||
this.buff = new byte[dataLen];
|
||||
}
|
||||
|
||||
@Override public String getTaggerId() { return taggerId; }
|
||||
@Override public int getDataLen() { return buff.length; }
|
||||
|
||||
private boolean isInBounds( int offset, int len )
|
||||
{
|
||||
return offset >= 0
|
||||
&& offset < buff.length
|
||||
&& ( offset + len ) <= buff.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putByte( int offset, byte b )
|
||||
{
|
||||
if( ! isInBounds( offset, 1 ) )
|
||||
return false;
|
||||
|
||||
buff[offset] = b;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putBytes( int offset, byte[] data, int len )
|
||||
{
|
||||
len = len >= 0 ? len : data.length;
|
||||
if( ! isInBounds( offset, len ) )
|
||||
return false;
|
||||
|
||||
System.arraycopy( data, 0, buff, offset, len );
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getByte( int offset )
|
||||
{
|
||||
return isInBounds( offset, 1 ) ? buff[offset] : ITag.Fail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes( int offset, int len )
|
||||
{
|
||||
len = len >= 0 ? len : buff.length - offset;
|
||||
if( ! isInBounds( offset, len ) )
|
||||
return null;
|
||||
|
||||
byte[] data = new byte[len];
|
||||
System.arraycopy( buff, offset, data, 0, len );
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.dom.ast.tag;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IBindingTagger;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagReader;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagWriter;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMBinding;
|
||||
import org.eclipse.cdt.internal.core.pdom.tag.PDOMTaggable;
|
||||
import org.eclipse.core.runtime.IConfigurationElement;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
|
||||
public class TagManager
|
||||
{
|
||||
private static TagManager INSTANCE;
|
||||
|
||||
private Map<String, TaggerDescriptor> taggers;
|
||||
|
||||
public static TagManager getInstance()
|
||||
{
|
||||
if( INSTANCE == null )
|
||||
INSTANCE = new TagManager();
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private TagManager()
|
||||
{
|
||||
taggers = loadExtensions();
|
||||
}
|
||||
|
||||
private static final String ExtensionPoint = "tagger"; //$NON-NLS-1$
|
||||
|
||||
private static Map<String, TaggerDescriptor> loadExtensions()
|
||||
{
|
||||
Map<String, TaggerDescriptor> taggers = new HashMap<String, TaggerDescriptor>();
|
||||
|
||||
// load the extensions
|
||||
IConfigurationElement[] elements
|
||||
= Platform.getExtensionRegistry().getConfigurationElementsFor( CCorePlugin.PLUGIN_ID, ExtensionPoint );
|
||||
for (IConfigurationElement element : elements)
|
||||
{
|
||||
TaggerDescriptor desc = new TaggerDescriptor( element );
|
||||
taggers.put( desc.getId(), desc );
|
||||
}
|
||||
|
||||
return taggers;
|
||||
}
|
||||
|
||||
/** Provide an opportunity for the specified tagger to process the given values. The tagger will only
|
||||
* run if its enablement expression returns true for the arguments. */
|
||||
public ITag process( String taggerId, ITagWriter tagWriter, IBinding binding, IASTName ast )
|
||||
{
|
||||
TaggerDescriptor desc = taggers.get( taggerId );
|
||||
if( desc == null )
|
||||
return null;
|
||||
|
||||
IBindingTagger tagger = desc.getBindingTaggerFor( binding, ast );
|
||||
return tagger == null ? null : tagger.process( tagWriter, binding, ast );
|
||||
}
|
||||
|
||||
/** Provide an opportunity for all enabled taggers to process the given values. */
|
||||
public Iterable<ITag> process( ITagWriter tagWriter, IBinding binding, IASTName ast )
|
||||
{
|
||||
List<ITag> tags = new LinkedList<ITag>();
|
||||
for( TaggerDescriptor desc : taggers.values() )
|
||||
{
|
||||
IBindingTagger tagger = desc.getBindingTaggerFor( binding, ast );
|
||||
if( tagger != null )
|
||||
{
|
||||
ITag tag = tagger.process( tagWriter, binding, ast );
|
||||
if( tag != null )
|
||||
tags.add( tag );
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
/** Add or remove tags from the destination to ensure that it has the same tag information as the source. */
|
||||
public void syncTags( IPDOMBinding dst, IBinding src )
|
||||
{
|
||||
if( dst == null )
|
||||
return;
|
||||
|
||||
ITagReader tagReader = CCorePlugin.getTagService().findTagReader( src );
|
||||
if( tagReader == null )
|
||||
return;
|
||||
|
||||
ITagWriter tagWriter = new PDOMTaggable( dst.getPDOM(), dst.getRecord() );
|
||||
tagWriter.setTags( tagReader.getTags() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.dom.ast.tag;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagReader;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagService;
|
||||
|
||||
public class TagService implements ITagService
|
||||
{
|
||||
/**
|
||||
* First gives the IBinding instance a chance to convert itself, by calling IAdaptable#getAdapter( ITagReader.class )
|
||||
* on the binding. If the binding doesn't provide an implementation then a simple, in-memory, non-cached
|
||||
* implementation is created and returned.
|
||||
*/
|
||||
@Override
|
||||
public ITagReader findTagReader( IBinding binding )
|
||||
{
|
||||
if( binding == null )
|
||||
return null;
|
||||
|
||||
// let the binding adapt to its own tag reader
|
||||
ITagReader tagReader = (ITagReader)binding.getAdapter( ITagReader.class );
|
||||
if( tagReader != null )
|
||||
return tagReader;
|
||||
|
||||
return new NonCachedTaggable( binding );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.dom.ast.tag;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IBindingTagger;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagWriter;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ILanguage;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.core.expressions.EvaluationContext;
|
||||
import org.eclipse.core.expressions.EvaluationResult;
|
||||
import org.eclipse.core.expressions.Expression;
|
||||
import org.eclipse.core.expressions.ExpressionConverter;
|
||||
import org.eclipse.core.expressions.ExpressionTagNames;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IConfigurationElement;
|
||||
|
||||
/**
|
||||
* Internal container for extensions of org.eclipse.cdt.core.tagger. The implementation of the
|
||||
* tagger is instantiated only after checking the enablement expression (if present) for the
|
||||
* specified binding. This avoids activating the contributing plugin until it is actually needed.
|
||||
*/
|
||||
public class TaggerDescriptor
|
||||
{
|
||||
private static final String Attr_LocalId = "local-id"; //$NON-NLS-1$
|
||||
private static final String Attr_Class = "class"; //$NON-NLS-1$
|
||||
|
||||
private final IConfigurationElement element;
|
||||
private final Expression enablementExpression;
|
||||
private Boolean fStatus = null;
|
||||
|
||||
private String id;
|
||||
private IBindingTagger tagger;
|
||||
|
||||
private static final String Var_projectNature = "projectNatures"; //$NON-NLS-1$
|
||||
private static final String Var_languageId = "languageId"; //$NON-NLS-1$
|
||||
|
||||
/** An empty implementation of the tagger used as a placeholder in descriptors that are unable to
|
||||
* load the contributed class. */
|
||||
private static final IBindingTagger NullTagger = new IBindingTagger()
|
||||
{
|
||||
@Override public ITag process(ITagWriter tagWriter, IBinding binding, IASTName ast) { return null; }
|
||||
};
|
||||
|
||||
public TaggerDescriptor( IConfigurationElement element )
|
||||
{
|
||||
this.element = element;
|
||||
|
||||
Expression expr = null;
|
||||
IConfigurationElement[] children = element.getChildren( ExpressionTagNames.ENABLEMENT );
|
||||
switch (children.length) {
|
||||
case 0:
|
||||
fStatus = Boolean.TRUE;
|
||||
break;
|
||||
case 1:
|
||||
try {
|
||||
ExpressionConverter parser = ExpressionConverter.getDefault();
|
||||
expr = parser.perform( children[0] );
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log( "Error in enablement expression of " + id, e ); //$NON-NLS-1$
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CCorePlugin.log( "Too many enablement expressions for " + id ); //$NON-NLS-1$
|
||||
fStatus = Boolean.FALSE;
|
||||
break;
|
||||
}
|
||||
enablementExpression = expr;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
if( id != null )
|
||||
return id;
|
||||
|
||||
String globalId = element.getContributor().getName();
|
||||
String localId = element.getAttribute( Attr_LocalId );
|
||||
|
||||
// there must be a valid local id
|
||||
if( localId == null )
|
||||
{
|
||||
String extId = element.getDeclaringExtension().getSimpleIdentifier();
|
||||
CCorePlugin.log( "Invalid extension " + globalId + '.' + extId + " must provide tagger's local-id" ); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return null;
|
||||
}
|
||||
|
||||
// the extension should not include the plugin id, but return immediately if it does
|
||||
if( localId.startsWith( globalId )
|
||||
&& localId.length() > globalId.length() )
|
||||
return localId;
|
||||
|
||||
// make sure the local id has real content
|
||||
if( localId.isEmpty() )
|
||||
{
|
||||
String extId = element.getDeclaringExtension().getSimpleIdentifier();
|
||||
CCorePlugin.log( "Invalid extension " + globalId + '.' + extId + " must provide value for tagger's local-id" ); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return null;
|
||||
}
|
||||
|
||||
// otherwise prepend with the globalId, and ensure a dot between them
|
||||
if( localId.charAt( 0 ) == '.' )
|
||||
return globalId + localId;
|
||||
return globalId + '.' + localId;
|
||||
}
|
||||
|
||||
private boolean matches( ITranslationUnit tu )
|
||||
{
|
||||
// if the enablement expression is missing or structurally invalid, then return immediately
|
||||
if( fStatus != null )
|
||||
return fStatus.booleanValue();
|
||||
|
||||
// if there is no tu, then the enablement expression cannot be evaluated, assume that all taggers
|
||||
// are needed
|
||||
if( tu == null )
|
||||
return true;
|
||||
|
||||
if( enablementExpression != null )
|
||||
try
|
||||
{
|
||||
IProject project = null;
|
||||
ICProject cProject = tu.getCProject();
|
||||
if( cProject != null )
|
||||
project = cProject.getProject();
|
||||
|
||||
EvaluationContext evalContext = new EvaluationContext( null, project );
|
||||
|
||||
// if the project is not accessible, then only taggers that don't care about it will
|
||||
// get a chance to run
|
||||
if( project != null )
|
||||
{
|
||||
String[] natures = project.getDescription().getNatureIds();
|
||||
evalContext.addVariable( Var_projectNature, Arrays.asList( natures ) );
|
||||
}
|
||||
|
||||
ILanguage language = tu.getLanguage();
|
||||
if( language != null )
|
||||
evalContext.addVariable( Var_languageId, language.getId() );
|
||||
|
||||
return enablementExpression.evaluate( evalContext ) == EvaluationResult.TRUE;
|
||||
}
|
||||
catch( CoreException e )
|
||||
{
|
||||
CCorePlugin.log( "Error while evaluating enablement expression for " + id, e ); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
fStatus = Boolean.FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
private IBindingTagger getTagger()
|
||||
{
|
||||
if( tagger == null )
|
||||
synchronized( this )
|
||||
{
|
||||
if( tagger == null )
|
||||
{
|
||||
try { tagger = (IBindingTagger)element.createExecutableExtension( Attr_Class ); }
|
||||
catch( CoreException e )
|
||||
{
|
||||
String id = element.getDeclaringExtension().getNamespaceIdentifier() + '.'
|
||||
+ element.getDeclaringExtension().getSimpleIdentifier();
|
||||
CCorePlugin.log( "Error in class attribute of " + id, e ); //$NON-NLS-1$
|
||||
|
||||
// mark the tagger with an empty implementation to prevent future load attempts
|
||||
tagger = NullTagger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tagger;
|
||||
}
|
||||
|
||||
// Activates the plugin if needed.
|
||||
public IBindingTagger getBindingTaggerFor( IBinding binding, IASTName ast )
|
||||
{
|
||||
// If there isn't an ast with an AST-TU accessible, then there is no way to defer processing,
|
||||
// just return the tagger and let it try to sort things out. E.g., this happens for built-in
|
||||
// things.
|
||||
if( ast == null )
|
||||
return getTagger();
|
||||
IASTTranslationUnit astTU = ast.getTranslationUnit();
|
||||
if( astTU == null )
|
||||
return getTagger();
|
||||
|
||||
// Otherwise evaluate the enablement expression for this TU
|
||||
return matches( astTU.getOriginatingTranslationUnit() ) ? getTagger() : null;
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ import org.eclipse.cdt.core.dom.ast.IVariable;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
|
@ -234,10 +235,11 @@ public class Value implements IValue {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a value representing the given template parameter.
|
||||
* Creates a value representing the given template parameter
|
||||
* in the given template.
|
||||
*/
|
||||
public static IValue create(ICPPTemplateNonTypeParameter tntp) {
|
||||
EvalBinding eval = new EvalBinding(tntp, null);
|
||||
public static IValue create(ICPPTemplateDefinition template, ICPPTemplateNonTypeParameter tntp) {
|
||||
EvalBinding eval = new EvalBinding(tntp, null, template);
|
||||
return new Value(null, eval);
|
||||
}
|
||||
|
||||
|
@ -284,7 +286,7 @@ public class Value implements IValue {
|
|||
}
|
||||
ICPPEvaluation arg1 = value.getEvaluation();
|
||||
EvalFixed arg2 = new EvalFixed(INT_TYPE, ValueCategory.PRVALUE, create(increment));
|
||||
return create(new EvalBinary(IASTBinaryExpression.op_plus, arg1, arg2));
|
||||
return create(new EvalBinary(IASTBinaryExpression.op_plus, arg1, arg2, arg1.getTemplateDefinition()));
|
||||
}
|
||||
|
||||
private static Number applyUnaryTypeIdOperator(int operator, IType type, IASTNode point) {
|
||||
|
|
|
@ -649,7 +649,7 @@ public class CVisitor extends ASTQueries {
|
|||
}
|
||||
}
|
||||
|
||||
return new CBasicType(Kind.eInt, 0, expr);
|
||||
return new CBasicType(Kind.eInt, IBasicType.IS_LONG, expr);
|
||||
}
|
||||
|
||||
static IType get_SIZE_T(IASTExpression expr) {
|
||||
|
|
|
@ -197,7 +197,7 @@ public class CPPASTArraySubscriptExpression extends ASTNode
|
|||
private ICPPEvaluation computeEvaluation() {
|
||||
if (arrayExpression == null || subscriptExp == null)
|
||||
return EvalFixed.INCOMPLETE;
|
||||
return new EvalBinary(EvalBinary.op_arrayAccess, arrayExpression.getEvaluation(), subscriptExp.getEvaluation());
|
||||
return new EvalBinary(EvalBinary.op_arrayAccess, arrayExpression.getEvaluation(), subscriptExp.getEvaluation(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -38,7 +38,7 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
private int op;
|
||||
private ICPPASTExpression operand1;
|
||||
private ICPPASTInitializerClause operand2;
|
||||
|
||||
|
||||
private ICPPEvaluation evaluation;
|
||||
private IASTImplicitName[] implicitNames = null;
|
||||
|
||||
|
@ -55,7 +55,7 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
public CPPASTBinaryExpression copy() {
|
||||
return copy(CopyStyle.withoutLocations);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CPPASTBinaryExpression copy(CopyStyle style) {
|
||||
CPPASTBinaryExpression copy = new CPPASTBinaryExpression();
|
||||
|
@ -99,7 +99,7 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
if (expression != null) {
|
||||
if (!(expression instanceof ICPPASTExpression))
|
||||
throw new IllegalArgumentException(expression.getClass().getName());
|
||||
|
||||
|
||||
expression.setParent(this);
|
||||
expression.setPropertyInParent(OPERAND_ONE);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
if (operand1 instanceof IASTBinaryExpression || operand2 instanceof IASTBinaryExpression) {
|
||||
return acceptWithoutRecursion(this, action);
|
||||
}
|
||||
|
||||
|
||||
if (action.shouldVisitExpressions) {
|
||||
switch (action.visit(this)) {
|
||||
case ASTVisitor.PROCESS_ABORT: return false;
|
||||
|
@ -230,13 +230,13 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
if (op2 != null && !op2.accept(action))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (action.shouldVisitExpressions && action.leave(expr) == ASTVisitor.PROCESS_ABORT)
|
||||
return false;
|
||||
|
||||
|
||||
stack= stack.fNext;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -262,22 +262,22 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
return ((EvalBinary) eval).getOverload(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ICPPEvaluation getEvaluation() {
|
||||
if (evaluation == null)
|
||||
if (evaluation == null)
|
||||
evaluation= computeEvaluation();
|
||||
|
||||
|
||||
return evaluation;
|
||||
}
|
||||
|
||||
|
||||
private ICPPEvaluation computeEvaluation() {
|
||||
if (operand1 == null || operand2 == null)
|
||||
return EvalFixed.INCOMPLETE;
|
||||
|
||||
return new EvalBinary(op, operand1.getEvaluation(), operand2.getEvaluation());
|
||||
return new EvalBinary(op, operand1.getEvaluation(), operand2.getEvaluation(), this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IType getExpressionType() {
|
||||
return getEvaluation().getTypeOrFunctionSet(this);
|
||||
|
|
|
@ -128,7 +128,7 @@ public class CPPASTBinaryTypeIdExpression extends ASTNode implements ICPPASTExpr
|
|||
if (t1 == null || t2 == null) {
|
||||
fEvaluation= EvalFixed.INCOMPLETE;
|
||||
} else {
|
||||
fEvaluation= new EvalBinaryTypeId(fOperator, t1, t2);
|
||||
fEvaluation= new EvalBinaryTypeId(fOperator, t1, t2, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ public class CPPASTCastExpression extends ASTNode implements ICPPASTCastExpressi
|
|||
if (type == null || type instanceof IProblemType)
|
||||
return EvalFixed.INCOMPLETE;
|
||||
|
||||
return new EvalTypeId(type, operand.getEvaluation());
|
||||
return new EvalTypeId(type, this, operand.getEvaluation());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -42,7 +42,7 @@ public class CPPASTCompoundStatementExpression extends ASTNode implements IGNUAS
|
|||
if (statements.length > 0) {
|
||||
IASTStatement st = statements[statements.length - 1];
|
||||
if (st instanceof IASTExpressionStatement) {
|
||||
fEval= new EvalCompound(((ICPPASTExpression) ((IASTExpressionStatement) st).getExpression()).getEvaluation());
|
||||
fEval= new EvalCompound(((ICPPASTExpression) ((IASTExpressionStatement) st).getExpression()).getEvaluation(), this);
|
||||
}
|
||||
}
|
||||
if (fEval == null)
|
||||
|
|
|
@ -170,7 +170,7 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
|
|||
final ICPPEvaluation condEval = fCondition.getEvaluation();
|
||||
final ICPPEvaluation posEval = fPositive == null ? null : fPositive.getEvaluation();
|
||||
fEval= new EvalConditional(condEval, posEval, fNegative.getEvaluation(),
|
||||
isThrowExpression(fPositive), isThrowExpression(fNegative));
|
||||
isThrowExpression(fPositive), isThrowExpression(fNegative), this);
|
||||
}
|
||||
}
|
||||
return fEval;
|
||||
|
|
|
@ -178,7 +178,7 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
|
|||
for (int i = 0; i < evals.length; i++) {
|
||||
evals[i]= ((ICPPASTExpression) exprs[i]).getEvaluation();
|
||||
}
|
||||
return new EvalComma(evals);
|
||||
return new EvalComma(evals, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -260,7 +260,7 @@ public class CPPASTFieldReference extends ASTNode
|
|||
if (binding instanceof IProblemBinding || binding instanceof IType || binding instanceof ICPPConstructor)
|
||||
return EvalFixed.INCOMPLETE;
|
||||
|
||||
return new EvalMemberAccess(ownerType, ownerEval.getValueCategory(this), binding, isDeref);
|
||||
return new EvalMemberAccess(ownerType, ownerEval.getValueCategory(this), binding, isDeref, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,7 @@ public class CPPASTFieldReference extends ASTNode
|
|||
return EvalFixed.INCOMPLETE;
|
||||
}
|
||||
}
|
||||
return new EvalID(ownerEval, qualifier, name.getSimpleID(), false, true, args);
|
||||
return new EvalID(ownerEval, qualifier, name.getSimpleID(), false, true, args, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -303,7 +303,7 @@ public class CPPASTFunctionCallExpression extends ASTNode
|
|||
for (int i = 1; i < args.length; i++) {
|
||||
args[i]= ((ICPPASTInitializerClause) fArguments[i - 1]).getEvaluation();
|
||||
}
|
||||
return new EvalFunctionCall(args);
|
||||
return new EvalFunctionCall(args, this);
|
||||
}
|
||||
|
||||
private ICPPEvaluation checkForExplicitTypeConversion() {
|
||||
|
@ -315,7 +315,7 @@ public class CPPASTFunctionCallExpression extends ASTNode
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
args[i]= ((ICPPASTInitializerClause) fArguments[i]).getEvaluation();
|
||||
}
|
||||
return new EvalTypeId((IType) b, args);
|
||||
return new EvalTypeId((IType) b, this, args);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -172,6 +172,6 @@ public class CPPASTInitializerList extends ASTNode implements ICPPASTInitializer
|
|||
for (int i = 0; i < evals.length; i++) {
|
||||
evals[i]= clauses[i].getEvaluation();
|
||||
}
|
||||
return new EvalInitList(evals);
|
||||
return new EvalInitList(evals, this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,9 +100,10 @@ public class CPPASTSimpleTypeConstructorExpression extends ASTNode implements
|
|||
for (int i = 0; i < a.length; i++) {
|
||||
args[i]= ((ICPPASTInitializerClause) a[i]).getEvaluation();
|
||||
}
|
||||
fEvaluation= new EvalTypeId(type, args);
|
||||
fEvaluation= new EvalTypeId(type, this, args);
|
||||
} else if (fInitializer instanceof ICPPASTInitializerList) {
|
||||
fEvaluation= new EvalTypeId(type, ((ICPPASTInitializerList) fInitializer).getEvaluation());
|
||||
fEvaluation= new EvalTypeId(type, this,
|
||||
((ICPPASTInitializerList) fInitializer).getEvaluation());
|
||||
} else {
|
||||
fEvaluation= EvalFixed.INCOMPLETE;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ public class CPPASTTypeIdExpression extends ASTNode implements ICPPASTTypeIdExpr
|
|||
if (type == null || type instanceof IProblemType) {
|
||||
fEvaluation= EvalFixed.INCOMPLETE;
|
||||
} else {
|
||||
fEvaluation= new EvalUnaryTypeID(op, type);
|
||||
fEvaluation= new EvalUnaryTypeID(op, type, this);
|
||||
}
|
||||
}
|
||||
return fEvaluation;
|
||||
|
|
|
@ -65,7 +65,7 @@ public class CPPASTTypeIdInitializerExpression extends ASTTypeIdInitializerExpre
|
|||
if (type == null || type instanceof IProblemType)
|
||||
return EvalFixed.INCOMPLETE;
|
||||
|
||||
return new EvalTypeId(type, ((ICPPASTInitializerClause) initializer).getEvaluation());
|
||||
return new EvalTypeId(type, this, ((ICPPASTInitializerClause) initializer).getEvaluation());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -204,7 +204,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
|||
return EvalFixed.INCOMPLETE;
|
||||
}
|
||||
}
|
||||
return new EvalUnary(fOperator, nestedEval, addressOfQualifiedNameBinding);
|
||||
return new EvalUnary(fOperator, nestedEval, addressOfQualifiedNameBinding, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -94,7 +94,7 @@ public class CPPTemplateNonTypeArgument implements ICPPTemplateArgument {
|
|||
EvalFixed fixed = (EvalFixed) fEvaluation;
|
||||
evaluation = new EvalFixed(t, fixed.getValueCategory(), fixed.getValue());
|
||||
} else {
|
||||
evaluation = new EvalTypeId(t, fEvaluation);
|
||||
evaluation = new EvalTypeId(t, fEvaluation.getTemplateDefinition(), fEvaluation);
|
||||
}
|
||||
return new CPPTemplateNonTypeArgument(evaluation, null);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
|
@ -104,4 +105,11 @@ public interface ICPPEvaluation extends ISerializableEvaluation {
|
|||
* evaluations.
|
||||
*/
|
||||
boolean referencesTemplateParameter();
|
||||
|
||||
/**
|
||||
* If the evaluation is dependent (or instantiated from a dependent
|
||||
* evaluation), returns the template definition in which the
|
||||
* evaluation occurs. Otherwise returns null.
|
||||
*/
|
||||
IBinding getTemplateDefinition();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Nathan Ridge.
|
||||
* 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:
|
||||
* Nathan Ridge
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ILinkage;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.PlatformObject;
|
||||
|
||||
/**
|
||||
* Base class for evaluations that are dependent, or that have been instantiated
|
||||
* from a dependent evaluation. These evaluations keep track of the template
|
||||
* in which they are defined, so that certain name lookups can be performed
|
||||
* starting from their point of definition.
|
||||
*/
|
||||
public abstract class CPPDependentEvaluation extends CPPEvaluation {
|
||||
|
||||
private IBinding fTemplateDefinition;
|
||||
private IScope fTemplateDefinitionScope;
|
||||
|
||||
CPPDependentEvaluation(IBinding templateDefinition) {
|
||||
fTemplateDefinition = templateDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinding getTemplateDefinition() {
|
||||
if (fTemplateDefinition instanceof DeferredResolutionBinding) {
|
||||
IBinding toResolve = fTemplateDefinition;
|
||||
// While resolve() is called, set fTemplateDefinition to null to avoid
|
||||
// infinite recursion in some cases where the resolution process ends
|
||||
// up (indirectly) calling getTemplateDefinition() on this evaluation.
|
||||
fTemplateDefinition = null;
|
||||
fTemplateDefinition = ((DeferredResolutionBinding) toResolve).resolve();
|
||||
}
|
||||
return fTemplateDefinition;
|
||||
}
|
||||
|
||||
protected IScope getTemplateDefinitionScope() {
|
||||
if (fTemplateDefinitionScope == null) {
|
||||
IBinding templateDefinition = getTemplateDefinition();
|
||||
if (templateDefinition != null) {
|
||||
if (templateDefinition instanceof ICPPClassType) {
|
||||
fTemplateDefinitionScope = ((ICPPClassType) templateDefinition).getCompositeScope();
|
||||
}
|
||||
try {
|
||||
fTemplateDefinitionScope = templateDefinition.getScope();
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return fTemplateDefinitionScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given node is contained in some template declaration,
|
||||
* return the binding for that template. Otherwise return null.
|
||||
*/
|
||||
protected static IBinding findEnclosingTemplate(IASTNode node) {
|
||||
while (node != null) {
|
||||
if (node instanceof ICPPASTTemplateDeclaration) {
|
||||
ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) node;
|
||||
IASTName templateName = CPPTemplates.getTemplateName(templateDecl);
|
||||
if (templateName == null)
|
||||
return null;
|
||||
return new DeferredResolutionBinding(templateName);
|
||||
}
|
||||
node = node.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void marshalTemplateDefinition(ITypeMarshalBuffer buffer) throws CoreException {
|
||||
// Don't marshal the template definition when building a signature.
|
||||
// While the template definition needs to be stored in the index, it does not
|
||||
// need to be part of the signature, and trying to resolve it at the time a
|
||||
// signature is built sometimes causes recursion (as the call to resolve()
|
||||
// may end up needing the signature).
|
||||
if (!(buffer instanceof SignatureBuilder))
|
||||
buffer.marshalBinding(getTemplateDefinition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to defer the resolution of a template definition until it is needed,
|
||||
* to avoid recursion. The only valid operation on this binding is resolve().
|
||||
*/
|
||||
private static class DeferredResolutionBinding extends PlatformObject implements IBinding {
|
||||
private final IASTName fName;
|
||||
|
||||
public DeferredResolutionBinding(IASTName name) {
|
||||
fName = name;
|
||||
}
|
||||
|
||||
public IBinding resolve() {
|
||||
return fName.resolveBinding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getNameCharArray() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILinkage getLinkage() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinding getOwner() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IScope getScope() throws DOMException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,6 +27,11 @@ public abstract class CPPEvaluation implements ICPPEvaluation {
|
|||
CPPEvaluation() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinding getTemplateDefinition() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getSignature() {
|
||||
SignatureBuilder buf = new SignatureBuilder();
|
||||
|
|
|
@ -391,7 +391,7 @@ public class CPPSemantics {
|
|||
if (CPPTemplates.areSameArguments(((ICPPClassTemplatePartialSpecialization) usedHere).getTemplateArguments(), dcl.getTemplateArguments()))
|
||||
binding= ((ICPPClassTemplatePartialSpecialization) usedHere).asDeferredInstance();
|
||||
} else if (usedHere instanceof ICPPClassTemplate) {
|
||||
if (CPPTemplates.areSameArguments(CPPTemplates.templateParametersAsArguments(((ICPPClassTemplate) usedHere).getTemplateParameters()), dcl.getTemplateArguments())) {
|
||||
if (CPPTemplates.areSameArguments(CPPTemplates.templateParametersAsArguments((ICPPClassTemplate) usedHere), dcl.getTemplateArguments())) {
|
||||
binding= ((ICPPClassTemplate) usedHere).asDeferredInstance();
|
||||
}
|
||||
}
|
||||
|
@ -2503,9 +2503,10 @@ public class CPPSemantics {
|
|||
isCandidate= true;
|
||||
} else {
|
||||
// See 14.3-7
|
||||
final ICPPTemplateParameter[] tpars = ((ICPPFunctionTemplate) f).getTemplateParameters();
|
||||
ICPPFunctionTemplate funcTemp = (ICPPFunctionTemplate) f;
|
||||
final ICPPTemplateParameter[] tpars = funcTemp.getTemplateParameters();
|
||||
final CPPTemplateParameterMap map = new CPPTemplateParameterMap(tpars.length);
|
||||
isCandidate= TemplateArgumentDeduction.addExplicitArguments(tpars, args, map, point);
|
||||
isCandidate= TemplateArgumentDeduction.addExplicitArguments(funcTemp, tpars, args, map, point);
|
||||
}
|
||||
} else {
|
||||
isCandidate= args == null;
|
||||
|
@ -2981,14 +2982,14 @@ public class CPPSemantics {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static ICPPFunction findOverloadedBinaryOperator(IASTNode point, OverloadableOperator op,
|
||||
ICPPEvaluation arg1, ICPPEvaluation arg2) {
|
||||
public static ICPPFunction findOverloadedBinaryOperator(IASTNode pointOfInstantiation, IScope pointOfDefinition,
|
||||
OverloadableOperator op, ICPPEvaluation arg1, ICPPEvaluation arg2) {
|
||||
if (op == null || arg1 == null || arg2 == null)
|
||||
return null;
|
||||
|
||||
IType op1type = getNestedType(arg1.getTypeOrFunctionSet(point), TDEF | REF | CVTYPE);
|
||||
IType op1type = getNestedType(arg1.getTypeOrFunctionSet(pointOfInstantiation), TDEF | REF | CVTYPE);
|
||||
if (!isUserDefined(op1type) && !isUserDefined(
|
||||
getNestedType(arg2.getTypeOrFunctionSet(point), TDEF | REF | CVTYPE)))
|
||||
getNestedType(arg2.getTypeOrFunctionSet(pointOfInstantiation), TDEF | REF | CVTYPE)))
|
||||
return null;
|
||||
|
||||
final LookupMode lookupNonMember;
|
||||
|
@ -2997,7 +2998,7 @@ public class CPPSemantics {
|
|||
} else {
|
||||
lookupNonMember= LookupMode.LIMITED_GLOBALS;
|
||||
}
|
||||
return findOverloadedOperator(point, new ICPPEvaluation[] {arg1, arg2},
|
||||
return findOverloadedOperator(pointOfInstantiation, pointOfDefinition, new ICPPEvaluation[] {arg1, arg2},
|
||||
op1type, op, lookupNonMember);
|
||||
}
|
||||
|
||||
|
@ -3008,8 +3009,8 @@ public class CPPSemantics {
|
|||
return null;
|
||||
|
||||
final IASTInitializerClause[] placement = expr.getPlacementArguments();
|
||||
final ICPPEvaluation arg1= new EvalUnary(IASTUnaryExpression.op_star, evaluation, null);
|
||||
final ICPPEvaluation arg2= new EvalUnary(IASTUnaryExpression.op_sizeof, evaluation, null);
|
||||
final ICPPEvaluation arg1= new EvalUnary(IASTUnaryExpression.op_star, evaluation, null, expr);
|
||||
final ICPPEvaluation arg2= new EvalUnary(IASTUnaryExpression.op_sizeof, evaluation, null, expr);
|
||||
|
||||
ICPPEvaluation[] args;
|
||||
if (placement == null) {
|
||||
|
@ -3028,7 +3029,7 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
IType type= getNestedType(arg1.getTypeOrFunctionSet(expr), TDEF | REF | CVTYPE);
|
||||
return findOverloadedOperator(expr, args, type, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
|
||||
return findOverloadedOperator(expr, null, args, type, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
|
||||
}
|
||||
|
||||
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression expr) {
|
||||
|
@ -3041,7 +3042,7 @@ public class CPPSemantics {
|
|||
new EvalFixed(type, LVALUE, Value.UNKNOWN),
|
||||
((ICPPASTExpression) expr.getOperand()).getEvaluation()
|
||||
};
|
||||
return findOverloadedOperator(expr, args, type, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
|
||||
return findOverloadedOperator(expr, null, args, type, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
|
||||
}
|
||||
|
||||
private static IType getTypeOfPointer(IType type) {
|
||||
|
@ -3235,9 +3236,10 @@ public class CPPSemantics {
|
|||
/**
|
||||
* For simplicity returns an operator of form RT (T, T) rather than RT (boolean, T, T)
|
||||
*/
|
||||
public static ICPPFunction findOverloadedConditionalOperator(IASTNode point, ICPPEvaluation positive, ICPPEvaluation negative) {
|
||||
public static ICPPFunction findOverloadedConditionalOperator(IASTNode pointOfInstantiation, IScope pointOfDefinition,
|
||||
ICPPEvaluation positive, ICPPEvaluation negative) {
|
||||
final ICPPEvaluation[] args = new ICPPEvaluation[] {positive, negative};
|
||||
return findOverloadedOperator(point, args, null,
|
||||
return findOverloadedOperator(pointOfInstantiation, pointOfDefinition, args, null,
|
||||
OverloadableOperator.CONDITIONAL_OPERATOR, LookupMode.NO_GLOBALS);
|
||||
}
|
||||
|
||||
|
@ -3245,27 +3247,29 @@ public class CPPSemantics {
|
|||
* Returns the operator,() function that would apply to the two given arguments.
|
||||
* The lookup type of the class where the operator,() might be found must also be provided.
|
||||
*/
|
||||
public static ICPPFunction findOverloadedOperatorComma(IASTNode point, ICPPEvaluation arg1, ICPPEvaluation arg2) {
|
||||
IType op1type = getNestedType(arg1.getTypeOrFunctionSet(point), TDEF | REF | CVTYPE);
|
||||
IType op2type = getNestedType(arg2.getTypeOrFunctionSet(point), TDEF | REF | CVTYPE);
|
||||
public static ICPPFunction findOverloadedOperatorComma(IASTNode pointOfInstantiation, IScope pointOfDefinition,
|
||||
ICPPEvaluation arg1, ICPPEvaluation arg2) {
|
||||
IType op1type = getNestedType(arg1.getTypeOrFunctionSet(pointOfInstantiation), TDEF | REF | CVTYPE);
|
||||
IType op2type = getNestedType(arg2.getTypeOrFunctionSet(pointOfInstantiation), TDEF | REF | CVTYPE);
|
||||
if (!isUserDefined(op1type) && !isUserDefined(op2type))
|
||||
return null;
|
||||
|
||||
ICPPEvaluation[] args = { arg1 , arg2 };
|
||||
return findOverloadedOperator(point, args, op1type, OverloadableOperator.COMMA, LookupMode.LIMITED_GLOBALS);
|
||||
return findOverloadedOperator(pointOfInstantiation, pointOfDefinition, args, op1type,
|
||||
OverloadableOperator.COMMA, LookupMode.LIMITED_GLOBALS);
|
||||
}
|
||||
|
||||
|
||||
static enum LookupMode {NO_GLOBALS, GLOBALS_IF_NO_MEMBERS, LIMITED_GLOBALS, ALL_GLOBALS}
|
||||
static ICPPFunction findOverloadedOperator(IASTNode point, ICPPEvaluation[] args, IType methodLookupType,
|
||||
OverloadableOperator operator, LookupMode mode) {
|
||||
while (point instanceof IASTName)
|
||||
point= point.getParent();
|
||||
static ICPPFunction findOverloadedOperator(IASTNode pointOfInstantiation, IScope pointOfDefinition,
|
||||
ICPPEvaluation[] args, IType methodLookupType, OverloadableOperator operator, LookupMode mode) {
|
||||
while (pointOfInstantiation instanceof IASTName)
|
||||
pointOfInstantiation= pointOfInstantiation.getParent();
|
||||
|
||||
ICPPClassType callToObjectOfClassType= null;
|
||||
IType type2= null;
|
||||
if (args.length >= 2) {
|
||||
type2 = args[1].getTypeOrFunctionSet(point);
|
||||
type2 = args[1].getTypeOrFunctionSet(pointOfInstantiation);
|
||||
type2= getNestedType(type2, TDEF | REF | CVTYPE);
|
||||
}
|
||||
|
||||
|
@ -3275,7 +3279,7 @@ public class CPPSemantics {
|
|||
return null;
|
||||
if (methodLookupType instanceof ICPPClassType) {
|
||||
ICPPClassType classType = (ICPPClassType) methodLookupType;
|
||||
methodData = new LookupData(operator.toCharArray(), null, point);
|
||||
methodData = new LookupData(operator.toCharArray(), null, pointOfInstantiation);
|
||||
methodData.setFunctionArguments(true, args);
|
||||
methodData.qualified = true; // (13.3.1.2.3)
|
||||
|
||||
|
@ -3294,7 +3298,7 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
// Find a function
|
||||
LookupData funcData = new LookupData(operator.toCharArray(), null, point);
|
||||
LookupData funcData = new LookupData(operator.toCharArray(), null, pointOfInstantiation);
|
||||
|
||||
// Global new and delete operators do not take an argument for the this pointer.
|
||||
switch (operator) {
|
||||
|
@ -3311,7 +3315,7 @@ public class CPPSemantics {
|
|||
if (mode == LookupMode.ALL_GLOBALS || mode == LookupMode.LIMITED_GLOBALS
|
||||
|| (mode == LookupMode.GLOBALS_IF_NO_MEMBERS && !haveMembers)) {
|
||||
try {
|
||||
IScope scope = CPPVisitor.getContainingScope(point);
|
||||
IScope scope = CPPVisitor.getContainingScope(pointOfInstantiation);
|
||||
if (scope == null)
|
||||
return null;
|
||||
lookup(funcData, scope);
|
||||
|
@ -3319,8 +3323,20 @@ public class CPPSemantics {
|
|||
doKoenigLookup(funcData);
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
|
||||
// Also do a lookup at the point of definition.
|
||||
if (pointOfDefinition != null) {
|
||||
LookupData funcData2 = new LookupData(operator.toCharArray(), null, pointOfInstantiation);
|
||||
funcData2.setFunctionArguments(true, args);
|
||||
funcData2.ignoreMembers = true;
|
||||
lookup(funcData2, pointOfDefinition);
|
||||
if (funcData2.hasResults()) {
|
||||
mergeResults(funcData, funcData2.foundItems, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Filter with file-set
|
||||
IASTTranslationUnit tu= point.getTranslationUnit();
|
||||
IASTTranslationUnit tu= pointOfInstantiation.getTranslationUnit();
|
||||
if (tu != null && funcData.foundItems instanceof Object[]) {
|
||||
final IIndexFileSet fileSet = tu.getIndexFileSet();
|
||||
if (fileSet != null) {
|
||||
|
@ -3395,7 +3411,7 @@ public class CPPSemantics {
|
|||
if (callToObjectOfClassType != null) {
|
||||
try {
|
||||
// 13.3.1.1.2 call to object of class type
|
||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType, point);
|
||||
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType, pointOfInstantiation);
|
||||
for (ICPPMethod op : ops) {
|
||||
if (op.isExplicit())
|
||||
continue;
|
||||
|
@ -3406,7 +3422,7 @@ public class CPPSemantics {
|
|||
IType ptt= SemanticUtil.getNestedType(((IPointerType) rt).getType(), SemanticUtil.TDEF);
|
||||
if (ptt instanceof IFunctionType) {
|
||||
IFunctionType ft2= (IFunctionType) ptt;
|
||||
IBinding sf= createSurrogateCallFunction(point.getTranslationUnit().getScope(), ft2.getReturnType(), rt, ft2.getParameterTypes());
|
||||
IBinding sf= createSurrogateCallFunction(pointOfInstantiation.getTranslationUnit().getScope(), ft2.getReturnType(), rt, ft2.getParameterTypes());
|
||||
mergeResults(funcData, sf, false);
|
||||
}
|
||||
}
|
||||
|
@ -3418,7 +3434,7 @@ public class CPPSemantics {
|
|||
}
|
||||
|
||||
if (methodLookupType instanceof ICPPClassType || type2 instanceof ICPPClassType) {
|
||||
ICPPFunction[] builtins= BuiltinOperators.create(operator, args, point, (Object[]) funcData.foundItems);
|
||||
ICPPFunction[] builtins= BuiltinOperators.create(operator, args, pointOfInstantiation, (Object[]) funcData.foundItems);
|
||||
mergeResults(funcData, builtins, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ public class CPPTemplates {
|
|||
}
|
||||
if (i < numArgs) {
|
||||
ICPPTemplateArgument arg= arguments[i];
|
||||
ICPPTemplateArgument newArg = matchTemplateParameterAndArgument(param, arg, map, point);
|
||||
ICPPTemplateArgument newArg = matchTemplateParameterAndArgument(template, param, arg, map, point);
|
||||
if (newArg == null)
|
||||
return createProblem(template, IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS, point);
|
||||
if (newArg != arg) {
|
||||
|
@ -499,12 +499,13 @@ public class CPPTemplates {
|
|||
if (ct instanceof ICPPClassTemplatePartialSpecialization) {
|
||||
args= ((ICPPClassTemplatePartialSpecialization) ct).getTemplateArguments();
|
||||
} else {
|
||||
args = templateParametersAsArguments(ct.getTemplateParameters());
|
||||
args = templateParametersAsArguments(ct);
|
||||
}
|
||||
return new CPPDeferredClassInstance(ct, args, (ICPPScope) ct.getCompositeScope());
|
||||
}
|
||||
|
||||
public static ICPPTemplateArgument[] templateParametersAsArguments(ICPPTemplateParameter[] tpars) {
|
||||
public static ICPPTemplateArgument[] templateParametersAsArguments(ICPPClassTemplate template) {
|
||||
ICPPTemplateParameter[] tpars = template.getTemplateParameters();
|
||||
ICPPTemplateArgument[] args;
|
||||
args = new ICPPTemplateArgument[tpars.length];
|
||||
for (int i = 0; i < tpars.length; i++) {
|
||||
|
@ -518,7 +519,7 @@ public class CPPTemplates {
|
|||
} else if (tp instanceof ICPPTemplateNonTypeParameter) {
|
||||
// Non-type template parameter pack already has type 'ICPPParameterPackType'
|
||||
final ICPPTemplateNonTypeParameter nttp = (ICPPTemplateNonTypeParameter) tp;
|
||||
args[i] = new CPPTemplateNonTypeArgument(Value.create(nttp), nttp.getType());
|
||||
args[i] = new CPPTemplateNonTypeArgument(Value.create(template, nttp), nttp.getType());
|
||||
} else {
|
||||
assert false;
|
||||
}
|
||||
|
@ -1102,6 +1103,7 @@ public class CPPTemplates {
|
|||
ICPPTemplateArgument origArg = args[i];
|
||||
ICPPTemplateArgument newArg;
|
||||
if (origArg.isPackExpansion()) {
|
||||
ICPPTemplateArgument unexpanded= origArg;
|
||||
origArg= origArg.getExpansionPattern();
|
||||
int packSize= determinePackSize(origArg, tpMap);
|
||||
if (packSize == PACK_SIZE_FAIL || packSize == PACK_SIZE_NOT_FOUND) {
|
||||
|
@ -1117,6 +1119,7 @@ public class CPPTemplates {
|
|||
if (!isValidArgument(newArg)) {
|
||||
if (strict)
|
||||
return null;
|
||||
result[i + resultShift] = unexpanded;
|
||||
newResult = result;
|
||||
shift = 0;
|
||||
break;
|
||||
|
@ -2274,8 +2277,8 @@ public class CPPTemplates {
|
|||
return arg != null && isValidType(arg.isTypeValue() ? arg.getTypeValue() : arg.getTypeOfNonTypeValue());
|
||||
}
|
||||
|
||||
static ICPPTemplateArgument matchTemplateParameterAndArgument(ICPPTemplateParameter param,
|
||||
ICPPTemplateArgument arg, CPPTemplateParameterMap map, IASTNode point) {
|
||||
static ICPPTemplateArgument matchTemplateParameterAndArgument(ICPPTemplateDefinition template,
|
||||
ICPPTemplateParameter param, ICPPTemplateArgument arg, CPPTemplateParameterMap map, IASTNode point) {
|
||||
if (arg == null || !isValidType(arg.getTypeValue())) {
|
||||
return null;
|
||||
}
|
||||
|
@ -2331,7 +2334,7 @@ public class CPPTemplates {
|
|||
if (argType instanceof ICPPUnknownType) {
|
||||
return new CPPTemplateNonTypeArgument(arg.getNonTypeValue(), pType);
|
||||
}
|
||||
return convertNonTypeTemplateArgument(pType, arg, point);
|
||||
return convertNonTypeTemplateArgument(template, pType, arg, point);
|
||||
} catch (DOMException e) {
|
||||
return null;
|
||||
}
|
||||
|
@ -2399,7 +2402,8 @@ public class CPPTemplates {
|
|||
* specified in 14.3.2 - 5.
|
||||
* @throws DOMException
|
||||
*/
|
||||
private static ICPPTemplateArgument convertNonTypeTemplateArgument(final IType paramType, ICPPTemplateArgument arg, IASTNode point) throws DOMException {
|
||||
private static ICPPTemplateArgument convertNonTypeTemplateArgument(ICPPTemplateDefinition template,
|
||||
final IType paramType, ICPPTemplateArgument arg, IASTNode point) throws DOMException {
|
||||
//14.1s8 function to pointer and array to pointer conversions
|
||||
IType a= arg.getTypeOfNonTypeValue();
|
||||
IType p;
|
||||
|
@ -2422,7 +2426,7 @@ public class CPPTemplates {
|
|||
for (ICPPFunction f : functionSet.getBindings()) {
|
||||
if (p.isSameType(f.getType())) {
|
||||
functionSet.applySelectedFunction(f);
|
||||
return new CPPTemplateNonTypeArgument(new EvalBinding(f, null), point);
|
||||
return new CPPTemplateNonTypeArgument(new EvalBinding(f, null, template), point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2460,6 +2464,8 @@ public class CPPTemplates {
|
|||
} else {
|
||||
if (arg.isTypeValue())
|
||||
return false;
|
||||
if (par.isParameterPack() != arg.isPackExpansion())
|
||||
return false;
|
||||
int parpos= Value.isTemplateParameter(arg.getNonTypeValue());
|
||||
if (parpos != par.getParameterID())
|
||||
return false;
|
||||
|
|
|
@ -216,8 +216,9 @@ import org.eclipse.cdt.internal.core.index.IIndexScope;
|
|||
* Collection of methods to extract information from a C++ translation unit.
|
||||
*/
|
||||
public class CPPVisitor extends ASTQueries {
|
||||
private static final CPPBasicType UNSIGNED_LONG = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG | IBasicType.IS_UNSIGNED);
|
||||
private static final CPPBasicType INT_TYPE = new CPPBasicType(Kind.eInt, 0);
|
||||
private static final CPPBasicType LONG_TYPE = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG);
|
||||
private static final CPPBasicType UNSIGNED_LONG = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG | IBasicType.IS_UNSIGNED);
|
||||
|
||||
public static final String BEGIN_STR = "begin"; //$NON-NLS-1$
|
||||
public static final char[] BEGIN = BEGIN_STR.toCharArray();
|
||||
|
@ -225,7 +226,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
static final String STD = "std"; //$NON-NLS-1$
|
||||
private static final char[] SIZE_T = "size_t".toCharArray(); //$NON-NLS-1$
|
||||
private static final char[] PTRDIFF_T = "ptrdiff_t".toCharArray(); //$NON-NLS-1$
|
||||
private static final char[] TYPE_INFO= "type_info".toCharArray(); //$NON-NLS-1$
|
||||
private static final char[] TYPE_INFO = "type_info".toCharArray(); //$NON-NLS-1$
|
||||
private static final char[] INITIALIZER_LIST = "initializer_list".toCharArray(); //$NON-NLS-1$
|
||||
private static final char[][] EMPTY_CHAR_ARRAY_ARRAY = {};
|
||||
public static final IASTInitializerClause[] NO_ARGS = {};
|
||||
|
@ -339,10 +340,10 @@ public class CPPVisitor extends ASTQueries {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (inScope == null)
|
||||
return false;
|
||||
|
||||
|
||||
IBinding pb= names[names.length-2].resolvePreBinding();
|
||||
if (pb instanceof IProblemBinding)
|
||||
return false;
|
||||
|
@ -356,7 +357,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
} else if (pb instanceof ICPPNamespace) {
|
||||
scope= ((ICPPNamespace)pb).getNamespaceScope();
|
||||
}
|
||||
|
||||
|
||||
return scope == inScope;
|
||||
}
|
||||
|
||||
|
@ -2276,7 +2277,7 @@ public class CPPVisitor extends ASTQueries {
|
|||
|
||||
public static IType getPointerDiffType(final IASTNode point) {
|
||||
IType t= getStdType(point, PTRDIFF_T);
|
||||
return t != null ? t : INT_TYPE;
|
||||
return t != null ? t : LONG_TYPE;
|
||||
}
|
||||
|
||||
private static IType getStdType(final IASTNode node, char[] name) {
|
||||
|
|
|
@ -46,6 +46,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
|
@ -70,7 +71,7 @@ import org.eclipse.core.runtime.CoreException;
|
|||
/**
|
||||
* Performs evaluation of an expression.
|
||||
*/
|
||||
public class EvalBinary extends CPPEvaluation {
|
||||
public class EvalBinary extends CPPDependentEvaluation {
|
||||
public final static int op_arrayAccess= Byte.MAX_VALUE;
|
||||
private final int fOperator;
|
||||
|
||||
|
@ -80,7 +81,11 @@ public class EvalBinary extends CPPEvaluation {
|
|||
private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION;
|
||||
private IType fType;
|
||||
|
||||
public EvalBinary(int operator, ICPPEvaluation arg1, ICPPEvaluation arg2) {
|
||||
public EvalBinary(int operator, ICPPEvaluation arg1, ICPPEvaluation arg2, IASTNode pointOfDefinition) {
|
||||
this(operator, arg1, arg2, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalBinary(int operator, ICPPEvaluation arg1, ICPPEvaluation arg2, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fOperator= operator;
|
||||
fArg1= arg1;
|
||||
fArg2= arg2;
|
||||
|
@ -234,12 +239,14 @@ public class EvalBinary extends CPPEvaluation {
|
|||
IType type = fArg1.getTypeOrFunctionSet(point);
|
||||
type= SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
|
||||
if (type instanceof ICPPClassType) {
|
||||
return CPPSemantics.findOverloadedBinaryOperator(point, OverloadableOperator.BRACKET, fArg1, fArg2);
|
||||
return CPPSemantics.findOverloadedBinaryOperator(point, getTemplateDefinitionScope(),
|
||||
OverloadableOperator.BRACKET, fArg1, fArg2);
|
||||
}
|
||||
} else {
|
||||
final OverloadableOperator op = OverloadableOperator.fromBinaryExpression(fOperator);
|
||||
if (op != null) {
|
||||
return CPPSemantics.findOverloadedBinaryOperator(point, op, fArg1, fArg2);
|
||||
return CPPSemantics.findOverloadedBinaryOperator(point, getTemplateDefinitionScope(),
|
||||
op, fArg1, fArg2);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -328,13 +335,15 @@ public class EvalBinary extends CPPEvaluation {
|
|||
buffer.putByte((byte) fOperator);
|
||||
buffer.marshalEvaluation(fArg1, includeValue);
|
||||
buffer.marshalEvaluation(fArg2, includeValue);
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
int op= buffer.getByte();
|
||||
ICPPEvaluation arg1= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
ICPPEvaluation arg2= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
return new EvalBinary(op, arg1, arg2);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalBinary(op, arg1, arg2, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -344,7 +353,7 @@ public class EvalBinary extends CPPEvaluation {
|
|||
ICPPEvaluation arg2 = fArg2.instantiate(tpMap, packOffset, within, maxdepth, point);
|
||||
if (arg1 == fArg1 && arg2 == fArg2)
|
||||
return this;
|
||||
return new EvalBinary(fOperator, arg1, arg2);
|
||||
return new EvalBinary(fOperator, arg1, arg2, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -354,7 +363,7 @@ public class EvalBinary extends CPPEvaluation {
|
|||
ICPPEvaluation arg2 = fArg2.computeForFunctionCall(parameterMap, maxdepth, point);
|
||||
if (arg1 == fArg1 && arg2 == fArg2)
|
||||
return this;
|
||||
return new EvalBinary(fOperator, arg1, arg2);
|
||||
return new EvalBinary(fOperator, arg1, arg2, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression.Operator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
|
@ -31,14 +32,18 @@ import org.eclipse.core.runtime.CoreException;
|
|||
/**
|
||||
* Performs evaluation of an expression.
|
||||
*/
|
||||
public class EvalBinaryTypeId extends CPPEvaluation {
|
||||
public class EvalBinaryTypeId extends CPPDependentEvaluation {
|
||||
private final Operator fOperator;
|
||||
private final IType fType1, fType2;
|
||||
|
||||
private boolean fCheckedValueDependent;
|
||||
private boolean fIsValueDependent;
|
||||
|
||||
public EvalBinaryTypeId(Operator kind, IType type1, IType type2) {
|
||||
public EvalBinaryTypeId(Operator kind, IType type1, IType type2, IASTNode pointOfDefinition) {
|
||||
this(kind, type1, type2, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalBinaryTypeId(Operator kind, IType type1, IType type2, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fOperator= kind;
|
||||
fType1= type1;
|
||||
fType2= type2;
|
||||
|
@ -108,13 +113,15 @@ public class EvalBinaryTypeId extends CPPEvaluation {
|
|||
buffer.putByte((byte) fOperator.ordinal());
|
||||
buffer.marshalType(fType1);
|
||||
buffer.marshalType(fType2);
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
int op= buffer.getByte();
|
||||
IType arg1= buffer.unmarshalType();
|
||||
IType arg2= buffer.unmarshalType();
|
||||
return new EvalBinaryTypeId(Operator.values()[op], arg1, arg2);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalBinaryTypeId(Operator.values()[op], arg1, arg2, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,7 +131,7 @@ public class EvalBinaryTypeId extends CPPEvaluation {
|
|||
IType type2 = CPPTemplates.instantiateType(fType2, tpMap, packOffset, within, point);
|
||||
if (type1 == fType1 && type2 == fType2)
|
||||
return this;
|
||||
return new EvalBinaryTypeId(fOperator, type1, type2);
|
||||
return new EvalBinaryTypeId(fOperator, type1, type2, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,7 +43,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class EvalBinding extends CPPEvaluation {
|
||||
public class EvalBinding extends CPPDependentEvaluation {
|
||||
/**
|
||||
* The function owning the parameter if the binding is a function parameter, otherwise
|
||||
* {@code null}. May be computed lazily and remains {@code null} until computed.
|
||||
|
@ -68,14 +68,22 @@ public class EvalBinding extends CPPEvaluation {
|
|||
private boolean fIsTypeDependent;
|
||||
private boolean fCheckedIsTypeDependent;
|
||||
|
||||
public EvalBinding(IBinding binding, IType type) {
|
||||
public EvalBinding(IBinding binding, IType type, IASTNode pointOfDefinition) {
|
||||
this(binding, type, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalBinding(IBinding binding, IType type, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fParameterPosition = -1;
|
||||
fBinding= binding;
|
||||
fType= type;
|
||||
fFixedType= type != null;
|
||||
}
|
||||
|
||||
public EvalBinding(ICPPFunction parameterOwner, int parameterPosition, IType type) {
|
||||
public EvalBinding(ICPPFunction parameterOwner, int parameterPosition, IType type, IASTNode pointOfDefinition) {
|
||||
this(parameterOwner, parameterPosition, type, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalBinding(ICPPFunction parameterOwner, int parameterPosition, IType type, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fParameterOwner = parameterOwner;
|
||||
fParameterPosition = parameterPosition;
|
||||
fType= type;
|
||||
|
@ -298,6 +306,7 @@ public class EvalBinding extends CPPEvaluation {
|
|||
buffer.marshalBinding(fBinding);
|
||||
}
|
||||
buffer.marshalType(fFixedType ? fType : null);
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -305,11 +314,13 @@ public class EvalBinding extends CPPEvaluation {
|
|||
ICPPFunction parameterOwner= (ICPPFunction) buffer.unmarshalBinding();
|
||||
int parameterPosition= buffer.getInt();
|
||||
IType type= buffer.unmarshalType();
|
||||
return new EvalBinding(parameterOwner, parameterPosition, type);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalBinding(parameterOwner, parameterPosition, type, templateDefinition);
|
||||
} else {
|
||||
IBinding binding= buffer.unmarshalBinding();
|
||||
IType type= buffer.unmarshalType();
|
||||
return new EvalBinding(binding, type);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalBinding(binding, type, templateDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,7 +344,7 @@ public class EvalBinding extends CPPEvaluation {
|
|||
} else {
|
||||
IBinding instantiatedBinding = instantiateBinding(origBinding, tpMap, packOffset, within, maxdepth, point);
|
||||
if (instantiatedBinding != origBinding)
|
||||
return new EvalBinding(instantiatedBinding, null);
|
||||
return new EvalBinding(instantiatedBinding, null, getTemplateDefinition());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionT
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
|
@ -28,7 +29,7 @@ import org.eclipse.cdt.internal.core.dom.parser.Value;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class EvalComma extends CPPEvaluation {
|
||||
public class EvalComma extends CPPDependentEvaluation {
|
||||
private static final ICPPFunction[] NO_FUNCTIONS = {};
|
||||
|
||||
private final ICPPEvaluation[] fArguments;
|
||||
|
@ -36,7 +37,11 @@ public class EvalComma extends CPPEvaluation {
|
|||
|
||||
private IType fType;
|
||||
|
||||
public EvalComma(ICPPEvaluation[] evals) {
|
||||
public EvalComma(ICPPEvaluation[] evals, IASTNode pointOfDefinition) {
|
||||
this(evals, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalComma(ICPPEvaluation[] evals, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fArguments= evals;
|
||||
}
|
||||
|
||||
|
@ -93,7 +98,7 @@ public class EvalComma extends CPPEvaluation {
|
|||
ICPPEvaluation e1= fArguments[0];
|
||||
for (int i = 1; i < fArguments.length; i++) {
|
||||
ICPPEvaluation e2 = fArguments[i];
|
||||
ICPPFunction overload = CPPSemantics.findOverloadedOperatorComma(point, e1, e2);
|
||||
ICPPFunction overload = CPPSemantics.findOverloadedOperatorComma(point, getTemplateDefinitionScope(), e1, e2);
|
||||
if (overload == null) {
|
||||
e1= e2;
|
||||
} else {
|
||||
|
@ -159,6 +164,7 @@ public class EvalComma extends CPPEvaluation {
|
|||
for (ICPPEvaluation arg : fArguments) {
|
||||
buffer.marshalEvaluation(arg, includeValue);
|
||||
}
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -167,7 +173,8 @@ public class EvalComma extends CPPEvaluation {
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
}
|
||||
return new EvalComma(args);
|
||||
IBinding templateDefinition = buffer.unmarshalBinding();
|
||||
return new EvalComma(args, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -186,7 +193,7 @@ public class EvalComma extends CPPEvaluation {
|
|||
}
|
||||
if (args == fArguments)
|
||||
return this;
|
||||
return new EvalComma(args);
|
||||
return new EvalComma(args, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -205,7 +212,7 @@ public class EvalComma extends CPPEvaluation {
|
|||
}
|
||||
if (args == fArguments)
|
||||
return this;
|
||||
return new EvalComma(args);
|
||||
return new EvalComma(args, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
|
@ -28,10 +29,14 @@ import org.eclipse.core.runtime.CoreException;
|
|||
* Performs evaluation of a compound statement expression. Most but not all methods
|
||||
* delegate to the evaluation of the last expression in the compound one.
|
||||
*/
|
||||
public class EvalCompound extends CPPEvaluation {
|
||||
public class EvalCompound extends CPPDependentEvaluation {
|
||||
private final ICPPEvaluation fDelegate;
|
||||
|
||||
public EvalCompound(ICPPEvaluation delegate) {
|
||||
public EvalCompound(ICPPEvaluation delegate, IASTNode pointOfDefinition) {
|
||||
this(delegate, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalCompound(ICPPEvaluation delegate, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fDelegate= delegate;
|
||||
}
|
||||
|
||||
|
@ -78,11 +83,13 @@ public class EvalCompound extends CPPEvaluation {
|
|||
public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException {
|
||||
buffer.putByte(ITypeMarshalBuffer.EVAL_COMPOUND);
|
||||
buffer.marshalEvaluation(fDelegate, includeValue);
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
ICPPEvaluation arg= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
return new EvalCompound(arg);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalCompound(arg, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,7 +98,7 @@ public class EvalCompound extends CPPEvaluation {
|
|||
ICPPEvaluation delegate = fDelegate.instantiate(tpMap, packOffset, within, maxdepth, point);
|
||||
if (delegate == fDelegate)
|
||||
return this;
|
||||
return new EvalCompound(delegate);
|
||||
return new EvalCompound(delegate, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,7 +107,7 @@ public class EvalCompound extends CPPEvaluation {
|
|||
ICPPEvaluation delegate = fDelegate.computeForFunctionCall(parameterMap, maxdepth, point);
|
||||
if (delegate == fDelegate)
|
||||
return this;
|
||||
return new EvalCompound(delegate);
|
||||
return new EvalCompound(delegate, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.DOMException;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
|
@ -47,7 +48,7 @@ import org.eclipse.core.runtime.CoreException;
|
|||
/**
|
||||
* Performs evaluation of an expression.
|
||||
*/
|
||||
public class EvalConditional extends CPPEvaluation {
|
||||
public class EvalConditional extends CPPDependentEvaluation {
|
||||
private final ICPPEvaluation fCondition, fPositive, fNegative;
|
||||
private final boolean fPositiveThrows, fNegativeThrows;
|
||||
|
||||
|
@ -56,7 +57,12 @@ public class EvalConditional extends CPPEvaluation {
|
|||
private ICPPFunction fOverload;
|
||||
|
||||
public EvalConditional(ICPPEvaluation condition, ICPPEvaluation positive, ICPPEvaluation negative,
|
||||
boolean positiveThrows, boolean negativeThrows) {
|
||||
boolean positiveThrows, boolean negativeThrows, IASTNode pointOfDefinition) {
|
||||
this(condition, positive, negative, positiveThrows, negativeThrows, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalConditional(ICPPEvaluation condition, ICPPEvaluation positive, ICPPEvaluation negative,
|
||||
boolean positiveThrows, boolean negativeThrows, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
// Gnu-extension: Empty positive expression is replaced by condition.
|
||||
fCondition= condition;
|
||||
fPositive= positive;
|
||||
|
@ -229,7 +235,7 @@ public class EvalConditional extends CPPEvaluation {
|
|||
|
||||
// 5.16-5: At least one class type but no conversion
|
||||
if (isClassType2 || isClassType3) {
|
||||
fOverload = CPPSemantics.findOverloadedConditionalOperator(point, positive, fNegative);
|
||||
fOverload = CPPSemantics.findOverloadedConditionalOperator(point, getTemplateDefinitionScope(), positive, fNegative);
|
||||
if (fOverload != null) {
|
||||
fType= ExpressionTypes.typeFromFunctionCall(fOverload);
|
||||
} else {
|
||||
|
@ -313,6 +319,7 @@ public class EvalConditional extends CPPEvaluation {
|
|||
buffer.marshalEvaluation(fCondition, includeValue);
|
||||
buffer.marshalEvaluation(fPositive, includeValue);
|
||||
buffer.marshalEvaluation(fNegative, includeValue);
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -321,7 +328,8 @@ public class EvalConditional extends CPPEvaluation {
|
|||
ICPPEvaluation cond= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
ICPPEvaluation pos= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
ICPPEvaluation neg= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
return new EvalConditional(cond, pos, neg, pth, nth);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalConditional(cond, pos, neg, pth, nth, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -333,7 +341,7 @@ public class EvalConditional extends CPPEvaluation {
|
|||
ICPPEvaluation negative = fNegative.instantiate(tpMap, packOffset, within, maxdepth, point);
|
||||
if (condition == fCondition && positive == fPositive && negative == fNegative)
|
||||
return this;
|
||||
return new EvalConditional(condition, positive, negative, fPositiveThrows, fNegativeThrows);
|
||||
return new EvalConditional(condition, positive, negative, fPositiveThrows, fNegativeThrows, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -345,7 +353,7 @@ public class EvalConditional extends CPPEvaluation {
|
|||
ICPPEvaluation negative = fNegative.computeForFunctionCall(parameterMap, maxdepth, point);
|
||||
if (condition == fCondition && positive == fPositive && negative == fNegative)
|
||||
return this;
|
||||
return new EvalConditional(condition, positive, negative, fPositiveThrows, fNegativeThrows);
|
||||
return new EvalConditional(condition, positive, negative, fPositiveThrows, fNegativeThrows, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,12 +43,16 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class EvalFunctionCall extends CPPEvaluation {
|
||||
public class EvalFunctionCall extends CPPDependentEvaluation {
|
||||
private final ICPPEvaluation[] fArguments;
|
||||
private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION;
|
||||
private IType fType;
|
||||
|
||||
public EvalFunctionCall(ICPPEvaluation[] args) {
|
||||
public EvalFunctionCall(ICPPEvaluation[] args, IASTNode pointOfDefinition) {
|
||||
this(args, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalFunctionCall(ICPPEvaluation[] args, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fArguments= args;
|
||||
}
|
||||
|
||||
|
@ -101,7 +105,8 @@ public class EvalFunctionCall extends CPPEvaluation {
|
|||
|
||||
IType t= SemanticUtil.getNestedType(fArguments[0].getTypeOrFunctionSet(point), TDEF | REF | CVTYPE);
|
||||
if (t instanceof ICPPClassType) {
|
||||
return CPPSemantics.findOverloadedOperator(point, fArguments, t, OverloadableOperator.PAREN, LookupMode.NO_GLOBALS);
|
||||
return CPPSemantics.findOverloadedOperator(point, getTemplateDefinitionScope(), fArguments, t,
|
||||
OverloadableOperator.PAREN, LookupMode.NO_GLOBALS);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -174,6 +179,7 @@ public class EvalFunctionCall extends CPPEvaluation {
|
|||
for (ICPPEvaluation arg : fArguments) {
|
||||
buffer.marshalEvaluation(arg, includeValue);
|
||||
}
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -182,7 +188,8 @@ public class EvalFunctionCall extends CPPEvaluation {
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
}
|
||||
return new EvalFunctionCall(args);
|
||||
IBinding templateDefinition = buffer.unmarshalBinding();
|
||||
return new EvalFunctionCall(args, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -206,7 +213,7 @@ public class EvalFunctionCall extends CPPEvaluation {
|
|||
// Resolve the function using the parameters of the function call.
|
||||
args[0] = ((EvalFunctionSet) args[0]).resolveFunction(Arrays.copyOfRange(args, 1, args.length), point);
|
||||
}
|
||||
return new EvalFunctionCall(args);
|
||||
return new EvalFunctionCall(args, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -228,7 +235,7 @@ public class EvalFunctionCall extends CPPEvaluation {
|
|||
}
|
||||
EvalFunctionCall eval = this;
|
||||
if (args != fArguments)
|
||||
eval = new EvalFunctionCall(args);
|
||||
eval = new EvalFunctionCall(args, getTemplateDefinition());
|
||||
return eval.computeForFunctionCall(maxdepth - 1, point);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,11 +38,15 @@ import org.eclipse.core.runtime.CoreException;
|
|||
/**
|
||||
* Performs evaluation of an expression.
|
||||
*/
|
||||
public class EvalFunctionSet extends CPPEvaluation {
|
||||
public class EvalFunctionSet extends CPPDependentEvaluation {
|
||||
private final CPPFunctionSet fFunctionSet;
|
||||
private final boolean fAddressOf;
|
||||
|
||||
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf) {
|
||||
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IASTNode pointOfDefinition) {
|
||||
this(set, addressOf, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalFunctionSet(CPPFunctionSet set, boolean addressOf, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fFunctionSet= set;
|
||||
fAddressOf= addressOf;
|
||||
}
|
||||
|
@ -122,6 +126,7 @@ public class EvalFunctionSet extends CPPEvaluation {
|
|||
buffer.marshalTemplateArgument(arg);
|
||||
}
|
||||
}
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -139,7 +144,8 @@ public class EvalFunctionSet extends CPPEvaluation {
|
|||
args[i]= buffer.unmarshalTemplateArgument();
|
||||
}
|
||||
}
|
||||
return new EvalFunctionSet(new CPPFunctionSet(bindings, args, null), addressOf);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalFunctionSet(new CPPFunctionSet(bindings, args, null), addressOf, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -173,7 +179,7 @@ public class EvalFunctionSet extends CPPEvaluation {
|
|||
}
|
||||
if (Arrays.equals(arguments, originalArguments) && functions == originalFunctions)
|
||||
return this;
|
||||
return new EvalFunctionSet(new CPPFunctionSet(functions, arguments, null), fAddressOf);
|
||||
return new EvalFunctionSet(new CPPFunctionSet(functions, arguments, null), fAddressOf, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -198,7 +204,7 @@ public class EvalFunctionSet extends CPPEvaluation {
|
|||
try {
|
||||
IBinding binding = CPPSemantics.resolveFunction(data, functions, true);
|
||||
if (binding instanceof ICPPFunction && !(binding instanceof ICPPUnknownBinding))
|
||||
return new EvalBinding(binding, null);
|
||||
return new EvalBinding(binding, null, getTemplateDefinition());
|
||||
} catch (DOMException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class EvalID extends CPPEvaluation {
|
||||
public class EvalID extends CPPDependentEvaluation {
|
||||
private final ICPPEvaluation fFieldOwner;
|
||||
private final char[] fName;
|
||||
private final IBinding fNameOwner;
|
||||
|
@ -63,7 +63,12 @@ public class EvalID extends CPPEvaluation {
|
|||
private final ICPPTemplateArgument[] fTemplateArgs;
|
||||
|
||||
public EvalID(ICPPEvaluation fieldOwner, IBinding nameOwner, char[] simpleID, boolean addressOf,
|
||||
boolean qualified, ICPPTemplateArgument[] templateArgs) {
|
||||
boolean qualified, ICPPTemplateArgument[] templateArgs, IASTNode pointOfDefinition) {
|
||||
this(fieldOwner, nameOwner, simpleID, addressOf, qualified, templateArgs, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalID(ICPPEvaluation fieldOwner, IBinding nameOwner, char[] simpleID, boolean addressOf,
|
||||
boolean qualified, ICPPTemplateArgument[] templateArgs, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fFieldOwner= fieldOwner;
|
||||
fName= simpleID;
|
||||
fNameOwner= nameOwner;
|
||||
|
@ -158,6 +163,7 @@ public class EvalID extends CPPEvaluation {
|
|||
buffer.marshalTemplateArgument(arg);
|
||||
}
|
||||
}
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -174,7 +180,8 @@ public class EvalID extends CPPEvaluation {
|
|||
args[i]= buffer.unmarshalTemplateArgument();
|
||||
}
|
||||
}
|
||||
return new EvalID(fieldOwner, nameOwner, name, addressOf, qualified, args);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalID(fieldOwner, nameOwner, name, addressOf, qualified, args, templateDefinition);
|
||||
}
|
||||
|
||||
public static ICPPEvaluation create(IASTIdExpression expr) {
|
||||
|
@ -183,7 +190,7 @@ public class EvalID extends CPPEvaluation {
|
|||
if (binding instanceof IProblemBinding || binding instanceof IType || binding instanceof ICPPConstructor)
|
||||
return EvalFixed.INCOMPLETE;
|
||||
if (binding instanceof CPPFunctionSet) {
|
||||
return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr));
|
||||
return new EvalFunctionSet((CPPFunctionSet) binding, isAddressOf(expr), expr);
|
||||
}
|
||||
if (binding instanceof ICPPUnknownBinding) {
|
||||
ICPPTemplateArgument[] templateArgs = null;
|
||||
|
@ -200,7 +207,7 @@ public class EvalID extends CPPEvaluation {
|
|||
CPPDeferredFunction deferredFunction = (CPPDeferredFunction) binding;
|
||||
if (deferredFunction.getCandidates() != null) {
|
||||
CPPFunctionSet functionSet = new CPPFunctionSet(deferredFunction.getCandidates(), templateArgs, null);
|
||||
return new EvalFunctionSet(functionSet, isAddressOf(expr));
|
||||
return new EvalFunctionSet(functionSet, isAddressOf(expr), expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,7 +222,7 @@ public class EvalID extends CPPEvaluation {
|
|||
}
|
||||
|
||||
return new EvalID(fieldOwner, owner, name.getSimpleID(), isAddressOf(expr),
|
||||
name instanceof ICPPASTQualifiedName, templateArgs);
|
||||
name instanceof ICPPASTQualifiedName, templateArgs, expr);
|
||||
}
|
||||
/**
|
||||
* 9.3.1-3 Transformation to class member access within a non-static member function.
|
||||
|
@ -224,7 +231,7 @@ public class EvalID extends CPPEvaluation {
|
|||
&& !(binding instanceof ICPPConstructor) &&!((ICPPMember) binding).isStatic()) {
|
||||
IType fieldOwnerType= withinNonStaticMethod(expr);
|
||||
if (fieldOwnerType != null) {
|
||||
return new EvalMemberAccess(fieldOwnerType, LVALUE, binding, true);
|
||||
return new EvalMemberAccess(fieldOwnerType, LVALUE, binding, true, expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,14 +248,14 @@ public class EvalID extends CPPEvaluation {
|
|||
// of the enumerator.
|
||||
type= CPPSemantics.INT_TYPE;
|
||||
}
|
||||
return new EvalBinding(binding, type);
|
||||
return new EvalBinding(binding, type, expr);
|
||||
}
|
||||
}
|
||||
return new EvalBinding(binding, null);
|
||||
return new EvalBinding(binding, null, expr);
|
||||
}
|
||||
if (binding instanceof ICPPTemplateNonTypeParameter || binding instanceof IVariable
|
||||
|| binding instanceof IFunction) {
|
||||
return new EvalBinding(binding, null);
|
||||
return new EvalBinding(binding, null, expr);
|
||||
}
|
||||
return EvalFixed.INCOMPLETE;
|
||||
}
|
||||
|
@ -318,7 +325,7 @@ public class EvalID extends CPPEvaluation {
|
|||
return eval;
|
||||
}
|
||||
|
||||
return new EvalID(fieldOwner, nameOwner, fName, fAddressOf, fQualified, templateArgs);
|
||||
return new EvalID(fieldOwner, nameOwner, fName, fAddressOf, fQualified, templateArgs, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -329,7 +336,7 @@ public class EvalID extends CPPEvaluation {
|
|||
ICPPEvaluation fieldOwner = fFieldOwner.computeForFunctionCall(parameterMap, maxdepth, point);
|
||||
if (fieldOwner == fFieldOwner)
|
||||
return this;
|
||||
return new EvalID(fieldOwner, fNameOwner, fName, fAddressOf, fQualified, fTemplateArgs);
|
||||
return new EvalID(fieldOwner, fNameOwner, fName, fAddressOf, fQualified, fTemplateArgs, getTemplateDefinition());
|
||||
}
|
||||
|
||||
private ICPPEvaluation resolveName(ICPPClassType nameOwner, ICPPTemplateArgument[] templateArgs,
|
||||
|
@ -344,15 +351,15 @@ public class EvalID extends CPPEvaluation {
|
|||
if (bindings.length > 1 && bindings[0] instanceof ICPPFunction) {
|
||||
ICPPFunction[] functions = new ICPPFunction[bindings.length];
|
||||
System.arraycopy(bindings, 0, functions, 0, bindings.length);
|
||||
return new EvalFunctionSet(new CPPFunctionSet(functions, templateArgs, null), fAddressOf);
|
||||
return new EvalFunctionSet(new CPPFunctionSet(functions, templateArgs, null), fAddressOf, getTemplateDefinition());
|
||||
}
|
||||
IBinding binding = bindings.length == 1 ? bindings[0] : null;
|
||||
if (binding instanceof IEnumerator) {
|
||||
return new EvalBinding(binding, null);
|
||||
return new EvalBinding(binding, null, getTemplateDefinition());
|
||||
} else if (binding instanceof ICPPMember) {
|
||||
return new EvalMemberAccess(nameOwner, ValueCategory.PRVALUE, binding, false);
|
||||
return new EvalMemberAccess(nameOwner, ValueCategory.PRVALUE, binding, false, getTemplateDefinition());
|
||||
} else if (binding instanceof CPPFunctionSet) {
|
||||
return new EvalFunctionSet((CPPFunctionSet) binding, fAddressOf);
|
||||
return new EvalFunctionSet((CPPFunctionSet) binding, fAddressOf, getTemplateDefinition());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
|
@ -28,10 +29,14 @@ import org.eclipse.core.runtime.CoreException;
|
|||
/**
|
||||
* Performs evaluation of an expression.
|
||||
*/
|
||||
public class EvalInitList extends CPPEvaluation {
|
||||
public class EvalInitList extends CPPDependentEvaluation {
|
||||
private final ICPPEvaluation[] fClauses;
|
||||
|
||||
public EvalInitList(ICPPEvaluation[] clauses) {
|
||||
public EvalInitList(ICPPEvaluation[] clauses, IASTNode pointOfDefinition) {
|
||||
this(clauses, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalInitList(ICPPEvaluation[] clauses, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fClauses= clauses;
|
||||
}
|
||||
|
||||
|
@ -91,6 +96,7 @@ public class EvalInitList extends CPPEvaluation {
|
|||
for (ICPPEvaluation arg : fClauses) {
|
||||
buffer.marshalEvaluation(arg, includeValue);
|
||||
}
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -99,7 +105,8 @@ public class EvalInitList extends CPPEvaluation {
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
}
|
||||
return new EvalInitList(args);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalInitList(args, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -118,7 +125,7 @@ public class EvalInitList extends CPPEvaluation {
|
|||
}
|
||||
if (clauses == fClauses)
|
||||
return this;
|
||||
return new EvalInitList(clauses);
|
||||
return new EvalInitList(clauses, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -137,7 +144,7 @@ public class EvalInitList extends CPPEvaluation {
|
|||
}
|
||||
if (clauses == fClauses)
|
||||
return this;
|
||||
return new EvalInitList(clauses);
|
||||
return new EvalInitList(clauses, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -54,7 +54,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class EvalMemberAccess extends CPPEvaluation {
|
||||
public class EvalMemberAccess extends CPPDependentEvaluation {
|
||||
private final IType fOwnerType;
|
||||
private final IBinding fMember;
|
||||
private final ValueCategory fOwnerValueCategory;
|
||||
|
@ -67,7 +67,12 @@ public class EvalMemberAccess extends CPPEvaluation {
|
|||
private boolean fCheckedIsValueDependent;
|
||||
|
||||
public EvalMemberAccess(IType ownerType, ValueCategory ownerValueCat, IBinding member,
|
||||
boolean isPointerDeref) {
|
||||
boolean isPointerDeref, IASTNode pointOfDefinition) {
|
||||
this(ownerType, ownerValueCat, member, isPointerDeref, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalMemberAccess(IType ownerType, ValueCategory ownerValueCat, IBinding member,
|
||||
boolean isPointerDeref, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fOwnerType= ownerType;
|
||||
fOwnerValueCategory= ownerValueCat;
|
||||
fMember= member;
|
||||
|
@ -176,7 +181,7 @@ public class EvalMemberAccess extends CPPEvaluation {
|
|||
*/
|
||||
|
||||
ICPPEvaluation[] args= { new EvalFixed(type, LVALUE, Value.UNKNOWN) };
|
||||
ICPPFunction op= CPPSemantics.findOverloadedOperator(point, args, classType,
|
||||
ICPPFunction op= CPPSemantics.findOverloadedOperator(point, null, args, classType,
|
||||
OverloadableOperator.ARROW, LookupMode.NO_GLOBALS);
|
||||
if (op == null)
|
||||
break;
|
||||
|
@ -302,6 +307,7 @@ public class EvalMemberAccess extends CPPEvaluation {
|
|||
buffer.putByte((byte) firstByte);
|
||||
buffer.marshalType(fOwnerType);
|
||||
buffer.marshalBinding(fMember);
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -317,7 +323,8 @@ public class EvalMemberAccess extends CPPEvaluation {
|
|||
|
||||
IType ownerType= buffer.unmarshalType();
|
||||
IBinding member= buffer.unmarshalBinding();
|
||||
return new EvalMemberAccess(ownerType, ownerValueCat, member, isDeref);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalMemberAccess(ownerType, ownerValueCat, member, isDeref, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -331,7 +338,7 @@ public class EvalMemberAccess extends CPPEvaluation {
|
|||
if (ownerType instanceof ICPPClassSpecialization) {
|
||||
member = CPPTemplates.createSpecialization((ICPPClassSpecialization) ownerType, fMember, point);
|
||||
}
|
||||
return new EvalMemberAccess(ownerType, fOwnerValueCategory, member, fIsPointerDeref);
|
||||
return new EvalMemberAccess(ownerType, fOwnerValueCategory, member, fIsPointerDeref, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionT
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
|
@ -30,14 +31,18 @@ import org.eclipse.core.runtime.CoreException;
|
|||
/**
|
||||
* Performs evaluation of an expression.
|
||||
*/
|
||||
public class EvalTypeId extends CPPEvaluation {
|
||||
public class EvalTypeId extends CPPDependentEvaluation {
|
||||
private final IType fInputType;
|
||||
private final ICPPEvaluation[] fArguments;
|
||||
private IType fOutputType;
|
||||
|
||||
public EvalTypeId(IType type, ICPPEvaluation... argument) {
|
||||
public EvalTypeId(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) {
|
||||
this(type, findEnclosingTemplate(pointOfDefinition), arguments);
|
||||
}
|
||||
public EvalTypeId(IType type, IBinding templateDefinition, ICPPEvaluation... arguments) {
|
||||
super(templateDefinition);
|
||||
fInputType= type;
|
||||
fArguments= argument;
|
||||
fArguments= arguments;
|
||||
}
|
||||
|
||||
public IType getInputType() {
|
||||
|
@ -128,6 +133,7 @@ public class EvalTypeId extends CPPEvaluation {
|
|||
buffer.marshalEvaluation(arg, includeValue);
|
||||
}
|
||||
}
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
|
@ -140,7 +146,8 @@ public class EvalTypeId extends CPPEvaluation {
|
|||
args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
}
|
||||
}
|
||||
return new EvalTypeId(type, args);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalTypeId(type, templateDefinition, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -162,7 +169,7 @@ public class EvalTypeId extends CPPEvaluation {
|
|||
IType type = CPPTemplates.instantiateType(fInputType, tpMap, packOffset, within, point);
|
||||
if (args == fArguments && type == fInputType)
|
||||
return this;
|
||||
return new EvalTypeId(type, args);
|
||||
return new EvalTypeId(type, getTemplateDefinition(), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -183,7 +190,7 @@ public class EvalTypeId extends CPPEvaluation {
|
|||
}
|
||||
if (args == fArguments)
|
||||
return this;
|
||||
return new EvalTypeId(fInputType, args);
|
||||
return new EvalTypeId(fInputType, getTemplateDefinition(), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -66,7 +66,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class EvalUnary extends CPPEvaluation {
|
||||
public class EvalUnary extends CPPDependentEvaluation {
|
||||
private static final ICPPEvaluation ZERO_EVAL = new EvalFixed(CPPSemantics.INT_TYPE, PRVALUE, Value.create(0));
|
||||
|
||||
private final int fOperator;
|
||||
|
@ -75,7 +75,13 @@ public class EvalUnary extends CPPEvaluation {
|
|||
private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION;
|
||||
private IType fType;
|
||||
|
||||
public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding) {
|
||||
public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding,
|
||||
IASTNode pointOfDefinition) {
|
||||
this(operator, operand, addressOfQualifiedNameBinding, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding,
|
||||
IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fOperator= operator;
|
||||
fArgument= operand;
|
||||
fAddressOfQualifiedNameBinding= addressOfQualifiedNameBinding;
|
||||
|
@ -170,7 +176,7 @@ public class EvalUnary extends CPPEvaluation {
|
|||
} else {
|
||||
args = new ICPPEvaluation[] { fArgument };
|
||||
}
|
||||
return CPPSemantics.findOverloadedOperator(point, args, type, op, LookupMode.LIMITED_GLOBALS);
|
||||
return CPPSemantics.findOverloadedOperator(point, getTemplateDefinitionScope(), args, type, op, LookupMode.LIMITED_GLOBALS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -298,13 +304,15 @@ public class EvalUnary extends CPPEvaluation {
|
|||
buffer.putByte((byte) fOperator);
|
||||
buffer.marshalEvaluation(fArgument, includeValue);
|
||||
buffer.marshalBinding(fAddressOfQualifiedNameBinding);
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
int op= buffer.getByte();
|
||||
ICPPEvaluation arg= (ICPPEvaluation) buffer.unmarshalEvaluation();
|
||||
IBinding binding= buffer.unmarshalBinding();
|
||||
return new EvalUnary(op, arg, binding);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalUnary(op, arg, binding, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -321,7 +329,7 @@ public class EvalUnary extends CPPEvaluation {
|
|||
if (argument == fArgument && aoqn == fAddressOfQualifiedNameBinding)
|
||||
return this;
|
||||
|
||||
return new EvalUnary(fOperator, argument, aoqn);
|
||||
return new EvalUnary(fOperator, argument, aoqn, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -331,7 +339,7 @@ public class EvalUnary extends CPPEvaluation {
|
|||
if (argument == fArgument)
|
||||
return this;
|
||||
|
||||
return new EvalUnary(fOperator, argument, fAddressOfQualifiedNameBinding);
|
||||
return new EvalUnary(fOperator, argument, fAddressOfQualifiedNameBinding, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,6 +37,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
|
@ -49,12 +50,16 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class EvalUnaryTypeID extends CPPEvaluation {
|
||||
public class EvalUnaryTypeID extends CPPDependentEvaluation {
|
||||
private final int fOperator;
|
||||
private final IType fOrigType;
|
||||
private IType fType;
|
||||
|
||||
public EvalUnaryTypeID(int operator, IType type) {
|
||||
public EvalUnaryTypeID(int operator, IType type, IASTNode pointOfDefinition) {
|
||||
this(operator, type, findEnclosingTemplate(pointOfDefinition));
|
||||
}
|
||||
public EvalUnaryTypeID(int operator, IType type, IBinding templateDefinition) {
|
||||
super(templateDefinition);
|
||||
fOperator= operator;
|
||||
fOrigType= type;
|
||||
}
|
||||
|
@ -173,12 +178,14 @@ public class EvalUnaryTypeID extends CPPEvaluation {
|
|||
buffer.putByte(ITypeMarshalBuffer.EVAL_UNARY_TYPE_ID);
|
||||
buffer.putByte((byte) fOperator);
|
||||
buffer.marshalType(fOrigType);
|
||||
marshalTemplateDefinition(buffer);
|
||||
}
|
||||
|
||||
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
|
||||
int op= buffer.getByte();
|
||||
IType arg= buffer.unmarshalType();
|
||||
return new EvalUnaryTypeID(op, arg);
|
||||
IBinding templateDefinition= buffer.unmarshalBinding();
|
||||
return new EvalUnaryTypeID(op, arg, templateDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -187,7 +194,7 @@ public class EvalUnaryTypeID extends CPPEvaluation {
|
|||
IType type = CPPTemplates.instantiateType(fOrigType, tpMap, packOffset, within, point);
|
||||
if (type == fOrigType)
|
||||
return this;
|
||||
return new EvalUnaryTypeID(fOperator, type);
|
||||
return new EvalUnaryTypeID(fOperator, type, getTemplateDefinition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -90,7 +90,7 @@ public class TemplateArgumentDeduction {
|
|||
CPPTemplateParameterMap map, IASTNode point) throws DOMException {
|
||||
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||
|
||||
if (tmplArgs != null && !addExplicitArguments(tmplParams, tmplArgs, map, point))
|
||||
if (tmplArgs != null && !addExplicitArguments(template, tmplParams, tmplArgs, map, point))
|
||||
return null;
|
||||
|
||||
if (!deduceFromFunctionArgs(template, fnArgs, argIsLValue, map, point))
|
||||
|
@ -315,7 +315,7 @@ public class TemplateArgumentDeduction {
|
|||
static ICPPTemplateArgument[] deduceForAddressOf(ICPPFunctionTemplate template,
|
||||
ICPPTemplateArgument[] tmplArgs, IFunctionType arg, CPPTemplateParameterMap map, IASTNode point) throws DOMException {
|
||||
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||
if (!addExplicitArguments(tmplParams, tmplArgs, map, point))
|
||||
if (!addExplicitArguments(template, tmplParams, tmplArgs, map, point))
|
||||
return null;
|
||||
|
||||
IType par= template.getType();
|
||||
|
@ -387,7 +387,7 @@ public class TemplateArgumentDeduction {
|
|||
ICPPTemplateArgument[] args, ICPPFunctionType ftype, CPPTemplateParameterMap map, IASTNode point) throws DOMException {
|
||||
final ICPPTemplateParameter[] tmplParams = template.getTemplateParameters();
|
||||
|
||||
if (!addExplicitArguments(tmplParams, args, map, point))
|
||||
if (!addExplicitArguments(template, tmplParams, args, map, point))
|
||||
return null;
|
||||
|
||||
IType a= SemanticUtil.getSimplifiedType(ftype);
|
||||
|
@ -479,7 +479,7 @@ public class TemplateArgumentDeduction {
|
|||
/**
|
||||
* Adds the explicit arguments to the map.
|
||||
*/
|
||||
public static boolean addExplicitArguments(final ICPPTemplateParameter[] tmplParams,
|
||||
public static boolean addExplicitArguments(ICPPFunctionTemplate template, final ICPPTemplateParameter[] tmplParams,
|
||||
ICPPTemplateArgument[] tmplArgs, CPPTemplateParameterMap map, IASTNode point) {
|
||||
tmplArgs= SemanticUtil.getSimplifiedArguments(tmplArgs);
|
||||
ICPPTemplateParameter tmplParam= null;
|
||||
|
@ -495,7 +495,7 @@ public class TemplateArgumentDeduction {
|
|||
}
|
||||
}
|
||||
ICPPTemplateArgument tmplArg= tmplArgs[i];
|
||||
tmplArg= CPPTemplates.matchTemplateParameterAndArgument(tmplParam, tmplArg, map, point);
|
||||
tmplArg= CPPTemplates.matchTemplateParameterAndArgument(template, tmplParam, tmplArg, map, point);
|
||||
if (tmplArg == null)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -232,6 +232,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
public ICPPEvaluation getCompositeEvaluation(ICPPEvaluation eval) {
|
||||
if (eval == null)
|
||||
return null;
|
||||
IBinding templateDefinition = eval.getTemplateDefinition();
|
||||
IBinding templateDefinition2 = getCompositeBinding((IIndexFragmentBinding) templateDefinition);
|
||||
if (eval instanceof EvalBinary) {
|
||||
EvalBinary e= (EvalBinary) eval;
|
||||
ICPPEvaluation a = e.getArg1();
|
||||
|
@ -239,8 +241,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
|
||||
ICPPEvaluation a2 = getCompositeEvaluation(a);
|
||||
ICPPEvaluation b2 = getCompositeEvaluation(b);
|
||||
if (a != a2 || b != b2)
|
||||
e= new EvalBinary(e.getOperator(), a2, b2);
|
||||
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalBinary(e.getOperator(), a2, b2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalBinaryTypeId) {
|
||||
|
@ -250,8 +252,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
|
||||
IType a2 = getCompositeType(a);
|
||||
IType b2 = getCompositeType(b);
|
||||
if (a != a2 || b != b2)
|
||||
e= new EvalBinaryTypeId(e.getOperator(), a2, b2);
|
||||
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalBinaryTypeId(e.getOperator(), a2, b2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalBinding) {
|
||||
|
@ -261,9 +263,9 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
IType b = e.getFixedType();
|
||||
IBinding a2 = getCompositeBinding((IIndexFragmentBinding) parameterOwner);
|
||||
IType b2 = getCompositeType(b);
|
||||
if (parameterOwner != a2 || b != b2) {
|
||||
if (parameterOwner != a2 || b != b2 || templateDefinition != templateDefinition2) {
|
||||
int parameterPosition = e.getFunctionParameterPosition();
|
||||
e= new EvalBinding((ICPPFunction) a2, parameterPosition, b2);
|
||||
e= new EvalBinding((ICPPFunction) a2, parameterPosition, b2, templateDefinition2);
|
||||
}
|
||||
} else {
|
||||
IBinding a = e.getBinding();
|
||||
|
@ -271,25 +273,27 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
|
||||
IBinding a2 = getCompositeBinding((IIndexFragmentBinding) a);
|
||||
IType b2 = getCompositeType(b);
|
||||
if (a != a2 || b != b2)
|
||||
e= new EvalBinding(a2, b2);
|
||||
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalBinding(a2, b2, templateDefinition2);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalComma) {
|
||||
EvalComma e= (EvalComma) eval;
|
||||
ICPPEvaluation[] a = e.getArguments();
|
||||
|
||||
ICPPEvaluation[] a2 = getCompositeEvaluationArray(a);
|
||||
if (a != a2)
|
||||
e= new EvalComma(a2);
|
||||
|
||||
if (a != a2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalComma(a2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalCompound) {
|
||||
EvalCompound e= (EvalCompound) eval;
|
||||
ICPPEvaluation a = e.getLastEvaluation();
|
||||
ICPPEvaluation a2 = getCompositeEvaluation(a);
|
||||
if (a != a2)
|
||||
e= new EvalCompound(a2);
|
||||
if (a != a2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalCompound(a2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalConditional) {
|
||||
|
@ -300,8 +304,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
ICPPEvaluation a2 = getCompositeEvaluation(a);
|
||||
ICPPEvaluation b2 = getCompositeEvaluation(b);
|
||||
ICPPEvaluation c2 = getCompositeEvaluation(c);
|
||||
if (a != a2 || b != b2 || c != c2)
|
||||
e= new EvalConditional(a2, b2, c2, e.isPositiveThrows(), e.isNegativeThrows());
|
||||
if (a != a2 || b != b2 || c != c2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalConditional(a2, b2, c2, e.isPositiveThrows(), e.isNegativeThrows(), templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalFixed) {
|
||||
|
@ -310,7 +314,7 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
IValue b = e.getValue();
|
||||
IType a2 = getCompositeType(a);
|
||||
IValue b2= getCompositeValue(b);
|
||||
if (a != a2 || b != b2)
|
||||
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalFixed(a2, e.getValueCategory(), b2);
|
||||
return e;
|
||||
}
|
||||
|
@ -318,8 +322,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
EvalFunctionCall e= (EvalFunctionCall) eval;
|
||||
ICPPEvaluation[] a = e.getArguments();
|
||||
ICPPEvaluation[] a2 = getCompositeEvaluationArray(a);
|
||||
if (a != a2)
|
||||
e= new EvalFunctionCall(a2);
|
||||
if (a != a2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalFunctionCall(a2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalFunctionSet) {
|
||||
|
@ -330,8 +334,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
|
||||
ICPPFunction[] a2 = getCompositeFunctionArray(a);
|
||||
ICPPTemplateArgument[] b2 = TemplateInstanceUtil.convert(this, b);
|
||||
if (a != a2 || b != b2)
|
||||
e= new EvalFunctionSet(new CPPFunctionSet(a2, b2, null), e.isAddressOf());
|
||||
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalFunctionSet(new CPPFunctionSet(a2, b2, null), e.isAddressOf(), templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalID) {
|
||||
|
@ -349,16 +353,16 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
}
|
||||
ICPPTemplateArgument[] c2 = TemplateInstanceUtil.convert(this, c);
|
||||
|
||||
if (a != a2 || b != b2 || c != c2)
|
||||
e= new EvalID(a2, b2, e.getName(), e.isAddressOf(), e.isQualified(), c2);
|
||||
if (a != a2 || b != b2 || c != c2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalID(a2, b2, e.getName(), e.isAddressOf(), e.isQualified(), c2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalInitList) {
|
||||
EvalInitList e= (EvalInitList) eval;
|
||||
ICPPEvaluation[] a = e.getClauses();
|
||||
ICPPEvaluation[] a2 = getCompositeEvaluationArray(a);
|
||||
if (a != a2)
|
||||
e= new EvalInitList(a2);
|
||||
if (a != a2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalInitList(a2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalMemberAccess) {
|
||||
|
@ -367,8 +371,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
IBinding b = e.getMember();
|
||||
IType a2= getCompositeType(a);
|
||||
IBinding b2= getCompositeBinding((IIndexFragmentBinding) b);
|
||||
if (a != a2 || b != b2)
|
||||
e= new EvalMemberAccess(a2, e.getOwnerValueCategory(), b2, e.isPointerDeref());
|
||||
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalMemberAccess(a2, e.getOwnerValueCategory(), b2, e.isPointerDeref(), templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalTypeId) {
|
||||
|
@ -377,8 +381,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
ICPPEvaluation[] b = e.getArguments();
|
||||
IType a2= getCompositeType(a);
|
||||
ICPPEvaluation[] b2 = getCompositeEvaluationArray(b);
|
||||
if (a != a2 || b != b2)
|
||||
e= new EvalTypeId(a2, b2);
|
||||
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalTypeId(a2, templateDefinition2, b2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalUnary) {
|
||||
|
@ -387,16 +391,16 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
|
|||
ICPPEvaluation a2 = getCompositeEvaluation(a);
|
||||
IBinding b= e.getAddressOfQualifiedNameBinding();
|
||||
IBinding b2= getCompositeBinding((IIndexFragmentBinding) b);
|
||||
if (a != a2 || b != b2)
|
||||
e= new EvalUnary(e.getOperator(), a2, b2);
|
||||
if (a != a2 || b != b2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalUnary(e.getOperator(), a2, b2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
if (eval instanceof EvalUnaryTypeID) {
|
||||
EvalUnaryTypeID e= (EvalUnaryTypeID) eval;
|
||||
IType a = e.getArgument();
|
||||
IType a2 = getCompositeType(a);
|
||||
if (a != a2)
|
||||
e= new EvalUnaryTypeID(e.getOperator(), a2);
|
||||
if (a != a2 || templateDefinition != templateDefinition2)
|
||||
e= new EvalUnaryTypeID(e.getOperator(), a2, templateDefinition2);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.eclipse.cdt.core.index.IIndexManager;
|
|||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
||||
import org.eclipse.cdt.core.model.AbstractLanguage;
|
||||
import org.eclipse.cdt.core.model.ILanguage;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.parser.FileContent;
|
||||
import org.eclipse.cdt.core.parser.IParserLogService;
|
||||
import org.eclipse.cdt.core.parser.IScannerInfo;
|
||||
|
@ -48,6 +49,7 @@ import org.eclipse.cdt.core.parser.ISignificantMacros;
|
|||
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
|
||||
import org.eclipse.cdt.core.parser.ParserUtil;
|
||||
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.index.FileContentKey;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexFragment;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
|
||||
|
@ -1004,6 +1006,9 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
|
|||
IASTTranslationUnit ast= createAST(lang, codeReader, scanInfo, isSource, fASTOptions, ctx, pm);
|
||||
fStatistics.fParsingTime += System.currentTimeMillis() - start;
|
||||
if (ast != null) {
|
||||
// Give the new AST-TU a chance to recognize its translation unit before it is written
|
||||
// to the index.
|
||||
( (ASTTranslationUnit)ast ).setOriginatingTranslationUnit( (ITranslationUnit)tu );
|
||||
writeToIndex(lang.getLinkageID(), ast, codeReader, ctx, pm);
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
|
|
|
@ -89,6 +89,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.PDOMMacroReferenceName;
|
|||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNamedNode;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
|
||||
import org.eclipse.cdt.internal.core.pdom.tag.PDOMTagIndex;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
|
@ -230,10 +231,12 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
* 138.0 - Constexpr functions, bug 395238.
|
||||
* 139.0 - More efficient and robust storage of types and template arguments, bug 395243.
|
||||
* 140.0 - Enumerators with dependent values, bug 389009.
|
||||
* 140.1 - Mechanism for tagging nodes with extended data, bug TODO
|
||||
* 141.0 - Storing enclosing template bindings for evaluations, bug 399829
|
||||
*/
|
||||
private static final int MIN_SUPPORTED_VERSION= version(140, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(140, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(140, 0);
|
||||
private static final int MIN_SUPPORTED_VERSION= version(141, 0);
|
||||
private static final int MAX_SUPPORTED_VERSION= version(141, Short.MAX_VALUE);
|
||||
private static final int DEFAULT_VERSION = version(141, 0);
|
||||
|
||||
private static int version(int major, int minor) {
|
||||
return (major << 16) + minor;
|
||||
|
@ -269,7 +272,8 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
public static final int INDEX_OF_DEFECTIVE_FILES = Database.DATA_AREA + 8;
|
||||
public static final int INDEX_OF_FILES_WITH_UNRESOLVED_INCLUDES = Database.DATA_AREA + 12;
|
||||
public static final int PROPERTIES = Database.DATA_AREA + 16;
|
||||
public static final int END= Database.DATA_AREA + 20;
|
||||
public static final int TAG_INDEX = Database.DATA_AREA + 20;
|
||||
public static final int END= Database.DATA_AREA + 24;
|
||||
static {
|
||||
assert END <= Database.CHUNK_SIZE;
|
||||
}
|
||||
|
@ -331,6 +335,7 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
// Local caches
|
||||
protected Database db;
|
||||
private BTree fileIndex;
|
||||
private PDOMTagIndex tagIndex;
|
||||
private BTree indexOfDefectiveFiles;
|
||||
private BTree indexOfFiledWithUnresolvedIncludes;
|
||||
private final Map<Integer, PDOMLinkage> fLinkageIDCache = new HashMap<Integer, PDOMLinkage>();
|
||||
|
@ -459,6 +464,15 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
return fileIndex;
|
||||
}
|
||||
|
||||
public PDOMTagIndex getTagIndex() throws CoreException {
|
||||
if (tagIndex == null)
|
||||
{
|
||||
// tag index can only be stored in database versions 139.1 or greater
|
||||
tagIndex = new PDOMTagIndex( db.getVersion() >= version( 139, 1 ) ? db : null, TAG_INDEX );
|
||||
}
|
||||
return tagIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of files that were read with I/O errors.
|
||||
*/
|
||||
|
@ -1357,6 +1371,7 @@ public class PDOM extends PlatformObject implements IPDOM {
|
|||
|
||||
private void clearCaches() {
|
||||
fileIndex= null;
|
||||
tagIndex = null;
|
||||
indexOfDefectiveFiles= null;
|
||||
indexOfFiledWithUnresolvedIncludes= null;
|
||||
fLinkageIDCache.clear();
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.db;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
* A container for storing a set of strings in the Database. The container allows only one
|
||||
* instance of each string to be stored.
|
||||
* <p>
|
||||
* This implementation should only be used when the set is expected to be small. It uses a
|
||||
* singly linked list for storing strings in Database. Which means that a linear lookup is needed
|
||||
* to find strings in the list. An in-memory, lazily-loaded, cache is provided so the list will
|
||||
* only be fully retrieved once in the lifetime of this instance. A BTree will be more efficient
|
||||
* for larger sets.
|
||||
*/
|
||||
public class PDOMStringSet
|
||||
{
|
||||
private final Database db;
|
||||
|
||||
private long ptr;
|
||||
private long head;
|
||||
private long loaded;
|
||||
|
||||
private Map<String, Long> lazyCache;
|
||||
|
||||
public PDOMStringSet( Database db, long ptr ) throws CoreException
|
||||
{
|
||||
this.db = db;
|
||||
this.ptr = ptr;
|
||||
|
||||
head = 0;
|
||||
loaded = 0;
|
||||
}
|
||||
|
||||
public void clearCaches()
|
||||
{
|
||||
head = 0;
|
||||
loaded = 0;
|
||||
|
||||
if( lazyCache != null )
|
||||
lazyCache = null;
|
||||
}
|
||||
|
||||
private long getHead() throws CoreException
|
||||
{
|
||||
if( head == 0 )
|
||||
head = db.getRecPtr( ptr );
|
||||
return head;
|
||||
}
|
||||
|
||||
// A simple enum describing the type of the information that is stored in the Database. Each
|
||||
// enumerator represents a single field in the persistent structure and is able to answer its
|
||||
// offset in that structure.
|
||||
private static enum NodeType
|
||||
{
|
||||
Next,
|
||||
Item,
|
||||
_last;
|
||||
|
||||
// NOTE: All fields are pointers, if that changes then these initializations will need
|
||||
// to be updated.
|
||||
public final long offset = ordinal() * Database.PTR_SIZE;
|
||||
public static final int sizeof = (int)_last.offset;
|
||||
|
||||
/** Return the value of the pointer stored in this field in the given instance. */
|
||||
public long get( Database db, long instance ) throws CoreException
|
||||
{
|
||||
return db.getRecPtr( instance + offset );
|
||||
}
|
||||
|
||||
/** Store the given pointer into this field in the given instance. */
|
||||
public void put( Database db, long instance, long value ) throws CoreException
|
||||
{
|
||||
db.putRecPtr( instance + offset, value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given string to the receiving set. May cause the entire list to be loaded from the
|
||||
* Database while testing for uniqueness. Returns the record of the string that was inserted into
|
||||
* the list.
|
||||
*/
|
||||
public long add( String str ) throws CoreException
|
||||
{
|
||||
long record = find( str );
|
||||
if( record != 0 )
|
||||
return record;
|
||||
|
||||
IString string = db.newString( str );
|
||||
record = string.getRecord();
|
||||
|
||||
long new_node = db.malloc( NodeType.sizeof );
|
||||
NodeType.Next.put( db, new_node, getHead() );
|
||||
NodeType.Item.put( db, new_node, record );
|
||||
|
||||
if( lazyCache == null )
|
||||
lazyCache = new HashMap<String, Long>();
|
||||
lazyCache.put( str, record );
|
||||
|
||||
// If the Database has already been partially searched, then the loaded pointer will be after the
|
||||
// head. Since we've already put this new record into the lazy cache, there is no reason to try to
|
||||
// load it again. We put the new node at the start of the list so that it will be before the loaded
|
||||
// pointer.
|
||||
head = new_node;
|
||||
if( loaded == 0 )
|
||||
loaded = new_node;
|
||||
db.putRecPtr( ptr, new_node );
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the given string in the receiver. This could cause the entire list to be loaded from
|
||||
* the Database. The results are cached, so the list will only be loaded one time during the lifetime
|
||||
* of this instance. Returns the record of the String.
|
||||
*/
|
||||
public long find( String str ) throws CoreException
|
||||
{
|
||||
if( lazyCache != null )
|
||||
{
|
||||
Long l = lazyCache.get( str );
|
||||
if( l != null )
|
||||
return l.longValue();
|
||||
}
|
||||
|
||||
// if there is nothing in the Database, then there is nothing to load
|
||||
if( getHead() == 0 )
|
||||
return 0;
|
||||
|
||||
// otherwise prepare the cache for the data that is about to be loaded
|
||||
if( lazyCache == null )
|
||||
lazyCache = new HashMap<String, Long>();
|
||||
|
||||
// if nothing has been loaded, then start loading with the head node, otherwise continue
|
||||
// loading from whatever is after the last loaded node
|
||||
long curr = loaded == 0 ? getHead() : NodeType.Next.get( db, loaded );
|
||||
while( curr != 0 )
|
||||
{
|
||||
long next = NodeType.Next.get( db, curr );
|
||||
long item = NodeType.Item.get( db, curr );
|
||||
|
||||
IString string = db.getString( item );
|
||||
|
||||
// put the value into the cache
|
||||
lazyCache.put( string.getString(), Long.valueOf( item ) );
|
||||
|
||||
// return immediately if this is the target
|
||||
if( string.compare( str, true ) == 0 )
|
||||
return item;
|
||||
|
||||
// otherwise keep looking
|
||||
loaded = curr;
|
||||
curr = next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer to the record of the String that was removed.
|
||||
*/
|
||||
public long remove( String str ) throws CoreException
|
||||
{
|
||||
if( lazyCache != null )
|
||||
lazyCache.remove( str );
|
||||
|
||||
long prev = 0;
|
||||
long curr = getHead();
|
||||
while( curr != 0 )
|
||||
{
|
||||
long next = NodeType.Next.get( db, curr );
|
||||
long item = NodeType.Item.get( db, curr );
|
||||
|
||||
IString string = db.getString( item );
|
||||
|
||||
if( string.compare( str, true ) == 0 )
|
||||
{
|
||||
if( head != curr )
|
||||
NodeType.Next.put( db, prev, next );
|
||||
else
|
||||
{
|
||||
db.putRecPtr( ptr, next );
|
||||
head = next;
|
||||
}
|
||||
|
||||
db.free( curr );
|
||||
return item;
|
||||
}
|
||||
|
||||
prev = curr;
|
||||
curr = next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IScope.ScopeLookupData;
|
|||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagReader;
|
||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||
|
@ -36,6 +37,7 @@ import org.eclipse.cdt.internal.core.index.IIndexScope;
|
|||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.IString;
|
||||
import org.eclipse.cdt.internal.core.pdom.tag.PDOMTaggable;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
|
@ -67,6 +69,14 @@ public abstract class PDOMBinding extends PDOMNamedNode implements IPDOMBinding
|
|||
if (adapter.isAssignableFrom(PDOMBinding.class))
|
||||
return this;
|
||||
|
||||
// Any PDOMBinding can have a persistent tag. These tags should be deleted when the PDOMBinding
|
||||
// is deleted. However, PDOMBinding's don't get deleted, so there is no way to trigger deleting
|
||||
// of the tags. If the implementation is changed so that PDOMBindings do get deleted, then call:
|
||||
// PDOMTagIndex.setTags( getPDOM(), pdomBinding.record, Collections.<ITag>emptyList() );
|
||||
// to clear out all tags for the binding.
|
||||
if (adapter == ITagReader.class)
|
||||
return new PDOMTaggable( getPDOM(), getRecord() );
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IType;
|
|||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.ast.tag.TagManager;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
||||
|
@ -97,6 +98,11 @@ class PDOMCLinkage extends PDOMLinkage implements IIndexCBindingConstants {
|
|||
if (pdomBinding != null) {
|
||||
getPDOM().putCachedResult(inputBinding, pdomBinding);
|
||||
}
|
||||
|
||||
// Synchronize the tags associated with the persistent binding to match the set that is
|
||||
// associated with the input binding.
|
||||
TagManager.getInstance().syncTags( pdomBinding, inputBinding );
|
||||
|
||||
return pdomBinding;
|
||||
}
|
||||
|
||||
|
@ -104,7 +110,13 @@ class PDOMCLinkage extends PDOMLinkage implements IIndexCBindingConstants {
|
|||
}
|
||||
|
||||
if (shouldUpdate(pdomBinding, fromName)) {
|
||||
pdomBinding.update(this, fromName.getBinding());
|
||||
IBinding fromBinding = fromName.getBinding();
|
||||
|
||||
pdomBinding.update(this, fromBinding);
|
||||
|
||||
// Update the tags based on the tags from the new binding. This was in PDOMBinding.update, but
|
||||
// I found that not all subclasses (e.g., PDOMCPPFunction) call the parent implementation.
|
||||
TagManager.getInstance().syncTags( pdomBinding, fromBinding );
|
||||
}
|
||||
return pdomBinding;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
|
|||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.internal.core.Util;
|
||||
import org.eclipse.cdt.internal.core.dom.ast.tag.TagManager;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
|
@ -358,6 +359,10 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
if (inputBinding instanceof CPPClosureType) {
|
||||
addImplicitMethods(pdomBinding, (ICPPClassType) binding, fromName);
|
||||
}
|
||||
|
||||
// Synchronize the tags associated with the persistent binding to match the set that is
|
||||
// associated with the input binding.
|
||||
TagManager.getInstance().syncTags( pdomBinding, inputBinding );
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
throw new CoreException(Util.createStatus(e));
|
||||
|
@ -367,8 +372,15 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
}
|
||||
|
||||
if (shouldUpdate(pdomBinding, fromName)) {
|
||||
pdomBinding.update(this, fromName.getBinding());
|
||||
IBinding fromBinding = fromName.getBinding();
|
||||
|
||||
pdomBinding.update(this, fromBinding);
|
||||
|
||||
// Update the tags based on the tags from the new binding. This was in PDOMBinding.update, but
|
||||
// I found that not all subclasses (e.g., PDOMCPPFunction) call the parent implementation.
|
||||
TagManager.getInstance().syncTags( pdomBinding, fromBinding );
|
||||
}
|
||||
|
||||
return pdomBinding;
|
||||
}
|
||||
|
||||
|
@ -408,7 +420,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
// template parameters are created directly by their owners.
|
||||
if (binding instanceof ICPPTemplateParameter)
|
||||
return null;
|
||||
if (binding instanceof ICPPUnknownBinding)
|
||||
if (binding instanceof ICPPUnknownBinding)
|
||||
return null;
|
||||
|
||||
if (binding instanceof ICPPSpecialization) {
|
||||
|
@ -561,6 +573,10 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
} else if (!getPDOM().hasLastingDefinition(pdomBinding)) {
|
||||
pdomBinding.update(this, method);
|
||||
old.remove(pdomBinding);
|
||||
|
||||
// Update the tags based on the tags from the new binding. This was in PDOMBinding.update, but
|
||||
// I found that not all subclasses (e.g., PDOMCPPFunction) call the parent implementation.
|
||||
TagManager.getInstance().syncTags( pdomBinding, method );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -691,7 +707,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Assign names to anonymous types.
|
||||
IBinding binding= PDOMASTAdapter.getAdapterForAnonymousASTBinding(inputBinding);
|
||||
if (binding == null) {
|
||||
|
@ -1111,7 +1127,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
return CPPPointerToMemberType.unmarshal(firstByte, buffer);
|
||||
case ITypeMarshalBuffer.DEPENDENT_EXPRESSION_TYPE:
|
||||
return TypeOfDependentExpression.unmarshal(firstByte, buffer);
|
||||
case ITypeMarshalBuffer.UNKNOWN_MEMBER:
|
||||
case ITypeMarshalBuffer.UNKNOWN_MEMBER:
|
||||
IBinding binding= CPPUnknownMember.unmarshal(getPDOM(), firstByte, buffer);
|
||||
if (binding instanceof IType)
|
||||
return (IType) binding;
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.tag;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.BTree;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class BTreeIterable<T> implements Iterable<T>
|
||||
{
|
||||
public static interface Descriptor<T>
|
||||
{
|
||||
public int compare( long record ) throws CoreException;
|
||||
public T create( long record );
|
||||
}
|
||||
|
||||
private final BTree btree;
|
||||
private final Descriptor<T> descriptor;
|
||||
|
||||
public BTreeIterable( BTree btree, Descriptor<T> descriptor )
|
||||
{
|
||||
this.btree = btree;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator()
|
||||
{
|
||||
Visitor v = new Visitor();
|
||||
try { btree.accept( v ); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return Collections.<T>emptyList().iterator(); }
|
||||
return new BTreeIterator( v.records );
|
||||
}
|
||||
|
||||
private class Visitor implements IBTreeVisitor
|
||||
{
|
||||
public final List<Long> records = new LinkedList<Long>();
|
||||
|
||||
@Override
|
||||
public int compare( long record ) throws CoreException
|
||||
{
|
||||
return BTreeIterable.this.descriptor.compare( record );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit( long record ) throws CoreException
|
||||
{
|
||||
records.add( Long.valueOf( record ) );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class BTreeIterator implements Iterator<T>
|
||||
{
|
||||
private final Iterator<Long> records;
|
||||
|
||||
public BTreeIterator( Iterable<Long> records )
|
||||
{
|
||||
this.records = records.iterator();
|
||||
}
|
||||
|
||||
@Override public void remove() { }
|
||||
@Override public boolean hasNext() { return records.hasNext(); }
|
||||
@Override public T next() { return BTreeIterable.this.descriptor.create( records.next() ); }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.tag;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IWritableTag;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class PDOMTag implements IWritableTag
|
||||
{
|
||||
private final Database db;
|
||||
private final long record;
|
||||
|
||||
private String taggerId;
|
||||
private int dataLen = -1;
|
||||
|
||||
private static enum Fields
|
||||
{
|
||||
Node,
|
||||
TaggerId,
|
||||
DataLen,
|
||||
Data;
|
||||
|
||||
public final long offset = ordinal() * Database.PTR_SIZE;
|
||||
public static int sizeof( int datalen ) { return (int)Data.offset + datalen; }
|
||||
|
||||
public long getRecPtr( Database db, long instance, long data_offset ) throws CoreException
|
||||
{
|
||||
return db.getRecPtr( instance + offset + data_offset );
|
||||
}
|
||||
|
||||
public void putRecPtr( Database db, long instance, long data_offset, long value ) throws CoreException
|
||||
{
|
||||
db.putRecPtr( instance + offset + data_offset, value );
|
||||
}
|
||||
|
||||
public void put( Database db, long instance, long data_offset, byte value ) throws CoreException
|
||||
{
|
||||
db.putByte( instance + offset + data_offset, value );
|
||||
}
|
||||
|
||||
public void put( Database db, long instance, byte[] data, long data_offset, int len ) throws CoreException
|
||||
{
|
||||
db.putBytes( instance + offset + data_offset, data, len );
|
||||
}
|
||||
|
||||
public byte getByte( Database db, long instance, long data_offset ) throws CoreException
|
||||
{
|
||||
return db.getByte( instance + offset + data_offset );
|
||||
}
|
||||
|
||||
public byte[] getBytes( Database db, long instance, long data_offset, int len ) throws CoreException
|
||||
{
|
||||
byte[] data = new byte[len];
|
||||
db.getBytes( instance + offset + data_offset, data );
|
||||
return data;
|
||||
}
|
||||
|
||||
public void put( Database db, long instance, long data_offset, int value ) throws CoreException
|
||||
{
|
||||
db.putInt( instance + offset + data_offset, value );
|
||||
}
|
||||
|
||||
public int getInt( Database db, long instance, long data_offset ) throws CoreException
|
||||
{
|
||||
return db.getInt( instance + offset + data_offset );
|
||||
}
|
||||
}
|
||||
|
||||
public PDOMTag( Database db, long record )
|
||||
{
|
||||
this.db = db;
|
||||
this.record = record;
|
||||
}
|
||||
|
||||
public PDOMTag( Database db, int dataLen ) throws CoreException
|
||||
{
|
||||
this.db = db;
|
||||
this.record = db.malloc( Fields.sizeof( dataLen ) );
|
||||
this.dataLen = dataLen;
|
||||
Fields.DataLen.put( db, record, 0, dataLen );
|
||||
}
|
||||
|
||||
public long getNode() throws CoreException
|
||||
{
|
||||
return Fields.Node.getRecPtr( db, record, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTaggerId()
|
||||
{
|
||||
if( taggerId == null )
|
||||
try
|
||||
{
|
||||
long taggerIdRecord = Fields.TaggerId.getRecPtr( db, record, 0 );
|
||||
taggerId = taggerIdRecord == 0L ? new String() : db.getString( taggerIdRecord ).getString();
|
||||
}
|
||||
catch( CoreException e )
|
||||
{
|
||||
CCorePlugin.log( e );
|
||||
}
|
||||
|
||||
return taggerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDataLen()
|
||||
{
|
||||
if( dataLen < 0 )
|
||||
try { dataLen = Fields.DataLen.getInt( db, record, 0 ); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return 0; }
|
||||
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
public long getRecord() { return record; }
|
||||
|
||||
/**
|
||||
* Create and return a new PDOMTag that has the same node/taggerId as the receiver but with the
|
||||
* specified data. Return null on failure.
|
||||
*/
|
||||
public PDOMTag cloneWith( byte[] data ) throws CoreException
|
||||
{
|
||||
PDOMTag partialTag = null;
|
||||
try
|
||||
{
|
||||
long existing_node = Fields.Node.getRecPtr( db, record, 0 );
|
||||
long existing_id = Fields.TaggerId.getRecPtr( db, record, 0 );
|
||||
|
||||
partialTag = new PDOMTag( db, data.length );
|
||||
Fields.Node.putRecPtr( db, partialTag.record, 0, existing_node );
|
||||
Fields.TaggerId.putRecPtr( db, partialTag.record, 0, existing_id );
|
||||
if( partialTag.putBytes( 0, data, data.length ) )
|
||||
{
|
||||
PDOMTag tag = partialTag;
|
||||
partialTag = null;
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( partialTag != null )
|
||||
partialTag.delete();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void delete()
|
||||
{
|
||||
if( db != null
|
||||
&& record != 0 )
|
||||
try { db.free( record ); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); }
|
||||
}
|
||||
|
||||
public static class BTreeComparator implements IBTreeComparator
|
||||
{
|
||||
private final Database db;
|
||||
public BTreeComparator( Database db ) { this.db = db; }
|
||||
|
||||
@Override
|
||||
public int compare(long record1, long record2) throws CoreException
|
||||
{
|
||||
if( record1 == record2 )
|
||||
return 0;
|
||||
|
||||
long node1 = Fields.Node.getRecPtr( db, record1, 0 );
|
||||
long node2 = Fields.Node.getRecPtr( db, record2, 0 );
|
||||
if( node1 < node2 )
|
||||
return -1;
|
||||
if( node1 > node2 )
|
||||
return 1;
|
||||
|
||||
long tagger1 = Fields.TaggerId.getRecPtr( db, record1, 0 );
|
||||
long tagger2 = Fields.TaggerId.getRecPtr( db, record2, 0 );
|
||||
if( tagger1 < tagger2 )
|
||||
return -1;
|
||||
if( tagger1 > tagger2 )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BTreeVisitor implements IBTreeVisitor
|
||||
{
|
||||
private final Database db;
|
||||
private final long node2;
|
||||
private final long tagger2;
|
||||
|
||||
public boolean hasResult = false;
|
||||
public long tagRecord = 0;
|
||||
|
||||
public BTreeVisitor( Database db, long node2, long tagger2 )
|
||||
{
|
||||
this.db = db;
|
||||
this.node2 = node2;
|
||||
this.tagger2 = tagger2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(long record1) throws CoreException {
|
||||
long node1 = Fields.Node.getRecPtr( db, record1, 0 );
|
||||
if( node1 < node2 )
|
||||
return -1;
|
||||
if( node1 > node2 )
|
||||
return 1;
|
||||
|
||||
long tagger1 = Fields.TaggerId.getRecPtr( db, record1, 0 );
|
||||
if( tagger1 < tagger2 )
|
||||
return -1;
|
||||
if( tagger1 > tagger2 )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(long record) throws CoreException {
|
||||
tagRecord = record;
|
||||
hasResult = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNode( long node ) throws CoreException
|
||||
{
|
||||
Fields.Node.putRecPtr( db, record, 0, node );
|
||||
}
|
||||
|
||||
public void setTaggerId( long idRecord ) throws CoreException
|
||||
{
|
||||
Fields.TaggerId.putRecPtr( db, record, 0, idRecord );
|
||||
}
|
||||
|
||||
private boolean isInBounds( int offset, int len )
|
||||
{
|
||||
int data_len = getDataLen();
|
||||
return offset >= 0
|
||||
&& offset < data_len
|
||||
&& ( offset + len ) <= data_len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putByte( int offset, byte data )
|
||||
{
|
||||
if( ! isInBounds( offset, 1 ) )
|
||||
return false;
|
||||
|
||||
try { Fields.Data.put( db, record, offset, data ); return true; }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return false; }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putBytes( int offset, byte[] data, int len )
|
||||
{
|
||||
boolean fullWrite = len < 0;
|
||||
if( fullWrite )
|
||||
len = data.length;
|
||||
if( ! isInBounds( offset, len ) )
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
Fields.Data.put( db, record, data, offset, len );
|
||||
|
||||
// if the new buffer replaces all of the existing one, then modify the receiver's stored length
|
||||
int currLen = getDataLen();
|
||||
if( fullWrite
|
||||
&& offset == 0
|
||||
&& currLen > len )
|
||||
{
|
||||
Fields.DataLen.put( db, record, 0, len );
|
||||
dataLen = len;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return false; }
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getByte( int offset )
|
||||
{
|
||||
if( ! isInBounds( offset, 1 ) )
|
||||
return Fail;
|
||||
|
||||
try { return Fields.Data.getByte( db, record, offset ); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return Fail; }
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes( int offset, int len )
|
||||
{
|
||||
len = len >= 0 ? len : getDataLen() - offset;
|
||||
if( ! isInBounds( offset, len ) )
|
||||
return null;
|
||||
|
||||
try { return Fields.Data.getBytes( db, record, offset, len ); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return null; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.tag;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IWritableTag;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.BTree;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.PDOMStringSet;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
* Not thread-safe.
|
||||
*/
|
||||
public class PDOMTagIndex
|
||||
{
|
||||
private final Database db;
|
||||
private final long ptr;
|
||||
private long rootRecord;
|
||||
|
||||
private static enum Fields
|
||||
{
|
||||
TaggerIds,
|
||||
Tags,
|
||||
_last;
|
||||
|
||||
public final long offset = ordinal() * Database.PTR_SIZE;
|
||||
public static int sizeof = _last.ordinal() * Database.PTR_SIZE;
|
||||
}
|
||||
|
||||
private PDOMStringSet taggerIds;
|
||||
private BTree tags;
|
||||
|
||||
public PDOMTagIndex( Database db, long ptr ) throws CoreException
|
||||
{
|
||||
this.db = db;
|
||||
this.ptr = ptr;
|
||||
this.rootRecord = 0;
|
||||
}
|
||||
|
||||
private long getFieldAddress( Fields field ) throws CoreException
|
||||
{
|
||||
if( rootRecord == 0 )
|
||||
rootRecord = db.getRecPtr( ptr );
|
||||
|
||||
if( rootRecord == 0 )
|
||||
{
|
||||
rootRecord = db.malloc( Fields.sizeof );
|
||||
db.putRecPtr( ptr, rootRecord );
|
||||
}
|
||||
|
||||
return rootRecord + field.offset;
|
||||
}
|
||||
|
||||
private PDOMStringSet getTaggerIds() throws CoreException
|
||||
{
|
||||
if( taggerIds == null )
|
||||
taggerIds = new PDOMStringSet( db, getFieldAddress( Fields.TaggerIds ) );
|
||||
return taggerIds;
|
||||
}
|
||||
|
||||
private BTree getTagsBTree() throws CoreException
|
||||
{
|
||||
if( tags == null )
|
||||
tags = new BTree( db, getFieldAddress( Fields.Tags ), new PDOMTag.BTreeComparator( db ) );
|
||||
return tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the record storing the specified tagger id. Create a new record if needed.
|
||||
*/
|
||||
private long getIdRecord( String taggerId, boolean createIfNeeded )
|
||||
{
|
||||
assert taggerId != null;
|
||||
assert ! taggerId.isEmpty();
|
||||
|
||||
if( db == null
|
||||
|| taggerId == null
|
||||
|| taggerId.isEmpty()
|
||||
|| ( taggerIds == null && ! createIfNeeded ) )
|
||||
return 0L;
|
||||
|
||||
try
|
||||
{
|
||||
long record = getTaggerIds().find( taggerId );
|
||||
if( record == 0
|
||||
&& createIfNeeded )
|
||||
record = getTaggerIds().add( taggerId );
|
||||
return record;
|
||||
}
|
||||
catch( CoreException e )
|
||||
{
|
||||
CCorePlugin.log( e );
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
|
||||
private IWritableTag createTag( long record, String id, int len )
|
||||
{
|
||||
if( db == null )
|
||||
return null;
|
||||
|
||||
long idRecord = getIdRecord( id, true );
|
||||
if( idRecord == 0L )
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
PDOMTag tag = new PDOMTag( db, len );
|
||||
tag.setNode( record );
|
||||
tag.setTaggerId( idRecord );
|
||||
|
||||
// return the tag if it was properly inserted
|
||||
long inserted = getTagsBTree().insert( tag.getRecord() );
|
||||
if( inserted == tag.getRecord() )
|
||||
return tag;
|
||||
|
||||
// TODO check that the existing record has the same length
|
||||
|
||||
// otherwise destroy this provisional one and return the tag that was actually inserted
|
||||
// TODO figure out what this case means
|
||||
tag.delete();
|
||||
return inserted == 0 ? null : new PDOMTag( db, inserted );
|
||||
}
|
||||
catch( CoreException e )
|
||||
{
|
||||
CCorePlugin.log( e );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ITag getTag( long record, String id )
|
||||
{
|
||||
if( db == null )
|
||||
return null;
|
||||
|
||||
long idRecord = getIdRecord( id, false );
|
||||
if( idRecord == 0L )
|
||||
return null;
|
||||
|
||||
PDOMTag.BTreeVisitor v = new PDOMTag.BTreeVisitor( db, record, idRecord );
|
||||
try { getTagsBTree().accept( v ); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); }
|
||||
|
||||
return v.hasResult ? new PDOMTag( db, v.tagRecord ) : null;
|
||||
}
|
||||
|
||||
private Iterable<ITag> getTags( long binding_record )
|
||||
{
|
||||
BTree btree = null;
|
||||
try { btree = getTagsBTree(); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return Collections.emptyList(); }
|
||||
|
||||
final Long bindingRecord = Long.valueOf( binding_record );
|
||||
return
|
||||
new BTreeIterable<ITag>(
|
||||
btree,
|
||||
new BTreeIterable.Descriptor<ITag>()
|
||||
{
|
||||
@Override public ITag create( long record ) { return new PDOMTag( db, record ); }
|
||||
@Override
|
||||
public int compare( long test_record ) throws CoreException
|
||||
{
|
||||
long test_node = new PDOMTag( db, test_record ).getNode();
|
||||
|
||||
// -1 if record < key, 0 if record == key, 1 if record > key
|
||||
return Long.valueOf( test_node ).compareTo( bindingRecord );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
private boolean setTags( long binding_record, Iterable<ITag> tags )
|
||||
{
|
||||
// There could be several tags for the given record in the database, one for each taggerId. We need
|
||||
// to delete all of those tags and replace them with given list. The incoming tags are first put
|
||||
// into a map, indexed by their taggerId. Then we examine the btree of tags to find all tags for this
|
||||
// record. In each case we decide whether to delete or update the tag. Tags of the same size can be
|
||||
// updated in place, otherwise the tag needs to be deleted and recreated.
|
||||
|
||||
final Map<String, ITag> newTags = new HashMap<String, ITag>();
|
||||
for( ITag tag : tags )
|
||||
{
|
||||
ITag dupTag = newTags.put( tag.getTaggerId(), tag );
|
||||
if( dupTag != null )
|
||||
CCorePlugin.log( "Duplicate incoming tag for record " + binding_record + " from taggerId " + tag.getTaggerId() ); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
BTree btree = null;
|
||||
try { btree = getTagsBTree(); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return false; }
|
||||
|
||||
PDOMTagSynchronizer sync = new PDOMTagSynchronizer( db, Long.valueOf( binding_record ), newTags );
|
||||
|
||||
// visit the full tree, then return true on success and false on failure
|
||||
try { btree.accept( sync ); }
|
||||
catch( CoreException e ) { CCorePlugin.log( e ); return false; }
|
||||
|
||||
// Complete the synchronization (delete/insert the records that could not be modified in-place). This
|
||||
// will only have something to do when a tag has changed length, which should be a rare.
|
||||
sync.synchronize( btree );
|
||||
|
||||
// insert any new tags that are left in the incoming list
|
||||
for( ITag newTag : newTags.values() )
|
||||
{
|
||||
IWritableTag pdomTag = createTag( binding_record, newTag.getTaggerId(), newTag.getDataLen() );
|
||||
pdomTag.putBytes( 0, newTag.getBytes( 0, -1 ), -1 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PDOMTagIndex getTagIndex( PDOM pdom )
|
||||
{
|
||||
if( pdom == null )
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
PDOMTagIndex index = pdom.getTagIndex();
|
||||
return index.db == null ? null : index;
|
||||
}
|
||||
catch( CoreException e ) { CCorePlugin.log(e); }
|
||||
return null;
|
||||
}
|
||||
|
||||
// common implementations
|
||||
public static IWritableTag createTag( PDOM pdom, long record, String id, int len )
|
||||
{
|
||||
PDOMTagIndex index = getTagIndex( pdom );
|
||||
if( index == null )
|
||||
return null;
|
||||
|
||||
return index.createTag( record, id, len );
|
||||
}
|
||||
|
||||
public static ITag getTag( PDOM pdom, long record, String id )
|
||||
{
|
||||
PDOMTagIndex index = getTagIndex( pdom );
|
||||
if( index == null )
|
||||
return null;
|
||||
|
||||
return index.getTag( record, id );
|
||||
}
|
||||
|
||||
public static Iterable<ITag> getTags( PDOM pdom, long record )
|
||||
{
|
||||
PDOMTagIndex index = getTagIndex( pdom );
|
||||
if( index == null )
|
||||
return Collections.emptyList();
|
||||
|
||||
return index.getTags( record );
|
||||
}
|
||||
|
||||
public static boolean setTags( PDOM pdom, long record, Iterable<ITag> tags )
|
||||
{
|
||||
if( record == 0 )
|
||||
return true;
|
||||
|
||||
PDOMTagIndex index = getTagIndex( pdom );
|
||||
if( index == null )
|
||||
return false;
|
||||
|
||||
return index.setTags( record, tags );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.tag;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.BTree;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
public class PDOMTagSynchronizer implements IBTreeVisitor
|
||||
{
|
||||
private final Database db;
|
||||
private final Long searchRecord;
|
||||
private final Map<String, ITag> newTags;
|
||||
|
||||
private final List<Long> toRemove = new LinkedList<Long>();
|
||||
private final List<Long> toInsert = new LinkedList<Long>();
|
||||
|
||||
public PDOMTagSynchronizer( Database db, Long searchRecord, Map<String, ITag> newTags )
|
||||
{
|
||||
this.db = db;
|
||||
this.searchRecord = searchRecord;
|
||||
this.newTags = newTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the synchronization by deleting and inserting all required records. Return
|
||||
* true if successful and false otherwise.
|
||||
*/
|
||||
public boolean synchronize( BTree tree )
|
||||
{
|
||||
for( Long rm : toRemove )
|
||||
try
|
||||
{
|
||||
long record = rm.longValue();
|
||||
tree.delete( record );
|
||||
db.free( record );
|
||||
}
|
||||
catch( CoreException e )
|
||||
{
|
||||
CCorePlugin.log( e );
|
||||
}
|
||||
toRemove.clear();
|
||||
|
||||
for( Long insert : toInsert )
|
||||
try { tree.insert( insert.longValue() ); }
|
||||
catch( CoreException e )
|
||||
{
|
||||
CCorePlugin.log( e );
|
||||
try { db.free( insert.longValue() ); }
|
||||
catch( CoreException e1 ) { CCorePlugin.log( e1 ); }
|
||||
}
|
||||
toInsert.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare( long test_record ) throws CoreException
|
||||
{
|
||||
// TODO this is the same as BTreeIterable.Descriptor.compare
|
||||
|
||||
long test_node = new PDOMTag( db, test_record ).getNode();
|
||||
|
||||
// -1 if record < key, 0 if record == key, 1 if record > key
|
||||
return Long.valueOf( test_node ).compareTo( searchRecord );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit( long existing_record ) throws CoreException
|
||||
{
|
||||
PDOMTag existingTag = new PDOMTag( db, existing_record );
|
||||
String taggerId = existingTag.getTaggerId();
|
||||
|
||||
ITag newTag = newTags.remove( taggerId );
|
||||
if( newTag == null )
|
||||
toRemove.add( Long.valueOf( existing_record ) );
|
||||
else if( newTag.getDataLen() > existingTag.getDataLen() )
|
||||
{
|
||||
toRemove.add( Long.valueOf( existing_record ) );
|
||||
|
||||
PDOMTag pdomTag = existingTag.cloneWith( newTag.getBytes( 0, -1 ) );
|
||||
if( pdomTag != null )
|
||||
toInsert.add( Long.valueOf( pdomTag.getRecord() ) );
|
||||
}
|
||||
else if( ! existingTag.putBytes( 0, newTag.getBytes( 0, -1 ), -1 ) )
|
||||
CCorePlugin.log( "Unable to modify data of tag record " + existing_record + " from taggerId " + taggerId ); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
// try to visit the full tree
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom.tag;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagReader;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagWriter;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IWritableTag;
|
||||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||
|
||||
public class PDOMTaggable implements ITagReader, ITagWriter
|
||||
{
|
||||
private final PDOM pdom;
|
||||
private final long record;
|
||||
|
||||
public PDOMTaggable( PDOM pdom, long record )
|
||||
{
|
||||
this.pdom = pdom;
|
||||
this.record = record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWritableTag createTag( String id, int len )
|
||||
{
|
||||
return PDOMTagIndex.createTag( pdom, record, id, len );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITag getTag( String id )
|
||||
{
|
||||
return PDOMTagIndex.getTag( pdom, record, id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ITag> getTags()
|
||||
{
|
||||
return PDOMTagIndex.getTags( pdom, record );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setTags( Iterable<ITag> tags )
|
||||
{
|
||||
return PDOMTagIndex.setTags( pdom, record, tags );
|
||||
}
|
||||
}
|
|
@ -121,6 +121,7 @@ CConfigurationDataProvider.name = CConfigurationData provider
|
|||
projectConverter.name = project converter
|
||||
CIndex.name = CIndex
|
||||
externalSettingsProvider.name = External Settings provider
|
||||
tagger.name = Parser Node Tagger Extension Point
|
||||
GeneratePDOMApplication.name = GeneratePDOM
|
||||
defaultProvider.name = Default Provider
|
||||
templatesExtensionPoint.name = Templates Extension point
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
<extension-point id="projectConverter" name="%projectConverter.name" schema="schema/projectConverter.exsd"/>
|
||||
<extension-point id="CIndex" name="%CIndex.name" schema="schema/CIndex.exsd"/>
|
||||
<extension-point id="externalSettingsProvider" name="%externalSettingsProvider.name" schema="schema/externalSettingsProvider.exsd"/>
|
||||
<extension-point id="tagger" name="%tagger.name" schema="schema/tagger.exsd"/>
|
||||
<!-- =================================================================================== -->
|
||||
<!-- CProjectDescriptionStorage provides addition types of project description storage -->
|
||||
<!-- =================================================================================== -->
|
||||
|
|
139
core/org.eclipse.cdt.core/schema/tagger.exsd
Normal file
139
core/org.eclipse.cdt.core/schema/tagger.exsd
Normal file
|
@ -0,0 +1,139 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Schema file written by PDE -->
|
||||
<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.schema plugin="org.eclipse.cdt.core" id="tagger" name="Node Tagger"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
This extension point allows extensions to contribute to the parsed nodes. When PDOM nodes are tagged, the content of the tag is stored in to the Database. The information for other nodes, e.g., the AST, is stored in memory.
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
|
||||
|
||||
<element name="extension">
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.element />
|
||||
</appInfo>
|
||||
</annotation>
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element ref="bindingTagger" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="point" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
a fully qualified identifier of the target extension point
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="id" type="string">
|
||||
<annotation>
|
||||
<documentation>
|
||||
an optional identifier of the extension instance
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="name" type="string">
|
||||
<annotation>
|
||||
<documentation>
|
||||
an optional name of the extension instance
|
||||
</documentation>
|
||||
<appInfo>
|
||||
<meta.attribute translatable="true"/>
|
||||
</appInfo>
|
||||
</annotation>
|
||||
</attribute>
|
||||
</complexType>
|
||||
</element>
|
||||
|
||||
<element name="bindingTagger">
|
||||
<complexType>
|
||||
<sequence>
|
||||
</sequence>
|
||||
<attribute name="class" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
|
||||
</documentation>
|
||||
<appInfo>
|
||||
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.dom.ast.tag.IBindingTagger"/>
|
||||
</appInfo>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="local-id" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
A unique identifier for this tagger's contributions.
|
||||
|
||||
The local id will be appended to the contributing plugin's id (separated with a dot '.') to form the globally unique identifier for this tagger. This id is used to uniquely associate the tag with this plugin.
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
</complexType>
|
||||
</element>
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="since"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
8.2
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="examples"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
The following is an example of a Tagger contribution:
|
||||
<p>
|
||||
<pre>
|
||||
<extension
|
||||
point="org.eclipse.cdt.core.tagger"
|
||||
id="example"
|
||||
name="Example Tagger Extension">
|
||||
<bindingTagger
|
||||
local-id="my-tagger"
|
||||
class="com.example.internal.ExampleTagger">
|
||||
<enablement>
|
||||
<with variable="projectNatures">
|
||||
<iterate operator="or">
|
||||
<equals value="com.example.my-nature"/>
|
||||
</iterate>
|
||||
</with>
|
||||
</enablement>
|
||||
</bindingTagger>
|
||||
</extension>
|
||||
</pre>
|
||||
</p>
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="apiInfo"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
The contributed class must implement <code>org.eclipse.cdt.core.dom.ast.tag.IBindingTagger</code>
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
|
||||
<annotation>
|
||||
<appInfo>
|
||||
<meta.section type="copyright"/>
|
||||
</appInfo>
|
||||
<documentation>
|
||||
Copyright (c) 2013 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
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
</schema>
|
|
@ -26,6 +26,7 @@ import java.util.ResourceBundle;
|
|||
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
|
||||
import org.eclipse.cdt.core.cdtvariables.IUserVarSupplier;
|
||||
import org.eclipse.cdt.core.dom.IPDOMManager;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagService;
|
||||
import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
|
||||
import org.eclipse.cdt.core.index.IIndexManager;
|
||||
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
|
||||
|
@ -50,6 +51,7 @@ import org.eclipse.cdt.internal.core.ICConsole;
|
|||
import org.eclipse.cdt.internal.core.PositionTrackerManager;
|
||||
import org.eclipse.cdt.internal.core.cdtvariables.CdtVariableManager;
|
||||
import org.eclipse.cdt.internal.core.cdtvariables.UserVarSupplier;
|
||||
import org.eclipse.cdt.internal.core.dom.ast.tag.TagService;
|
||||
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
|
||||
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsScannerInfoProvider;
|
||||
import org.eclipse.cdt.internal.core.model.CModelManager;
|
||||
|
@ -214,6 +216,8 @@ public class CCorePlugin extends Plugin {
|
|||
|
||||
private PDOMManager pdomManager;
|
||||
|
||||
private ITagService tagService = new TagService();
|
||||
|
||||
private CdtVarPathEntryVariableManager fPathEntryVariableManager;
|
||||
|
||||
private final class NullConsole implements IConsole {
|
||||
|
@ -713,6 +717,13 @@ public class CCorePlugin extends Plugin {
|
|||
return getDefault().pdomManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.5
|
||||
*/
|
||||
public static ITagService getTagService() {
|
||||
return getDefault().tagService;
|
||||
}
|
||||
|
||||
public IPathEntryVariableManager getPathEntryVariableManager() {
|
||||
return fPathEntryVariableManager;
|
||||
}
|
||||
|
|
|
@ -489,21 +489,25 @@ public class LanguageSettingEntryDialog extends AbstractPropertyDialog {
|
|||
|
||||
inputValue.setEnabled(isMacroSelected);
|
||||
|
||||
int indexPathKind = comboPathCategory.getSelectionIndex();
|
||||
boolean isProjectSelected = (indexPathKind == COMBO_PATH_INDEX_PROJECT);
|
||||
boolean isWorkspaceSelected = (indexPathKind == COMBO_PATH_INDEX_WORKSPACE);
|
||||
boolean isFilesystemSelected = (indexPathKind == COMBO_PATH_INDEX_FILESYSTEM);
|
||||
|
||||
String path = inputName.getText().trim();
|
||||
if (path.isEmpty()) {
|
||||
buttonOk.setEnabled(false);
|
||||
if (isMacroSelected) {
|
||||
buttonOk.setEnabled(!inputName.getText().trim().isEmpty());
|
||||
} else {
|
||||
buttonOk.setEnabled((isProjectSelected && !path.startsWith(SLASH)) ||
|
||||
(isWorkspaceSelected && path.startsWith(SLASH)) || isFilesystemSelected);
|
||||
int indexPathKind = comboPathCategory.getSelectionIndex();
|
||||
boolean isProjectSelected = (indexPathKind == COMBO_PATH_INDEX_PROJECT);
|
||||
boolean isWorkspaceSelected = (indexPathKind == COMBO_PATH_INDEX_WORKSPACE);
|
||||
boolean isFilesystemSelected = (indexPathKind == COMBO_PATH_INDEX_FILESYSTEM);
|
||||
|
||||
String path = inputName.getText().trim();
|
||||
if (path.isEmpty()) {
|
||||
buttonOk.setEnabled(false);
|
||||
} else {
|
||||
buttonOk.setEnabled((isProjectSelected && !path.startsWith(SLASH)) ||
|
||||
(isWorkspaceSelected && path.startsWith(SLASH)) || isFilesystemSelected);
|
||||
}
|
||||
|
||||
buttonVars.setEnabled(isFilesystemSelected);
|
||||
}
|
||||
|
||||
buttonVars.setEnabled(isFilesystemSelected);
|
||||
|
||||
compositeArea.layout(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ public class Messages extends NLS {
|
|||
public static String CMainWizardPage_5;
|
||||
public static String CMainWizardPage_6;
|
||||
public static String CMainWizardPage_7;
|
||||
public static String CMainWizardPage_DirReadOnlyError;
|
||||
public static String ConfigDescriptionTab_0;
|
||||
public static String ConfigDescriptionTab_1;
|
||||
public static String ConfigDescriptionTab_2;
|
||||
|
|
|
@ -273,6 +273,7 @@ CMainWizardPage_3=No project types available. Project cannot be created
|
|||
CMainWizardPage_5=Cannot create ICProjectTypeHandler:
|
||||
CMainWizardPage_6=File with specified name already exists.
|
||||
CMainWizardPage_7=Directory with specified name already exists.
|
||||
CMainWizardPage_DirReadOnlyError=Directory with specified name already exists and is read-only.
|
||||
|
||||
ProjectContentsArea_0=Browse...
|
||||
ProjectContentsArea_1=Use default location
|
||||
|
|
|
@ -211,7 +211,12 @@ import org.eclipse.cdt.internal.ui.newui.Messages;
|
|||
IFileInfo f = fs.fetchInfo();
|
||||
if (f.exists()) {
|
||||
if (f.isDirectory()) {
|
||||
setMessage(Messages.CMainWizardPage_7, IMessageProvider.WARNING);
|
||||
if (f.getAttribute(EFS.ATTRIBUTE_READ_ONLY)) {
|
||||
setErrorMessage(Messages.CMainWizardPage_DirReadOnlyError);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
setMessage(Messages.CMainWizardPage_7, IMessageProvider.WARNING);
|
||||
} else {
|
||||
setErrorMessage(Messages.CMainWizardPage_6);
|
||||
return false;
|
||||
|
|
|
@ -3,10 +3,10 @@ Bundle-ManifestVersion: 2
|
|||
Bundle-Name: CDT Qt Support Core
|
||||
Bundle-SymbolicName: org.eclipse.cdt.qt.core;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.qt.core.Activator
|
||||
Bundle-Activator: org.eclipse.cdt.qt.core.QtPlugin
|
||||
Bundle-Vendor: Eclipse CDT
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
org.eclipse.core.resources;bundle-version="3.8.100",
|
||||
org.eclipse.core.resources,
|
||||
org.eclipse.cdt.core
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-ActivationPolicy: lazy
|
||||
|
|
|
@ -50,4 +50,20 @@
|
|||
</run>
|
||||
</runtime>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.cdt.core.tagger"
|
||||
id="qt.signalslots"
|
||||
name="Qt Signal/Slot Tagger">
|
||||
<bindingTagger
|
||||
local-id="signalslot.tagger"
|
||||
class="org.eclipse.cdt.qt.internal.core.QtSignalSlotTagger">
|
||||
<enablement>
|
||||
<with variable="projectNatures">
|
||||
<iterate operator="or">
|
||||
<equals value="org.eclipse.cdt.qt.core.qtNature"/>
|
||||
</iterate>
|
||||
</with>
|
||||
</enablement>
|
||||
</bindingTagger>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package org.eclipse.cdt.qt.core;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
|
||||
private static BundleContext context;
|
||||
|
||||
static BundleContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void start(BundleContext bundleContext) throws Exception {
|
||||
Activator.context = bundleContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
public void stop(BundleContext bundleContext) throws Exception {
|
||||
Activator.context = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,4 +17,10 @@ public class QtKeywords
|
|||
public static final String Q_SLOTS = "Q_SLOTS";
|
||||
public static final String SIGNALS = "signals";
|
||||
public static final String SLOTS = "slots";
|
||||
|
||||
public static final String SIGNAL = "SIGNAL";
|
||||
public static final String SLOT = "SLOT";
|
||||
|
||||
public static final String QOBJECT = "QObject";
|
||||
public static final String CONNECT = "connect";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package org.eclipse.cdt.qt.core;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class QtPlugin implements BundleActivator {
|
||||
|
||||
public static final String ID = "org.eclipse.cdt.qt.core";
|
||||
public static final String SIGNAL_SLOT_TAGGER_ID = ID + ".signalslot.tagger";
|
||||
|
||||
public static final int SignalSlot_Mask_signal = 1;
|
||||
public static final int SignalSlot_Mask_slot = 2;
|
||||
|
||||
private static BundleContext context;
|
||||
|
||||
static BundleContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
@Override
|
||||
public void start(BundleContext bundleContext) throws Exception {
|
||||
QtPlugin.context = bundleContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
|
||||
*/
|
||||
@Override
|
||||
public void stop(BundleContext bundleContext) throws Exception {
|
||||
QtPlugin.context = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.qt.internal.core;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IBindingTagger;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagWriter;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.IWritableTag;
|
||||
import org.eclipse.cdt.qt.core.QtKeywords;
|
||||
import org.eclipse.cdt.qt.core.QtPlugin;
|
||||
|
||||
public class QtSignalSlotTagger implements IBindingTagger
|
||||
{
|
||||
private static ICPPASTVisibilityLabel findVisibilityLabel( ICPPMethod method, IASTNode ast )
|
||||
{
|
||||
// the visibility cannot be found without an ast
|
||||
if( ast == null )
|
||||
return null;
|
||||
|
||||
IASTNode methodDecl = ast;
|
||||
ICPPASTCompositeTypeSpecifier classType = null;
|
||||
while( methodDecl != null
|
||||
&& classType == null )
|
||||
{
|
||||
IASTNode parent = methodDecl.getParent();
|
||||
if( parent instanceof ICPPASTCompositeTypeSpecifier )
|
||||
classType = (ICPPASTCompositeTypeSpecifier)parent;
|
||||
else
|
||||
methodDecl = parent;
|
||||
}
|
||||
|
||||
if( methodDecl == null
|
||||
|| classType == null )
|
||||
return null;
|
||||
|
||||
ICPPASTVisibilityLabel lastLabel = null;
|
||||
for( IASTDeclaration decl : classType.getMembers() )
|
||||
{
|
||||
if( decl instanceof ICPPASTVisibilityLabel )
|
||||
lastLabel = (ICPPASTVisibilityLabel)decl;
|
||||
else if( decl == methodDecl )
|
||||
return lastLabel;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITag process( ITagWriter tagWriter, IBinding binding, IASTName ast )
|
||||
{
|
||||
// only methods a be signals or slots
|
||||
if( ! ( binding instanceof ICPPMethod ) )
|
||||
return null;
|
||||
|
||||
// a visibility label is required in order to decide whether the method is a signal/slot
|
||||
ICPPMethod method = (ICPPMethod)binding;
|
||||
ICPPASTVisibilityLabel v = findVisibilityLabel( method, ast );
|
||||
if( v == null )
|
||||
return null;
|
||||
|
||||
byte bitset = 0;
|
||||
for( IASTNodeLocation loc : v.getNodeLocations() )
|
||||
if( loc instanceof IASTMacroExpansionLocation )
|
||||
{
|
||||
IASTMacroExpansionLocation macroExpansion = (IASTMacroExpansionLocation)loc;
|
||||
IASTPreprocessorMacroExpansion exp = macroExpansion.getExpansion();
|
||||
String macro = exp.getMacroReference().toString();
|
||||
|
||||
if( QtKeywords.SIGNALS.equals( macro ) || QtKeywords.Q_SIGNALS.equals( macro ) )
|
||||
bitset |= QtPlugin.SignalSlot_Mask_signal;
|
||||
else if( QtKeywords.SLOTS.equals( macro ) || QtKeywords.Q_SLOTS.equals( macro ) )
|
||||
bitset |= QtPlugin.SignalSlot_Mask_slot;
|
||||
}
|
||||
|
||||
if( bitset != 0 )
|
||||
{
|
||||
IWritableTag tag = tagWriter.createTag( QtPlugin.SIGNAL_SLOT_TAGGER_ID, 1 );
|
||||
if( tag != null
|
||||
&& tag.putByte( 0, bitset ) )
|
||||
return tag;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -3,13 +3,15 @@ Bundle-ManifestVersion: 2
|
|||
Bundle-Name: CDT Qt Support UI
|
||||
Bundle-SymbolicName: org.eclipse.cdt.qt.ui;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.qt.ui.Activator
|
||||
Bundle-Activator: org.eclipse.cdt.qt.ui.QtUIPlugin
|
||||
Bundle-Vendor: Eclipse CDT
|
||||
Bundle-Localization: plugin
|
||||
Require-Bundle: org.eclipse.ui,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.cdt.ui,
|
||||
org.eclipse.cdt.core,
|
||||
org.eclipse.cdt.qt.core
|
||||
org.eclipse.cdt.qt.core,
|
||||
org.eclipse.jface.text,
|
||||
org.eclipse.core.resources
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-ActivationPolicy: lazy
|
||||
|
|
|
@ -23,4 +23,16 @@
|
|||
</enablement>
|
||||
</semanticHighlighting>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.cdt.ui.completionProposalComputer"
|
||||
id="QtCompletionProposalComputer"
|
||||
name="Qt Completion Proposal Computer">
|
||||
<completionProposalComputer
|
||||
categoryId="org.eclipse.cdt.ui.parserProposalCategory"
|
||||
class="org.eclipse.cdt.qt.internal.ui.QtCompletionProposalComputer"
|
||||
activate="true">
|
||||
<partition type="__dftl_partition_content_type"/>
|
||||
<partition type="__c_preprocessor"/>
|
||||
</completionProposalComputer>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
|
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* Copyright (c) 2013 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
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.qt.internal.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompletionNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITag;
|
||||
import org.eclipse.cdt.core.dom.ast.tag.ITagReader;
|
||||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
import org.eclipse.cdt.internal.ui.text.contentassist.CCompletionProposal;
|
||||
import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistInvocationContext;
|
||||
import org.eclipse.cdt.internal.ui.text.contentassist.ParsingBasedProposalComputer;
|
||||
import org.eclipse.cdt.internal.ui.text.contentassist.RelevanceConstants;
|
||||
import org.eclipse.cdt.qt.core.QtKeywords;
|
||||
import org.eclipse.cdt.qt.core.QtNature;
|
||||
import org.eclipse.cdt.qt.core.QtPlugin;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.contentassist.ICompletionProposal;
|
||||
|
||||
@SuppressWarnings( "restriction" )
|
||||
public class QtCompletionProposalComputer extends ParsingBasedProposalComputer
|
||||
{
|
||||
private boolean isApplicable( CContentAssistInvocationContext context )
|
||||
{
|
||||
ITranslationUnit tu = context.getTranslationUnit();
|
||||
if( tu == null )
|
||||
return false;
|
||||
|
||||
ICProject cProject = tu.getCProject();
|
||||
if( cProject == null )
|
||||
return false;
|
||||
|
||||
IProject project = cProject.getProject();
|
||||
if( project == null )
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
return project.hasNature( QtNature.ID );
|
||||
}
|
||||
catch( CoreException e )
|
||||
{
|
||||
CUIPlugin.log( e );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean is_QObject_connect( CContentAssistInvocationContext context, IASTCompletionContext astContext, IASTName name )
|
||||
{
|
||||
IASTName connectName = name.getLastName();
|
||||
if( ! QtKeywords.CONNECT.equals( new String( connectName.getSimpleID() ) ) )
|
||||
return false;
|
||||
|
||||
IBinding[] funcBindings = astContext.findBindings( connectName, ! context.isContextInformationStyle() );
|
||||
for( IBinding funcBinding : funcBindings )
|
||||
if( funcBinding instanceof ICPPFunction )
|
||||
{
|
||||
IBinding ownerBinding = ( (ICPPFunction)funcBinding ).getOwner();
|
||||
if( ownerBinding != null && QtKeywords.QOBJECT.equals( ownerBinding.getName() ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class Completion
|
||||
{
|
||||
private final String replacement;
|
||||
private final String display;
|
||||
private final int cursorOffset;
|
||||
|
||||
public static final Completion SIGNAL = new Completion( "SIGNAL()", "SIGNAL(a)", -1 );
|
||||
public static final Completion SLOT = new Completion( "SLOT()", "SLOT(a)", -1 );
|
||||
|
||||
public Completion( String replacement )
|
||||
{
|
||||
this( replacement, replacement, 0 );
|
||||
}
|
||||
|
||||
public Completion( String replacement, String display, int cursorOffset )
|
||||
{
|
||||
this.replacement = replacement;
|
||||
this.display = display;
|
||||
this.cursorOffset = cursorOffset;
|
||||
}
|
||||
|
||||
public ICompletionProposal createProposal( CContentAssistInvocationContext context )
|
||||
{
|
||||
int repLength = replacement.length();
|
||||
int repOffset = context.getInvocationOffset();
|
||||
CCompletionProposal p = new CCompletionProposal( replacement, repOffset, repLength, null, display, RelevanceConstants.DEFAULT_TYPE_RELEVANCE, context.getViewer() );
|
||||
p.setCursorPosition( repLength + cursorOffset );
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if( replacement == null )
|
||||
return super.toString();
|
||||
return replacement + '@' + cursorOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private static interface MethodFilter
|
||||
{
|
||||
public boolean keep( ICPPMethod method );
|
||||
|
||||
public static class Qt
|
||||
{
|
||||
public static final MethodFilter Signal = new MethodFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean keep( ICPPMethod method )
|
||||
{
|
||||
ITagReader tagReader = CCorePlugin.getTagService().findTagReader( method );
|
||||
if( tagReader == null )
|
||||
return false;
|
||||
|
||||
ITag tag = tagReader.getTag( QtPlugin.SIGNAL_SLOT_TAGGER_ID );
|
||||
if( tag == null )
|
||||
return false;
|
||||
|
||||
int result = tag.getByte( 0 );
|
||||
return result != ITag.Fail
|
||||
&& ( ( result & QtPlugin.SignalSlot_Mask_signal ) == QtPlugin.SignalSlot_Mask_signal );
|
||||
}
|
||||
};
|
||||
|
||||
public static final MethodFilter Slot = new MethodFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean keep( ICPPMethod method )
|
||||
{
|
||||
ITagReader tagReader = CCorePlugin.getTagService().findTagReader( method );
|
||||
if( tagReader == null )
|
||||
return false;
|
||||
|
||||
ITag tag = tagReader.getTag( QtPlugin.SIGNAL_SLOT_TAGGER_ID );
|
||||
if( tag == null )
|
||||
return false;
|
||||
|
||||
int result = tag.getByte( 0 );
|
||||
return result != ITag.Fail
|
||||
&& ( ( result & QtPlugin.SignalSlot_Mask_slot ) == QtPlugin.SignalSlot_Mask_slot );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static Iterable<ICPPMethod> filterMethods( final ICPPClassType cls, final MethodFilter filter )
|
||||
{
|
||||
return new Iterable<ICPPMethod>()
|
||||
{
|
||||
@Override
|
||||
public Iterator<ICPPMethod> iterator()
|
||||
{
|
||||
return new Iterator<ICPPMethod>()
|
||||
{
|
||||
private int index = 0;
|
||||
private final ICPPMethod[] methods = cls.getMethods();
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
for( ; index < methods.length; ++index )
|
||||
if( filter.keep( methods[index] ) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public ICPPMethod next() { return methods[index++]; }
|
||||
@Override public void remove() { }
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static String getSignature( ICPPMethod method )
|
||||
{
|
||||
StringBuilder signature = new StringBuilder();
|
||||
|
||||
signature.append( method.getName() );
|
||||
signature.append( '(' );
|
||||
boolean first = true;
|
||||
for( ICPPParameter param : method.getParameters() )
|
||||
{
|
||||
if( first )
|
||||
first = false;
|
||||
else
|
||||
signature.append( ", " );
|
||||
signature.append( ASTTypeUtil.getType( param.getType() ) );
|
||||
}
|
||||
|
||||
signature.append( ')' );
|
||||
return signature.toString();
|
||||
}
|
||||
|
||||
private static void addCompletionsFor( Collection<Completion> completions, IASTInitializerClause init, MethodFilter filter )
|
||||
{
|
||||
if( !( init instanceof ICPPASTInitializerClause ) )
|
||||
return;
|
||||
|
||||
ICPPEvaluation eval = ( (ICPPASTInitializerClause)init ).getEvaluation();
|
||||
if( eval == null )
|
||||
return;
|
||||
|
||||
IType type = eval.getTypeOrFunctionSet( init );
|
||||
while( type instanceof IPointerType )
|
||||
type = ( (IPointerType)type ).getType();
|
||||
|
||||
if( type instanceof ICPPClassType )
|
||||
for( ICPPMethod signal : filterMethods( (ICPPClassType)type, filter ) )
|
||||
completions.add( new Completion( getSignature( signal ) ) );
|
||||
}
|
||||
|
||||
// Copied from org.eclipse.cdt.internal.ui.text.CParameterListValidator
|
||||
private static int indexOfClosingPeer(String code, char left, char right, int pos) {
|
||||
int level= 0;
|
||||
final int length= code.length();
|
||||
while (pos < length) {
|
||||
char ch= code.charAt(pos);
|
||||
if (ch == left) {
|
||||
++level;
|
||||
} else if (ch == right) {
|
||||
if (--level == 0) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copied from org.eclipse.cdt.internal.ui.text.CParameterListValidator
|
||||
private static int[] computeCommaPositions(String code) {
|
||||
final int length= code.length();
|
||||
int pos= 0;
|
||||
List<Integer> positions= new ArrayList<Integer>();
|
||||
positions.add(new Integer(-1));
|
||||
while (pos < length && pos != -1) {
|
||||
char ch= code.charAt(pos);
|
||||
switch (ch) {
|
||||
case ',':
|
||||
positions.add(new Integer(pos));
|
||||
break;
|
||||
case '(':
|
||||
pos= indexOfClosingPeer(code, '(', ')', pos);
|
||||
break;
|
||||
case '<':
|
||||
pos= indexOfClosingPeer(code, '<', '>', pos);
|
||||
break;
|
||||
case '[':
|
||||
pos= indexOfClosingPeer(code, '[', ']', pos);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (pos != -1)
|
||||
pos++;
|
||||
}
|
||||
positions.add(new Integer(length));
|
||||
|
||||
int[] fields= new int[positions.size()];
|
||||
for (int i= 0; i < fields.length; i++)
|
||||
fields[i]= positions.get(i).intValue();
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
||||
private void addConnectParameterCompletions( List<ICompletionProposal> proposals, CContentAssistInvocationContext context, IASTCompletionNode completionNode, String prefix )
|
||||
{
|
||||
IASTName[] names = completionNode.getNames();
|
||||
List<Completion> completions = new LinkedList<Completion>();
|
||||
|
||||
for( IASTName name : names )
|
||||
{
|
||||
// The node isn't properly hooked up, must have backtracked out of this node
|
||||
if( name.getTranslationUnit() == null )
|
||||
continue;
|
||||
|
||||
IASTCompletionContext astContext = name.getCompletionContext();
|
||||
if( astContext == null || ! ( astContext instanceof IASTNode ) )
|
||||
continue;
|
||||
IASTNode astNode = (IASTNode)astContext;
|
||||
|
||||
if( is_QObject_connect( context, astContext, name ) )
|
||||
{
|
||||
int parseOffset = context.getParseOffset();
|
||||
int invocationOffset = context.getInvocationOffset();
|
||||
|
||||
String unparsed = "";
|
||||
try { unparsed = context.getDocument().get( parseOffset, invocationOffset - parseOffset ); }
|
||||
catch( BadLocationException e ) { CCorePlugin.log( e ); }
|
||||
|
||||
if( unparsed.length() > 0 && unparsed.charAt( 0 ) == '(' )
|
||||
unparsed = unparsed.substring( 1 );
|
||||
|
||||
int[] commas = computeCommaPositions( unparsed );
|
||||
switch( commas.length )
|
||||
{
|
||||
case 3:
|
||||
completions.add( Completion.SIGNAL );
|
||||
break;
|
||||
case 5:
|
||||
completions.add( Completion.SLOT );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( astNode.getPropertyInParent() == IASTFunctionCallExpression.ARGUMENT )
|
||||
{
|
||||
IASTNode parent = astNode.getParent();
|
||||
if( ! ( parent instanceof IASTFunctionCallExpression ) )
|
||||
continue;
|
||||
IASTFunctionCallExpression call = (IASTFunctionCallExpression)parent;
|
||||
IASTExpression nameExpr = call.getFunctionNameExpression();
|
||||
if( !( nameExpr instanceof IASTIdExpression ) )
|
||||
continue;
|
||||
IASTIdExpression funcNameIdExpr = (IASTIdExpression)nameExpr;
|
||||
IASTName funcName = funcNameIdExpr.getName();
|
||||
|
||||
if( !is_QObject_connect( context, astContext, funcName ) )
|
||||
continue;
|
||||
|
||||
IASTInitializerClause[] args = call.getArguments();
|
||||
switch( args.length )
|
||||
{
|
||||
case 2:
|
||||
//if( QtKeywords.SIGNAL.equals( prefix ) )
|
||||
addCompletionsFor( completions, args[0], MethodFilter.Qt.Signal );
|
||||
break;
|
||||
case 4:
|
||||
if( QtKeywords.SLOT.equals( prefix ) )
|
||||
addCompletionsFor( completions, args[2], MethodFilter.Qt.Slot );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( Completion completion : completions )
|
||||
{
|
||||
ICompletionProposal proposal = completion.createProposal( context );
|
||||
if( proposal != null )
|
||||
proposals.add( proposal );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ICompletionProposal> computeCompletionProposals( CContentAssistInvocationContext context, IASTCompletionNode completionNode, String prefix ) throws CoreException
|
||||
{
|
||||
if( !isApplicable( context ) )
|
||||
return Collections.emptyList();
|
||||
|
||||
List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();
|
||||
addConnectParameterCompletions( proposals, context, completionNode, prefix );
|
||||
return proposals;
|
||||
}
|
||||
}
|
|
@ -6,18 +6,18 @@ import org.osgi.framework.BundleContext;
|
|||
/**
|
||||
* The activator class controls the plug-in life cycle
|
||||
*/
|
||||
public class Activator extends AbstractUIPlugin {
|
||||
public class QtUIPlugin extends AbstractUIPlugin {
|
||||
|
||||
// The plug-in ID
|
||||
public static final String PLUGIN_ID = "org.eclipse.cdt.qt.ui"; //$NON-NLS-1$
|
||||
|
||||
// The shared instance
|
||||
private static Activator plugin;
|
||||
private static QtUIPlugin plugin;
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public Activator() {
|
||||
public QtUIPlugin() {
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -43,7 +43,7 @@ public class Activator extends AbstractUIPlugin {
|
|||
*
|
||||
* @return the shared instance
|
||||
*/
|
||||
public static Activator getDefault() {
|
||||
public static QtUIPlugin getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue