diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/AllLanguageTests.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/AllLanguageTests.java
new file mode 100644
index 00000000000..d251291b662
--- /dev/null
+++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/AllLanguageTests.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core.language;
+
+import org.eclipse.cdt.internal.index.tests.IndexTests;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * @author crecoskie
+ *
+ */
+public class AllLanguageTests extends TestSuite {
+ public static Test suite() {
+ TestSuite suite = new IndexTests();
+
+ suite.addTest(LanguageInheritanceTests.suite());
+
+ return suite;
+ }
+}
diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/LanguageInheritanceTests.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/LanguageInheritanceTests.java
new file mode 100644
index 00000000000..2c5c99efbdc
--- /dev/null
+++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/LanguageInheritanceTests.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core.language;
+
+import java.util.Collections;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+import org.eclipse.cdt.core.dom.IPDOMManager;
+import org.eclipse.cdt.core.dom.ast.gnu.c.GCCLanguage;
+import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ILanguage;
+import org.eclipse.cdt.core.model.LanguageManager;
+import org.eclipse.cdt.core.testplugin.CProjectHelper;
+import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
+import org.eclipse.cdt.internal.core.CContentTypes;
+import org.eclipse.cdt.internal.index.tests.IndexCompositeTests;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.content.IContentType;
+
+/**
+ * Tests for language inheritance computations.
+ */
+public class LanguageInheritanceTests extends BaseTestCase {
+
+ private static final String BIN_FOLDER = "bin";
+ private static final String FILE_NAME = "test.c";
+ private static final IContentType[] EMPTY_CONTENT_TYPES = new IContentType[0];
+
+ private ICProject fCProject;
+ private IFile fFile;
+ private LanguageManager fManager;
+ private ILanguage fLanguage1;
+ private ILanguage fLanguage2;
+
+ private IProject fProject;
+
+ public static Test suite() {
+ return suite(LanguageInheritanceTests.class);
+ }
+
+ protected void setUp() throws Exception {
+ String name = getClass().getName() + "_" + getName();
+ fCProject = CProjectHelper.createCCProject(name , BIN_FOLDER, IPDOMManager.ID_NO_INDEXER);
+
+ fProject = fCProject.getProject();
+ fFile = fProject.getFile(FILE_NAME);
+
+ fManager = LanguageManager.getInstance();
+ fLanguage1 = fManager.getLanguage(GPPLanguage.ID);
+ fLanguage2 = fManager.getLanguage(GCCLanguage.ID);
+
+ // Ensure global language mappings are cleared.
+ WorkspaceLanguageConfiguration config = fManager.getWorkspaceLanguageConfiguration();
+ config.setWorkspaceMappings(Collections.EMPTY_MAP);
+ fManager.storeWorkspaceLanguageConfiguration(EMPTY_CONTENT_TYPES);
+ }
+
+ protected void tearDown() throws Exception {
+ CProjectHelper.delete(fCProject);
+ }
+
+ public void testDirectFileMapping() throws Exception {
+ ILanguage originalLanguage = fManager.getLanguageForFile(fFile);
+ assertDifferentLanguages(originalLanguage, fLanguage1);
+
+ ProjectLanguageConfiguration config = fManager.getLanguageConfiguration(fCProject.getProject());
+ config.addFileMapping(fFile, GPPLanguage.ID);
+ fManager.storeLanguageMappingConfiguration(fFile);
+
+ assertSameLanguage(fLanguage1, fManager.getLanguageForFile(fFile));
+
+ config.removeFileMapping(fFile);
+ fManager.storeLanguageMappingConfiguration(fFile);
+
+ assertSameLanguage(originalLanguage, fManager.getLanguageForFile(fFile));
+ }
+
+ public void testDirectProjectContentTypeMapping() throws Exception {
+ ILanguage originalLanguage = fManager.getLanguageForFile(fFile);
+ assertDifferentLanguages(originalLanguage, fLanguage1);
+
+ String filename = fFile.getLocation().toString();
+ IContentType contentType = CContentTypes.getContentType(fProject, filename);
+ ProjectLanguageConfiguration config = fManager.getLanguageConfiguration(fCProject.getProject());
+ config.addContentTypeMapping(contentType.getId(), GPPLanguage.ID);
+ fManager.storeLanguageMappingConfiguration(fProject, EMPTY_CONTENT_TYPES);
+
+ assertSameLanguage(fLanguage1, fManager.getLanguageForFile(fFile));
+
+ config.removeContentTypeMapping(contentType.getId());
+ fManager.storeLanguageMappingConfiguration(fFile);
+
+ assertSameLanguage(originalLanguage, fManager.getLanguageForFile(fFile));
+ }
+
+ public void testDirectWorkspaceContentTypeMapping() throws Exception {
+ ILanguage originalLanguage = fManager.getLanguageForFile(fFile);
+ assertDifferentLanguages(originalLanguage, fLanguage1);
+
+ String filename = fFile.getLocation().toString();
+ IContentType contentType = CContentTypes.getContentType(fProject, filename);
+ WorkspaceLanguageConfiguration config = fManager.getWorkspaceLanguageConfiguration();
+ config.addWorkspaceMapping(contentType.getId(), GPPLanguage.ID);
+ fManager.storeWorkspaceLanguageConfiguration(EMPTY_CONTENT_TYPES);
+
+ assertEquals(fLanguage1, fManager.getLanguageForFile(fFile));
+
+ config.removeWorkspaceMapping(contentType.getId());
+ fManager.storeLanguageMappingConfiguration(fFile);
+
+ assertEquals(originalLanguage, fManager.getLanguageForFile(fFile));
+ }
+
+ public void testOverriddenWorkspaceContentTypeMapping1() throws Exception {
+ ILanguage originalLanguage = fManager.getLanguageForFile(fFile);
+ assertDifferentLanguages(originalLanguage, fLanguage1);
+
+ String filename = fFile.getLocation().toString();
+ IContentType contentType = CContentTypes.getContentType(fProject, filename);
+
+ // Set workspace mapping
+ WorkspaceLanguageConfiguration config = fManager.getWorkspaceLanguageConfiguration();
+ config.addWorkspaceMapping(contentType.getId(), GPPLanguage.ID);
+ fManager.storeWorkspaceLanguageConfiguration(EMPTY_CONTENT_TYPES);
+
+ // Override with project mapping
+ ProjectLanguageConfiguration config2 = fManager.getLanguageConfiguration(fCProject.getProject());
+ config2.addContentTypeMapping(contentType.getId(), GCCLanguage.ID);
+ fManager.storeLanguageMappingConfiguration(fProject, EMPTY_CONTENT_TYPES);
+
+ assertSameLanguage(fLanguage2, fManager.getLanguageForFile(fFile));
+ }
+
+ public void testOverriddenWorkspaceContentTypeMapping2() throws Exception {
+ ILanguage originalLanguage = fManager.getLanguageForFile(fFile);
+ assertDifferentLanguages(originalLanguage, fLanguage1);
+
+ String filename = fFile.getLocation().toString();
+ IContentType contentType = CContentTypes.getContentType(fProject, filename);
+
+ // Set workspace mapping
+ WorkspaceLanguageConfiguration config = fManager.getWorkspaceLanguageConfiguration();
+ config.addWorkspaceMapping(contentType.getId(), GPPLanguage.ID);
+ fManager.storeWorkspaceLanguageConfiguration(EMPTY_CONTENT_TYPES);
+
+ // Override with file mapping
+ ProjectLanguageConfiguration config2 = fManager.getLanguageConfiguration(fCProject.getProject());
+ config2.addFileMapping(fFile, GCCLanguage.ID);
+ fManager.storeLanguageMappingConfiguration(fFile);
+
+ assertSameLanguage(fLanguage2, fManager.getLanguageForFile(fFile));
+ }
+
+ public void testOverriddenProjectContentTypeMapping() throws Exception {
+ ILanguage originalLanguage = fManager.getLanguageForFile(fFile);
+ assertDifferentLanguages(originalLanguage, fLanguage1);
+
+ String filename = fFile.getLocation().toString();
+ IContentType contentType = CContentTypes.getContentType(fProject, filename);
+
+ // Set project mapping
+ ProjectLanguageConfiguration config = fManager.getLanguageConfiguration(fCProject.getProject());
+ config.addContentTypeMapping(contentType.getId(), GPPLanguage.ID);
+ fManager.storeLanguageMappingConfiguration(fProject, EMPTY_CONTENT_TYPES);
+
+ // Override with file mapping
+ ProjectLanguageConfiguration config2 = fManager.getLanguageConfiguration(fCProject.getProject());
+ config2.addFileMapping(fFile, GCCLanguage.ID);
+ fManager.storeLanguageMappingConfiguration(fFile);
+
+ assertSameLanguage(fLanguage2, fManager.getLanguageForFile(fFile));
+ }
+
+ protected void assertSameLanguage(ILanguage expected, ILanguage actual) {
+ if (expected != null) {
+ assertNotNull(actual);
+ assertEquals(expected.getId(), actual.getId());
+ } else {
+ assertNull(actual);
+ }
+ }
+
+ protected void assertDifferentLanguages(ILanguage language1, ILanguage language2) {
+ assertNotNull(language1);
+ assertNotNull(language2);
+ assertNotSame(language1.getId(), language2.getId());
+ }
+}
diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java
index 39b16eb1b30..aa1e66eb93c 100644
--- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java
+++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java
@@ -24,6 +24,7 @@ import junit.framework.TestSuite;
import org.eclipse.cdt.core.cdescriptor.tests.CDescriptorTests;
import org.eclipse.cdt.core.internal.errorparsers.tests.ErrorParserTests;
import org.eclipse.cdt.core.internal.tests.PositionTrackerTests;
+import org.eclipse.cdt.core.language.AllLanguageTests;
import org.eclipse.cdt.core.model.tests.AllCoreTests;
import org.eclipse.cdt.core.model.tests.BinaryTests;
import org.eclipse.cdt.core.model.tests.ElementDeltaTests;
@@ -69,6 +70,7 @@ public class AutomatedIntegrationSuite extends TestSuite {
suite.addTest(ElementDeltaTests.suite());
suite.addTest(WorkingCopyTests.suite());
suite.addTest(PositionTrackerTests.suite());
+ suite.addTest(AllLanguageTests.suite());
// TODO turning off indexer/search tests until the PDOM
// settles. These'll probably have to be rewritten anyway.
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/ProjectLanguageConfiguration.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/ProjectLanguageConfiguration.java
index f1c819efd4c..80da29b963f 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/ProjectLanguageConfiguration.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/ProjectLanguageConfiguration.java
@@ -158,9 +158,9 @@ public class ProjectLanguageConfiguration {
* Replaces the existing file-specific language mappings with the given
* mappings. The given mappings should be between full paths
* (String
) and language ids (String
)
- * @param projectMappings
+ * @param fileMappings
*/
public void setFileMappings(Map/**/ fileMappings) {
- fContentTypeMappings = new TreeMap(fileMappings);
+ fFileMappings = new TreeMap(fileMappings);
}
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/LanguageManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/LanguageManager.java
index e75e28704d5..32555141393 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/LanguageManager.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/LanguageManager.java
@@ -27,6 +27,7 @@ import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.language.ProjectLanguageConfiguration;
import org.eclipse.cdt.core.language.WorkspaceLanguageConfiguration;
import org.eclipse.cdt.internal.core.CContentTypes;
+import org.eclipse.cdt.internal.core.language.LanguageMappingResolver;
import org.eclipse.cdt.internal.core.language.LanguageMappingStore;
import org.eclipse.cdt.internal.core.model.LanguageDescriptor;
import org.eclipse.cdt.internal.core.model.TranslationUnit;
@@ -67,6 +68,7 @@ public class LanguageManager {
private HashMap fIdToLanguageDescriptorCache;//= new HashMap();
private HashMap fContentTypeToDescriptorListCache;
private ListenerList fLanguageChangeListeners = new ListenerList(ListenerList.IDENTITY);
+ private WorkspaceLanguageConfiguration fWorkspaceMappings;
public static LanguageManager getInstance() {
if (instance == null)
@@ -373,8 +375,15 @@ public class LanguageManager {
* @since 4.0
*/
public WorkspaceLanguageConfiguration getWorkspaceLanguageConfiguration() throws CoreException {
- // TODO: Implement this.
- return new WorkspaceLanguageConfiguration();
+ synchronized (this) {
+ if (fWorkspaceMappings != null) {
+ return fWorkspaceMappings;
+ }
+
+ LanguageMappingStore store = new LanguageMappingStore();
+ fWorkspaceMappings = store.decodeWorkspaceMappings();
+ return fWorkspaceMappings;
+ }
}
/**
@@ -385,7 +394,20 @@ public class LanguageManager {
* @since 4.0
*/
public void storeWorkspaceLanguageConfiguration(IContentType[] affectedContentTypes) throws CoreException {
- // TODO: Implement this.
+ synchronized (this) {
+ if (fWorkspaceMappings == null) {
+ return;
+ }
+
+ LanguageMappingStore store = new LanguageMappingStore();
+ store.storeMappings(fWorkspaceMappings);
+ }
+
+ // Notify listeners that the language mappings have changed.
+ LanguageMappingChangeEvent event = new LanguageMappingChangeEvent();
+ event.setType(LanguageMappingChangeEvent.TYPE_WORKSPACE);
+ event.setAffectedContentTypes(affectedContentTypes);
+ notifyLanguageChangeListeners(event);
}
/**
@@ -402,8 +424,8 @@ public class LanguageManager {
return mappings;
}
- LanguageMappingStore store = new LanguageMappingStore(project);
- mappings = store.decodeMappings();
+ LanguageMappingStore store = new LanguageMappingStore();
+ mappings = store.decodeMappings(project);
fLanguageConfigurationCache.put(project, mappings);
return mappings;
}
@@ -419,11 +441,18 @@ public class LanguageManager {
* @since 4.0
*/
public void storeLanguageMappingConfiguration(IProject project, IContentType[] affectedContentTypes) throws CoreException {
- ProjectLanguageConfiguration mappings = (ProjectLanguageConfiguration) fLanguageConfigurationCache.get(project);
- LanguageMappingStore store = new LanguageMappingStore(project);
- store.storeMappings(mappings);
+ synchronized (this) {
+ ProjectLanguageConfiguration mappings = (ProjectLanguageConfiguration) fLanguageConfigurationCache.get(project);
+ LanguageMappingStore store = new LanguageMappingStore();
+ store.storeMappings(project, mappings);
+ }
- // TODO: Notify listeners that the language mappings have changed.
+ // Notify listeners that the language mappings have changed.
+ LanguageMappingChangeEvent event = new LanguageMappingChangeEvent();
+ event.setType(LanguageMappingChangeEvent.TYPE_PROJECT);
+ event.setProject(project);
+ event.setAffectedContentTypes(affectedContentTypes);
+ notifyLanguageChangeListeners(event);
}
/**
@@ -448,7 +477,7 @@ public class LanguageManager {
String contentTypeID = contentType.getId();
- return computeLanguage(project, fullPathToFile, contentTypeID);
+ return LanguageMappingResolver.computeLanguage(project, fullPathToFile, contentTypeID, false)[0].language;
}
/**
@@ -492,7 +521,7 @@ public class LanguageManager {
contentTypeID= ct.getId();
}
- return computeLanguage(project, pathToFile.toPortableString(), contentTypeID);
+ return LanguageMappingResolver.computeLanguage(project, pathToFile.toPortableString(), contentTypeID, false)[0].language;
}
/**
@@ -527,34 +556,7 @@ public class LanguageManager {
contentTypeId= contentType.getId();
}
- return computeLanguage(project, file.getProjectRelativePath().toPortableString(), contentTypeId);
- }
-
- private ILanguage computeLanguage(IProject project, String filePath, String contentTypeId) throws CoreException {
- ProjectLanguageConfiguration mappings = getLanguageConfiguration(project);
- if (mappings != null) {
- // File-level mappings
- String id = mappings.getLanguageForFile(filePath);
- if (id != null) {
- return getLanguage(id);
- }
-
- // Project-level mappings
- id = mappings.getLanguageForContentType(contentTypeId);
- if (id != null) {
- return getLanguage(id);
- }
- }
-
- // Workspace mappings
- WorkspaceLanguageConfiguration workspaceMappings = getWorkspaceLanguageConfiguration();
- String id = workspaceMappings.getLanguageForContentType(contentTypeId);
- if (id != null) {
- return getLanguage(id);
- }
-
- // Content type mappings
- return getLanguageForContentTypeID(contentTypeId);
+ return LanguageMappingResolver.computeLanguage(project, file.getProjectRelativePath().toPortableString(), contentTypeId, false)[0].language;
}
/**
@@ -601,8 +603,8 @@ public class LanguageManager {
IProject project = file.getProject();
synchronized (this) {
ProjectLanguageConfiguration mappings = (ProjectLanguageConfiguration) fLanguageConfigurationCache.get(project);
- LanguageMappingStore store = new LanguageMappingStore(project);
- store.storeMappings(mappings);
+ LanguageMappingStore store = new LanguageMappingStore();
+ store.storeMappings(project, mappings);
}
// Notify listeners that the language mappings have changed.
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMapping.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMapping.java
new file mode 100644
index 00000000000..ffb2d0ff657
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMapping.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.language;
+
+import org.eclipse.cdt.core.model.ILanguage;
+
+/**
+ * A language mapping.
+ */
+public class LanguageMapping {
+ public ILanguage language;
+ public int inheritedFrom;
+
+ public LanguageMapping(ILanguage language, int inheritedFrom) {
+ this.language = language;
+ this.inheritedFrom = inheritedFrom;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMappingResolver.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMappingResolver.java
new file mode 100644
index 00000000000..b9941d81517
--- /dev/null
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMappingResolver.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.language;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.core.language.ProjectLanguageConfiguration;
+import org.eclipse.cdt.core.language.WorkspaceLanguageConfiguration;
+import org.eclipse.cdt.core.model.LanguageManager;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+
+/**
+ * Resolves the effective language for various resources such as
+ * files and projects.
+ */
+public class LanguageMappingResolver {
+ public static final int DEFAULT_MAPPING = 0;
+ public static final int WORKSPACE_MAPPING = 1;
+ public static final int PROJECT_MAPPING = 2;
+ public static final int FILE_MAPPING = 3;
+
+ /**
+ * Returns the effective language for the file specified by the given path.
+ * If fetchAll
is true
all inherited language
+ * mappings will be returned in order of precedence. Otherwise, only the
+ * effective language will be returned.
+ *
+ * This method will always return at least one mapping.
+ *
+ * @param project the project that contains the given file
+ * @param filePath the path to the file
+ * @param contentTypeId the content type of the file (optional)
+ * @param fetchAll if true
, returns all inherited language mappings.
+ * Otherwise, returns only the effective language.
+ * @return the effective language for the file specified by the given path.
+ * @throws CoreException
+ */
+ public static LanguageMapping[] computeLanguage(IProject project, String filePath, String contentTypeId, boolean fetchAll) throws CoreException {
+ LanguageManager manager = LanguageManager.getInstance();
+ List inheritedLanguages = new LinkedList();
+
+ if (project != null) {
+ ProjectLanguageConfiguration mappings = manager.getLanguageConfiguration(project);
+
+ if (mappings != null) {
+ // File-level mappings
+ if (filePath != null) {
+ String id = mappings.getLanguageForFile(filePath);
+ if (id != null) {
+ inheritedLanguages.add(new LanguageMapping(manager.getLanguage(id), FILE_MAPPING));
+ if (!fetchAll) {
+ return createLanguageMappingArray(inheritedLanguages);
+ }
+ }
+ }
+
+ // Project-level mappings
+ String id = mappings.getLanguageForContentType(contentTypeId);
+ if (id != null) {
+ inheritedLanguages.add(new LanguageMapping(manager.getLanguage(id), PROJECT_MAPPING));
+ if (!fetchAll) {
+ return createLanguageMappingArray(inheritedLanguages);
+ }
+ }
+ }
+ }
+
+ // Workspace mappings
+ WorkspaceLanguageConfiguration workspaceMappings = manager.getWorkspaceLanguageConfiguration();
+ String id = workspaceMappings.getLanguageForContentType(contentTypeId);
+ if (id != null) {
+ inheritedLanguages.add(new LanguageMapping(manager.getLanguage(id), WORKSPACE_MAPPING));
+ if (!fetchAll) {
+ return createLanguageMappingArray(inheritedLanguages);
+ }
+ }
+
+ // Platform mappings
+ IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId);
+ inheritedLanguages.add(new LanguageMapping(manager.getLanguage(contentType), DEFAULT_MAPPING));
+ return createLanguageMappingArray(inheritedLanguages);
+ }
+
+ private static LanguageMapping[] createLanguageMappingArray(List inheritedLanguages) {
+ LanguageMapping[] results = new LanguageMapping[inheritedLanguages.size()];
+ Iterator mappings = inheritedLanguages.iterator();
+ int i = 0;
+ while (mappings.hasNext()) {
+ LanguageMapping mapping = (LanguageMapping) mappings.next();
+ results[i] = mapping;
+ i++;
+ }
+ return results;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMappingStore.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMappingStore.java
index 88ed2147ba2..16cb515b056 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMappingStore.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/LanguageMappingStore.java
@@ -10,77 +10,176 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.language;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.cdt.core.ICDescriptor;
import org.eclipse.cdt.core.language.ProjectLanguageConfiguration;
+import org.eclipse.cdt.core.language.WorkspaceLanguageConfiguration;
+import org.eclipse.cdt.internal.core.Util;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Preferences;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+/**
+ * Serializes and deserializes language mappings to and from persistent storage.
+ */
public class LanguageMappingStore {
private static final String LANGUAGE_MAPPING_ID = "org.eclipse.cdt.core.language.mapping"; //$NON-NLS-1$
private static final String PROJECT_MAPPINGS = "project-mappings"; //$NON-NLS-1$
- private static final String PROJECT_MAPPING = "project-mapping"; //$NON-NLS-1$
+ private static final String WORKSPACE_MAPPINGS = "workspace-mappings"; //$NON-NLS-1$
+
+ private static final String CONTENT_TYPE_MAPPING = "content-type-mapping"; //$NON-NLS-1$
+
+ private static final String FILE_MAPPING = "file-mapping"; //$NON-NLS-1$
+ private static final String ATTRIBUTE_PATH = "path"; //$NON-NLS-1$
+
private static final String ATTRIBUTE_CONTENT_TYPE = "content-type"; //$NON-NLS-1$
private static final String ATTRIBUTE_LANGUAGE = "language"; //$NON-NLS-1$
- private IProject fProject;
-
- public LanguageMappingStore(IProject project) {
- fProject = project;
+ public LanguageMappingStore() {
}
- public ProjectLanguageConfiguration decodeMappings() throws CoreException {
+ public ProjectLanguageConfiguration decodeMappings(IProject project) throws CoreException {
ProjectLanguageConfiguration config = new ProjectLanguageConfiguration();
- ICDescriptor descriptor = getProjectDescription();
+ ICDescriptor descriptor = getProjectDescription(project);
Element rootElement = descriptor.getProjectData(LANGUAGE_MAPPING_ID);
if (rootElement == null) {
return config;
}
- config.setContentTypeMappings(decodeProjectMappings(rootElement));
+
+ NodeList mappingElements = rootElement.getElementsByTagName(PROJECT_MAPPINGS);
+ if (mappingElements.getLength() > 0) {
+ Element element = (Element) mappingElements.item(0);
+ config.setContentTypeMappings(decodeContentTypeMappings(element));
+ config.setFileMappings(decodeFileMappings(element));
+ }
return config;
}
- protected ICDescriptor getProjectDescription() throws CoreException {
- return CCorePlugin.getDefault().getCProjectDescription(fProject, true);
+ protected ICDescriptor getProjectDescription(IProject project) throws CoreException {
+ return CCorePlugin.getDefault().getCProjectDescription(project, true);
}
- private Map decodeProjectMappings(Element rootElement) throws CoreException {
+ private Map decodeContentTypeMappings(Element rootElement) throws CoreException {
+ return decodeMappings(rootElement, CONTENT_TYPE_MAPPING, ATTRIBUTE_CONTENT_TYPE, ATTRIBUTE_LANGUAGE);
+ }
+
+ private Map decodeFileMappings(Element rootElement) throws CoreException {
+ return decodeMappings(rootElement, FILE_MAPPING, ATTRIBUTE_PATH, ATTRIBUTE_LANGUAGE);
+ }
+
+ private Map decodeMappings(Element rootElement, String category, String keyName, String valueName) {
Map decodedMappings = new TreeMap();
- NodeList elements = rootElement.getElementsByTagName(PROJECT_MAPPINGS);
- for (int i = 0; i < elements.getLength(); i++) {
- Element projectMappings = (Element) elements.item(i);
- NodeList mappingElements = projectMappings.getElementsByTagName(PROJECT_MAPPING);
- for (int j = 0; j < mappingElements.getLength(); j++) {
- Element mapping = (Element) mappingElements.item(j);
- String contentType = mapping.getAttribute(ATTRIBUTE_CONTENT_TYPE);
- String language = mapping.getAttribute(ATTRIBUTE_LANGUAGE);
- decodedMappings.put(contentType, language);
- }
+ NodeList mappingElements = rootElement.getElementsByTagName(category);
+ for (int j = 0; j < mappingElements.getLength(); j++) {
+ Element mapping = (Element) mappingElements.item(j);
+ String key = mapping.getAttribute(keyName);
+ String value = mapping.getAttribute(valueName);
+ decodedMappings.put(key, value);
}
return decodedMappings;
}
- public void storeMappings(ProjectLanguageConfiguration config) throws CoreException {
- ICDescriptor descriptor = getProjectDescription();
+ public void storeMappings(IProject project, ProjectLanguageConfiguration config) throws CoreException {
+ ICDescriptor descriptor = getProjectDescription(project);
Element rootElement = descriptor.getProjectData(LANGUAGE_MAPPING_ID);
clearChildren(rootElement);
- addProjectMappings(config.getContentTypeMappings(), rootElement);
+
+ Document document = rootElement.getOwnerDocument();
+ Element projectMappings = document.createElement(PROJECT_MAPPINGS);
+ rootElement.appendChild(projectMappings);
+
+ addContentTypeMappings(config.getContentTypeMappings(), projectMappings);
+ addFileMappings(config.getFileMappings(), projectMappings);
descriptor.saveProjectData();
}
+ public void storeMappings(WorkspaceLanguageConfiguration config) throws CoreException {
+ try {
+ // Encode mappings as XML and serialize as a String.
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ Element rootElement = doc.createElement(WORKSPACE_MAPPINGS);
+ doc.appendChild(rootElement);
+ addContentTypeMappings(config.getWorkspaceMappings(), rootElement);
+ Transformer serializer = createSerializer();
+ DOMSource source = new DOMSource(doc);
+ StringWriter buffer = new StringWriter();
+ StreamResult result = new StreamResult(buffer);
+ serializer.transform(source, result);
+ String encodedMappings = buffer.getBuffer().toString();
+
+ Preferences node = CCorePlugin.getDefault().getPluginPreferences();;
+ node.setValue(CCorePreferenceConstants.WORKSPACE_LANGUAGE_MAPPINGS, encodedMappings);
+ CCorePlugin.getDefault().savePluginPreferences();
+ } catch (ParserConfigurationException e) {
+ throw new CoreException(Util.createStatus(e));
+ } catch (TransformerException e) {
+ throw new CoreException(Util.createStatus(e));
+ }
+ }
+
+ public WorkspaceLanguageConfiguration decodeWorkspaceMappings() throws CoreException {
+ Preferences node = CCorePlugin.getDefault().getPluginPreferences();;
+ String encodedMappings = node.getString(CCorePreferenceConstants.WORKSPACE_LANGUAGE_MAPPINGS);
+ WorkspaceLanguageConfiguration config = new WorkspaceLanguageConfiguration();
+
+ if (encodedMappings == null || encodedMappings.length() == 0) {
+ return config;
+ }
+
+ // The mappings are encoded as XML in a String so we need to parse it.
+ InputSource input = new InputSource(new StringReader(encodedMappings));
+ try {
+ Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input);
+ config.setWorkspaceMappings(decodeContentTypeMappings(document.getDocumentElement()));
+ return config;
+ } catch (SAXException e) {
+ throw new CoreException(Util.createStatus(e));
+ } catch (IOException e) {
+ throw new CoreException(Util.createStatus(e));
+ } catch (ParserConfigurationException e) {
+ throw new CoreException(Util.createStatus(e));
+ }
+ }
+
+ private Transformer createSerializer() throws CoreException {
+ try {
+ return TransformerFactory.newInstance().newTransformer();
+ } catch (TransformerConfigurationException e) {
+ throw new CoreException(Util.createStatus(e));
+ } catch (TransformerFactoryConfigurationError e) {
+ throw new CoreException(Util.createStatus(e));
+ }
+ }
+
private void clearChildren(Element element) {
Node child = element.getFirstChild();
while (child != null) {
@@ -89,17 +188,23 @@ public class LanguageMappingStore {
}
}
- private void addProjectMappings(Map mappings, Element rootElement) {
+ private void addMappings(Map mappings, Element rootElement, String category, String keyName, String valueName) {
Document document = rootElement.getOwnerDocument();
- Element projectMappings = document.createElement(PROJECT_MAPPINGS);
Iterator entries = mappings.entrySet().iterator();
while (entries.hasNext()) {
Entry entry = (Entry) entries.next();
- Element mapping = document.createElement(PROJECT_MAPPING);
- mapping.setAttribute(ATTRIBUTE_CONTENT_TYPE, (String) entry.getKey());
- mapping.setAttribute(ATTRIBUTE_LANGUAGE, (String) entry.getValue());
- projectMappings.appendChild(mapping);
+ Element mapping = document.createElement(category);
+ mapping.setAttribute(keyName, (String) entry.getKey());
+ mapping.setAttribute(valueName, (String) entry.getValue());
+ rootElement.appendChild(mapping);
}
- rootElement.appendChild(projectMappings);
+ }
+
+ private void addContentTypeMappings(Map mappings, Element rootElement) {
+ addMappings(mappings, rootElement, CONTENT_TYPE_MAPPING, ATTRIBUTE_CONTENT_TYPE, ATTRIBUTE_LANGUAGE);
+ }
+
+ private void addFileMappings(Map mappings, Element rootElement) {
+ addMappings(mappings, rootElement, FILE_MAPPING, ATTRIBUTE_PATH, ATTRIBUTE_LANGUAGE);
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/LanguageMappingChangeListener.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/LanguageMappingChangeListener.java
new file mode 100644
index 00000000000..162bf224806
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/LanguageMappingChangeListener.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.pdom;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICElementDelta;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.model.ILanguageMappingChangeListener;
+import org.eclipse.cdt.core.model.ILanguageMappingChangeEvent;
+import org.eclipse.cdt.core.model.LanguageManager;
+import org.eclipse.cdt.internal.core.model.CElementDelta;
+import org.eclipse.cdt.internal.core.model.CModelManager;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * @author crecoskie
+ *
+ * This class handles changes in language mappings for the PDOM by reindexing the appropriate projects.
+ * This class is a a work in progress and will be changed soon to be smarter about the resources it reindexes.
+ */
+public class LanguageMappingChangeListener implements
+ ILanguageMappingChangeListener {
+
+ private PDOMManager fManager;
+
+ public LanguageMappingChangeListener(PDOMManager manager) {
+ fManager = manager;
+ LanguageManager.getInstance().registerLanguageChangeListener(this);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.model.ILanguageMappingChangeListener#handleLanguageMappingChangeEvent(org.eclipse.cdt.core.model.ILanguageMappingsChangeEvent)
+ */
+ public void handleLanguageMappingChangeEvent(ILanguageMappingChangeEvent event) {
+ IProject project = event.getProject();
+
+ CModelManager manager = CModelManager.getDefault();
+ if(project != null) {
+ ICProject cProject = manager.getCModel().findCProject(project);
+
+ if(cProject != null)
+ try {
+ fManager.reindex(cProject);
+ } catch (CoreException e) {
+ CCorePlugin.log(e);
+ }
+ }
+
+ if (event.getType() == ILanguageMappingChangeEvent.TYPE_WORKSPACE) {
+ // For now reindex all projects.
+ // TODO: This should be smarter about figuring out which projects
+ // are potentially unaffected due to project settings
+ try {
+ ICProject[] cProjects = manager.getCModel().getCProjects();
+ for(int k = 0; k < cProjects.length; k++) {
+ try {
+ fManager.reindex(cProjects[k]);
+ } catch (CoreException e) {
+ CCorePlugin.log(e);
+ }
+ }
+ } catch (CModelException e) {
+ CCorePlugin.log(e);
+ }
+ } else if (event.getType() == ILanguageMappingChangeEvent.TYPE_PROJECT) {
+ // For now, reindex the entire project since we don't know which
+ // files are affected.
+ try {
+ ICProject cProject = manager.getCModel().getCProject(event.getProject());
+ fManager.reindex(cProject);
+ } catch (CModelException e) {
+ CCorePlugin.log(e);
+ } catch (CoreException e) {
+ CCorePlugin.log(e);
+ }
+ } else if (event.getType() == ILanguageMappingChangeEvent.TYPE_FILE) {
+ // Just reindex the affected file.
+ IFile file = event.getFile();
+ ICProject cProject = manager.getCModel().getCProject(file);
+ ICElement element = manager.create(file, cProject);
+ CElementDelta delta = new CElementDelta(element);
+ delta.changed(element, ICElementDelta.F_CONTENT);
+ try {
+ fManager.changeProject(cProject, delta);
+ } catch (CoreException e) {
+ CCorePlugin.log(e);
+ }
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java
index b3335f478a4..79c1f452002 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java
@@ -40,6 +40,7 @@ import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElementDelta;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IElementChangedListener;
+import org.eclipse.cdt.core.model.ILanguageMappingChangeListener;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
@@ -143,6 +144,8 @@ public class PDOMManager implements IWritableIndexManager, IListener {
private IElementChangedListener fCModelListener= new CModelListener(this);
private IndexFactory fIndexFactory= new IndexFactory(this);
private IndexProviderManager manager = new IndexProviderManager();
+
+ private ILanguageMappingChangeListener fLanguageChangeListener = new LanguageMappingChangeListener(this);
/**
* Serializes creation of new indexer, when acquiring the lock you are
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java
index 1be07179f6d..ddbfd2798ca 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java
@@ -65,4 +65,14 @@ public class CCorePreferenceConstants {
* Default absolute maximum size of the index-db in megabytes.
*/
public static final String DEFAULT_MAX_INDEX_DB_CACHE_SIZE_MB = "64"; //$NON-NLS-1$
+
+ /**
+ * Workspace-wide language mappings.
+ */
+ public static final String WORKSPACE_LANGUAGE_MAPPINGS = CCorePlugin.PLUGIN_ID + ".workspaceLanguageMappings"; //$NON-NLS-1$
+
+ /**
+ * Default workspace-wide language mappings.
+ */
+ public static final String DEFAULT_WORKSPACE_LANGUAGE_MAPPINGS = ""; //$NON-NLS-1$
}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java
index 0907f914743..d5ff529f0af 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java
@@ -45,6 +45,7 @@ public class CCorePreferenceInitializer extends AbstractPreferenceInitializer {
defaultOptionsMap.put(CCorePreferenceConstants.INDEX_DB_CACHE_SIZE_PCT, CCorePreferenceConstants.DEFAULT_INDEX_DB_CACHE_SIZE_PCT);
defaultOptionsMap.put(CCorePreferenceConstants.MAX_INDEX_DB_CACHE_SIZE_MB, CCorePreferenceConstants.DEFAULT_MAX_INDEX_DB_CACHE_SIZE_MB);
+ defaultOptionsMap.put(CCorePreferenceConstants.WORKSPACE_LANGUAGE_MAPPINGS, CCorePreferenceConstants.DEFAULT_WORKSPACE_LANGUAGE_MAPPINGS);
// Store default values to default preferences
IEclipsePreferences defaultPreferences = ((IScopeContext) new DefaultScope()).getNode(CCorePlugin.PLUGIN_ID);
for (Iterator iter = defaultOptionsMap.entrySet().iterator(); iter.hasNext();) {
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index b7fb3cde4d1..89ff1db9896 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -685,6 +685,12 @@
class="org.eclipse.cdt.internal.ui.preferences.IndexerPreferencePage"
id="org.eclipse.cdt.ui.preferences.IndexerPreferencePage"
name="%indexerPrefName"/>
+
+