1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-30 12:25:35 +02:00

bug 290631: Added New Scanner Discovery core functionality from branch

sd90 (Not connected to the rest of the code yet)
This commit is contained in:
Andrew Gvozdev 2012-01-26 15:09:13 -05:00
parent ad2208cc77
commit b4230c0fff
42 changed files with 9391 additions and 37 deletions

View file

@ -12,6 +12,7 @@ Export-Package: org.eclipse.cdt.core.cdescriptor.tests,
org.eclipse.cdt.core.internal.tests;x-internal:=true,
org.eclipse.cdt.core.internal.tests.filesystem.ram,
org.eclipse.cdt.core.language,
org.eclipse.cdt.core.language.settings.providers,
org.eclipse.cdt.core.model.tests,
org.eclipse.cdt.core.parser.tests,
org.eclipse.cdt.core.parser.tests.ast2,

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2010, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Test suite to cover core Language Settings Providers functionality.
*/
public class AllLanguageSettingsProvidersCoreTests {
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
public static Test suite() {
TestSuite suite = new TestSuite(AllLanguageSettingsProvidersCoreTests.class.getName());
suite.addTest(LanguageSettingsExtensionsTests.suite());
suite.addTest(LanguageSettingsManagerTests.suite());
suite.addTest(LanguageSettingsSerializableProviderTests.suite());
suite.addTest(LanguageSettingsPersistenceProjectTests.suite());
return suite;
}
}

View file

@ -0,0 +1,402 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.settings.model.CIncludeFileEntry;
import org.eclipse.cdt.core.settings.model.CIncludePathEntry;
import org.eclipse.cdt.core.settings.model.CLibraryFileEntry;
import org.eclipse.cdt.core.settings.model.CLibraryPathEntry;
import org.eclipse.cdt.core.settings.model.CMacroEntry;
import org.eclipse.cdt.core.settings.model.CMacroFileEntry;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsExtensionManager;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
/**
* Test cases testing LanguageSettingsProvider extensions
*/
public class LanguageSettingsExtensionsTests extends BaseTestCase {
// These should match corresponding entries defined in plugin.xml
/*package*/ static final String EXTENSION_BASE_PROVIDER_ID = "org.eclipse.cdt.core.tests.language.settings.base.provider";
/*package*/ static final String EXTENSION_BASE_PROVIDER_NAME = "Test Plugin Mock Language Settings Base Provider";
/*package*/ static final String EXTENSION_BASE_PROVIDER_LANG_ID = "org.eclipse.cdt.core.tests.language.id";
/*package*/ static final String EXTENSION_BASE_PROVIDER_PARAMETER = "custom parameter";
/*package*/ static final String EXTENSION_BASE_PROVIDER_ATTR_PARAMETER = "parameter";
/*package*/ static final String EXTENSION_CUSTOM_PROVIDER_ID = "org.eclipse.cdt.core.tests.custom.language.settings.provider";
/*package*/ static final String EXTENSION_CUSTOM_PROVIDER_NAME = "Test Plugin Mock Language Settings Provider";
/*package*/ static final String EXTENSION_BASE_SUBCLASS_PROVIDER_ID = "org.eclipse.cdt.core.tests.language.settings.base.provider.subclass";
/*package*/ static final String EXTENSION_BASE_SUBCLASS_PROVIDER_PARAMETER = "custom parameter subclass";
/*package*/ static final String EXTENSION_SERIALIZABLE_PROVIDER_ID = "org.eclipse.cdt.core.tests.custom.serializable.language.settings.provider";
/*package*/ static final String EXTENSION_SERIALIZABLE_PROVIDER_NAME = "Test Plugin Mock Serializable Language Settings Provider";
/*package*/ static final String EXTENSION_SERIALIZABLE_PROVIDER_MISSING_PARAMETER = "parameter";
/*package*/ static final String EXTENSION_EDITABLE_PROVIDER_ID = "org.eclipse.cdt.core.tests.custom.editable.language.settings.provider";
/*package*/ static final String EXTENSION_EDITABLE_PROVIDER_NAME = "Test Plugin Mock Editable Language Settings Provider";
/*package*/ static final ICLanguageSettingEntry EXTENSION_SERIALIZABLE_PROVIDER_ENTRY = new CMacroEntry("MACRO", "value", 0);
/*package*/ static final ICLanguageSettingEntry EXTENSION_EDITABLE_PROVIDER_ENTRY = new CMacroEntry("MACRO", "value", 0);
/*package*/ static final String EXTENSION_REGISTERER_PROVIDER_ID = "org.eclipse.cdt.core.tests.language.settings.listener.registerer.provider";
/*package*/ static final String EXTENSION_USER_PROVIDER_ID = "org.eclipse.cdt.ui.UserLanguageSettingsProvider";
// Arbitrary sample parameters used by the test
private static final String PROVIDER_0 = "test.provider.0.id";
private static final String PROVIDER_NAME_0 = "test.provider.0.name";
private static final String LANG_ID = "test.lang.id";
private static final IFile FILE_0 = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path("/project/path0"));
// Constants used in LanguageSettingsSerializableProvider
private static final String ATTR_ID = LanguageSettingsProvidersSerializer.ATTR_ID;
private static final String ATTR_NAME = LanguageSettingsProvidersSerializer.ATTR_NAME;
private static final String ATTR_CLASS = LanguageSettingsProvidersSerializer.ATTR_CLASS;
/**
* Constructor.
* @param name - name of the test.
*/
public LanguageSettingsExtensionsTests(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
/**
* @return - new TestSuite.
*/
public static TestSuite suite() {
return new TestSuite(LanguageSettingsExtensionsTests.class);
}
/**
* main function of the class.
*
* @param args - arguments
*/
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
/**
* Check that regular {@link ICLanguageSettingsProvider} extension defined in plugin.xml is accessible.
*/
public void testExtension() throws Exception {
{
// test provider defined as an extension
List<ILanguageSettingsProvider> providers = LanguageSettingsManager.getWorkspaceProviders();
List<String> ids = new ArrayList<String>();
for (ILanguageSettingsProvider provider : providers) {
ids.add(provider.getId());
}
assertTrue("extension " + EXTENSION_BASE_PROVIDER_ID + " not found", ids.contains(EXTENSION_BASE_PROVIDER_ID));
}
{
// test provider that is not in the list
ILanguageSettingsProvider providerExt = LanguageSettingsManager.getExtensionProviderCopy("missing.povider", true);
assertNull(providerExt);
}
// this extension provider is not copyable
ILanguageSettingsProvider providerExtCopy = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_BASE_PROVIDER_ID, true);
assertNull(providerExtCopy);
// test raw workspace provider defined as an extension
ILanguageSettingsProvider providerExt = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_BASE_PROVIDER_ID);
assertTrue(LanguageSettingsManager.isWorkspaceProvider(providerExt));
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(providerExt);
assertTrue(rawProvider instanceof LanguageSettingsBaseProvider);
LanguageSettingsBaseProvider provider = (LanguageSettingsBaseProvider)rawProvider;
assertEquals(EXTENSION_BASE_PROVIDER_ID, provider.getId());
assertEquals(EXTENSION_BASE_PROVIDER_NAME, provider.getName());
assertEquals(EXTENSION_BASE_PROVIDER_PARAMETER, provider.getProperty(EXTENSION_BASE_PROVIDER_ATTR_PARAMETER));
// these attributes are not exposed as properties
assertEquals("", provider.getProperty(ATTR_ID));
assertEquals("", provider.getProperty(ATTR_NAME));
assertEquals("", provider.getProperty(ATTR_CLASS));
// attempt to get entries for wrong language
assertNull(provider.getSettingEntries(null, FILE_0, LANG_ID));
// benchmarks matching extension point definition
List<ICLanguageSettingEntry> entriesExt = new ArrayList<ICLanguageSettingEntry>();
entriesExt.add(new CIncludePathEntry("/usr/include/",
ICSettingEntry.BUILTIN
| ICSettingEntry.LOCAL
| ICSettingEntry.RESOLVED
| ICSettingEntry.VALUE_WORKSPACE_PATH
| ICSettingEntry.UNDEFINED
));
entriesExt.add(new CMacroEntry("TEST_DEFINE", "100", 0));
entriesExt.add(new CIncludeFileEntry("/include/file.inc", 0));
entriesExt.add(new CLibraryPathEntry("/usr/lib/", 0));
entriesExt.add(new CLibraryFileEntry("libdomain.a", 0));
entriesExt.add(new CMacroFileEntry("/macro/file.mac", 0));
// retrieve entries from extension point
List<ICLanguageSettingEntry> actual = provider.getSettingEntries(null, FILE_0, EXTENSION_BASE_PROVIDER_LANG_ID);
for (int i=0;i<entriesExt.size();i++) {
assertEquals("i="+i, entriesExt.get(i), actual.get(i));
}
assertEquals(entriesExt.size(), actual.size());
}
/**
* Check that subclassed {@link LanguageSettingsBaseProvider} extension defined in plugin.xml is accessible.
*/
public void testExtensionBaseProviderSubclass() throws Exception {
// get test plugin extension provider
ILanguageSettingsProvider providerExtCopy = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_BASE_SUBCLASS_PROVIDER_ID, true);
assertNull(providerExtCopy);
ILanguageSettingsProvider providerExt = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_BASE_SUBCLASS_PROVIDER_ID);
assertTrue(LanguageSettingsManager.isWorkspaceProvider(providerExt));
// get raw extension provider
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(providerExt);
assertTrue(rawProvider instanceof MockLanguageSettingsBaseProvider);
MockLanguageSettingsBaseProvider provider = (MockLanguageSettingsBaseProvider)rawProvider;
assertEquals(EXTENSION_BASE_SUBCLASS_PROVIDER_ID, provider.getId());
assertEquals(EXTENSION_BASE_SUBCLASS_PROVIDER_PARAMETER, provider.getCustomParameter());
// Test for null languages
assertNull(provider.getLanguageScope());
// benchmarks matching extension point definition
List<ICLanguageSettingEntry> entriesExt = new ArrayList<ICLanguageSettingEntry>();
entriesExt.add(new CIncludePathEntry("/usr/include/", ICSettingEntry.BUILTIN));
// retrieve entries from extension point
List<ICLanguageSettingEntry> actual = provider.getSettingEntries(null, FILE_0, LANG_ID);
for (int i=0;i<entriesExt.size();i++) {
assertEquals("i="+i, entriesExt.get(i), actual.get(i));
}
assertEquals(entriesExt.size(), actual.size());
}
/**
* Make sure extensions contributed through extension point created with proper ID/name.
*/
public void testExtensionCustomProvider() throws Exception {
// get test plugin extension non-default provider
ILanguageSettingsProvider providerExtCopy = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_CUSTOM_PROVIDER_ID, true);
assertNull(providerExtCopy);
ILanguageSettingsProvider providerExt = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_CUSTOM_PROVIDER_ID);
assertTrue(LanguageSettingsManager.isWorkspaceProvider(providerExt));
// get raw extension provider
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(providerExt);
assertTrue(rawProvider instanceof MockLanguageSettingsProvider);
assertEquals(EXTENSION_CUSTOM_PROVIDER_ID, rawProvider.getId());
assertEquals(EXTENSION_CUSTOM_PROVIDER_NAME, rawProvider.getName());
}
/**
* Basic test for {@link LanguageSettingsBaseProvider}.
*/
public void testBaseProvider() throws Exception {
// define benchmarks
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(new CIncludePathEntry("path0", 0));
List<String> languages = new ArrayList<String>(2);
languages.add("bogus.language.id");
languages.add(LANG_ID);
// create base provider
LanguageSettingsBaseProvider provider = new LanguageSettingsBaseProvider(PROVIDER_0, PROVIDER_NAME_0, languages, entries);
{
// attempt to get entries for wrong language
List<ICLanguageSettingEntry> actual = provider.getSettingEntries(null, FILE_0, "wrong.lang.id");
assertNull(actual);
}
{
// retrieve the entries
List<ICLanguageSettingEntry> actual = provider.getSettingEntries(null, FILE_0, LANG_ID);
assertEquals(entries.get(0), actual.get(0));
assertNotSame(entries, actual);
// retrieve languages
List<String> actualLanguageIds = provider.getLanguageScope();
for (String languageId: languages) {
assertTrue(actualLanguageIds.contains(languageId));
}
assertEquals(languages.size(), actualLanguageIds.size());
}
}
/**
* Test ability to configure {@link LanguageSettingsBaseProvider}.
*/
public void testBaseProviderConfigure() throws Exception {
// sample entries
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(new CIncludePathEntry("/usr/include/", 0));
List<String> languages = new ArrayList<String>();
languages.add(LANG_ID);
// create LanguageSettingsBaseProvider
LanguageSettingsBaseProvider provider1 = new LanguageSettingsBaseProvider();
LanguageSettingsBaseProvider provider2 = new LanguageSettingsBaseProvider();
{
// configure provider1
Map<String, String> properties = new HashMap<String, String>();
properties.put("key1", "value1");
properties.put("key2", null);
properties.put("key3", "");
properties.put("key4", "false");
provider1.configureProvider(PROVIDER_0, PROVIDER_NAME_0, languages, entries, properties);
assertEquals(PROVIDER_0, provider1.getId());
assertEquals(PROVIDER_NAME_0, provider1.getName());
assertEquals(languages, provider1.getLanguageScope());
assertEquals(entries, provider1.getSettingEntries(null, null, LANG_ID));
assertEquals("value1", provider1.getProperty("key1"));
assertEquals("", provider1.getProperty("key2"));
assertEquals("", provider1.getProperty("key3"));
assertEquals("false", provider1.getProperty("key4"));
assertEquals(false, provider1.getPropertyBool("key4"));
assertEquals("", provider1.getProperty("keyX"));
assertEquals(false, provider1.getPropertyBool("keyX"));
}
{
// configure provider2
Map<String, String> properties = new HashMap<String, String>();
properties.put("key1", "value1");
provider2.configureProvider(PROVIDER_0, PROVIDER_NAME_0, languages, entries, properties);
assertEquals(PROVIDER_0, provider2.getId());
assertEquals(PROVIDER_NAME_0, provider2.getName());
assertEquals(languages, provider2.getLanguageScope());
assertEquals(entries, provider2.getSettingEntries(null, null, LANG_ID));
assertEquals("value1", provider2.getProperty("key1"));
assertEquals("", provider2.getProperty("keyX"));
assertEquals(false, provider2.getPropertyBool("keyX"));
}
// test equality
assertTrue(provider1.equals(provider2));
}
/**
* {@link LanguageSettingsBaseProvider} is not allowed to be configured twice.
*/
public void testBaseProviderCantReconfigure() throws Exception {
// create LanguageSettingsBaseProvider
LanguageSettingsBaseProvider provider = new LanguageSettingsBaseProvider();
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(new CIncludePathEntry("/usr/include/", 0));
// configure it
provider.configureProvider("test.id", "test.name", null, entries, null);
try {
// attempt to configure it twice should fail
provider.configureProvider("test.id", "test.name", null, entries, null);
fail("LanguageSettingsBaseProvider is not allowed to be configured twice");
} catch (UnsupportedOperationException e) {
}
}
/**
* Test {@link LanguageSettingsSerializableProvider} defined via extension point.
*/
public void testSerializableProvider() throws Exception {
// get test plugin extension for serializable provider
ILanguageSettingsProvider providerExtCopy = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_SERIALIZABLE_PROVIDER_ID, true);
assertNull(providerExtCopy);
ILanguageSettingsProvider providerExt = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_SERIALIZABLE_PROVIDER_ID);
assertTrue(LanguageSettingsManager.isWorkspaceProvider(providerExt));
// get raw extension provider
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(providerExt);
assertTrue(rawProvider instanceof LanguageSettingsSerializableProvider);
LanguageSettingsSerializableProvider provider = (LanguageSettingsSerializableProvider) rawProvider;
assertEquals(null, provider.getLanguageScope());
assertEquals("", provider.getProperty(EXTENSION_SERIALIZABLE_PROVIDER_MISSING_PARAMETER));
List<ICLanguageSettingEntry> expected = new ArrayList<ICLanguageSettingEntry>();
expected.add(EXTENSION_EDITABLE_PROVIDER_ENTRY);
assertEquals(expected, provider.getSettingEntries(null, null, null));
}
/**
* Test {@link ILanguageSettingsEditableProvider} defined via extension point.
*/
public void testEditableProvider() throws Exception {
// Non-editable providers cannot be copied so they are singletons
{
// get test plugin extension for serializable provider
ILanguageSettingsProvider providerExtCopy = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_SERIALIZABLE_PROVIDER_ID, true);
assertNull(providerExtCopy);
ILanguageSettingsProvider providerExt = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_SERIALIZABLE_PROVIDER_ID);
assertTrue(LanguageSettingsManager.isWorkspaceProvider(providerExt));
// get raw extension provider
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(providerExt);
assertTrue(rawProvider instanceof LanguageSettingsSerializableProvider);
assertTrue(LanguageSettingsManager.isEqualExtensionProvider(rawProvider, true));
assertEquals(true, LanguageSettingsExtensionManager.isPreferShared(EXTENSION_SERIALIZABLE_PROVIDER_ID));
}
// Editable providers are retrieved by copy
{
// get extension provider
ILanguageSettingsProvider providerExt = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_EDITABLE_PROVIDER_ID, true);
assertFalse(LanguageSettingsManager.isWorkspaceProvider(providerExt));
assertTrue(providerExt instanceof ILanguageSettingsEditableProvider);
assertTrue(LanguageSettingsManager.isEqualExtensionProvider(providerExt, true));
assertEquals(LanguageSettingsExtensionManager.isPreferShared(EXTENSION_EDITABLE_PROVIDER_ID), false);
// test that different copies are not same
ILanguageSettingsProvider providerExt2 = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_EDITABLE_PROVIDER_ID, true);
assertNotSame(providerExt, providerExt2);
assertEquals(providerExt, providerExt2);
// test that workspace provider is not the same as extension provider
ILanguageSettingsProvider providerWsp = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_EDITABLE_PROVIDER_ID);
ILanguageSettingsProvider providerWspRaw = LanguageSettingsManager.getRawProvider(providerWsp);
assertNotSame(providerExt, providerWspRaw);
assertEquals(providerExt, providerWspRaw);
assertTrue(LanguageSettingsManager.isEqualExtensionProvider(providerWspRaw, true));
}
// Test shallow copy
{
ILanguageSettingsProvider provider = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_EDITABLE_PROVIDER_ID, true);
assertNotNull(provider);
assertTrue(provider instanceof ILanguageSettingsEditableProvider);
ILanguageSettingsProvider providerShallow = LanguageSettingsManager.getExtensionProviderCopy(EXTENSION_EDITABLE_PROVIDER_ID, false);
assertNotNull(providerShallow);
assertTrue(providerShallow instanceof ILanguageSettingsEditableProvider);
assertFalse(provider.equals(providerShallow));
assertFalse(LanguageSettingsManager.isEqualExtensionProvider(providerShallow, true));
assertTrue(LanguageSettingsManager.isEqualExtensionProvider(providerShallow, false));
}
}
}

View file

@ -0,0 +1,608 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.AbstractExecutableExtensionBase;
import org.eclipse.cdt.core.settings.model.CIncludePathEntry;
import org.eclipse.cdt.core.settings.model.CMacroEntry;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.testplugin.CModelMock;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
/**
* Test cases testing {@link LanguageSettingsManager} utility methods.
*/
public class LanguageSettingsManagerTests extends BaseTestCase {
// Those should match ids of plugin extensions defined in plugin.xml
private static final String EXTENSION_SERIALIZABLE_PROVIDER_ID = LanguageSettingsExtensionsTests.EXTENSION_SERIALIZABLE_PROVIDER_ID;
private static final String EXTENSION_SERIALIZABLE_PROVIDER_NAME = LanguageSettingsExtensionsTests.EXTENSION_SERIALIZABLE_PROVIDER_NAME;
private static final String EXTENSION_EDITABLE_PROVIDER_ID = LanguageSettingsExtensionsTests.EXTENSION_EDITABLE_PROVIDER_ID;
// Arbitrary sample parameters used by the test case
private static final String PROVIDER_0 = "test.provider.0.id";
private static final String PROVIDER_1 = "test.provider.1.id";
private static final String PROVIDER_2 = "test.provider.2.id";
private static final String PROVIDER_NAME_0 = "test.provider.0.name";
private static final String PROVIDER_NAME_1 = "test.provider.1.name";
private static final String PROVIDER_NAME_2 = "test.provider.2.name";
private static final String CFG_ID = "test.configuration.id";
private static final String LANG_ID = "test.lang.id";
private static final IFile FILE_0 = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path("/project/path0"));
/**
* Mock configuration description.
*/
class MockConfigurationDescription extends CModelMock.DummyCConfigurationDescription implements ILanguageSettingsProvidersKeeper {
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
String[] defaultProvidersIds = null;
public MockConfigurationDescription(String id) {
super(id);
}
@Override
public void setLanguageSettingProviders(List<ILanguageSettingsProvider> providers) {
this.providers = new ArrayList<ILanguageSettingsProvider>(providers);
}
@Override
public List<ILanguageSettingsProvider> getLanguageSettingProviders() {
return providers;
}
@Override
public void setDefaultLanguageSettingsProvidersIds(String[] ids) {
defaultProvidersIds = ids;
}
@Override
public String[] getDefaultLanguageSettingsProvidersIds() {
return defaultProvidersIds;
}
}
/**
* Mock language sttings provider.
*/
private class MockProvider extends AbstractExecutableExtensionBase implements ILanguageSettingsProvider {
private List<ICLanguageSettingEntry> entries;
public MockProvider(String id, String name, List<ICLanguageSettingEntry> entries) {
super(id, name);
this.entries = entries;
}
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
return entries;
}
}
/**
* Constructor.
* @param name - name of the test.
*/
public LanguageSettingsManagerTests(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
LanguageSettingsManager.setWorkspaceProviders(null);
super.tearDown(); // includes ResourceHelper cleanup
}
/**
* @return - new TestSuite.
*/
public static TestSuite suite() {
return new TestSuite(LanguageSettingsManagerTests.class);
}
/**
* main function of the class.
*
* @param args - arguments
*/
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
/**
* Test ILanguageSettingsProvidersKeeper API (getters and setters).
*/
public void testConfigurationDescription_Providers() throws Exception {
// mock configuration description
MockConfigurationDescription cfgDescription = new MockConfigurationDescription(CFG_ID);
// set providers
ILanguageSettingsProvider provider1 = new MockProvider(PROVIDER_1, PROVIDER_NAME_1, null);
ILanguageSettingsProvider provider2 = new MockProvider(PROVIDER_2, PROVIDER_NAME_2, null);
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(provider1);
providers.add(provider2);
cfgDescription.setLanguageSettingProviders(providers);
// get providers
List<ILanguageSettingsProvider> actual = cfgDescription.getLanguageSettingProviders();
assertEquals(provider1, actual.get(0));
assertEquals(provider2, actual.get(1));
assertEquals(providers.size(), actual.size());
assertNotSame(actual, providers);
// set default providers
String[] defaultProviders = { PROVIDER_0, PROVIDER_1 };
cfgDescription.setDefaultLanguageSettingsProvidersIds(defaultProviders);
// get default providers
assertEquals(defaultProviders, cfgDescription.getDefaultLanguageSettingsProvidersIds());
}
/**
* Test various cases of ill-defined providers.
*/
public void testRudeProviders() throws Exception {
// mock configuration description
MockConfigurationDescription cfgDescription = new MockConfigurationDescription(CFG_ID);
// set impolite provider returning null by getSettingEntries()
ILanguageSettingsProvider providerNull = new MockProvider(PROVIDER_1, PROVIDER_NAME_1, null);
{
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(providerNull);
cfgDescription.setLanguageSettingProviders(providers);
}
// use provider returning null, no exception should be recorded
{
List<ICLanguageSettingEntry> actual = LanguageSettingsManager
.getSettingEntriesUpResourceTree(providerNull, cfgDescription, FILE_0, LANG_ID);
assertNotNull(actual);
assertEquals(0, actual.size());
}
{
List<ICLanguageSettingEntry> actual = LanguageSettingsProvidersSerializer
.getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, 0);
assertNotNull(actual);
assertEquals(0, actual.size());
}
// set impolite provider returning null in getSettingEntries() array
ILanguageSettingsProvider providerNull_2 = new MockProvider(PROVIDER_2, PROVIDER_NAME_2,
new ArrayList<ICLanguageSettingEntry>() {
{ // init via static initializer
add(null);
}
});
{
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(providerNull);
cfgDescription.setLanguageSettingProviders(providers);
}
// use provider returning null as item in array
{
List<ICLanguageSettingEntry> actual = LanguageSettingsManager
.getSettingEntriesUpResourceTree(providerNull_2, cfgDescription, FILE_0, LANG_ID);
assertNotNull(actual);
assertEquals(1, actual.size());
}
{
List<ICLanguageSettingEntry> actual = LanguageSettingsProvidersSerializer
.getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, 0);
assertNotNull(actual);
assertEquals(0, actual.size());
}
// use careless provider causing an exception
{
setExpectedNumberOfLoggedNonOKStatusObjects(1);
ILanguageSettingsProvider providerNPE = new MockProvider(PROVIDER_1, PROVIDER_NAME_1, null) {
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
throw new NullPointerException("Can you handle me?");
}
};
try {
List<ICLanguageSettingEntry> actual = LanguageSettingsManager
.getSettingEntriesUpResourceTree(providerNPE, null, null, LANG_ID);
assertNotNull(actual);
assertEquals(0, actual.size());
} catch (Throwable e) {
fail("Exceptions are expected to be swallowed (after logging) but got " + e);
}
}
}
/**
* Test assigning and retrieving providers from a configuration.
*/
public void testProvider_Basic() throws Exception {
final MockConfigurationDescription modelCfgDescription = new MockConfigurationDescription(CFG_ID);
final List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(new CIncludePathEntry("path0", 0));
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
// define provider returning entries when configuration id matches and null otherwise
ILanguageSettingsProvider providerYes = new MockProvider(PROVIDER_0, PROVIDER_NAME_0, null) {
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
if (cfgDescription.getId().equals(modelCfgDescription.getId())) {
return entries;
}
return null;
}
};
providers.add(providerYes);
// define provider returning entries when configuration id does NOT match and null otherwise
ILanguageSettingsProvider providerNo = new MockProvider(PROVIDER_1, PROVIDER_NAME_1, null) {
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
if (cfgDescription!= null && !cfgDescription.getId().equals(modelCfgDescription.getId())) {
return entries;
}
return null;
}
};
providers.add(providerNo);
modelCfgDescription.setLanguageSettingProviders(providers);
{
// retrieve the entries with provider returning the given list
List<ICLanguageSettingEntry> actual = LanguageSettingsManager
.getSettingEntriesUpResourceTree(providerYes, modelCfgDescription, FILE_0, LANG_ID);
assertEquals(entries.get(0), actual.get(0));
assertEquals(entries.size(), actual.size());
}
{
// retrieve the entries with provider returning empty list
List<ICLanguageSettingEntry> actual = LanguageSettingsManager
.getSettingEntriesUpResourceTree(providerNo, modelCfgDescription, FILE_0, LANG_ID);
assertEquals(0, actual.size());
}
}
/**
* Test regular functionality with a few providers.
*/
public void testProvider_Regular() throws Exception {
MockConfigurationDescription cfgDescription = new MockConfigurationDescription(CFG_ID);
// create couple of providers
List<ICLanguageSettingEntry> entries1 = new ArrayList<ICLanguageSettingEntry>();
entries1.add(new CIncludePathEntry("value1", 1));
entries1.add(new CIncludePathEntry("value2", 2));
List<ICLanguageSettingEntry> entries2 = new ArrayList<ICLanguageSettingEntry>();
entries2.add(new CIncludePathEntry("value1", 1));
entries2.add(new CIncludePathEntry("value2", 2));
entries2.add(new CIncludePathEntry("value3", 2));
ILanguageSettingsProvider provider1 = new MockProvider(PROVIDER_1, PROVIDER_NAME_1, entries1);
ILanguageSettingsProvider provider2 = new MockProvider(PROVIDER_2, PROVIDER_NAME_2, entries2);
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(provider1);
providers.add(provider2);
cfgDescription.setLanguageSettingProviders(providers);
{
// retrieve the entries for provider-1
List<ICLanguageSettingEntry> actual = LanguageSettingsManager
.getSettingEntriesUpResourceTree(provider1, cfgDescription, FILE_0, LANG_ID);
assertNotSame(entries1, actual);
ICLanguageSettingEntry[] entriesArray = entries1.toArray(new ICLanguageSettingEntry[0]);
ICLanguageSettingEntry[] actualArray = actual.toArray(new ICLanguageSettingEntry[0]);
for (int i=0;i<entries1.size();i++) {
assertEquals("i="+i, entriesArray[i], actualArray[i]);
}
assertEquals(entries1.size(), actual.size());
}
{
// retrieve the entries for provider-2
List<ICLanguageSettingEntry> actual = LanguageSettingsManager
.getSettingEntriesUpResourceTree(provider2, cfgDescription, FILE_0, LANG_ID);
assertNotSame(entries2, actual);
ICLanguageSettingEntry[] entriesArray = entries2.toArray(new ICLanguageSettingEntry[0]);
ICLanguageSettingEntry[] actualArray = actual.toArray(new ICLanguageSettingEntry[0]);
for (int i=0;i<entries2.size();i++) {
assertEquals("i="+i, entriesArray[i], actualArray[i]);
}
assertEquals(entries2.size(), actual.size());
}
}
/**
* Test ability to get entries by kind.
*/
public void testEntriesByKind_Regular() throws Exception {
MockConfigurationDescription cfgDescription = new MockConfigurationDescription(CFG_ID);
// contribute the entries
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(new CIncludePathEntry("path0", 0));
entries.add(new CMacroEntry("MACRO0", "value0",0));
entries.add(new CIncludePathEntry("path1", 0));
entries.add(new CMacroEntry("MACRO1", "value1",0));
entries.add(new CIncludePathEntry("path2", 0));
ILanguageSettingsProvider provider0 = new MockProvider(PROVIDER_0, PROVIDER_NAME_0, entries);
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(provider0);
cfgDescription.setLanguageSettingProviders(providers);
// retrieve entries by kind
List<ICLanguageSettingEntry> includes = LanguageSettingsProvidersSerializer
.getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH);
assertEquals(new CIncludePathEntry("path0", 0),includes.get(0));
assertEquals(new CIncludePathEntry("path1", 0),includes.get(1));
assertEquals(new CIncludePathEntry("path2", 0),includes.get(2));
assertEquals(3, includes.size());
List<ICLanguageSettingEntry> macros = LanguageSettingsProvidersSerializer
.getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.MACRO);
assertEquals(new CMacroEntry("MACRO0", "value0",0), macros.get(0));
assertEquals(new CMacroEntry("MACRO1", "value1",0), macros.get(1));
assertEquals(2, macros.size());
}
/**
* Test how conflicting entries are resolved.
*/
public void testEntriesByKind_ConflictingEntries() throws Exception {
MockConfigurationDescription cfgDescription = new MockConfigurationDescription(CFG_ID);
// contribute the entries
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(new CIncludePathEntry("path", ICSettingEntry.BUILTIN));
entries.add(new CIncludePathEntry("path", ICSettingEntry.UNDEFINED));
entries.add(new CIncludePathEntry("path", 0));
ILanguageSettingsProvider provider0 = new MockProvider(PROVIDER_0, PROVIDER_NAME_0, entries);
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(provider0);
cfgDescription.setLanguageSettingProviders(providers);
// retrieve entries by kind, only first entry should be returned
List<ICLanguageSettingEntry> includes = LanguageSettingsProvidersSerializer.getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH);
assertEquals(1, includes.size());
assertEquals(entries.get(0),includes.get(0));
}
/**
* Check handling of {@link ICSettingEntry#UNDEFINED} flag.
*/
public void testEntriesByKind_Undefined() throws Exception {
MockConfigurationDescription cfgDescription = new MockConfigurationDescription(CFG_ID);
// contribute the entries
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(new CIncludePathEntry("path", ICSettingEntry.UNDEFINED));
entries.add(new CIncludePathEntry("path", 0));
ILanguageSettingsProvider provider0 = new MockProvider(PROVIDER_0, PROVIDER_NAME_0, entries);
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(provider0);
cfgDescription.setLanguageSettingProviders(providers);
// retrieve entries by kind, no entries should be returned
List<ICLanguageSettingEntry> includes = LanguageSettingsProvidersSerializer
.getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH);
assertEquals(0, includes.size());
}
/**
* Check handling of local vs. system entries, see {@link ICSettingEntry#LOCAL} flag.
*/
public void testEntriesByKind_LocalAndSystem() throws Exception {
MockConfigurationDescription cfgDescription = new MockConfigurationDescription(CFG_ID);
// contribute the entries
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
CIncludePathEntry localIncludeEntry = new CIncludePathEntry("path-local", ICSettingEntry.LOCAL);
CIncludePathEntry systemIncludeEntry = new CIncludePathEntry("path-system", 0);
entries.add(localIncludeEntry);
entries.add(systemIncludeEntry);
ILanguageSettingsProvider provider0 = new MockProvider(PROVIDER_0, PROVIDER_NAME_0, entries);
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(provider0);
cfgDescription.setLanguageSettingProviders(providers);
{
// retrieve local entries
List<ICLanguageSettingEntry> includes = LanguageSettingsProvidersSerializer
.getLocalSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH);
assertEquals(localIncludeEntry, includes.get(0));
assertEquals(1, includes.size());
}
{
// retrieve system entries
List<ICLanguageSettingEntry> includes = LanguageSettingsProvidersSerializer
.getSystemSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH);
assertEquals(systemIncludeEntry, includes.get(0));
assertEquals(1, includes.size());
}
{
// retrieve both local and system
List<ICLanguageSettingEntry> includes = LanguageSettingsProvidersSerializer
.getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH);
assertEquals(entries.get(0), includes.get(0));
assertEquals(entries.get(1), includes.get(1));
assertEquals(2, includes.size());
}
}
/**
* Test conflicting entries contributed by different providers.
*/
public void testEntriesByKind_ConflictingProviders() throws Exception {
MockConfigurationDescription cfgDescription = new MockConfigurationDescription(CFG_ID);
// contribute the entries
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
// contribute the higher ranked entries
List<ICLanguageSettingEntry> entriesHigh = new ArrayList<ICLanguageSettingEntry>();
entriesHigh.add(new CIncludePathEntry("path0", ICSettingEntry.RESOLVED));
entriesHigh.add(new CIncludePathEntry("path1", 0));
entriesHigh.add(new CIncludePathEntry("path2", ICSettingEntry.UNDEFINED));
ILanguageSettingsProvider highRankProvider = new MockProvider(PROVIDER_2, PROVIDER_NAME_2, entriesHigh);
providers.add(highRankProvider);
// contribute the lower ranked entries
List<ICLanguageSettingEntry> entriesLow = new ArrayList<ICLanguageSettingEntry>();
entriesLow.add(new CIncludePathEntry("path0", ICSettingEntry.BUILTIN));
entriesLow.add(new CIncludePathEntry("path1", ICSettingEntry.UNDEFINED));
entriesLow.add(new CIncludePathEntry("path2", 0));
entriesLow.add(new CIncludePathEntry("path3", 0));
ILanguageSettingsProvider lowRankProvider = new MockProvider(PROVIDER_1, PROVIDER_NAME_1, entriesLow);
providers.add(lowRankProvider);
cfgDescription.setLanguageSettingProviders(providers);
// retrieve entries by kind
List<ICLanguageSettingEntry> includes = LanguageSettingsProvidersSerializer
.getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH);
// path0 is taken from higher priority provider
assertEquals(entriesHigh.get(0),includes.get(0));
// path1 disablement by lower priority provider is ignored
assertEquals(entriesHigh.get(1),includes.get(1));
// path2 is removed because of DISABLED flag of high priority provider
// path3 gets there from low priority provider
assertEquals(entriesLow.get(3),includes.get(2));
assertEquals(3, includes.size());
}
/**
* Test a workspace provider basics.
*/
public void testWorkspaceProvider_Basic() throws Exception {
// get workspace provider
ILanguageSettingsProvider provider = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_SERIALIZABLE_PROVIDER_ID);
assertEquals(EXTENSION_SERIALIZABLE_PROVIDER_ID, provider.getId());
assertEquals(EXTENSION_SERIALIZABLE_PROVIDER_NAME, provider.getName());
// get raw provider
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
assertEquals(EXTENSION_SERIALIZABLE_PROVIDER_ID, rawProvider.getId());
assertEquals(EXTENSION_SERIALIZABLE_PROVIDER_NAME, rawProvider.getName());
assertTrue(rawProvider instanceof LanguageSettingsSerializableProvider);
// assert they are not the same object
assertNotSame(provider, rawProvider);
{
// make sure entries are the same
List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null);
assertEquals(1, entries.size()); // defined in the extension
List<ICLanguageSettingEntry> rawEntries = rawProvider.getSettingEntries(null, null, null);
assertEquals(entries, rawEntries);
}
{
// set new entries to the raw provider
List<ICLanguageSettingEntry> newEntries = new ArrayList<ICLanguageSettingEntry>();
newEntries.add(new CIncludePathEntry("path0", 0));
newEntries.add(new CIncludePathEntry("path1", 0));
((LanguageSettingsSerializableProvider)rawProvider).setSettingEntries(null, null, null, newEntries);
// check that the workspace provider gets them too
List<ICLanguageSettingEntry> newRawEntries = rawProvider.getSettingEntries(null, null, null);
assertEquals(newEntries, newRawEntries);
assertEquals(2, newEntries.size());
}
}
/**
* Test workspace providers equality.
*/
public void testWorkspaceProvider_Equals() throws Exception {
ILanguageSettingsProvider providerA = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_SERIALIZABLE_PROVIDER_ID);
ILanguageSettingsProvider providerB = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_SERIALIZABLE_PROVIDER_ID);
assertEquals(providerA, providerB);
}
/**
* Test ability to replace underlying raw provider.
*/
public void testWorkspaceProvider_ReplaceRawProvider() throws Exception {
// get sample workspace provider
ILanguageSettingsProvider provider = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_EDITABLE_PROVIDER_ID);
{
// check on its entries (1 predefined entry via extension point)
List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null);
assertEquals(1, entries.size()); // defined in the extension
}
// define new entries for the raw provider
List<ICLanguageSettingEntry> newEntries = new ArrayList<ICLanguageSettingEntry>();
newEntries.add(new CIncludePathEntry("path0", 0));
newEntries.add(new CIncludePathEntry("path1", 0));
newEntries.add(new CIncludePathEntry("path2", 0));
{
// replace raw provider
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
LanguageSettingsSerializableProvider newRawProvider = new LanguageSettingsSerializableProvider(EXTENSION_EDITABLE_PROVIDER_ID, PROVIDER_NAME_0);
newRawProvider.setSettingEntries(null, null, null, newEntries);
providers.add(newRawProvider);
LanguageSettingsManager.setWorkspaceProviders(providers);
}
{
// check that provider provides the new entries
List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null);
assertEquals(newEntries.size(), entries.size());
assertEquals(newEntries, entries);
}
}
/**
* Test ability to be called with workspace provider as well (NOOP).
*/
public void testWorkspaceProvider_ReplaceWithWorkspaceProvider() throws Exception {
// get sample workspace provider
ILanguageSettingsProvider provider = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_SERIALIZABLE_PROVIDER_ID);
ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider);
assertNotSame(provider, rawProvider);
// attempt to "replace" with workspace provider (which is a wrapper around raw provider), should be NOOP
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
providers.add(provider);
LanguageSettingsManager.setWorkspaceProviders(providers);
ILanguageSettingsProvider newRawProvider = LanguageSettingsManager.getRawProvider(provider);
assertSame(rawProvider, newRawProvider);
// check for no side effect
assertSame(provider, providers.get(0));
}
}

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
/**
* Mock of {@link LanguageSettingsBaseProvider} for testing.
*/
public class MockLanguageSettingsBaseProvider extends LanguageSettingsBaseProvider {
private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$
/**
* @return the custom parameter defined in the extension in {@code plugin.xml}.
*/
public String getCustomParameter() {
return getProperty(ATTR_PARAMETER);
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
/**
* Mock of {@link ILanguageSettingsEditableProvider} for testing.
*/
public class MockLanguageSettingsEditableProvider extends LanguageSettingsSerializableProvider implements ILanguageSettingsEditableProvider {
public MockLanguageSettingsEditableProvider() {
super();
}
public MockLanguageSettingsEditableProvider(String id, String name) {
super(id, name);
}
@Override
public MockLanguageSettingsEditableProvider cloneShallow() throws CloneNotSupportedException {
return (MockLanguageSettingsEditableProvider) super.cloneShallow();
}
@Override
public MockLanguageSettingsEditableProvider clone() throws CloneNotSupportedException {
return (MockLanguageSettingsEditableProvider) super.clone();
}
}

View file

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.List;
import org.eclipse.cdt.core.AbstractExecutableExtensionBase;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.core.resources.IResource;
/**
* Mock of {@link ILanguageSettingsProvider} for testing.
*/
public class MockLanguageSettingsProvider extends AbstractExecutableExtensionBase implements ILanguageSettingsProvider {
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
return null;
}
}

View file

@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2009, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
/**
* Mock of {@link LanguageSettingsSerializableProvider} for testing.
*/
public class MockLanguageSettingsSerializableProvider extends LanguageSettingsSerializableProvider {
public MockLanguageSettingsSerializableProvider() {
super();
}
public MockLanguageSettingsSerializableProvider(String id, String name) {
super(id, name);
}
}

View file

@ -0,0 +1,104 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.core.runtime.Assert;
/**
* Mock Language Settings Provider that keeps count how many times it has been registered.
*/
public class MockListenerRegisterer extends LanguageSettingsSerializableProvider implements ILanguageSettingsEditableProvider, ICListenerAgent {
private static MockListenerManager mockListenerManager = new MockListenerManager();
private static class MockListenerManager {
private class ListenerCount {
private MockListenerRegisterer listener;
private int count;
public ListenerCount(MockListenerRegisterer l, int cnt) {
listener = l;
count = cnt;
}
}
private List<ListenerCount> register = new ArrayList<ListenerCount>();
public void registerListener(MockListenerRegisterer listener) {
for (ListenerCount lc : register) {
if (lc.listener == listener) {
lc.count++;
return;
}
}
register.add(new ListenerCount(listener, 1));
}
public void unregisterListener(MockListenerRegisterer listener) {
for (ListenerCount lc : register) {
if (lc.listener == listener) {
lc.count--;
Assert.isTrue(lc.count>=0);
return;
}
}
// attempt to unregister non-registered listener
Assert.isTrue(false);
}
/**
* Note that that count includes all listeners with that id.
*/
public int getCount(String id) {
int count = 0;
for (ListenerCount lc : register) {
if (lc.listener.getId().equals(id)) {
count = count + lc.count;
}
}
return count;
}
}
public MockListenerRegisterer() {
super();
}
public MockListenerRegisterer(String id, String name) {
super(id, name);
}
@Override
public void registerListener(ICConfigurationDescription cfgDescription) {
mockListenerManager.registerListener(this);
}
@Override
public void unregisterListener() {
mockListenerManager.unregisterListener(this);
}
@Override
public MockListenerRegisterer cloneShallow() throws CloneNotSupportedException {
return (MockListenerRegisterer) super.cloneShallow();
}
@Override
public MockListenerRegisterer clone() throws CloneNotSupportedException {
return (MockListenerRegisterer) super.clone();
}
public static int getCount(String id) {
return mockListenerManager.getCount(id);
}
}

View file

@ -14,6 +14,7 @@ package org.eclipse.cdt.core.model.tests;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.language.settings.providers.AllLanguageSettingsProvidersCoreTests;
import org.eclipse.cdt.core.settings.model.AllCProjectDescriptionTests;
import org.eclipse.cdt.core.settings.model.PathSettingsContainerTests;
@ -60,6 +61,8 @@ public class AllCoreTests {
suite.addTest(AsmModelBuilderTest.suite());
suite.addTest(CModelBuilderBugsTest.suite());
suite.addTest(Bug311189.suite());
suite.addTest(AllLanguageSettingsProvidersCoreTests.suite());
return suite;
}

View file

@ -183,6 +183,168 @@
scheme="EFSExtensionProviderTestsScheme">
</EFSExtensionProvider>
</extension>
<extension
point="org.eclipse.cdt.core.LanguageSettingsProvider">
<!-- uncomment to test message about missing class in the log -->
<!--
<provider
class="org.eclipse.cdt.core.language.settings.providers.MissingClass"
id="org.eclipse.cdt.core.tests.missing.language.settings.provider"
name="Test Plugin Missing Language Settings Provider">
</provider>
-->
<provider
id="org.eclipse.cdt.core.tests.language.settings.base.provider"
name="Test Plugin Mock Language Settings Base Provider"
parameter="custom parameter">
<language-scope
id="org.eclipse.cdt.core.tests.language.id">
</language-scope>
<entry
kind="includePath"
name="/usr/include/">
<flag
value="BUILTIN">
</flag>
<flag
value="LOCAL">
</flag>
<flag
value="VALUE_WORKSPACE_PATH">
</flag>
<flag
value="RESOLVED">
</flag>
<flag
value="UNDEFINED">
</flag>
</entry>
<entry
kind="macro"
name="TEST_DEFINE"
value="100">
</entry>
<entry
kind="includeFile"
name="/include/file.inc">
</entry>
<entry
kind="libraryPath"
name="/usr/lib/">
</entry>
<entry
kind="libraryFile"
name="libdomain.a">
</entry>
<entry
kind="macroFile"
name="/macro/file.mac">
</entry>
</provider>
<provider
class="org.eclipse.cdt.core.language.settings.providers.MockLanguageSettingsProvider"
id="org.eclipse.cdt.core.tests.custom.language.settings.provider"
name="Test Plugin Mock Language Settings Provider">
</provider>
<provider
class="org.eclipse.cdt.core.language.settings.providers.MockLanguageSettingsSerializableProvider"
id="org.eclipse.cdt.core.tests.custom.serializable.language.settings.provider"
name="Test Plugin Mock Serializable Language Settings Provider">
<entry
kind="macro"
name="MACRO"
value="value">
</entry>
</provider>
<provider
class="org.eclipse.cdt.core.language.settings.providers.MockLanguageSettingsEditableProvider"
id="org.eclipse.cdt.core.tests.custom.editable.language.settings.provider"
name="Test Plugin Mock Editable Language Settings Provider"
prefer-non-shared="true">
<entry
kind="macro"
name="MACRO"
value="value">
</entry>
</provider>
<provider
class="org.eclipse.cdt.core.language.settings.providers.MockLanguageSettingsBaseProvider"
id="org.eclipse.cdt.core.tests.language.settings.base.provider.subclass"
name="Test Plugin Mock Base Provider Subclass"
parameter="custom parameter subclass">
<entry
kind="includePath"
name="/usr/include/">
<flag
value="BUILTIN">
</flag>
</entry>
</provider>
<provider
class="org.eclipse.cdt.core.language.settings.providers.MockListenerRegisterer"
id="org.eclipse.cdt.core.tests.language.settings.listener.registerer.provider"
name="Test Plugin Mock Listener Language Settings Provider">
<entry
kind="macro"
name="MACRO"
value="value">
</entry>
</provider>
<provider
id="org.eclipse.cdt.core.tests.language.settings"
name="Test Plugin Setting Entries UI Tester">
<language-scope
id="org.eclipse.cdt.core.gcc">
</language-scope>
<entry
kind="includePath"
name="/test/include/path">
</entry>
<entry
kind="includePath"
name="/test/workspace/include/path">
<flag
value="VALUE_WORKSPACE_PATH">
</flag>
</entry>
<entry
kind="includePath"
name="/test/builtin/include/path">
<flag
value="BUILTIN">
</flag>
</entry>
<entry
kind="macro"
name="MACRO"
value="macro">
</entry>
<entry
kind="macro"
name="BUILTIN_MACRO"
value="builtin-macro">
<flag
value="BUILTIN">
</flag>
</entry>
<entry
kind="includeFile"
name="/test/includes/file">
</entry>
<entry
kind="libraryPath"
name="/test/library/path">
</entry>
<entry
kind="libraryFile"
name="/test/library/file">
</entry>
<entry
kind="macroFile"
name="/test/macro/file">
</entry>
</provider>
</extension>
<extension
point="org.eclipse.cdt.core.RefreshExclusionFactory">
<exclusionFactory

View file

@ -0,0 +1,494 @@
/*******************************************************************************
* Copyright (c) 2010, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.testplugin;
import java.util.Map;
import org.eclipse.cdt.core.cdtvariables.ICdtVariablesContributor;
import org.eclipse.cdt.core.settings.model.CConfigurationStatus;
import org.eclipse.cdt.core.settings.model.ICBuildSetting;
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICExternalSetting;
import org.eclipse.cdt.core.settings.model.ICFileDescription;
import org.eclipse.cdt.core.settings.model.ICFolderDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSetting;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.core.settings.model.ICSettingContainer;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingObject;
import org.eclipse.cdt.core.settings.model.ICSourceEntry;
import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.core.settings.model.ICTargetPlatformSetting;
import org.eclipse.cdt.core.settings.model.WriteAccessException;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.QualifiedName;
/**
* Collection of mock classes for testing
*/
public class CModelMock {
/**
* Dummy implementation of ICProjectDescription for testing.
* Feel free to override the methods you are interested to mock.
*/
public static class DummyCProjectDescription implements ICProjectDescription {
@Override
public ICSettingObject[] getChildSettings() {
return null;
}
@Override
public String getId() {
return null;
}
@Override
public String getName() {
return null;
}
@Override
public int getType() {
return 0;
}
@Override
public boolean isValid() {
return false;
}
@Override
public ICConfigurationDescription getConfiguration() {
return null;
}
@Override
public ICSettingContainer getParent() {
return null;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public ICStorageElement getStorage(String id, boolean create)
throws CoreException {
return null;
}
@Override
public void removeStorage(String id) throws CoreException {
}
@Override
public ICStorageElement importStorage(String id, ICStorageElement el)
throws UnsupportedOperationException, CoreException {
return null;
}
@Override
public void setReadOnly(boolean readOnly, boolean keepModify) {
}
@Override
public int getConfigurationRelations() {
return 0;
}
@Override
public void setConfigurationRelations(int status) {
}
@Override
public void useDefaultConfigurationRelations() {
}
@Override
public boolean isDefaultConfigurationRelations() {
return false;
}
@Override
public ICConfigurationDescription[] getConfigurations() {
return null;
}
@Override
public ICConfigurationDescription getActiveConfiguration() {
return null;
}
@Override
public void setActiveConfiguration(ICConfigurationDescription cfg)
throws WriteAccessException {
}
@Override
public ICConfigurationDescription createConfiguration(String id,
String name, ICConfigurationDescription base)
throws CoreException, WriteAccessException {
return null;
}
@Override
public ICConfigurationDescription createConfiguration(
String buildSystemId, CConfigurationData data)
throws CoreException, WriteAccessException {
return null;
}
@Override
public ICConfigurationDescription getConfigurationByName(String name) {
return null;
}
@Override
public ICConfigurationDescription getConfigurationById(String id) {
return null;
}
@Override
public void removeConfiguration(String name)
throws WriteAccessException {
}
@Override
public void removeConfiguration(ICConfigurationDescription cfg)
throws WriteAccessException {
}
@Override
public IProject getProject() {
return null;
}
@Override
public boolean isModified() {
return false;
}
@Override
public Object getSessionProperty(QualifiedName name) {
return null;
}
@Override
public void setSessionProperty(QualifiedName name, Object value) {
}
@Override
public ICConfigurationDescription getDefaultSettingConfiguration() {
return null;
}
@Override
public void setDefaultSettingConfiguration(
ICConfigurationDescription cfg) {
}
@Override
public boolean isCdtProjectCreating() {
return false;
}
@Override
public void setCdtProjectCreated() {
}
}
/**
* Dummy implementation of ICConfigurationDescription for testing.
* Feel free to override the methods you are interested to mock.
*/
public static class DummyCConfigurationDescription implements ICConfigurationDescription {
private String id;
public DummyCConfigurationDescription(String id) {
this.id = id;
}
@Override
public ICSettingObject[] getChildSettings() {
return null;
}
@Override
public String getId() {
return id;
}
@Override
public String getName() {
return null;
}
@Override
public int getType() {
return 0;
}
@Override
public boolean isValid() {
return false;
}
@Override
public ICConfigurationDescription getConfiguration() {
return null;
}
@Override
public ICSettingContainer getParent() {
return null;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public ICStorageElement getStorage(String id, boolean create)
throws CoreException {
return null;
}
@Override
public void removeStorage(String id) throws CoreException {
}
@Override
public ICStorageElement importStorage(String id, ICStorageElement el)
throws UnsupportedOperationException, CoreException {
return null;
}
@Override
public void setReadOnly(boolean readOnly, boolean keepModify) {
}
@Override
public boolean isActive() {
return false;
}
@Override
public String getDescription() {
return null;
}
@Override
public void setDescription(String des) throws WriteAccessException {
}
@Override
public ICProjectDescription getProjectDescription() {
return null;
}
@Override
public ICFolderDescription getRootFolderDescription() {
return null;
}
@Override
public ICFolderDescription[] getFolderDescriptions() {
return null;
}
@Override
public ICFileDescription[] getFileDescriptions() {
return null;
}
@Override
public ICResourceDescription[] getResourceDescriptions() {
return null;
}
@Override
public ICResourceDescription getResourceDescription(IPath path,
boolean exactPath) {
return null;
}
@Override
public void removeResourceDescription(ICResourceDescription des)
throws CoreException, WriteAccessException {
}
@Override
public ICFileDescription createFileDescription(IPath path,
ICResourceDescription base) throws CoreException,
WriteAccessException {
return null;
}
@Override
public ICFolderDescription createFolderDescription(IPath path,
ICFolderDescription base) throws CoreException,
WriteAccessException {
return null;
}
@Override
public String getBuildSystemId() {
return null;
}
@Override
public CConfigurationData getConfigurationData() {
return null;
}
@Override
public void setActive() throws WriteAccessException {
}
@Override
public void setConfigurationData(String buildSystemId, CConfigurationData data) throws WriteAccessException {
}
@Override
public boolean isModified() {
return false;
}
@Override
public ICTargetPlatformSetting getTargetPlatformSetting() {
return null;
}
@Override
public ICSourceEntry[] getSourceEntries() {
return null;
}
@Override
public ICSourceEntry[] getResolvedSourceEntries() {
return null;
}
@Override
public void setSourceEntries(ICSourceEntry[] entries) throws CoreException, WriteAccessException {
}
@Override
public Map<String, String> getReferenceInfo() {
return null;
}
@Override
public void setReferenceInfo(Map<String, String> refs) throws WriteAccessException {
}
@Override
public ICExternalSetting[] getExternalSettings() {
return null;
}
@Override
public ICExternalSetting createExternalSetting(String[] languageIDs,
String[] contentTypeIds, String[] extensions,
ICSettingEntry[] entries) throws WriteAccessException {
return null;
}
@Override
public void removeExternalSetting(ICExternalSetting setting) throws WriteAccessException {
}
@Override
public void removeExternalSettings() throws WriteAccessException {
}
@Override
public ICBuildSetting getBuildSetting() {
return null;
}
@Override
public ICdtVariablesContributor getBuildVariablesContributor() {
return null;
}
@Override
public Object getSessionProperty(QualifiedName name) {
return null;
}
@Override
public void setSessionProperty(QualifiedName name, Object value) {
}
@Override
public void setName(String name) throws WriteAccessException {
}
@Override
public ICConfigExtensionReference[] get(String extensionPointID) {
return null;
}
@Override
public ICConfigExtensionReference create(String extensionPoint, String extension) throws CoreException {
return null;
}
@Override
public void remove(ICConfigExtensionReference ext) throws CoreException {
}
@Override
public void remove(String extensionPoint) throws CoreException {
}
@Override
public boolean isPreferenceConfiguration() {
return false;
}
@Override
public ICLanguageSetting getLanguageSettingForFile(IPath path, boolean ignoreExludeStatus) {
return null;
}
@Override
public void setExternalSettingsProviderIds(String[] ids) {
}
@Override
public String[] getExternalSettingsProviderIds() {
return null;
}
@Override
public void updateExternalSettingsProviders(String[] ids) throws WriteAccessException {
}
@Override
public CConfigurationStatus getConfigurationStatus() {
return null;
}
}
}

View file

@ -15,11 +15,14 @@ package org.eclipse.cdt.core.testplugin;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@ -66,7 +69,7 @@ import org.eclipse.core.runtime.jobs.Job;
public class ResourceHelper {
private final static IProgressMonitor NULL_MONITOR = new NullProgressMonitor();
private static final int MAX_RETRY= 5;
private final static Set<String> externalFilesCreated = new HashSet<String>();
private final static Set<IResource> resourcesCreated = new HashSet<IResource>();
@ -190,7 +193,7 @@ public class ResourceHelper {
/**
* Create a plain Eclipse project.
*
*
* @param projectName
* @return the project handle
* @throws CoreException if project could not be created
@ -202,17 +205,17 @@ public class ResourceHelper {
project.create(NULL_MONITOR);
else
project.refreshLocal(IResource.DEPTH_INFINITE, null);
if (!project.isOpen())
project.open(NULL_MONITOR);
resourcesCreated.add(project);
return project;
}
/**
* Delete project by name.
*
*
* @param projectName
* @throws CoreException
*/
@ -222,20 +225,20 @@ public class ResourceHelper {
if (project.exists())
delete(project);
}
/**
* Delete given project with content.
*
*
* @param project
* @throws CoreException
*/
public static void delete(final IProject project) throws CoreException {
delete(project, true);
}
/**
* Delete project.
*
*
* @param project
* @param deleteContent whether to delete project content
* @throws CoreException
@ -252,7 +255,7 @@ public class ResourceHelper {
try {
Thread.sleep(1000); // sleep a second
} catch (InterruptedException e) {
}
}
}
}
}
@ -297,7 +300,7 @@ public class ResourceHelper {
* can include relative path as a part of the name but the the path
* has to be present on disk.
* The intention of the method is to create files which do not belong to any project.
*
*
* @param name - filename.
* @return full path of the created file.
*
@ -375,7 +378,7 @@ public class ResourceHelper {
public static IPath createTemporaryFolder() throws CoreException, IOException {
return ResourceHelper.createWorkspaceFolder("tmp/"+System.currentTimeMillis()+'.'+UUID.randomUUID());
}
/**
* Creates new eclipse file-link from project root to file system file. The filename
* can include relative path as a part of the name but the the path
@ -514,7 +517,7 @@ public class ResourceHelper {
* Checks if symbolic links are supported on the system.
* Used in particular by method {@link #createSymbolicLink(IPath, IPath)}
* and other flavors to create symbolic links.
*
*
* Note that Windows links .lnk are not supported here.
* @return {@code true} if symbolic links are suppoted, {@code false} otherwise.
*/
@ -675,6 +678,42 @@ public class ResourceHelper {
return windowsPath.trim();
}
/**
* Get contents of file on file-system.
*
* @param fullPath - full path to the file on the file-system.
* @return contents of the file.
* @throws IOException on IO problem.
*/
public static String getContents(IPath fullPath) throws IOException {
FileInputStream stream = new FileInputStream(fullPath.toFile());
try {
// Avoid using java.nio.channels.FileChannel,
// see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154
Reader reader = new BufferedReader(new InputStreamReader(stream, Charset.defaultCharset()));
StringBuilder builder = new StringBuilder();
char[] buffer = new char[8192];
int read;
while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
builder.append(buffer, 0, read);
}
return builder.toString();
} finally {
stream.close();
}
}
/**
* Get contents of file on file-system.
*
* @param fullPath - full path to the file on the file-system.
* @return contents of the file.
* @throws IOException on IO problem.
*/
public static String getContents(String fullPath) throws IOException {
return getContents(new Path(fullPath));
}
/**
* Clean-up any files created as part of a unit test.
* This method removes *all* Workspace IResources and any external

View file

@ -27,6 +27,7 @@ Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.core.index.export,
org.eclipse.cdt.core.index.provider,
org.eclipse.cdt.core.language,
org.eclipse.cdt.core.language.settings.providers,
org.eclipse.cdt.core.model,
org.eclipse.cdt.core.model.util,
org.eclipse.cdt.core.parser,
@ -66,6 +67,7 @@ Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.internal.core.index.provider;x-internal:=true,
org.eclipse.cdt.internal.core.indexer;x-internal:=true,
org.eclipse.cdt.internal.core.language;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.language.settings.providers;x-internal:=true,
org.eclipse.cdt.internal.core.model;x-friends:="org.eclipse.cdt.ui,org.eclipse.cdt.debug.core,org.eclipse.cdt.debug.ui",
org.eclipse.cdt.internal.core.model.ext;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.parser;x-internal:=true,

View file

@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
/**
* Helper class to allow listeners of arbitrary events self-register/dispose.
*
* Called by CDT core when {@linkplain ICListenerAgent} added/removed to
* the list of {@link ILanguageSettingsProvider}s managed by the model.
* {@linkplain ICListenerAgent} would commonly be implemented by a language
* settings provider.
* <br><br>
* Implementers are to create a specific listener and register it to
* appropriate event manager in {@link #registerListener(ICConfigurationDescription)}
* then unregister and dispose in {@link #unregisterListener()}.
*
* @since 5.4
*/
public interface ICListenerAgent {
/**
* Registers a specific listener.
*
* @param cfgDescription - configuration description for the listener.
*/
public void registerListener(ICConfigurationDescription cfgDescription);
/**
* Unregister listener and dispose all resources.
*/
public void unregisterListener();
}

View file

@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.List;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.core.resources.IResource;
/**
* This interface is to be implemented by providers which want to broadcast the changes in their setting entries
* with {@link ILanguageSettingsChangeEvent}.
*
* @since 5.4
*/
public interface ILanguageSettingsBroadcastingProvider extends ILanguageSettingsProvider {
@Override
public String getId();
@Override
public String getName();
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId);
/**
* Return a copy of internal storage. This should be a deep copy/clone of the storage.
* It is used to calculate the delta and being kept in the last state object of configuration
* description to compare to a new state later.
*
* @return a copy of internal storage.
*/
public LanguageSettingsStorage copyStorage();
}

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
/**
* Contains the details of changes that occurred as a result of modifying
* language settings entries {@link ICLanguageSettingEntry}. This event is
* intended to be fired for changes in entries, not necessarily providers.
* The event is associated with a project.
*
* <p>
* <strong>EXPERIMENTAL</strong>. This class interface is not stable yet as
* it is not currently clear how it may need to be used in future. Only bare
* minimum is provided here at this point (CDT 9.0, Juno).
* There is no guarantee that this API will work or that it will remain the same.
* Please do not use this API without consulting with the CDT team.
* </p>
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*
* @since 5.4
*/
public interface ILanguageSettingsChangeEvent {
/**
* @return project name where the event occurred.
*/
public String getProjectName();
/**
* @return configuration IDs which are affected by the language settings changes.
*/
public String[] getConfigurationDescriptionIds();
}

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
/**
* An interface for listeners to changes in language settings {@link ICLanguageSettingEntry}.
*
* @see LanguageSettingsManager#registerLanguageSettingsChangeListener(ILanguageSettingsChangeListener)
* @see LanguageSettingsManager#unregisterLanguageSettingsChangeListener(ILanguageSettingsChangeListener)
*
* @since 5.4
*/
public interface ILanguageSettingsChangeListener {
/**
* Indicates that language settings have been changed.
*
* @param event - details of the event.
*/
public void handleEvent(ILanguageSettingsChangeEvent event);
}

View file

@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.List;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.core.resources.IResource;
/**
* This interface is used in UI to identify classes allowing user to modify settings externally
* contrary to some subclasses of {@link LanguageSettingsSerializableProvider} managing
* their settings themselves and not providing such option to the user.
*
* @since 5.4
*
*/
public interface ILanguageSettingsEditableProvider extends ILanguageSettingsBroadcastingProvider, Cloneable {
@Override
public String getId();
@Override
public String getName();
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId);
/**
* Sets language settings entries for the provider.
*
* @param cfgDescription - configuration description.
* @param rc - resource such as file or folder. If {@code null} the entries are
* considered to be being defined as default entries for resources.
* @param languageId - language id. If {@code null}, then entries are considered
* to be defined as default entries for languages.
* @param entries - language settings entries to set.
*/
public void setSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId, List<ICLanguageSettingEntry> entries);
/**
* Shallow clone of the provider. "Shallow" is defined here as the exact copy except that
* the copy will have zero language settings entries.
*
* @return shallow copy of the provider.
* @throws CloneNotSupportedException in case {@link #clone()} throws the exception.
*/
public ILanguageSettingsEditableProvider cloneShallow() throws CloneNotSupportedException;
/*
* @see Object#clone()
*/
public ILanguageSettingsEditableProvider clone() throws CloneNotSupportedException;
}

View file

@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.List;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.core.resources.IResource;
/**
* Base interface to provide list of {@link ICLanguageSettingEntry}.
* This interface is used to deliver additions to compiler options such as
* include paths (-I) or preprocessor defines (-D) and others (see
* {@link ICSettingEntry#INCLUDE_PATH} and other kinds).
* <br><br>
* To define a provider like that use extension point
* {@code org.eclipse.cdt.core.LanguageSettingsProvider} and implement this
* interface. The recommended way of implementing is to extend
* {@link LanguageSettingsSerializableProvider} and implement {@link ILanguageSettingsEditableProvider}.
* That will give the ability to persist and edit/clean entries by user in UI.
* The clone methods defined by {@link ILanguageSettingsEditableProvider} should be
* chained as done for example by {@link LanguageSettingsGenericProvider}.
* <br><br>
* CDT provides a few general use implementations in the core such as {@link LanguageSettingsBaseProvider}
* or {@link LanguageSettingsSerializableProvider} or {@link LanguageSettingsGenericProvider}
* which could be used out of the box or built upon. There are also abstract classes in build
* plugins {@code AbstractBuildCommandParser} and {@code AbstractBuiltinSpecsDetector} which
* serve as a base for output parsers and built-in compiler language settings detectors.
* See also extension point schema description LanguageSettingsProvider.exsd.
*
* @since 5.4
*/
public interface ILanguageSettingsProvider {
/**
* Id is used to keep track of the providers internally. Use unique id
* to represent the provider.
*
* @return Id of the provider.
*/
public String getId();
/**
* Name is used to present the provider to the end user in UI.
*
* @return name of the provider.
*/
public String getName();
/**
* Returns the list of setting entries for the given configuration description,
* resource and language.
* <br><br>
* Note to implementers - this method should not be used to do any long running
* operations such as extensive calculations or reading files. If you need to do
* so, the recommended way is to do the calculations outside of
* this function call - in advance and on appropriate event. For example, Build
* Output Parser prepares the list and stores it in internal cache while parsing output.
* {@link #getSettingEntries(ICConfigurationDescription, IResource, String)} will
* return cached entries when asked. You can also implement {@link ICListenerAgent}
* interface to get registered and listen to arbitrary events.
*
* @param cfgDescription - configuration description.
* @param rc - resource such as file or folder.
* If {@code null}, the default entries for all resources are returned.
* @param languageId - language id.
* If {@code null}, the default entries for all languages are returned.
* (see {@link LanguageManager#getLanguageForFile(org.eclipse.core.resources.IFile, ICConfigurationDescription)}).
*
* @return the list of setting entries or {@code null} if no settings defined.
* The list needs to be a pooled list created by {@link LanguageSettingsStorage#getPooledList(List)}
* to save memory and avoid deep equality comparisons.
*/
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId);
}

View file

@ -0,0 +1,69 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.List;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
/**
* Interface to express ability (of a configuration description) to handle Language Settings
* Providers.
* @see ILanguageSettingsProvider
*
* @since 5.4
*
*/
public interface ILanguageSettingsProvidersKeeper {
/**
* Sets the list of language settings providers. Language settings providers are
* used to supply language settings {@link ICLanguageSettingEntry} such as include paths
* or preprocessor macros.
*
* @param providers - the list of providers to assign to the owner (configuration description).
* This method clones the internal list or otherwise ensures immutability of the internal
* list before actual addition to the project model. That is to ensure that there is no
* back-door access and all changes in the list done by this method which fires notifications
* to the registered listeners about the accompanied changes in settings entries, see
* {@link LanguageSettingsManager#registerLanguageSettingsChangeListener(ILanguageSettingsChangeListener)}.
*/
public void setLanguageSettingProviders(List<ILanguageSettingsProvider> providers);
/**
* Returns the list of language settings providers. Language settings providers are
* used to supply language settings {@link ICLanguageSettingEntry} such as include paths
* or preprocessor macros.
*
* @return the list of providers to assign to the owner (configuration description). This
* returns immutable list. Use {@link #setLanguageSettingProviders(List)} to change.
* This method does not return {@code null}.
*/
public List<ILanguageSettingsProvider> getLanguageSettingProviders();
/**
* Sets the list of IDs of default language settings providers.
* <br><br>
* The method is intended to be used by MBS to set the list from tool-chain definition.
* The default list from the tool-chain is used, for example, while resetting
* configuration providers to default in UI.
*
* @param ids - default provider IDs specified in the tool-chain.
*/
public void setDefaultLanguageSettingsProvidersIds(String[] ids);
/**
* Retrieve the list of IDs of default language settings providers.
* Normally the list would come from the tool-chain definition.
*
* @return default provider IDs or {@code null} if default providers are not defined.
*/
public String[] getDefaultLanguageSettingsProvidersIds();
}

View file

@ -0,0 +1,288 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.AbstractExecutableExtensionBase;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.internal.core.settings.model.SettingsModelMessages;
import org.eclipse.core.resources.IResource;
/**
* {@code LanguageSettingsBaseProvider} is a basic implementation of {@link ILanguageSettingsProvider}
* for the extensions defined by {@code org.eclipse.cdt.core.LanguageSettingsProvider} extension point.
*
* This implementation supports "static" list of entries for languages specified in
* the extension point.
*
* @since 5.4
*/
public class LanguageSettingsBaseProvider extends AbstractExecutableExtensionBase implements ILanguageSettingsProvider {
/** Language scope, i.e. list of languages the entries will be provided for. */
protected List<String> languageScope = null;
/** Provider-specific properties */
protected Map<String, String> properties = new HashMap<String, String>();
/** List of entries defined by this provider. */
private List<ICLanguageSettingEntry> entries = null;
/**
* Default constructor.
*/
public LanguageSettingsBaseProvider() {
super();
}
/**
* Constructor. Creates an "empty" non-configured provider.
*
* @param id - id of the provider.
* @param name - name of the provider to be presented to a user.
*/
public LanguageSettingsBaseProvider(String id, String name) {
super(id, name);
}
/**
* Constructor.
*
* @param id - id of the provider.
* @param name - name of the provider to be presented to a user.
* @param languages - list of languages the {@code entries} provided for.
* {@code languages} can be {@code null}, in this case the {@code entries}
* are provided for any language.
* @param entries - the list of language settings entries this provider provides.
* If {@code null} is passed, the provider creates an empty list.
*/
public LanguageSettingsBaseProvider(String id, String name, List<String> languages,
List<ICLanguageSettingEntry> entries) {
super(id, name);
this.languageScope = languages!=null ? new ArrayList<String>(languages) : null;
this.entries = getPooledList(entries);
}
/**
* Constructor.
*
* @param id - id of the provider.
* @param name - name of the provider to be presented to a user.
* @param languages - list of languages the {@code entries} provided for.
* {@code languages} can be {@code null}, in this case the {@code entries}
* are provided for any language.
* @param entries - the list of language settings entries this provider provides.
* If {@code null} is passed, the provider creates an empty list.
* @param properties - custom properties as the means to customize providers.
*/
public LanguageSettingsBaseProvider(String id, String name, List<String> languages,
List<ICLanguageSettingEntry> entries, Map<String, String> properties) {
super(id, name);
this.languageScope = languages!=null ? new ArrayList<String>(languages) : null;
this.entries = getPooledList(entries);
if (properties != null)
this.properties = new HashMap<String, String>(properties);
}
/**
* A method to configure the provider. The initialization of provider from
* the extension point is done in 2 steps. First, the class is created as
* an executable extension using the default provider. Then this method is
* used to configure the provider.
*<br><br>
* It is not allowed to reconfigure the provider.
*
* @param id - id of the provider.
* @param name - name of the provider to be presented to a user.
* @param languages - list of languages the {@code entries} provided for.
* {@code languages} can be {@code null}, in this case the {@code entries}
* are provided for any language.
* @param entries - the list of language settings entries this provider provides.
* If {@code null} is passed, the provider creates an empty list.
* @param properties - custom properties as the means to customize providers.
*
* @throws UnsupportedOperationException if an attempt to reconfigure provider is made.
*/
public void configureProvider(String id, String name, List<String> languages,
List<ICLanguageSettingEntry> entries, Map<String, String> properties) {
if (this.entries!=null || !this.properties.isEmpty())
throw new UnsupportedOperationException(SettingsModelMessages.getString("LanguageSettingsBaseProvider.CanBeConfiguredOnlyOnce")); //$NON-NLS-1$
setId(id);
setName(name);
this.languageScope = languages!=null ? new ArrayList<String>(languages) : null;
this.entries = getPooledList(entries);
if (properties != null)
this.properties = new HashMap<String, String>(properties);
}
/**
* {@code LanguageSettingsBaseProvider} keeps the list of key-value pairs
* so extenders of this class can customize the provider. The properties
* of {@code LanguageSettingsBaseProvider} come from the extension in plugin.xml
* although the extenders can provide their own method.
* <br><br>
* Please note that empty string value is treated as "default" value and
* the same as {@code null} and the same as missing property, which allows
* {@link #equals(Object)} evaluate the property as equal while comparing providers.
*
* @param key - property to check the value.
* @return value of the property. If the property is missing returns empty string.
*/
public String getProperty(String key) {
String value = properties.get(key);
if (value == null) {
value = ""; //$NON-NLS-1$
}
return value;
}
/**
* Convenience method to get boolean property.
* @see #getProperty(String)
*
* @param key - property to check the value.
* @return boolean value of the property. If the property is missing or cannot be
* interpreted as boolean returns {@code false}.
*/
public boolean getPropertyBool(String key) {
return Boolean.parseBoolean(properties.get(key));
}
private List<ICLanguageSettingEntry> getPooledList(List<ICLanguageSettingEntry> entries) {
if (entries != null) {
return LanguageSettingsStorage.getPooledList(entries);
}
return null;
}
/**
* {@inheritDoc}
*
* @param languageId - language id. If {@code null}, then entries defined for
* the language scope are returned. See {@link #getLanguageScope()}
*
* @return unmodifiable list of setting entries or {@code null} if no settings defined.
* the list is internally pooled and guaranteed to be the same object for equal
* lists.
*/
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription,
IResource rc, String languageId) {
if (languageScope == null) {
return entries;
}
for (String lang : languageScope) {
if (lang.equals(languageId)) {
return entries;
}
}
return null;
}
/**
* @return the unmodifiable list of languages this provider provides for.
* If {@code null}, the provider provides for any language.
*/
public List<String> getLanguageScope() {
if (languageScope==null)
return null;
return Collections.unmodifiableList(languageScope);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
result = prime * result + ((entries == null) ? 0 : entries.hashCode());
result = prime * result + ((languageScope == null) ? 0 : languageScope.hashCode());
// exclude field "properties" because of special rules for equals()
result = prime * result + getClass().hashCode();
return result;
}
/**
* @return {@code true} if the objects are equal, {@code false } otherwise.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LanguageSettingsBaseProvider other = (LanguageSettingsBaseProvider) obj;
String id = getId();
String otherId = other.getId();
if (id == null) {
if (otherId != null)
return false;
} else if (!id.equals(otherId))
return false;
String name = getName();
String otherName = other.getName();
if (name == null) {
if (otherName != null)
return false;
} else if (!name.equals(otherName))
return false;
if (entries == null) {
if (other.entries != null)
return false;
} else if (!entries.equals(other.entries))
return false;
if (languageScope == null) {
if (other.languageScope != null)
return false;
} else if (!languageScope.equals(other.languageScope))
return false;
if (properties == null) {
if (other.properties != null)
return false;
} else if (other.properties == null) {
return false;
} else {
// The trouble to ensure default properties are equal to missing ones.
Set<String> keys = new HashSet<String>(properties.keySet());
keys.addAll(other.properties.keySet());
for (String key : keys) {
String value = properties.get(key);
if (value == null || value.equals(Boolean.FALSE.toString()))
value = ""; //$NON-NLS-1$
String otherValue = other.properties.get(key);
if (otherValue == null || otherValue.equals(Boolean.FALSE.toString()))
otherValue = ""; //$NON-NLS-1$
if (!value.equals(otherValue))
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
/**
* Generic implementation of language settings provider which can be edited in UI
* with entries persisted between eclipse sessions.
* The instances of this class can be used in plugin.xml to create a new provider
* but this class is not intended to be extended. For more details how to create a
* language settings provider see the description of {@link ILanguageSettingsProvider}.
*
* @since 5.4
*/
final public class LanguageSettingsGenericProvider extends LanguageSettingsSerializableProvider
implements ILanguageSettingsEditableProvider {
@Override
public LanguageSettingsGenericProvider clone() throws CloneNotSupportedException {
return (LanguageSettingsGenericProvider) super.clone();
}
@Override
public LanguageSettingsGenericProvider cloneShallow() throws CloneNotSupportedException {
return (LanguageSettingsGenericProvider) super.cloneShallow();
}
}

View file

@ -0,0 +1,338 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICFileDescription;
import org.eclipse.cdt.core.settings.model.ICFolderDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSetting;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsExtensionManager;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
/**
* A collection of utility methods to manage language settings providers.
* See {@link ILanguageSettingsProvider}.
*
* @since 5.4
*/
public class LanguageSettingsManager {
/**
* Returns the list of setting entries of the given provider
* for the given configuration description, resource and language.
* This method reaches to the parent folder of the resource recursively
* if the resource does not define the entries for the given provider.
*
* @param provider - language settings provider.
* @param cfgDescription - configuration description.
* @param rc - resource such as file or folder.
* @param languageId - language id.
*
* @return the list of setting entries. Never returns {@code null}
* although individual providers return {@code null} if no settings defined.
*/
public static List<ICLanguageSettingEntry> getSettingEntriesUpResourceTree(ILanguageSettingsProvider provider, ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
return LanguageSettingsProvidersSerializer.getSettingEntriesUpResourceTree(provider, cfgDescription, rc, languageId);
}
/**
* Get Language Settings Provider from the list of workspace providers,
* see {@link #getWorkspaceProviders()}.
*
* @param id - id of provider to find.
* @return the workspace provider. If workspace provider is not defined
* a new instance is created and returned.
*/
public static ILanguageSettingsProvider getWorkspaceProvider(String id) {
return LanguageSettingsProvidersSerializer.getWorkspaceProvider(id);
}
/**
* Get Language Settings Providers defined in the workspace. That includes
* user-defined providers and after that providers defined as extensions via
* {@code org.eclipse.cdt.core.LanguageSettingsProvider} extension point.
* Note that this returns wrappers around workspace provider so underlying
* provider could be replaced internally without need to change configuration.
* See also {@link #getRawProvider(ILanguageSettingsProvider)}.
*
* @return list of workspace providers.
*/
public static List<ILanguageSettingsProvider> getWorkspaceProviders() {
return LanguageSettingsProvidersSerializer.getWorkspaceProviders();
}
/**
* Checks if the provider is a workspace level provider.
* This method is intended to check providers retrieved from a configuration.
* Raw providers from {@link #getRawProvider(ILanguageSettingsProvider)}
* are not considered as workspace providers.
*
* @param provider - provider to check.
* @return {@code true} if the given provider is workspace provider, {@code false} otherwise.
*/
public static boolean isWorkspaceProvider(ILanguageSettingsProvider provider) {
return LanguageSettingsProvidersSerializer.isWorkspaceProvider(provider);
}
/**
* Helper method to get to real underlying provider collecting entries as opposed to wrapper
* which is normally used for workspace provider.
* @see LanguageSettingsProvidersSerializer#isWorkspaceProvider(ILanguageSettingsProvider)
*
* @param provider - the provider to get raw provider for. Can be either workspace provider
* or regular one.
* @return raw underlying provider for workspace provider or provider itself if no wrapper is used.
*/
public static ILanguageSettingsProvider getRawProvider(ILanguageSettingsProvider provider) {
if (LanguageSettingsManager.isWorkspaceProvider(provider)) {
provider = LanguageSettingsProvidersSerializer.getRawWorkspaceProvider(provider.getId());
}
return provider;
}
/**
* Set and store in workspace area user defined providers.
*
* @param providers - array of user defined workspace providers.
* Note that those providers will shadow extension providers with the same ID.
* All not shadowed extension providers will be added to the list to be present
* as workspace providers. {@code null} is equivalent to passing an empty array
* and so will reset workspace providers to match extension providers.
* @throws CoreException in case of problems (such as problems with persistence).
*/
public static void setWorkspaceProviders(List<ILanguageSettingsProvider> providers) throws CoreException {
LanguageSettingsProvidersSerializer.setWorkspaceProviders(providers);
}
/**
* Copy language settings provider. It is different from clone() methods in that
* it does not throw {@code CloneNotSupportedException} but returns {@code null}
* instead.
*
* @param provider - language settings provider to copy.
* @param deep - {@code true} to request deep copy including copying settings entries
* or {@code false} to return shallow copy with no settings entries.
*
* @return a copy of the provider or null if copying is not possible.
*/
public static ILanguageSettingsEditableProvider getProviderCopy(ILanguageSettingsEditableProvider provider, boolean deep) {
return LanguageSettingsExtensionManager.getProviderCopy(provider, deep);
}
/**
* Returns list of provider id-s contributed by all extensions.
* @return the provider id-s.
*/
public static Set<String> getExtensionProviderIds() {
return LanguageSettingsExtensionManager.getExtensionProviderIds();
}
/**
* Get language settings provider defined via extension point
* {@code org.eclipse.cdt.core.LanguageSettingsProvider}.
* A new copy of the extension provider is returned.
*
* @param id - ID of the extension provider.
* @param deep - {@code true} to request deep copy including copying settings entries
* or {@code false} to return shallow copy with no settings entries.
* @return the copy of the extension provider if possible (i.e. for {@link ILanguageSettingsEditableProvider})
* or {@code null} if provider is not copyable.
*/
public static ILanguageSettingsProvider getExtensionProviderCopy(String id, boolean deep) {
return LanguageSettingsExtensionManager.getExtensionProviderCopy(id, deep);
}
/**
* Test if the provider is equal to the one defined via extension point
* {@code org.eclipse.cdt.core.LanguageSettingsProvider}.
*
* @param provider - the provider to test.
* @param deep - {@code true} to check for deep equality testing also settings entries
* or {@code false} to test shallow copy with no settings entries.
* @return - {@code true} if the provider matches the extension or {@code false} otherwise.
*/
public static boolean isEqualExtensionProvider(ILanguageSettingsProvider provider, boolean deep) {
return LanguageSettingsExtensionManager.isEqualExtensionProvider(provider, deep);
}
/**
* Find language IDs for the resource represented by resource description.
* Under the hood build component is inquired and the language IDs would
* commonly come from the input type(s).
*
* @param rcDescription - resource description
* @return list of language IDs for the resource.
* Never returns {@code null} but empty list if no languages can be found.
*
*/
public static List<String> getLanguages(ICResourceDescription rcDescription) {
ICLanguageSetting[] languageSettings = null;
if (rcDescription instanceof ICFileDescription) {
ICLanguageSetting languageSetting = ((ICFileDescription)rcDescription).getLanguageSetting();
if (languageSetting != null) {
languageSettings = new ICLanguageSetting[] {languageSetting};
}
} else if (rcDescription instanceof ICFolderDescription) {
languageSettings = ((ICFolderDescription)rcDescription).getLanguageSettings();
}
List<String> languageIds = new ArrayList<String>();
if (languageSettings != null) {
for (ICLanguageSetting languageSetting : languageSettings) {
if (languageSetting!=null) {
String languageId = languageSetting.getLanguageId();
if (languageId != null && !languageId.isEmpty()) {
languageIds.add(languageId);
}
}
}
}
return languageIds;
}
/**
* Find language IDs for the resource in given build configuration.
* Under the hood build component is inquired and the language IDs would
* commonly come from the input type(s).
*
* @param resource - the resource to find languages for.
* @param cfgDescription
* @return list of language IDs for the resource.
* Never returns {@code null} but empty list if no languages can be found.
*/
public static List<String> getLanguages(IResource resource, ICConfigurationDescription cfgDescription) {
List<String> languageIds = new ArrayList<String>();
IPath prjRelPath = resource.getProjectRelativePath();
if (resource instanceof IFile) {
String langId = null;
if (cfgDescription != null) {
// Inquire MBS
ICLanguageSetting ls = cfgDescription.getLanguageSettingForFile(prjRelPath, true);
if (ls != null) {
langId = ls.getLanguageId();
}
}
if (langId == null) {
// Try getting language from content types
try {
ILanguage lang = LanguageManager.getInstance().getLanguageForFile((IFile) resource, cfgDescription);
if (lang != null) {
langId = lang.getId();
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
if (langId != null) {
languageIds.add(langId);
}
} else {
ICResourceDescription rcDes = cfgDescription.getResourceDescription(prjRelPath, false);
if (rcDes == null) {
rcDes = cfgDescription.getRootFolderDescription();
}
languageIds = getLanguages(rcDes);
}
return languageIds;
}
/**
* Adds a listener that will be notified of changes in language settings.
*
* @param listener the listener to add
*/
public static void registerLanguageSettingsChangeListener(ILanguageSettingsChangeListener listener) {
LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(listener);
}
/**
* Removes a language settings change listener.
*
* @param listener the listener to remove.
*/
public static void unregisterLanguageSettingsChangeListener(ILanguageSettingsChangeListener listener) {
LanguageSettingsProvidersSerializer.unregisterLanguageSettingsChangeListener(listener);
}
/**
* Tells if the provider is meant to be shared between projects in workspace
* or belong to a specific configuration. This attribute is defined in
* {@code org.eclipse.cdt.core.LanguageSettingsProvider} extension point.
* <br>Note that only {@link ILanguageSettingsEditableProvider} can be owned by
* a configuration.
*
* @param id - ID of the provider to inquire.
* @return {@code true} if the provider is designed to be shared,
* {@code false} if configuration-owned.
*/
public static boolean isPreferShared(String id) {
return LanguageSettingsExtensionManager.isPreferShared(id);
}
/**
* Tells if language settings entries of the provider are persisted with the project
* (under .settings/ folder) or in workspace area. Persistence in the project area lets
* the entries migrate with the project.
*
* @param provider - provider to check the persistence mode.
* @return {@code true} if LSE persisted with the project or {@code false} if in the workspace.
*/
public static boolean isStoringEntriesInProjectArea(LanguageSettingsSerializableProvider provider) {
return LanguageSettingsProvidersSerializer.isStoringEntriesInProjectArea(provider);
}
/**
* Define where language settings are persisted for the provider.
*
* @param provider - provider to set the persistence mode.
* @param storeEntriesWithProject - {@code true} if with the project,
* {@code false} if in workspace area.
*/
public static void setStoringEntriesInProjectArea(LanguageSettingsSerializableProvider provider, boolean storeEntriesWithProject) {
LanguageSettingsProvidersSerializer.setStoringEntriesInProjectArea(provider, storeEntriesWithProject);
}
/**
* Save language settings providers of a project to persistent storage.
*
* @param prjDescription - project description of the project.
* @throws CoreException if something goes wrong.
*/
public static void serializeLanguageSettings(ICProjectDescription prjDescription) throws CoreException {
LanguageSettingsProvidersSerializer.serializeLanguageSettings(prjDescription);
}
/**
* Save language settings providers of the workspace (global providers) to persistent storage.
*
* @throws CoreException
*/
public static void serializeLanguageSettingsWorkspace() throws CoreException {
LanguageSettingsProvidersSerializer.serializeLanguageSettingsWorkspace();
}
}

View file

@ -0,0 +1,434 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsSerializableStorage;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* This class is the base class for language settings providers able to serialize
* into XML storage.
* Although this class has setter methods, its instances are not editable in UI by
* design. Implement {@link ILanguageSettingsEditableProvider} interface for that.
* For more on the suggested way of extending this class see the description of
* {@link ILanguageSettingsProvider}.
*
* @since 5.4
*/
public class LanguageSettingsSerializableProvider extends LanguageSettingsBaseProvider implements ILanguageSettingsBroadcastingProvider {
protected static final String ATTR_ID = LanguageSettingsProvidersSerializer.ATTR_ID;
protected static final String ATTR_NAME = LanguageSettingsProvidersSerializer.ATTR_NAME;
protected static final String ATTR_CLASS = LanguageSettingsProvidersSerializer.ATTR_CLASS;
protected static final String ELEM_PROVIDER = LanguageSettingsProvidersSerializer.ELEM_PROVIDER;
protected static final String ELEM_LANGUAGE_SCOPE = LanguageSettingsProvidersSerializer.ELEM_LANGUAGE_SCOPE;
private LanguageSettingsSerializableStorage fStorage = new LanguageSettingsSerializableStorage();
/**
* Default constructor. This constructor has to be always followed with setting id and name of the provider.
* This constructor is necessary to instantiate the class via the extension point in plugin.xml.
*/
public LanguageSettingsSerializableProvider() {
super();
}
/**
* Constructor.
*
* @param id - id of the provider.
* @param name - name of the provider. Note that this name shows up in UI.
*/
public LanguageSettingsSerializableProvider(String id, String name) {
super(id, name);
}
/**
* Constructor which allows to instantiate provider defined via XML markup.
*
* @param elementProvider
*/
public LanguageSettingsSerializableProvider(Element elementProvider) {
super();
load(elementProvider);
}
@Override
public void configureProvider(String id, String name, List<String> languages, List<ICLanguageSettingEntry> entries, Map<String, String> properties) {
// do not pass entries to super, keep them in local storage
super.configureProvider(id, name, languages, null, properties);
fStorage.clear();
if (entries!=null) {
// note that these entries are intended to be retrieved by LanguageSettingsManager.getSettingEntriesUpResourceTree()
// when the whole resource hierarchy has been traversed up
setSettingEntries(null, null, null, entries);
}
}
/**
* @return {@code true} if the provider does not keep any settings yet or {@code false} if there are some.
*/
public boolean isEmpty() {
return fStorage.isEmpty();
}
/**
* Set the language scope of the provider.
*
* @param languages - the list of languages this provider provides for.
* If {@code null}, the provider provides for any language.
*
* @see #getLanguageScope()
*/
public void setLanguageScope(List <String> languages) {
if (languages==null)
this.languageScope = null;
else
this.languageScope = new ArrayList<String>(languages);
}
/**
* Clear all the entries for all configurations, all resources and all languages.
*/
public void clear() {
fStorage.clear();
}
/**
* Sets language settings entries for the provider.
* Note that the entries are not persisted at that point. Use this method to set
* the entries for all resources one by one and after all done persist in one shot
* using {@link #serializeLanguageSettings(ICConfigurationDescription)}.
* See for example {@code AbstractBuildCommandParser} and {@code AbstractBuiltinSpecsDetector}
* in build plugins.
*
* @param cfgDescription - configuration description.
* @param rc - resource such as file or folder. If {@code null} the entries are
* considered to be being defined as default entries for resources.
* @param languageId - language id. If {@code null}, then entries are considered
* to be defined for the language scope. See {@link #getLanguageScope()}
* @param entries - language settings entries to set.
*/
public void setSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId, List<ICLanguageSettingEntry> entries) {
String rcProjectPath = rc!=null ? rc.getProjectRelativePath().toString() : null;
fStorage.setSettingEntries(rcProjectPath, languageId, entries);
}
/**
* {@inheritDoc}
* <br>
* Note that this list is <b>unmodifiable</b>. To modify the list copy it, change and use
* {@link #setSettingEntries(ICConfigurationDescription, IResource, String, List)}.
* <br><br>
* Note also that <b>you can compare these lists with simple equality operator ==</b>,
* as the lists themselves are backed by WeakHashSet<List<ICLanguageSettingEntry>> where
* identical copies (deep comparison is used) are replaced with the same one instance.
*/
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
String rcProjectPath = rc!=null ? rc.getProjectRelativePath().toString() : null;
List<ICLanguageSettingEntry> entries = fStorage.getSettingEntries(rcProjectPath, languageId);
if (entries == null) {
if (languageId != null && (languageScope == null || languageScope.contains(languageId))) {
entries = fStorage.getSettingEntries(rcProjectPath, null);
}
}
return entries;
}
/**
* Serialize the provider under parent XML element.
* This is convenience method not intended to be overridden on purpose.
* Override {@link #serializeAttributes(Element)} or
* {@link #serializeEntries(Element)} instead.
*
* @param parentElement - element where to serialize.
* @return - newly created "provider" element. That element will already be
* attached to the parent element.
*/
final public Element serialize(Element parentElement) {
/*
<provider id="provider.id" ...>
<language-scope id="lang.id"/>
<language id="lang.id">
<resource project-relative-path="/">
<entry flags="" kind="includePath" name="path"/>
</resource>
</language>
</provider>
*/
Element elementProvider = serializeAttributes(parentElement);
serializeEntries(elementProvider);
return elementProvider;
}
/**
* Serialize the provider attributes under parent XML element. That is
* equivalent to serializing everything (including language scope) except entries.
*
* @param parentElement - element where to serialize.
* @return - newly created "provider" element. That element will already be
* attached to the parent element.
*/
public Element serializeAttributes(Element parentElement) {
// Keeps pairs: key, value. See JavaDoc XmlUtil.appendElement(Node, String, String[]).
List<String> attributes = new ArrayList<String>();
attributes.add(ATTR_ID);
attributes.add(getId());
attributes.add(ATTR_NAME);
attributes.add(getName());
attributes.add(ATTR_CLASS);
attributes.add(getClass().getCanonicalName());
for (Entry<String, String> entry : properties.entrySet()) {
attributes.add(entry.getKey());
attributes.add(entry.getValue());
}
Element elementProvider = XmlUtil.appendElement(parentElement, ELEM_PROVIDER, attributes.toArray(new String[0]));
if (languageScope!=null) {
for (String langId : languageScope) {
XmlUtil.appendElement(elementProvider, ELEM_LANGUAGE_SCOPE, new String[] {ATTR_ID, langId});
}
}
return elementProvider;
}
/**
* Serialize the provider entries under parent XML element.
* @param elementProvider - element where to serialize the entries.
*/
public void serializeEntries(Element elementProvider) {
fStorage.serializeEntries(elementProvider);
}
/**
* Convenience method to persist language settings entries for the project or
* workspace as often-used operation.
* Note that configuration description is passed as an argument but the
* current implementation saves all configurations.
*
* @param cfgDescription - configuration description.
* If not {@code null}, all providers of the project are serialized.
* If {@code null}, global workspace providers are serialized.
*
* @return - status of operation.
*/
public IStatus serializeLanguageSettings(ICConfigurationDescription cfgDescription) {
IStatus status = Status.OK_STATUS;
try {
if (cfgDescription != null) {
LanguageSettingsManager.serializeLanguageSettings(cfgDescription.getProjectDescription());
} else {
LanguageSettingsManager.serializeLanguageSettingsWorkspace();
}
} catch (CoreException e) {
status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, IStatus.ERROR, "Error serializing language settings", e); //$NON-NLS-1$
CCorePlugin.log(status);
}
return status;
}
/**
* Load provider from XML provider element.
* This is convenience method not intended to be overridden on purpose.
* Override {@link #loadAttributes(Element)} or
* {@link #loadEntries(Element)} instead.
*
* @param providerNode - XML element "provider" to load provider from.
*/
final public void load(Element providerNode) {
fStorage.clear();
languageScope = null;
// provider/configuration/language/resource/entry
if (providerNode!=null) {
loadAttributes(providerNode);
loadEntries(providerNode);
}
}
/**
* Determine and set language scope from given XML node.
*/
private void loadLanguageScopeElement(Node parentNode) {
if (languageScope==null) {
languageScope = new ArrayList<String>();
}
String id = XmlUtil.determineAttributeValue(parentNode, ATTR_ID);
languageScope.add(id);
}
/**
* Load attributes from XML provider element.
* @param providerNode - XML element "provider" to load attributes from.
*/
public void loadAttributes(Element providerNode) {
String providerId = XmlUtil.determineAttributeValue(providerNode, ATTR_ID);
String providerName = XmlUtil.determineAttributeValue(providerNode, ATTR_NAME);
properties.clear();
NamedNodeMap attrs = providerNode.getAttributes();
for (int i=0; i<attrs.getLength(); i++) {
Node attr = attrs.item(i);
if (attr.getNodeType()==Node.ATTRIBUTE_NODE) {
String key = attr.getNodeName();
if (!key.equals(ATTR_ID) && !key.equals(ATTR_NAME) && !key.equals(ATTR_CLASS)) {
String value = attr.getNodeValue();
properties.put(key, value);
}
}
}
this.setId(providerId);
this.setName(providerName);
NodeList nodes = providerNode.getChildNodes();
for (int i=0;i<nodes.getLength();i++) {
Node elementNode = nodes.item(i);
if(elementNode.getNodeType() != Node.ELEMENT_NODE)
continue;
if (ELEM_LANGUAGE_SCOPE.equals(elementNode.getNodeName())) {
loadLanguageScopeElement(elementNode);
}
}
}
/**
* Load provider entries from XML provider element.
* @param providerNode - parent XML element "provider" where entries are defined.
*/
public void loadEntries(Element providerNode) {
fStorage.loadEntries(providerNode);
}
/**
* Set a custom property of the provider.
* <br><br>
* A note of caution - do not use default values for a provider which are different
* from empty or {@code null} value. When providers are checked for equality
* (during internal operations in core) the missing properties are evaluated as
* empty ones.
*
* @see LanguageSettingsBaseProvider#getProperty(String)
*
* @param key - name of the property.
* @param value - value of the property.
* If value is {@code null} the property is removed from the list.
*/
public void setProperty(String key, String value) {
properties.put(key, value);
}
/**
* Set a custom boolean property of the provider.
* <br>Please, note that default value is always {@code false}.
* @see LanguageSettingsBaseProvider#getProperty(String)
*
* @param key - name of the property.
* @param value - {@code boolean} value of the property.
*/
public void setPropertyBool(String key, boolean value) {
properties.put(key, Boolean.toString(value));
}
/**
* See {@link #cloneShallow()}. This method is extracted to avoid expressing
* {@link #clone()} via {@link #cloneShallow()}. Do not inline to "optimize"!
*/
private LanguageSettingsSerializableProvider cloneShallowInternal() throws CloneNotSupportedException {
LanguageSettingsSerializableProvider clone = (LanguageSettingsSerializableProvider)super.clone();
if (languageScope!=null)
clone.languageScope = new ArrayList<String>(languageScope);
clone.properties = new HashMap<String, String>(properties);
clone.fStorage = new LanguageSettingsSerializableStorage();
return clone;
}
/**
* Shallow clone of the provider. "Shallow" is defined here as the exact copy except that
* the copy will have zero language settings entries.
*
* @return shallow copy of the provider.
* @throws CloneNotSupportedException in case {@link #clone()} throws the exception.
*/
protected LanguageSettingsSerializableProvider cloneShallow() throws CloneNotSupportedException {
return cloneShallowInternal();
}
@Override
protected LanguageSettingsSerializableProvider clone() throws CloneNotSupportedException {
LanguageSettingsSerializableProvider clone = cloneShallowInternal();
clone.fStorage = fStorage.clone();
return clone;
}
@Override
public LanguageSettingsStorage copyStorage() {
try {
return fStorage.clone();
} catch (CloneNotSupportedException e) {
CCorePlugin.log(e);
}
return null;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((fStorage == null) ? 0 : fStorage.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
LanguageSettingsSerializableProvider other = (LanguageSettingsSerializableProvider) obj;
if (fStorage == null) {
if (other.fStorage != null)
return false;
} else if (!fStorage.equals(other.fStorage))
return false;
return true;
}
}

View file

@ -0,0 +1,241 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.internal.core.parser.util.WeakHashSet;
/**
* The class representing the (in-memory) storage for language settings entries {@link ICLanguageSettingEntry}.
*
* @since 5.4
*/
public class LanguageSettingsStorage implements Cloneable {
/** Storage to keep settings entries. */
protected Map<String, // languageId
Map<String, // resource project path
List<ICLanguageSettingEntry>>> fStorage = new HashMap<String, Map<String, List<ICLanguageSettingEntry>>>();
/**
* Pool of LSE lists implemented as WeakHashSet. That allows to gain memory savings
* at the expense of CPU time. WeakHashSet handles garbage collection when a list is not
* referenced anywhere else. See JavaDoc {@link java.lang.ref.WeakReference} about weak reference objects.
*/
private static WeakHashSet<List<ICLanguageSettingEntry>> listPool = new WeakHashSet<List<ICLanguageSettingEntry>>() {
@Override
public synchronized List<ICLanguageSettingEntry> add(List<ICLanguageSettingEntry> list) {
return super.add(list);
}
};
/**
* Returns the list of setting entries for the given resource and language.
* <br> Note that this list is <b>unmodifiable</b>.
*
* @param rcProjectPath - path to the resource relative to the project.
* @param languageId - language id.
*
* @return the list of setting entries or {@code null} if no settings defined.
*/
public List<ICLanguageSettingEntry> getSettingEntries(String rcProjectPath, String languageId) {
List<ICLanguageSettingEntry> entries = null;
Map<String, List<ICLanguageSettingEntry>> langMap = fStorage.get(languageId);
if (langMap!=null) {
entries = langMap.get(rcProjectPath);
}
return entries;
}
/**
* Some providers may collect entries in pretty much random order. For the intent of
* predictability, UI usability and efficient storage the entries are sorted by kinds
* and secondary by name for kinds where the secondary order is not significant.
*
* @param entries - list of entries to sort.
* @return - sorted entries.
*/
private List<ICLanguageSettingEntry> sortEntries(List<ICLanguageSettingEntry> entries) {
List<ICLanguageSettingEntry> sortedEntries = new ArrayList<ICLanguageSettingEntry>(entries);
Collections.sort(sortedEntries, new Comparator<ICLanguageSettingEntry>() {
/**
* This comparator sorts by kinds first and the macros are sorted additionally by name.
*/
@Override
public int compare(ICLanguageSettingEntry entry0, ICLanguageSettingEntry entry1) {
int kind0 = entry0.getKind();
int kind1 = entry1.getKind();
if (kind0==ICSettingEntry.MACRO && kind1==ICSettingEntry.MACRO) {
return entry0.getName().compareTo(entry1.getName());
}
return kind0 - kind1;
}});
return sortedEntries;
}
/**
* Sets language settings entries for the resource and language.
*
* @param rcProjectPath - path to the resource relative to the project.
* @param languageId - language id.
* @param entries - language settings entries to set.
*/
public void setSettingEntries(String rcProjectPath, String languageId, List<ICLanguageSettingEntry> entries) {
synchronized (fStorage) {
if (entries!=null) {
Map<String, List<ICLanguageSettingEntry>> langMap = fStorage.get(languageId);
if (langMap==null) {
langMap = new HashMap<String, List<ICLanguageSettingEntry>>();
fStorage.put(languageId, langMap);
}
List<ICLanguageSettingEntry> sortedEntries = getPooledList(sortEntries(entries), false);
langMap.put(rcProjectPath, sortedEntries);
} else {
// reduct the empty maps in the tables
Map<String, List<ICLanguageSettingEntry>> langMap = fStorage.get(languageId);
if (langMap!=null) {
langMap.remove(rcProjectPath);
if (langMap.size()==0) {
fStorage.remove(languageId);
}
}
}
}
}
/**
* @return {@code true} if the storage is empty or {@code false} otherwise.
*/
public boolean isEmpty() {
return fStorage.isEmpty();
}
/**
* Clear all the entries for all resources and all languages.
*/
public void clear() {
synchronized (fStorage) {
fStorage.clear();
}
}
/**
* Find and return the equal list of entries from the pool.
*
* @param entries - list of entries to pool.
* @param copy - specify {@code true} to copy the list in order to prevent
* back-door modification on the original list changes.
* @return returns the list of entries from the pool.
*/
private static List<ICLanguageSettingEntry> getPooledList(List<ICLanguageSettingEntry> entries, boolean copy) {
if (entries == null)
return null;
List<ICLanguageSettingEntry> pooledList = listPool.get(entries);
if (pooledList != null) {
return pooledList;
}
if (entries.size() == 0) {
return getPooledEmptyList();
}
if (copy) {
entries = new ArrayList<ICLanguageSettingEntry>(entries);
}
pooledList = Collections.unmodifiableList(entries);
return listPool.add(pooledList);
}
/**
* Find and return the equal list of entries from the pool to conserve the memory.
*
* @param entries - list of entries to pool.
* @return returns the list of entries from the pool.
*/
public static List<ICLanguageSettingEntry> getPooledList(List<ICLanguageSettingEntry> entries) {
return getPooledList(entries, true);
}
/**
* @return Returns the empty immutable list which is pooled. Use this call rather than creating
* new empty array to ensure that faster shallow operator '==' can be used instead of equals()
* which goes deep on HashMaps.
*/
public static List<ICLanguageSettingEntry> getPooledEmptyList() {
List<ICLanguageSettingEntry> pooledEmptyList = Collections.emptyList();
return listPool.add(pooledEmptyList);
}
/**
* Clone storage for the entries. Copies references for lists of entries as a whole.
* Note that that is OK as the lists kept in storage are unmodifiable and pooled.
*/
@Override
public LanguageSettingsStorage clone() throws CloneNotSupportedException {
LanguageSettingsStorage storageClone = (LanguageSettingsStorage) super.clone();
storageClone.fStorage = new HashMap<String, Map<String, List<ICLanguageSettingEntry>>>();
synchronized (fStorage) {
Set<Entry<String, Map<String, List<ICLanguageSettingEntry>>>> entrySetLang = fStorage.entrySet();
for (Entry<String, Map<String, List<ICLanguageSettingEntry>>> entryLang : entrySetLang) {
String langId = entryLang.getKey();
Map<String, List<ICLanguageSettingEntry>> mapRc = entryLang.getValue();
Map<String, List<ICLanguageSettingEntry>> mapRcClone = new HashMap<String, List<ICLanguageSettingEntry>>();
Set<Entry<String, List<ICLanguageSettingEntry>>> entrySetRc = mapRc.entrySet();
for (Entry<String, List<ICLanguageSettingEntry>> entryRc : entrySetRc) {
String rcProjectPath = entryRc.getKey();
List<ICLanguageSettingEntry> lsEntries = entryRc.getValue();
// don't need to clone entries, they are from the LSE lists pool
mapRcClone.put(rcProjectPath, lsEntries);
}
storageClone.fStorage.put(langId, mapRcClone);
}
}
return storageClone;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((fStorage == null) ? 0 : fStorage.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LanguageSettingsStorage other = (LanguageSettingsStorage) obj;
if (fStorage == null) {
if (other.fStorage != null)
return false;
} else if (!fStorage.equals(other.fStorage))
return false;
return true;
}
}

View file

@ -0,0 +1,99 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.language.settings.providers;
import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.internal.core.LocalProjectScope;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
/**
* Collection of utilities for legacy support of older Scanner Discovery functionality.
* This class is temporary and not intended to be used by clients.
*
* @noextend This class is not intended to be subclassed by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*
* @since 5.4
*/
public class ScannerDiscoveryLegacySupport {
/** ID of User language settings provider (from org.eclipse.cdt.ui) */
public static final String USER_LANGUAGE_SETTINGS_PROVIDER_ID = "org.eclipse.cdt.ui.UserLanguageSettingsProvider"; //$NON-NLS-1$
/** ID of MBS language settings provider (from org.eclipse.cdt.managedbuilder.core) */
public static final String MBS_LANGUAGE_SETTINGS_PROVIDER_ID = "org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider"; //$NON-NLS-1$
private static String USE_LANGUAGE_SETTINGS_PROVIDERS_PREFERENCE = "enabled"; //$NON-NLS-1$
// the default needs to be "false" for legacy projects to be open with old SD enabled for MBS provider
private static boolean USE_LANGUAGE_SETTINGS_PROVIDERS_DEFAULT = false;
private static final String PREFERENCES_QUALIFIER = CCorePlugin.PLUGIN_ID;
private static final String LANGUAGE_SETTINGS_PROVIDERS_NODE = "languageSettingsProviders"; //$NON-NLS-1$
private static Preferences getPreferences(IProject project) {
if (project == null)
return InstanceScope.INSTANCE.getNode(PREFERENCES_QUALIFIER).node(LANGUAGE_SETTINGS_PROVIDERS_NODE);
else
return new LocalProjectScope(project).getNode(PREFERENCES_QUALIFIER).node(LANGUAGE_SETTINGS_PROVIDERS_NODE);
}
/**
* Checks if Language Settings functionality is enabled for given project.
*
* @param project - project to check the preference
* @return {@code true} if functionality is enabled
*
* @noreference This method is temporary and not intended to be referenced by clients.
*/
public static boolean isLanguageSettingsProvidersFunctionalityEnabled(IProject project) {
Preferences pref = getPreferences(project);
return pref.getBoolean(USE_LANGUAGE_SETTINGS_PROVIDERS_PREFERENCE, USE_LANGUAGE_SETTINGS_PROVIDERS_DEFAULT);
}
/**
* Enable/disable Language Settings functionality for the given project.
*
* @param project
* @param value {@code true} to enable or {@code false} to disable the functionality.
*
* @noreference This method is temporary and not intended to be referenced by clients.
*/
public static void setLanguageSettingsProvidersFunctionalityEnabled(IProject project, boolean value) {
Preferences pref = getPreferences(project);
pref.putBoolean(USE_LANGUAGE_SETTINGS_PROVIDERS_PREFERENCE, value);
try {
pref.flush();
} catch (BackingStoreException e) {
CCorePlugin.log(e);
}
}
/**
* @noreference This is internal helper method to support compatibility with previous versions
* which is not intended to be referenced by clients.
*/
public static boolean isMbsLanguageSettingsProviderOn(ICConfigurationDescription cfgDescription) {
if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) {
List<ILanguageSettingsProvider> lsProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
for (ILanguageSettingsProvider lsp : lsProviders) {
if (MBS_LANGUAGE_SETTINGS_PROVIDER_ID.equals(lsp.getId())) {
return true;
}
}
}
return false;
}
}

View file

@ -40,10 +40,10 @@ public class LanguageSettingEntriesSerializer {
public static final String ATTRIBUTE_SOURCE_ATTACHMENT_PATH = "srcPath"; //$NON-NLS-1$
public static final String ATTRIBUTE_SOURCE_ATTACHMENT_ROOT_PATH = "srcRootPath"; //$NON-NLS-1$
public static final String ATTRIBUTE_SOURCE_ATTACHMENT_PREFIX_MAPPING = "srcPrefixMapping"; //$NON-NLS-1$
// public static final String ATTRIBUTE_FULL_PATH = "fullPath"; //$NON-NLS-1$
// public static final String ATTRIBUTE_LOCATION = "location"; //$NON-NLS-1$
public static final String INCLUDE_PATH = "includePath"; //$NON-NLS-1$
public static final String INCLUDE_FILE = "includeFile"; //$NON-NLS-1$
@ -59,7 +59,9 @@ public class LanguageSettingEntriesSerializer {
public static final String LOCAL = "LOCAL"; //$NON-NLS-1$
public static final String VALUE_WORKSPACE_PATH = "VALUE_WORKSPACE_PATH"; //$NON-NLS-1$
public static final String RESOLVED = "RESOLVED"; //$NON-NLS-1$
private static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
private static final String FRAMEWORK = "FRAMEWORK"; //$NON-NLS-1$
public static final String FLAGS_SEPARATOR = "|"; //$NON-NLS-1$
public static ICSettingEntry[] loadEntries(ICStorageElement el){
@ -84,7 +86,7 @@ public class LanguageSettingEntriesSerializer {
child = children[i];
if(ELEMENT_ENTRY.equals(child.getName())){
entry = loadEntry(child);
if(entry != null
if(entry != null
&& (kindFilter == 0
|| (kindFilter & entry.getKind()) != 0))
list.add(entry);
@ -97,11 +99,11 @@ public class LanguageSettingEntriesSerializer {
int kind = stringToKind(el.getAttribute(ATTRIBUTE_KIND));
if(kind == 0)
return null;
int flags = composeFlags(el.getAttribute(ATTRIBUTE_FLAGS));
String name = el.getAttribute(ATTRIBUTE_NAME);
switch(kind){
case ICSettingEntry.INCLUDE_PATH:
return new CIncludePathEntry(name, flags);
@ -126,7 +128,7 @@ public class LanguageSettingEntriesSerializer {
}
return null;
}
private static IPath loadPath(ICStorageElement el, String attr){
String value = el.getAttribute(attr);
if(value != null)
@ -149,18 +151,18 @@ public class LanguageSettingEntriesSerializer {
}
return paths;
}
return null;
return null;
}
private static void storeExclusions(ICStorageElement el, IPath[] paths){
if(paths == null || paths.length == 0)
return;
String[] strs = new String[paths.length];
for(int i = 0; i < strs.length; i++){
strs[i] = paths[i].toString();
}
String attr = CDataUtil.arrayToString(strs, FLAGS_SEPARATOR);
el.setAttribute(ATTRIBUTE_EXCLUDING, attr);
}
@ -174,7 +176,7 @@ public class LanguageSettingEntriesSerializer {
}
}
}
public static void serializeEntry(ICSettingEntry entry, ICStorageElement element){
String kind = kindToString(entry.getKind());
String flags = composeFlagsString(entry.getFlags());
@ -197,7 +199,7 @@ public class LanguageSettingEntriesSerializer {
IPath path = libFile.getSourceAttachmentPath();
if(path != null)
element.setAttribute(ATTRIBUTE_SOURCE_ATTACHMENT_PATH, path.toString());
path = libFile.getSourceAttachmentRootPath();
if(path != null)
element.setAttribute(ATTRIBUTE_SOURCE_ATTACHMENT_ROOT_PATH, path.toString());
@ -207,7 +209,7 @@ public class LanguageSettingEntriesSerializer {
element.setAttribute(ATTRIBUTE_SOURCE_ATTACHMENT_PREFIX_MAPPING, path.toString());
}
}
public static String kindToString(int kind){
switch(kind){
case ICSettingEntry.INCLUDE_PATH:
@ -259,34 +261,49 @@ public class LanguageSettingEntriesSerializer {
if((flags & ICSettingEntry.READONLY) != 0){
if(buf.length() != 0)
buf.append(FLAGS_SEPARATOR);
buf.append(READONLY);
}
if((flags & ICSettingEntry.LOCAL) != 0){
if(buf.length() != 0)
buf.append(FLAGS_SEPARATOR);
buf.append(LOCAL);
}
if((flags & ICSettingEntry.VALUE_WORKSPACE_PATH) != 0){
if(buf.length() != 0)
buf.append(FLAGS_SEPARATOR);
buf.append(VALUE_WORKSPACE_PATH);
}
if((flags & ICSettingEntry.RESOLVED) != 0){
if(buf.length() != 0)
buf.append(FLAGS_SEPARATOR);
buf.append(RESOLVED);
}
if((flags & ICLanguageSettingEntry.UNDEFINED) != 0){
if(buf.length() != 0)
buf.append(FLAGS_SEPARATOR);
buf.append(UNDEFINED);
}
if((flags & ICLanguageSettingEntry.FRAMEWORKS_MAC) != 0){
if(buf.length() != 0)
buf.append(FLAGS_SEPARATOR);
buf.append(FRAMEWORK);
}
return buf.toString();
}
private static int composeFlags(String flagsString){
/**
* @since 5.4
*/
public static int composeFlags(String flagsString){
if(flagsString == null || flagsString.length() == 0)
return 0;
StringTokenizer tokenizer = new StringTokenizer(flagsString, FLAGS_SEPARATOR);
int flags = 0;
String f;
@ -301,9 +318,13 @@ public class LanguageSettingEntriesSerializer {
if(VALUE_WORKSPACE_PATH.equals(f))
flags |= ICSettingEntry.VALUE_WORKSPACE_PATH;
if(RESOLVED.equals(f))
flags |= ICSettingEntry.RESOLVED;
flags |= ICSettingEntry.RESOLVED;
if(UNDEFINED.equals(f))
flags |= ICSettingEntry.UNDEFINED;
if(FRAMEWORK.equals(f))
flags |= ICSettingEntry.FRAMEWORKS_MAC;
}
return flags;
}

View file

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2011, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.language.settings.providers;
import java.util.LinkedHashMap;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
/**
* Contains the delta of changes that occurred as a result of modifying
* language settings entries {@link ICLanguageSettingEntry}. The delta is
* associated with a configuration description.
*
* <p>
* <strong>EXPERIMENTAL</strong>. This class interface is not stable yet as
* it is not currently clear how it may need to be used in future. Only bare
* minimum is provided here at this point (CDT 9.0, Juno).
* There is no guarantee that this API will work or that it will remain the same.
* Please do not use this API without consulting with the CDT team.
* </p>
*
* @noextend This interface is not intended to be extended by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public class LanguageSettingsDelta {
// maps need to be ordered by providers
@SuppressWarnings("unused")
private LinkedHashMap<String/*providerId*/, LanguageSettingsStorage> oldLanguageSettingsState;
@SuppressWarnings("unused")
private LinkedHashMap<String/*providerId*/, LanguageSettingsStorage> newLanguageSettingsState;
/**
* Constructor.
*
* @param oldState - old language settings storage state.
* @param newState - new language settings storage state.
*/
public LanguageSettingsDelta(LinkedHashMap<String, LanguageSettingsStorage> oldState, LinkedHashMap<String, LanguageSettingsStorage> newState) {
oldLanguageSettingsState = oldState;
newLanguageSettingsState = newState;
}
}

View file

@ -0,0 +1,396 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.language.settings.providers;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.cdt.core.AbstractExecutableExtensionBase;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsBaseProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsGenericProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializableProvider;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
/**
* Class {@code LanguageSettingsExtensionManager} manages {@link ILanguageSettingsProvider} extensions
*/
public class LanguageSettingsExtensionManager {
/** Name of the extension point for contributing language settings */
static final String PROVIDER_EXTENSION_POINT_ID = "org.eclipse.cdt.core.LanguageSettingsProvider"; //$NON-NLS-1$
static final String PROVIDER_EXTENSION_SIMPLE_ID = "LanguageSettingsProvider"; //$NON-NLS-1$
static final String ATTR_ID = "id"; //$NON-NLS-1$
static final String ATTR_NAME = "name"; //$NON-NLS-1$
static final String ATTR_CLASS = "class"; //$NON-NLS-1$
static final String ATTR_PREFER_NON_SHARED = "prefer-non-shared"; //$NON-NLS-1$
static final String ELEM_PROVIDER = "provider"; //$NON-NLS-1$
static final String ELEM_LANGUAGE_SCOPE = "language-scope"; //$NON-NLS-1$
static final String ELEM_ENTRY = "entry"; //$NON-NLS-1$
static final String ATTR_ENTRY_NAME = "name"; //$NON-NLS-1$
static final String ATTR_ENTRY_KIND = "kind"; //$NON-NLS-1$
static final String ATTR_ENTRY_VALUE = "value"; //$NON-NLS-1$
static final String ELEM_ENTRY_FLAG = "flag"; //$NON-NLS-1$
/**
* Extension providers loaded once and used for equality only.
* Those who request extension provider will get copy rather than real instance.
*/
private static final LinkedHashMap<String, ILanguageSettingsProvider> fExtensionProviders = new LinkedHashMap<String, ILanguageSettingsProvider>();
/**
* Providers loaded initially via static initializer.
*/
static {
try {
loadProviderExtensions();
} catch (Throwable e) {
CCorePlugin.log("Error loading language settings providers extensions", e); //$NON-NLS-1$
}
}
/**
* Load language settings providers contributed via the extension point.
*/
synchronized private static void loadProviderExtensions() {
// sort by name - the providers defined via extensions are kept in separate list sorted by name
Set<ILanguageSettingsProvider> sortedProviders = new TreeSet<ILanguageSettingsProvider>(
new Comparator<ILanguageSettingsProvider>() {
@Override
public int compare(ILanguageSettingsProvider pr1, ILanguageSettingsProvider pr2) {
return pr1.getName().compareTo(pr2.getName());
}
}
);
loadProviderExtensions(Platform.getExtensionRegistry(), sortedProviders);
fExtensionProviders.clear();
for (ILanguageSettingsProvider provider : sortedProviders) {
fExtensionProviders.put(provider.getId(), provider);
}
}
/**
* Load contributed extensions from extension registry.
*
* @param registry - extension registry
* @param providers - resulting set of providers
*/
private static void loadProviderExtensions(IExtensionRegistry registry, Set<ILanguageSettingsProvider> providers) {
providers.clear();
IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, PROVIDER_EXTENSION_SIMPLE_ID);
if (extension != null) {
IExtension[] extensions = extension.getExtensions();
for (IExtension ext : extensions) {
for (IConfigurationElement cfgEl : ext.getConfigurationElements()) {
ILanguageSettingsProvider provider = null;
String id = null;
try {
if (cfgEl.getName().equals(ELEM_PROVIDER)) {
id = determineAttributeValue(cfgEl, ATTR_ID);
provider = createExecutableExtension(cfgEl);
configureExecutableProvider(provider, cfgEl);
providers.add(provider);
}
} catch (Throwable e) {
CCorePlugin.log("Cannot load LanguageSettingsProvider extension id=" + id, e); //$NON-NLS-1$
}
}
}
}
}
private static String determineAttributeValue(IConfigurationElement ce, String attr) {
String value = ce.getAttribute(attr);
return value != null ? value : ""; //$NON-NLS-1$
}
/**
* Creates empty non-configured provider as executable extension from extension point definition.
* If "class" attribute is empty {@link LanguageSettingsBaseProvider} is created.
*
* @param ce - configuration element with provider definition
* @return new non-configured provider
* @throws CoreException in case of failure
*/
private static ILanguageSettingsProvider createExecutableExtension(IConfigurationElement ce) throws CoreException {
String ceClass = ce.getAttribute(ATTR_CLASS);
ILanguageSettingsProvider provider = null;
if (ceClass==null || ceClass.trim().length()==0 || ceClass.equals(LanguageSettingsBaseProvider.class.getCanonicalName())) {
provider = new LanguageSettingsBaseProvider();
} else {
provider = (ILanguageSettingsProvider)ce.createExecutableExtension(ATTR_CLASS);
}
return provider;
}
/**
* Configure language settings provider with parameters defined in XML metadata.
*
* @param provider - empty non-configured provider.
* @param ce - configuration element from registry representing XML.
*/
private static void configureExecutableProvider(ILanguageSettingsProvider provider, IConfigurationElement ce) {
String ceId = determineAttributeValue(ce, ATTR_ID);
String ceName = determineAttributeValue(ce, ATTR_NAME);
Map<String, String> ceAttributes = new HashMap<String, String>();
List<String> languages = null;
List<ICLanguageSettingEntry> entries = null;
for (String attr : ce.getAttributeNames()) {
if (!attr.equals(ATTR_ID) && !attr.equals(ATTR_NAME) && !attr.equals(ATTR_CLASS)) {
ceAttributes.put(attr, determineAttributeValue(ce, attr));
}
}
for (IConfigurationElement ceLang : ce.getChildren(ELEM_LANGUAGE_SCOPE)) {
String langId = determineAttributeValue(ceLang, ATTR_ID);
if (langId.length() > 0) {
if (languages == null) {
languages = new ArrayList<String>();
}
languages.add(langId);
}
}
for (IConfigurationElement ceEntry : ce.getChildren(ELEM_ENTRY)) {
try {
int entryKind = LanguageSettingEntriesSerializer.stringToKind(determineAttributeValue(ceEntry, ATTR_ENTRY_KIND));
String entryName = determineAttributeValue(ceEntry, ATTR_ENTRY_NAME);
String entryValue = determineAttributeValue(ceEntry, ATTR_ENTRY_VALUE);
int flags = 0;
for (IConfigurationElement ceFlags : ceEntry.getChildren(ELEM_ENTRY_FLAG)) {
int bitFlag = LanguageSettingEntriesSerializer.composeFlags(determineAttributeValue(ceFlags, ATTR_ENTRY_VALUE));
flags |= bitFlag;
}
ICLanguageSettingEntry entry = (ICLanguageSettingEntry) CDataUtil.createEntry(
entryKind, entryName, entryValue, null, flags);
if (entries == null) {
entries = new ArrayList<ICLanguageSettingEntry>();
}
entries.add(entry);
} catch (Exception e) {
CCorePlugin.log("Error creating language settings entry ", e); //$NON-NLS-1$
}
}
if (provider instanceof LanguageSettingsBaseProvider) {
((LanguageSettingsBaseProvider) provider).configureProvider(ceId, ceName, languages, entries, ceAttributes);
} else if (provider instanceof AbstractExecutableExtensionBase) {
((AbstractExecutableExtensionBase) provider).setId(ceId);
((AbstractExecutableExtensionBase) provider).setName(ceName);
}
}
/**
* Creates provider from extension point definition which matches value of the given attribute.
* The method will inspect extension registry for extension point "org.eclipse.cdt.core.LanguageSettingsProvider"
* to determine bundle and instantiate the class.
*
* @param attr - attribute to match.
* @param attrValue - value of the attribute to match.
* @param registry - extension registry.
* @param configure - flag which indicates if provider needs to be configured.
* @return new instance of the provider
*/
private static ILanguageSettingsProvider loadProviderFromRegistry(String attr, String attrValue,
IExtensionRegistry registry, boolean configure) {
try {
IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, PROVIDER_EXTENSION_SIMPLE_ID);
if (extension != null) {
IExtension[] extensions = extension.getExtensions();
for (IExtension ext : extensions) {
for (IConfigurationElement cfgEl : ext.getConfigurationElements()) {
if (cfgEl.getName().equals(ELEM_PROVIDER) && attrValue.equals(cfgEl.getAttribute(attr))) {
ILanguageSettingsProvider provider = createExecutableExtension(cfgEl);
if (configure) {
configureExecutableProvider(provider, cfgEl);
}
return provider;
}
}
}
}
} catch (Exception e) {
CCorePlugin.log("Error creating language settings provider.", e); //$NON-NLS-1$
}
return null;
}
/**
* Create an instance of non-configured language settings provider of given class name.
* The class should be known to this method or registered with the extension point.
*
* @param className - class name to instantiate.
* @return new instance of language settings provider.
*
* @throws CoreException if not able to create a new instance.
*/
/*package*/ static ILanguageSettingsProvider instantiateProviderClass(String className) throws CoreException {
if (className==null || className.equals(LanguageSettingsSerializableProvider.class.getName())) {
return new LanguageSettingsSerializableProvider();
}
if (className.equals(LanguageSettingsGenericProvider.class.getName())) {
return new LanguageSettingsGenericProvider();
}
// Create it as executable extension from the extension registry.
ILanguageSettingsProvider provider = loadProviderFromRegistry(ATTR_CLASS, className, Platform.getExtensionRegistry(), false);
if (provider == null) {
String msg = "Not able to load provider class=" + className; //$NON-NLS-1$
throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, msg));
}
return provider;
}
/**
* Load an instance of language settings provider of given id from the extension point.
* The class should be registered with the extension point.
*
* @param id - class name to instantiate.
* @return new instance of language settings provider.
*/
/*package*/ static ILanguageSettingsProvider loadProvider(String id) {
if (id==null) {
return null;
}
// Create it as executable extension from the extension registry.
ILanguageSettingsProvider provider = loadProviderFromRegistry(ATTR_ID, id, Platform.getExtensionRegistry(), true);
if (provider == null) {
String msg = "Not able to load provider id=" + id; //$NON-NLS-1$
CCorePlugin.log(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, msg, new Exception(msg)));
}
return provider;
}
/**
* Returns list of provider id-s contributed by all extensions.
* @return the provider id-s.
*/
public static Set<String> getExtensionProviderIds() {
return fExtensionProviders.keySet();
}
/**
* Copy language settings provider. It is different from clone() methods in that
* it does not throw {@code CloneNotSupportedException} but returns {@code null}
* instead.
*
* @param provider - language settings provider to copy.
* @param deep - {@code true} to request deep copy including copying settings entries
* or {@code false} to return shallow copy with no settings entries.
*
* @return a copy of the provider or {@code null} if copying is not possible.
*/
public static ILanguageSettingsEditableProvider getProviderCopy(ILanguageSettingsEditableProvider provider, boolean deep) {
try {
if (deep) {
return provider.clone();
} else {
return provider.cloneShallow();
}
} catch (CloneNotSupportedException e) {
CCorePlugin.log("Error cloning provider " + provider.getId() + ", class " + provider.getClass(), e); //$NON-NLS-1$ //$NON-NLS-2$
}
return null;
}
/**
* Get language settings provider defined via extension point
* {@code org.eclipse.cdt.core.LanguageSettingsProvider}.
* A new copy of the extension provider is returned.
*
* @param id - ID of the extension provider.
* @param deep - {@code true} to request deep copy including copying settings entries
* or {@code false} to return shallow copy with no settings entries.
* @return the copy of the extension provider if possible (i.e. for {@link ILanguageSettingsEditableProvider})
* or {@code null} if provider is not copyable.
*/
public static ILanguageSettingsProvider getExtensionProviderCopy(String id, boolean deep) {
ILanguageSettingsProvider provider = fExtensionProviders.get(id);
if (provider instanceof ILanguageSettingsEditableProvider) {
return getProviderCopy((ILanguageSettingsEditableProvider) provider, deep);
}
return null;
}
/**
* Test if the provider is equal to the one defined via extension point
* {@code org.eclipse.cdt.core.LanguageSettingsProvider}.
*
* @param provider - the provider to test.
* @param deep - {@code true} to check for deep equality testing also settings entries
* or {@code false} to test shallow copy with no settings entries.
* Shallow equality is applicable only for {@link ILanguageSettingsEditableProvider}.
* @return - {@code true} if the provider matches the extension or {@code false} otherwise.
*/
public static boolean isEqualExtensionProvider(ILanguageSettingsProvider provider, boolean deep) {
String id = provider.getId();
if (deep || !(provider instanceof ILanguageSettingsEditableProvider)) {
ILanguageSettingsProvider extensionProvider = fExtensionProviders.get(id);
return provider.equals(extensionProvider);
} else {
ILanguageSettingsEditableProvider providerShallow = getProviderCopy((ILanguageSettingsEditableProvider) provider, false);
ILanguageSettingsProvider extensionProviderShallow = getExtensionProviderCopy(id, false);
return providerShallow == extensionProviderShallow
|| (providerShallow != null && providerShallow.equals(extensionProviderShallow));
}
}
/**
* Tells if the provider is meant to be shared between projects in workspace
* or belong to a specific configuration. This attribute is defined in
* {@code org.eclipse.cdt.core.LanguageSettingsProvider} extension point.
* <br>Note that only {@link ILanguageSettingsEditableProvider} can be owned by
* a configuration.
*
* @param id - ID of the provider to inquire.
* @return {@code true} if the provider is designed to be shared,
* {@code false} if configuration-owned.
*/
public static boolean isPreferShared(String id) {
ILanguageSettingsProvider provider = fExtensionProviders.get(id);
if (provider instanceof LanguageSettingsBaseProvider && provider instanceof ILanguageSettingsEditableProvider) {
return ! ((LanguageSettingsBaseProvider) provider).getPropertyBool(ATTR_PREFER_NON_SHARED);
}
return true;
}
}

View file

@ -0,0 +1,270 @@
/*******************************************************************************
* Copyright (c) 2010, 2012 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.language.settings.providers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfoChangeListener;
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
import org.eclipse.cdt.core.settings.model.ACPathEntry;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICMacroEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.cdt.internal.core.settings.model.SettingsModelMessages;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;
/**
* Implementation of {@link IScannerInfoProvider} backed by the list of
* language settings providers of "default settings configuration"
* (see {@link ICProjectDescription#getDefaultSettingConfiguration()}).
*
* @see IScannerInfo#getIncludePaths()
*
*/
public class LanguageSettingsScannerInfoProvider implements IScannerInfoProvider {
private static final String FRAMEWORK_PRIVATE_HEADERS_INCLUDE = "/__framework__.framework/PrivateHeaders/__header__"; //$NON-NLS-1$
private static final String FRAMEWORK_HEADERS_INCLUDE = "/__framework__.framework/Headers/__header__"; //$NON-NLS-1$
private static final ExtendedScannerInfo DUMMY_SCANNER_INFO = new ExtendedScannerInfo();
@Override
public ExtendedScannerInfo getScannerInformation(IResource rc) {
IProject project = rc.getProject();
if (project==null)
return DUMMY_SCANNER_INFO;
ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false);
if (prjDescription==null)
return DUMMY_SCANNER_INFO;
ICConfigurationDescription cfgDescription = prjDescription.getDefaultSettingConfiguration();
if (cfgDescription==null)
return DUMMY_SCANNER_INFO;
List<String> languageIds = LanguageSettingsManager.getLanguages(rc, cfgDescription);
if (languageIds.isEmpty()) {
String msg = NLS.bind(SettingsModelMessages.getString("LanguageSettingsScannerInfoProvider.UnableToDetermineLanguage"), rc.toString()); //$NON-NLS-1$
IStatus status = new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, msg, new Exception());
CCorePlugin.log(status);
return DUMMY_SCANNER_INFO;
}
LinkedHashSet<ICLanguageSettingEntry> includePathEntries = new LinkedHashSet<ICLanguageSettingEntry>();
LinkedHashSet<ICLanguageSettingEntry> includePathLocalEntries = new LinkedHashSet<ICLanguageSettingEntry>();
LinkedHashSet<ICLanguageSettingEntry> includeFileEntries = new LinkedHashSet<ICLanguageSettingEntry>();
LinkedHashSet<ICLanguageSettingEntry> macroFileEntries = new LinkedHashSet<ICLanguageSettingEntry>();
LinkedHashSet<ICLanguageSettingEntry> macroEntries = new LinkedHashSet<ICLanguageSettingEntry>();
for (String langId : languageIds) {
List<ICLanguageSettingEntry> incSys = LanguageSettingsProvidersSerializer.getSystemSettingEntriesByKind(cfgDescription, rc, langId,
ICSettingEntry.INCLUDE_PATH);
includePathEntries.addAll(incSys);
List<ICLanguageSettingEntry> incLocal = LanguageSettingsProvidersSerializer.getLocalSettingEntriesByKind(cfgDescription, rc, langId,
ICSettingEntry.INCLUDE_PATH);
includePathLocalEntries.addAll(incLocal);
List<ICLanguageSettingEntry> incFiles = LanguageSettingsProvidersSerializer.getSettingEntriesByKind(cfgDescription, rc, langId,
ICSettingEntry.INCLUDE_FILE);
includeFileEntries.addAll(incFiles);
List<ICLanguageSettingEntry> macroFiles = LanguageSettingsProvidersSerializer.getSettingEntriesByKind(cfgDescription, rc, langId,
ICSettingEntry.MACRO_FILE);
macroFileEntries.addAll(macroFiles);
List<ICLanguageSettingEntry> macros = LanguageSettingsProvidersSerializer.getSettingEntriesByKind(cfgDescription, rc, langId,
ICSettingEntry.MACRO);
macroEntries.addAll(macros);
}
String[] includePaths = convertToLocations(includePathEntries, cfgDescription);
String[] includePathsLocal = convertToLocations(includePathLocalEntries, cfgDescription);
String[] includeFiles = convertToLocations(includeFileEntries, cfgDescription);
String[] macroFiles = convertToLocations(macroFileEntries, cfgDescription);
Map<String, String> definedMacros = new HashMap<String, String>();
for (ICLanguageSettingEntry entry : macroEntries) {
ICMacroEntry macroEntry = (ICMacroEntry)entry;
String name = macroEntry.getName();
String value = macroEntry.getValue();
definedMacros.put(name, value);
}
return new ExtendedScannerInfo(definedMacros, includePaths, macroFiles, includeFiles, includePathsLocal);
}
private IPath expandVariables(IPath path, ICConfigurationDescription cfgDescription) {
ICdtVariableManager varManager = CCorePlugin.getDefault().getCdtVariableManager();
String pathStr = path.toString();
try {
pathStr = varManager.resolveValue(pathStr, "", null, cfgDescription); //$NON-NLS-1$
} catch (CdtVariableException e) {
// Swallow exceptions but also log them
CCorePlugin.log(e);
}
IPath resolvedLoc = new Path(pathStr);
return resolvedLoc;
}
/**
* Get build working directory for the provided configuration. Returns
* project location if none defined.
*/
private static IPath getBuildCWD(ICConfigurationDescription cfgDescription) {
IPath buildCWD = cfgDescription.getBuildSetting().getBuilderCWD();
if (buildCWD==null) {
IProject project = cfgDescription.getProjectDescription().getProject();
buildCWD = project.getLocation();
} else {
ICdtVariableManager mngr = CCorePlugin.getDefault().getCdtVariableManager();
try {
// Note that IPath buildCWD holding variables is mis-constructed,
// i.e. ${workspace_loc:/path} gets split into 2 path segments
// still, MBS does that and we need to handle that
String buildPathString = buildCWD.toString();
buildPathString = mngr.resolveValue(buildPathString, "", null, cfgDescription); //$NON-NLS-1$
buildCWD = new Path(buildPathString);
} catch (CdtVariableException e) {
CCorePlugin.log(e);
}
}
buildCWD = buildCWD.addTrailingSeparator();
return buildCWD;
}
/**
* Resolve location to file system location in a configuration context.
* Resolving includes replacing build/environment variables with values, making relative path absolute etc.
*
* @param location - location to resolve. If relative, it is taken to be rooted in build working directory.
* @param cfgDescription - the configuration context.
* @return resolved file system location.
*/
private static String resolveEntry(String location, ICConfigurationDescription cfgDescription) {
// Substitute build/environment variables
ICdtVariableManager varManager = CCorePlugin.getDefault().getCdtVariableManager();
try {
location = varManager.resolveValue(location, "", null, cfgDescription); //$NON-NLS-1$
} catch (CdtVariableException e) {
// Swallow exceptions but also log them
CCorePlugin.log(e);
}
// use OS file separators (i.e. '\' on Windows)
if (java.io.File.separatorChar != '/') {
location = location.replace('/', java.io.File.separatorChar);
}
// note that we avoid using org.eclipse.core.runtime.Path for manipulations being careful
// to preserve "../" segments and not let collapsing them which is not correct for symbolic links.
Path locPath = new Path(location);
if (locPath.isAbsolute() && locPath.getDevice()==null) {
// prepend device (C:) for Windows
IPath buildCWD = getBuildCWD(cfgDescription);
String device = buildCWD.getDevice();
if (device!=null)
location = device + location;
}
if (!locPath.isAbsolute()) {
// consider relative path to be from build working directory
IPath buildCWD = getBuildCWD(cfgDescription);
location = buildCWD.toOSString() + locPath;
}
return location;
}
/**
* Convert the path entries to absolute file system locations represented as String array.
* Resolve the entries which are not resolved.
*
* @param entriesPath - language settings path entries.
* @param cfgDescription - configuration description for resolving entries.
* @return array of the locations.
*/
private String[] convertToLocations(LinkedHashSet<ICLanguageSettingEntry> entriesPath, ICConfigurationDescription cfgDescription){
List<String> locations = new ArrayList<String>(entriesPath.size());
for (ICLanguageSettingEntry entry : entriesPath) {
ACPathEntry entryPath = (ACPathEntry)entry;
if (entryPath.isValueWorkspacePath()) {
IPath loc = entryPath.getLocation();
if (loc!=null) {
if (checkBit(entryPath.getFlags(), ICSettingEntry.FRAMEWORKS_MAC)) {
// handle frameworks, see IScannerInfo.getIncludePaths()
locations.add(loc.append(FRAMEWORK_HEADERS_INCLUDE).toOSString());
locations.add(loc.append(FRAMEWORK_PRIVATE_HEADERS_INCLUDE).toOSString());
} else {
locations.add(loc.toOSString());
}
}
} else {
String locStr = entryPath.getName();
if (entryPath.isResolved()) {
locations.add(locStr);
} else {
locStr = resolveEntry(locStr, cfgDescription);
if (locStr!=null) {
if (checkBit(entryPath.getFlags(), ICSettingEntry.FRAMEWORKS_MAC)) {
// handle frameworks, see IScannerInfo.getIncludePaths()
locations.add(locStr+FRAMEWORK_HEADERS_INCLUDE);
locations.add(locStr+FRAMEWORK_PRIVATE_HEADERS_INCLUDE);
} else {
locations.add(locStr);
// add relative paths again for indexer to resolve from source file location
IPath unresolvedPath = entryPath.getLocation();
if (!unresolvedPath.isAbsolute()) {
IPath expandedPath = expandVariables(unresolvedPath, cfgDescription);
if (!expandedPath.isAbsolute()) {
locations.add(expandedPath.toOSString());
}
}
}
}
}
}
}
return locations.toArray(new String[locations.size()]);
}
private static boolean checkBit(int flags, int bit) {
return (flags & bit) == bit;
}
@Override
public void subscribe(IResource resource, IScannerInfoChangeListener listener) {
// Handled by ScannerInfoProviderProxy for the moment
}
@Override
public void unsubscribe(IResource resource, IScannerInfoChangeListener listener) {
// Handled by ScannerInfoProviderProxy for the moment
}
}

View file

@ -0,0 +1,228 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.language.settings.providers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The class representing persistent storage for language settings entries {@link ICLanguageSettingEntry}.
*/
public class LanguageSettingsSerializableStorage extends LanguageSettingsStorage {
private static final String ELEM_LANGUAGE = "language"; //$NON-NLS-1$
private static final String ATTR_LANGUAGE_ID = "id"; //$NON-NLS-1$
private static final String ELEM_RESOURCE = "resource"; //$NON-NLS-1$
private static final String ATTR_PROJECT_PATH = "project-relative-path"; //$NON-NLS-1$
private static final String ELEM_ENTRY = LanguageSettingsExtensionManager.ELEM_ENTRY;
private static final String ATTR_ENTRY_KIND = LanguageSettingsExtensionManager.ATTR_ENTRY_KIND;
private static final String ATTR_ENTRY_NAME = LanguageSettingsExtensionManager.ATTR_ENTRY_NAME;
private static final String ATTR_ENTRY_VALUE = LanguageSettingsExtensionManager.ATTR_ENTRY_VALUE;
private static final String ELEM_ENTRY_FLAG = LanguageSettingsExtensionManager.ELEM_ENTRY_FLAG;
/**
* Serialize the provider entries under parent XML element.
*
* @param elementProvider - element where to serialize the entries.
*/
public void serializeEntries(Element elementProvider) {
synchronized (fStorage) {
for (Entry<String, Map<String, List<ICLanguageSettingEntry>>> entryLang : fStorage.entrySet()) {
serializeLanguage(elementProvider, entryLang.getKey(), entryLang.getValue());
}
}
}
/**
* Serialize the provider entries for a given language list.
*/
private void serializeLanguage(Element parentElement, String langId, Map<String, List<ICLanguageSettingEntry>> langMap) {
if (langId!=null) {
Element elementLanguage = XmlUtil.appendElement(parentElement, ELEM_LANGUAGE, new String[] {ATTR_LANGUAGE_ID, langId});
parentElement = elementLanguage;
}
for (Entry<String, List<ICLanguageSettingEntry>> entryRc : langMap.entrySet()) {
serializeResource(parentElement, entryRc.getKey(), entryRc.getValue());
}
}
/**
* Serialize the provider entries for a given resource list.
*/
private void serializeResource(Element parentElement, String rcProjectPath, List<ICLanguageSettingEntry> rcList) {
if (rcProjectPath!=null) {
Element elementRc = XmlUtil.appendElement(parentElement, ELEM_RESOURCE, new String[] {ATTR_PROJECT_PATH, rcProjectPath});
parentElement = elementRc;
}
serializeSettingEntries(parentElement, rcList);
}
/**
* Serialize given settings entries.
*/
private void serializeSettingEntries(Element parentElement, List<ICLanguageSettingEntry> settingEntries) {
for (ICLanguageSettingEntry entry : settingEntries) {
Element elementSettingEntry = XmlUtil.appendElement(parentElement, ELEM_ENTRY, new String[] {
ATTR_ENTRY_KIND, LanguageSettingEntriesSerializer.kindToString(entry.getKind()),
ATTR_ENTRY_NAME, entry.getName(),
});
switch (entry.getKind()) {
case ICSettingEntry.MACRO:
elementSettingEntry.setAttribute(ATTR_ENTRY_VALUE, entry.getValue());
break;
// case ICLanguageSettingEntry.LIBRARY_FILE:
// // YAGNI: sourceAttachment fields may need to be covered
// break;
}
int flags = entry.getFlags();
if (flags != 0) {
// Element elementFlag =
XmlUtil.appendElement(elementSettingEntry, ELEM_ENTRY_FLAG, new String[] {
ATTR_ENTRY_VALUE, LanguageSettingEntriesSerializer.composeFlagsString(entry.getFlags())
});
}
}
}
/**
* Load provider entries from XML provider element.
*
* @param providerNode - parent XML element "provider" where entries are defined.
*/
public void loadEntries(Element providerNode) {
List<ICLanguageSettingEntry> settings = new ArrayList<ICLanguageSettingEntry>();
NodeList nodes = providerNode.getChildNodes();
for (int i=0;i<nodes.getLength();i++) {
Node elementNode = nodes.item(i);
if (elementNode.getNodeType() != Node.ELEMENT_NODE)
continue;
if (ELEM_LANGUAGE.equals(elementNode.getNodeName())) {
loadLanguageElement(elementNode, null);
} else if (ELEM_RESOURCE.equals(elementNode.getNodeName())) {
loadResourceElement(elementNode, null, null);
} else if (ELEM_ENTRY.equals(elementNode.getNodeName())) {
ICLanguageSettingEntry entry = loadSettingEntry(elementNode);
if (entry!=null) {
settings.add(entry);
}
}
}
// set settings
if (settings.size() > 0) {
setSettingEntries(null, null, settings);
}
}
/**
* Load a setting entry from XML element.
*/
private ICLanguageSettingEntry loadSettingEntry(Node parentElement) {
String settingKind = XmlUtil.determineAttributeValue(parentElement, ATTR_ENTRY_KIND);
String settingName = XmlUtil.determineAttributeValue(parentElement, ATTR_ENTRY_NAME);
NodeList flagNodes = parentElement.getChildNodes();
int flags = 0;
for (int i=0;i<flagNodes.getLength();i++) {
Node flagNode = flagNodes.item(i);
if (flagNode.getNodeType() != Node.ELEMENT_NODE || !ELEM_ENTRY_FLAG.equals(flagNode.getNodeName()))
continue;
String settingFlags = XmlUtil.determineAttributeValue(flagNode, ATTR_ENTRY_VALUE);
int bitFlag = LanguageSettingEntriesSerializer.composeFlags(settingFlags);
flags |= bitFlag;
}
String settingValue = null;
int kind = LanguageSettingEntriesSerializer.stringToKind(settingKind);
if (kind == ICSettingEntry.MACRO)
settingValue = XmlUtil.determineAttributeValue(parentElement, ATTR_ENTRY_VALUE);
ICLanguageSettingEntry entry = (ICLanguageSettingEntry) CDataUtil.createEntry(kind, settingName, settingValue, null, flags);
return entry;
}
/**
* Load entries defined in language element.
*/
private void loadLanguageElement(Node parentNode, String cfgId) {
String langId = XmlUtil.determineAttributeValue(parentNode, ATTR_LANGUAGE_ID);
if (langId.length() == 0) {
langId=null;
}
List<ICLanguageSettingEntry> settings = new ArrayList<ICLanguageSettingEntry>();
NodeList nodes = parentNode.getChildNodes();
for (int i=0;i<nodes.getLength();i++) {
Node elementNode = nodes.item(i);
if (elementNode.getNodeType() != Node.ELEMENT_NODE)
continue;
if (ELEM_RESOURCE.equals(elementNode.getNodeName())) {
loadResourceElement(elementNode, cfgId, langId);
} else if (ELEM_ENTRY.equals(elementNode.getNodeName())) {
ICLanguageSettingEntry entry = loadSettingEntry(elementNode);
if (entry!=null) {
settings.add(entry);
}
}
}
// set settings
if (settings.size() > 0) {
setSettingEntries(null, langId, settings);
}
}
/**
* Load entries defined in resource element.
*/
private void loadResourceElement(Node parentNode, String cfgId, String langId) {
String rcProjectPath = XmlUtil.determineAttributeValue(parentNode, ATTR_PROJECT_PATH);
List<ICLanguageSettingEntry> settings = new ArrayList<ICLanguageSettingEntry>();
NodeList nodes = parentNode.getChildNodes();
for (int i=0;i<nodes.getLength();i++) {
Node elementNode = nodes.item(i);
if (elementNode.getNodeType() != Node.ELEMENT_NODE)
continue;
if (ELEM_ENTRY.equals(elementNode.getNodeName())) {
ICLanguageSettingEntry entry = loadSettingEntry(elementNode);
if (entry!=null) {
settings.add(entry);
}
}
}
// set settings
if (settings.size() > 0) {
setSettingEntries(rcProjectPath, langId, settings);
}
}
@Override
public LanguageSettingsSerializableStorage clone() throws CloneNotSupportedException {
return (LanguageSettingsSerializableStorage) super.clone();
}
}

View file

@ -11,15 +11,21 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.settings.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsBroadcastingProvider;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage;
import org.eclipse.cdt.core.settings.model.CExternalSetting;
import org.eclipse.cdt.core.settings.model.ICBuildSetting;
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
@ -37,6 +43,7 @@ import org.eclipse.cdt.internal.core.COwner;
import org.eclipse.cdt.internal.core.COwnerConfiguration;
import org.eclipse.cdt.internal.core.cdtvariables.StorableCdtVariables;
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsDelta;
import org.eclipse.cdt.utils.envvar.StorableEnvironment;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
@ -87,6 +94,10 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
// private CConfigBasedDescriptor fDescriptor;
// private Map fExternalSettingsProviderMap;
private List<ILanguageSettingsProvider> fLanguageSettingsProviders = new ArrayList<ILanguageSettingsProvider>(0);
private LinkedHashMap<String /*provider*/, LanguageSettingsStorage> lspPersistedState = new LinkedHashMap<String, LanguageSettingsStorage>();
private class DeltaSet {
public Set<ICConfigExtensionReference> extSet;
public Set<String> idSet;
@ -977,4 +988,33 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
public void updateExternalSettingsProviders(String[] ids){
ExtensionContainerFactory.updateReferencedProviderIds(fCfg, ids);
}
/**
* Returns delta and updates last persisted state to the new state.
* That implies that the delta needs to be used to fire an event of it will
* be lost.
*/
public LanguageSettingsDelta dropDelta() {
LanguageSettingsDelta languageSettingsDelta = null;
LinkedHashMap<String, LanguageSettingsStorage> newState = new LinkedHashMap<String, LanguageSettingsStorage>();
for (ILanguageSettingsProvider provider : fLanguageSettingsProviders) {
if (LanguageSettingsManager.isWorkspaceProvider(provider)) {
provider = LanguageSettingsManager.getRawProvider(provider);
}
if (provider instanceof ILanguageSettingsBroadcastingProvider) {
LanguageSettingsStorage store = ((ILanguageSettingsBroadcastingProvider) provider).copyStorage();
// avoid triggering event if empty provider was added
if (store != null && !store.isEmpty()) {
newState.put(provider.getId(), store);
}
}
}
if (!newState.equals(lspPersistedState)) {
languageSettingsDelta = new LanguageSettingsDelta(lspPersistedState, newState);
lspPersistedState = newState;
}
return languageSettingsDelta;
}
}

View file

@ -15,8 +15,8 @@ CConfigurationDescription.0=data was not created
CConfigurationDescription.1=expected proxy of type ICFileDescription, but was
CConfigurationDescription.2=data was not created
CConfigurationDescription.3=expected proxy of type ICFolderDescription, but was
CConfigurationStatus.1=configurations settings invalid
CConfigurationDescriptionCache.0=description is read only
CConfigurationStatus.1=configurations settings invalid
CProjectConverterDesciptor.0=illegal provider implementation
CProjectConverterDesciptor.1=no provider defined
CProjectDescriptionManager.1=required build system is not installed
@ -49,5 +49,8 @@ CExternalSettingsManager.3=writable ref info is requested for the read only conf
CfgExportSettingContainerFactory.2=invalid id: project name not specified
ExtensionContainerFactory.4=invalid setting provider class specified
ExtensionContainerFactory.5=provider element not specified
LanguageSettingsBaseProvider.CanBeConfiguredOnlyOnce=LanguageSettingsBaseProvider can be configured only once
LanguageSettingsScannerInfoProvider.UnableToDetermineLanguage=Error getting ScannerInfo: Unable to determine language for resource {0}
SettingsContext.0=no project associated with the context
SettingsContext.1=can not accept the not-context project description

View file

@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsChangeEvent;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsChangeListener;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
/**
* This class handles changes in language settings for the PDOM.
*/
public class LanguageSettingsChangeListener implements ILanguageSettingsChangeListener {
private PDOMManager fManager;
/**
* Constructor.
*
* @param manager - PDOM manager.
*/
public LanguageSettingsChangeListener(PDOMManager manager) {
fManager = manager;
}
@Override
public void handleEvent(ILanguageSettingsChangeEvent event) {
IWorkspaceRoot wspRoot = ResourcesPlugin.getWorkspace().getRoot();
IProject project = wspRoot.getProject(event.getProjectName());
if (project != null) {
ICProjectDescription prjDescription = CCorePlugin.getDefault().getProjectDescription(project);
if (prjDescription != null) {
ICConfigurationDescription indexedCfgDescription = prjDescription.getDefaultSettingConfiguration();
String indexedCfgId = indexedCfgDescription.getId();
for (String cfgId : event.getConfigurationDescriptionIds()) {
if (cfgId.equals(indexedCfgId)) {
fManager.handlePostBuildEvent();
return;
}
}
}
}
}
}

View file

@ -26,6 +26,7 @@ ErrorParser.name=Error Parser
BinaryParser.name=Binary Parser
PathEntryStore.name=Path Entry Store
ScannerInfoProvider.name=Scanner Information Provider
LanguageSettingsProvider.name=Language Settings Provider
CIndexer.name= C/C++ Indexer
language.name= CDT Language

View file

@ -655,6 +655,7 @@
<extension-point id="ScannerInfoProvider2" name="%scannerInfoProvider2.name" schema="schema/ScannerInfoProvider2.exsd"/>
<extension-point id="EFSExtensionProvider" name="%efsExtensionProvider.name" schema="schema/EFSExtensionProvider.exsd"/>
<extension-point id="RefreshExclusionFactory" name="%refreshExclusionFactory.name" schema="schema/RefreshExclusionFactory.exsd"/>
<extension-point id="LanguageSettingsProvider" name="%LanguageSettingsProvider.name" schema="schema/LanguageSettingsProvider.exsd"/>
<extension-point id="UNCPathConverter" name="%uncPathConverter.name" schema="schema/UNCPathConverter.exsd"/>
<extension

View file

@ -0,0 +1,276 @@
<?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="LanguageSettingsProvider" name="LanguageSettingsProvider"/>
</appInfo>
<documentation>
This extension point is used to contribute a new Language Settings Provider. A Language Settings Provider is used to get additions to compiler options such as include paths (-I) or preprocessor defines (-D) and others into the project model.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
<documentation>
This extension point is used to contribute a new Language Settings Provider. A Language Settings Provider is used to get additions to compiler options such as include paths (-I) or preprocessor defines (-D) and others into the project model.
</documentation>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="provider"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
ID of the extension point, not used
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
Name of the extension point, not used
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="provider">
<annotation>
<documentation>
The definition of a language settings provider.
</documentation>
</annotation>
<complexType>
<sequence>
<element ref="language-scope" minOccurs="0" maxOccurs="unbounded"/>
<element ref="entry" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="class" type="string">
<annotation>
<documentation>
A fully qualified name of the Java class that implements &lt;samp&gt;org.eclipse.cdt.core.settings.model.ILanguageSettingsProvider&lt;/samp&gt; interface. If empty, &lt;samp&gt;org.eclipse.cdt.core.language.settings.providers.LanguageSettingsBaseProvider&lt;/samp&gt; is used by default which provides basic functionality defined by this extension point.
If there is a need to configure a provider in more deliberate way, attribute &lt;samp&gt;parameter&lt;/samp&gt; could be used in a class extending &lt;samp&gt;LanguageSettingsBaseProvider&lt;/samp&gt;.
Default constructor (constructor without arguments) of this class must be public and the package be exported in order to be able to instantiate via extension point.
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn="org.eclipse.cdt.core.language.settings.providers.LanguageSettingsBaseProvider:org.eclipse.cdt.core.settings.model.ILanguageSettingsProvider"/>
</appInfo>
</annotation>
</attribute>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
Unique ID of the provider.
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string" use="required">
<annotation>
<documentation>
Name of the provider. This name will be presented to a user in UI.
</documentation>
</annotation>
</attribute>
<attribute name="parameter" type="string">
<annotation>
<documentation>
A custom parameter to initialize provider. For example, used to deliver command for GCCBuiltinSpecsDetector.
</documentation>
</annotation>
</attribute>
<attribute name="prefer-non-shared" type="boolean" use="default" value="false">
<annotation>
<documentation>
A flag indicating that the provider should be owned by a configuration rather than be global in workspace and shared between projects (when the choice has not been indicated yet by other means). This preference is consulted in order to initially set the &quot;shared&quot; attribute, for example when a user adds a provider from the list of extension providers.
The value &quot;true&quot; of this attribute is meaningful only for providers capable of being non-shared, i.e. providers extending ILanguageSettingsEditableProvider.
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<element name="language-scope">
<annotation>
<documentation>
The definition of language scope. Includes the list of language ID this provider is applicable to. If a language scope is not present, the provider will provide for any language.
</documentation>
</annotation>
<complexType>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
ID of the language for which this provider provides the entries. As an example, those are languages contributed by CDT (see extension org.eclipse.cdt.core.language):
&lt;p&gt;- &quot;&lt;samp&gt;org.eclipse.cdt.core.gcc&lt;/samp&gt;&quot; for C,&lt;/p&gt;
&lt;p&gt;- &quot;&lt;samp&gt;org.eclipse.cdt.core.g++&lt;/samp&gt;&quot; for C++.&lt;/p&gt;
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<element name="entry">
<annotation>
<documentation>
The Language Settings Entries used to provide additions to compiler options such as include paths (-I) or preprocessor defines (-D) and others into the project model.
</documentation>
</annotation>
<complexType>
<sequence>
<element ref="flag" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="kind" use="required">
<annotation>
<documentation>
Kind of language settings entry which maps to compiler options. For example, following mapping is used for gcc options:
&lt;br&gt;&quot;&lt;samp&gt;-I&lt;/samp&gt;&quot; : includePath
&lt;br&gt;&quot;&lt;samp&gt;-D&lt;/samp&gt;&quot; : macro
&lt;br&gt;&quot;&lt;samp&gt;-include&lt;/samp&gt;&quot; : includeFile
&lt;br&gt;&quot;&lt;samp&gt;-L&lt;/samp&gt;&quot; : libraryPath
&lt;br&gt;&quot;&lt;samp&gt;-l&lt;/samp&gt;&quot; : libraryFile
&lt;br&gt;&quot;&lt;samp&gt;-imacros&lt;/samp&gt;&quot; : macroFile
</documentation>
</annotation>
<simpleType>
<restriction base="string">
<enumeration value="includePath">
</enumeration>
<enumeration value="macro">
</enumeration>
<enumeration value="includeFile">
</enumeration>
<enumeration value="libraryPath">
</enumeration>
<enumeration value="libraryFile">
</enumeration>
<enumeration value="macroFile">
</enumeration>
</restriction>
</simpleType>
</attribute>
<attribute name="name" type="string" use="required">
<annotation>
<documentation>
&quot;name&quot; attribute maps to path for the entries representing a path to a folder or file and to name for &lt;samp&gt;macro&lt;/samp&gt; kind representing name-value pair. For example:
&lt;br&gt;&quot;&lt;samp&gt;/usr/include/&lt;/samp&gt;&quot;
&lt;br&gt;&quot;&lt;samp&gt;MACRO&lt;/samp&gt;&quot; (for &lt;samp&gt;#define MACRO value&lt;/samp&gt;)
&lt;br&gt;Note that relative paths are treated as rooted in build working directory (when applicable).
</documentation>
</annotation>
</attribute>
<attribute name="value" type="string">
<annotation>
<documentation>
&quot;value&quot; attribute is used for &lt;samp&gt;macro&lt;/samp&gt; kind representing name-value pair only. It is not used for the entries representing a path. For example:
&lt;br&gt;&quot;&lt;samp&gt;value&lt;/samp&gt;&quot; (for &lt;samp&gt;#define MACRO value&lt;/samp&gt;)
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<element name="flag">
<annotation>
<documentation>
Combination of flags for the entry.
</documentation>
</annotation>
<complexType>
<attribute name="value" use="required">
<annotation>
<documentation>
A value of the flag. Corresponds to &lt;samp&gt;ICSettingEntry&lt;/samp&gt; flags, see JavaDoc there for more details. Here is an excerpt from the Javadoc for the flags intended to be used with this extension point (the others might be not supported):
&lt;br&gt;- &lt;samp&gt;BUILTIN&lt;/samp&gt; : Indicates settings built in a tool (compiler) itself. That kind of settings are not passed as options to a compiler but indexer or other clients might need them.
&lt;br&gt;- &lt;samp&gt;LOCAL&lt;/samp&gt; : Applicable for &lt;samp&gt;includePath&lt;/samp&gt; only which could be local (#include &quot;...&quot;) or system (#include &lt;...&gt;). If an &lt;samp&gt;includePath&lt;/samp&gt; is not marked as &lt;samp&gt;LOCAL&lt;/samp&gt; it is treated as system.
&lt;br&gt;- &lt;samp&gt;RESOLVED&lt;/samp&gt; : Indicates that the entries do not need to be resolved such as expansion of environment variables, normalizing the path against build working directory etc.
&lt;br&gt;- &lt;samp&gt;VALUE_WORKSPACE_PATH&lt;/samp&gt; : is used to indicate that the entry is a resource managed by eclipse in the workspace. The path is rooted in the workspace root.
&lt;br&gt;- &lt;samp&gt;UNDEFINED&lt;/samp&gt; : indicates that the entry should not be defined, corresponds to &lt;samp&gt;-U&lt;/samp&gt; option of gcc compiler. If this flag is defined it will negate entries with the same name (and kind) for all providers down the list.
</documentation>
</annotation>
<simpleType>
<restriction base="string">
<enumeration value="BUILTIN">
</enumeration>
<enumeration value="LOCAL">
</enumeration>
<enumeration value="RESOLVED">
</enumeration>
<enumeration value="VALUE_WORKSPACE_PATH">
</enumeration>
<enumeration value="UNDEFINED">
</enumeration>
</restriction>
</simpleType>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
CDT 9.0
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiinfo"/>
</appInfo>
<documentation>
Plug-ins that want to extend this extension point must implement &lt;samp&gt;org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider&lt;/samp&gt; interface.
&lt;br/&gt;
For those cases where contributed settings entries (representing the compiler options) are not changed dynamically it is sufficient to configure existing class LanguageSettingsBaseProvider which is provided by default.
&lt;br/&gt;
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="copyright"/>
</appInfo>
<documentation>
Copyright (c) 2009, 2011 Andrew Gvozdev 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>

View file

@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 Andrew Gvozdev and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andrew Gvozdev - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core;
/**
* Helper abstract class serving as a base for creating a frame of executable class
* defined as an extension in plugin.xml.
*
* @since 5.4
*
*/
public abstract class AbstractExecutableExtensionBase {
private String fId;
private String fName;
/**
* Default constructor will initialize with the name of the class
* using reflection mechanism.
*/
public AbstractExecutableExtensionBase() {
fName = this.getClass().getSimpleName();
fId = this.getClass().getCanonicalName();
}
/**
* Constructor to initialize with ID and name of the extension.
*
* @param id - ID of the extension.
* @param name - name of the extension.
*/
public AbstractExecutableExtensionBase(String id, String name) {
fName = name;
fId = id;
}
/**
* Set extension ID.
*
* @param id of extension
*/
public void setId(String id) {
fId = id;
}
/**
* Set extension name.
*
* @param name of extension
*/
public void setName(String name) {
fName = name;
}
/**
* @return id of extension
*/
public String getId() {
return fId;
}
/**
* @return name of extension
*/
public String getName() {
return fName;
}
/**
* Method toString() for debugging purposes.
*/
@SuppressWarnings("nls")
@Override
public String toString() {
return "id="+fId+", name="+fName;
}
}