1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-06 07:45:50 +02:00

ASSIGNED - bug 151850: allow user to specify which parser/language to parse a given content type with

https://bugs.eclipse.org/bugs/show_bug.cgi?id=151850

Combined patch from myself and Jason Montojo
This commit is contained in:
Chris Recoskie 2007-04-05 19:07:10 +00:00
parent 0da5cc01ce
commit 5638a8eeb6
21 changed files with 1329 additions and 214 deletions

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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.

View file

@ -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
* (<code>String</code>) and language ids (<code>String</code>)
* @param projectMappings
* @param fileMappings
*/
public void setFileMappings(Map/*<String, String>*/ fileMappings) {
fContentTypeMappings = new TreeMap(fileMappings);
fFileMappings = new TreeMap(fileMappings);
}
}

View file

@ -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.

View file

@ -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;
}
}

View file

@ -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 <code>fetchAll</code> is <code>true</code> 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 <code>true</code>, 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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}
}
}

View file

@ -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

View file

@ -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$
}

View file

@ -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();) {

View file

@ -685,6 +685,12 @@
class="org.eclipse.cdt.internal.ui.preferences.IndexerPreferencePage"
id="org.eclipse.cdt.ui.preferences.IndexerPreferencePage"
name="%indexerPrefName"/>
<page
category="org.eclipse.cdt.ui.preferences.CPluginPreferencePage"
class="org.eclipse.cdt.internal.ui.language.WorkspaceLanguageMappingPreferencePage"
id="org.eclipse.cdt.ui.preferences.LanguageMappings"
name="%CDTLanguagesProperty.name">
</page>
<!--page
name="%WorkInProgress.name"
category="org.eclipse.cdt.ui.preferences.CPluginPreferencePage"
@ -1466,6 +1472,16 @@
</adapt>
</enabledWhen>
</page>
<page
class="org.eclipse.cdt.internal.ui.language.FileLanguageMappingPropertyPage"
id="org.eclipse.cdt.ui.fileLanguageMappings"
name="%CDTLanguagesProperty.name">
<enabledWhen>
<adapt
type="org.eclipse.cdt.core.model.ITranslationUnit">
</adapt>
</enabledWhen>
</page>
</extension>
<extension
point="org.eclipse.cdt.ui.PathContainerPage">

View file

@ -29,6 +29,7 @@ import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;

View file

@ -0,0 +1,199 @@
package org.eclipse.cdt.internal.ui.language;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.ProjectLanguageConfiguration;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.internal.core.CContentTypes;
import org.eclipse.cdt.internal.core.Util;
import org.eclipse.cdt.internal.core.language.LanguageMapping;
import org.eclipse.cdt.internal.core.language.LanguageMappingResolver;
import org.eclipse.cdt.internal.ui.preferences.PreferencesMessages;
import org.eclipse.cdt.internal.ui.util.Messages;
public class FileLanguageMappingPropertyPage extends PropertyPage {
private Map fLanguageNamesToIDsMap;
private Combo fLanguage;
private IContentType fContentType;
private Composite fContents;
public FileLanguageMappingPropertyPage() {
super();
fLanguageNamesToIDsMap = new TreeMap();
}
protected Control createContents(Composite parent) {
IFile file = getFile();
IProject project = file.getProject();
fContentType = CContentTypes.getContentType(project, file.getLocation().toString());
fContents = new Composite(parent, SWT.NONE);
fContents.setLayout(new GridLayout(2, false));
Label contentTypeLabel = new Label(fContents, SWT.NONE);
contentTypeLabel.setText(PreferencesMessages.FileLanguagesPropertyPage_contentTypeLabel);
contentTypeLabel.setLayoutData(new GridData(SWT.TRAIL, SWT.CENTER, false, false));
Label contentTypeDescriptionLabel = new Label(fContents, SWT.NONE);
contentTypeDescriptionLabel.setText(fContentType.getName());
contentTypeDescriptionLabel.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false));
Label languageLabel = new Label(fContents, SWT.NONE);
languageLabel.setText(PreferencesMessages.FileLanguagesPropertyPage_languageLabel);
languageLabel.setLayoutData(new GridData(SWT.TRAIL, SWT.CENTER, false, false));
fLanguage = new Combo(fContents, SWT.DROP_DOWN | SWT.READ_ONLY);
fLanguage.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false));
refreshMappings();
Link link = new Link(fContents, SWT.NONE);
link.setText(PreferencesMessages.FileLanguagesPropertyPage_description);
link.addListener(SWT.Selection, new LanguageMappingLinkListener(parent.getShell(), project) {
protected void refresh() {
refreshMappings();
}
});
link.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false, 2, 1));
return fContents;
}
private void refreshMappings() {
try {
fLanguage.setItems(getLanguages());
findSelection();
fContents.layout();
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
private void findSelection() throws CoreException {
IFile file = getFile();
LanguageManager manager = LanguageManager.getInstance();
ProjectLanguageConfiguration config = manager.getLanguageConfiguration(file.getProject());
String languageId = config.getLanguageForFile(file);
if (languageId == null) {
// No mapping was defined so we'll choose the default.
fLanguage.select(0);
return;
}
ILanguage language = manager.getLanguage(languageId);
String name = language.getName();
for (int i = 1; i < fLanguage.getItemCount(); i++) {
if (name.equals(fLanguage.getItem(i))) {
fLanguage.select(i);
return;
}
}
// Couldn't find the mapping so we'll choose the default.
fLanguage.select(0);
}
public boolean performOk() {
String languageId;
String selectedLanguageName = fLanguage.getText();
languageId = (String) fLanguageNamesToIDsMap.get(selectedLanguageName);
try {
IFile file = getFile();
IProject project = file.getProject();
LanguageManager manager = LanguageManager.getInstance();
ProjectLanguageConfiguration config = manager.getLanguageConfiguration(project);
String oldMapping = config.getLanguageForFile(file);
if (oldMapping == languageId) {
// No changes. We're all done.
return true;
}
if (languageId == null) {
config.removeFileMapping(file);
} else {
config.addFileMapping(file, languageId);
}
manager.storeLanguageMappingConfiguration(file);
return true;
} catch (CoreException e) {
CCorePlugin.log(e);
return false;
}
}
private IFile getFile() {
return (IFile) getElement().getAdapter(IFile.class);
}
protected void performDefaults() {
super.performDefaults();
}
private String[] getLanguages() throws CoreException {
ILanguage[] languages = LanguageManager.getInstance().getRegisteredLanguages();
String[] descriptions = new String[languages.length];
IFile file = getFile();
IProject project = file.getProject();
LanguageMapping mappings[] = LanguageMappingResolver.computeLanguage(project, file.getProjectRelativePath().toPortableString(), fContentType.getId(), true);
LanguageMapping inheritedMapping = mappings[0];
// Skip over the file mapping because we want to know what mapping the file
// mapping overrides.
if (inheritedMapping.inheritedFrom == LanguageMappingResolver.FILE_MAPPING ) {
inheritedMapping = mappings[1];
}
ILanguage inheritedLanguage = inheritedMapping.language;
String inheritedFrom;
switch (inheritedMapping.inheritedFrom) {
case LanguageMappingResolver.DEFAULT_MAPPING:
inheritedFrom = PreferencesMessages.FileLanguagesPropertyPage_inheritedFromSystem;
break;
case LanguageMappingResolver.PROJECT_MAPPING:
inheritedFrom = PreferencesMessages.FileLanguagesPropertyPage_inheritedFromProject;
break;
case LanguageMappingResolver.WORKSPACE_MAPPING:
inheritedFrom = PreferencesMessages.FileLanguagesPropertyPage_inheritedFromWorkspace;
break;
default:
throw new CoreException(Util.createStatus(new IllegalArgumentException()));
}
int index = 0;
descriptions[index] = Messages.format(inheritedFrom, inheritedLanguage.getName());
index++;
for (int i = 0; i < languages.length; i++) {
String id = languages[i].getId();
if (!languages[i].equals(inheritedLanguage)) {
descriptions[index] = languages[i].getName();
fLanguageNamesToIDsMap.put(descriptions[index], id);
index++;
}
}
return descriptions;
}
}

View file

@ -0,0 +1,46 @@
/*******************************************************************************
* 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.ui.language;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.PreferencesUtil;
public class LanguageMappingLinkListener implements Listener {
private static final String WORKSPACE_PREFERENCE_PAGE = "org.eclipse.cdt.ui.preferences.LanguageMappings"; //$NON-NLS-1$
private static final String PROJECT_PROPERTY_PAGE = "org.eclipse.cdt.ui.projectLanguageMappings"; //$NON-NLS-1$
private static final String WORKSPACE_LINK = "workspace"; //$NON-NLS-1$
private static final String PROJECT_LINK = "project"; //$NON-NLS-1$
private Shell fShell;
private IAdaptable fElement;
public LanguageMappingLinkListener(Shell shell, IAdaptable element) {
fShell = shell;
fElement = element;
}
public void handleEvent(Event event) {
if (WORKSPACE_LINK.equals(event.text)) {
PreferencesUtil.createPreferenceDialogOn(fShell, WORKSPACE_PREFERENCE_PAGE, null, null).open();
} else if (PROJECT_LINK.equals(event.text)) {
PreferencesUtil.createPropertyDialogOn(fShell, fElement, PROJECT_PROPERTY_PAGE, null, null).open();
}
refresh();
}
protected void refresh() {
}
}

View file

@ -0,0 +1,243 @@
/*******************************************************************************
* 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.ui.language;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.internal.ui.preferences.PreferencesMessages;
import org.eclipse.cdt.internal.ui.util.Messages;
public class LanguageMappingWidget {
private static final int MINIMUM_COLUMN_WIDTH = 150;
private Table fTable;
private HashMap fContentTypeNamesToIDsMap;
private Set fAffectedContentTypes;
private Composite fContents;
private Map fContentTypeMappings;
private boolean fIsReadOnly;
private Set fOverriddenContentTypes;
private Font fOverriddenFont;
private LanguageMappingWidget fChild;
private IAdaptable fElement;
public LanguageMappingWidget() {
fOverriddenFont = JFaceResources.getFontRegistry().getItalic(JFaceResources.DIALOG_FONT);
fOverriddenContentTypes = Collections.EMPTY_SET;
// keep a mapping of all registered content types and their names
fContentTypeNamesToIDsMap = new HashMap();
String[] contentTypesIDs = LanguageManager.getInstance().getRegisteredContentTypeIds();
IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
for (int i = 0; i < contentTypesIDs.length; i++) {
String name = contentTypeManager.getContentType(contentTypesIDs[i]).getName();
// keep track of what ID this name corresponds to so that when we
// setup the mapping
// later based upon user selection, we'll know what ID to use
fContentTypeNamesToIDsMap.put(name, contentTypesIDs[i]);
}
fContentTypeMappings = new TreeMap();
fAffectedContentTypes = new HashSet();
}
public Composite createContents(Composite parent, String description) {
fContents = new Composite(parent, SWT.NONE);
fContents.setLayout(new GridLayout(2, false));
if (description != null) {
createHeader(parent, description);
}
Composite tableParent = new Composite(fContents, SWT.NONE);
tableParent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
fTable = new Table(tableParent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.FULL_SELECTION);
fTable.setHeaderVisible(true);
fTable.setLinesVisible(true);
TableColumn contentTypeColumn = new TableColumn(fTable, SWT.LEAD);
contentTypeColumn.setText(PreferencesMessages.ProjectLanguagesPropertyPage_contentTypeColumn);
TableColumn languageColumn = new TableColumn(fTable, SWT.LEAD);
languageColumn.setText(PreferencesMessages.ProjectLanguagesPropertyPage_languageColumn);
TableColumnLayout layout = new TableColumnLayout();
layout.setColumnData(contentTypeColumn, new ColumnWeightData(1, MINIMUM_COLUMN_WIDTH, true));
layout.setColumnData(languageColumn, new ColumnWeightData(1, MINIMUM_COLUMN_WIDTH, true));
tableParent.setLayout(layout);
if (!fIsReadOnly) {
Composite buttons = new Composite(fContents, SWT.NONE);
buttons.setLayout(new GridLayout());
buttons.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
Button addButton = new Button(buttons, SWT.PUSH);
addButton.setText(PreferencesMessages.ProjectLanguagesPropertyPage_addMappingButton);
addButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
ContentTypeMappingDialog dialog = new ContentTypeMappingDialog(fContents.getShell());
dialog.setContentTypeFilter(fContentTypeMappings.keySet());
dialog.setBlockOnOpen(true);
if (dialog.open() == Window.OK) {
String contentType = dialog.getContentTypeID();
String language = dialog.getLanguageID();
fContentTypeMappings.put(contentType, language);
IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
fAffectedContentTypes.add(contentTypeManager.getContentType(contentType));
refreshMappings();
}
}
});
Button removeButton = new Button(buttons, SWT.PUSH);
removeButton.setText(PreferencesMessages.ProjectLanguagesPropertyPage_removeMappingButton);
removeButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
TableItem[] selection = fTable.getSelection();
for (int i = 0; i < selection.length; i++) {
String contentType = (String) fContentTypeNamesToIDsMap.get(selection[i].getText(0));
fContentTypeMappings.remove(contentType);
IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
fAffectedContentTypes.add(contentTypeManager.getContentType(contentType));
}
refreshMappings();
}
});
}
refreshMappings();
return fContents;
}
private void createHeader(Composite parent, String description) {
Link link = new Link(fContents, SWT.NONE);
link.setText(description);
link.addListener(SWT.Selection, new LanguageMappingLinkListener(fContents.getShell(), getElement()) {
protected void refresh() {
refreshMappings();
}
});
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
gridData.horizontalSpan = 2;
link.setLayoutData(gridData);
}
public IAdaptable getElement() {
return fElement;
}
public void setElement(IAdaptable element) {
fElement = element;
}
public void refreshMappings() {
if (fTable == null) {
return;
}
fTable.removeAll();
Iterator mappings = fContentTypeMappings.entrySet().iterator();
IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
while (mappings.hasNext()) {
Entry entry = (Entry) mappings.next();
TableItem item = new TableItem(fTable, SWT.NONE);
String contentType = (String) entry.getKey();
String contentTypeName = contentTypeManager.getContentType(contentType).getName();
String languageName = LanguageManager.getInstance().getLanguage((String) entry.getValue()).getName();
if (fOverriddenContentTypes.contains(contentType)) {
item.setText(0, Messages.format(PreferencesMessages.ProjectLanguagesPropertyPage_overriddenContentType, contentTypeName));
item.setFont(fOverriddenFont);
} else {
item.setText(0, contentTypeName);
}
item.setText(1, languageName);
}
if (fChild != null) {
Set overrides = new HashSet(fContentTypeMappings.keySet());
overrides.addAll(fOverriddenContentTypes);
fChild.setOverriddenContentTypes(overrides);
fChild.refreshMappings();
}
}
public void setOverriddenContentTypes(Set contentTypes) {
fOverriddenContentTypes = contentTypes;
}
public void setMappings(Map mappings) {
fContentTypeMappings = new TreeMap(mappings);
}
public IContentType[] getAffectedContentTypes() {
return (IContentType[]) fAffectedContentTypes.toArray(new IContentType[fAffectedContentTypes.size()]);
}
public Map getContentTypeMappings() {
return Collections.unmodifiableMap(fContentTypeMappings);
}
public void setReadOnly(boolean isReadOnly) {
fIsReadOnly = isReadOnly;
}
public void setChild(LanguageMappingWidget child) {
fChild = child;
}
}

View file

@ -10,200 +10,122 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.language;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
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;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Group;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.ProjectLanguageConfiguration;
import org.eclipse.cdt.core.language.WorkspaceLanguageConfiguration;
import org.eclipse.cdt.core.model.ILanguageMappingChangeEvent;
import org.eclipse.cdt.core.model.ILanguageMappingChangeListener;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.internal.ui.preferences.PreferencesMessages;
public class ProjectLanguageMappingPropertyPage extends PropertyPage {
private static final int MINIMUM_COLUMN_WIDTH = 150;
private LanguageMappingWidget fMappingWidget;
private LanguageMappingWidget fInheritedMappingWidget;
private ProjectLanguageConfiguration fMappings;
private Table fTable;
private HashMap fContentTypeNamesToIDsMap;
private ILanguageMappingChangeListener fInheritedMappingsChangeListener;
public ProjectLanguageMappingPropertyPage() {
super();
// keep a mapping of all registered content types and their names
fContentTypeNamesToIDsMap = new HashMap();
String[] contentTypesIDs = LanguageManager.getInstance()
.getRegisteredContentTypeIds();
IContentTypeManager contentTypeManager = Platform
.getContentTypeManager();
for (int i = 0; i < contentTypesIDs.length; i++) {
String name = contentTypeManager.getContentType(contentTypesIDs[i])
.getName();
// keep track of what ID this name corresponds to so that when we
// setup the mapping
// later based upon user selection, we'll know what ID to use
fContentTypeNamesToIDsMap.put(name, contentTypesIDs[i]);
}
fMappingWidget = new LanguageMappingWidget();
fInheritedMappingWidget = new LanguageMappingWidget();
fInheritedMappingWidget.setReadOnly(true);
fMappingWidget.setChild(fInheritedMappingWidget);
}
/**
* @see PreferencePage#createContents(Composite)
*/
protected Control createContents(Composite parent) {
fetchMappings();
Composite composite = new Composite(parent, SWT.NONE);
composite
.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
composite.setLayout(new GridLayout(2, false));
Composite tableParent = new Composite(composite, SWT.NONE);
tableParent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
fMappingWidget.setElement(getProject());
fTable = new Table(tableParent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.FULL_SELECTION);
fTable.setHeaderVisible(true);
fTable.setLinesVisible(true);
TableColumn contentTypeColumn = new TableColumn(fTable, SWT.LEAD);
contentTypeColumn
.setText(PreferencesMessages.ProjectLanguagesPropertyPage_contentTypeColumn);
TableColumn languageColumn = new TableColumn(fTable, SWT.LEAD);
languageColumn
.setText(PreferencesMessages.ProjectLanguagesPropertyPage_languageColumn);
TableColumnLayout layout = new TableColumnLayout();
layout.setColumnData(contentTypeColumn, new ColumnWeightData(1,
MINIMUM_COLUMN_WIDTH, true));
layout.setColumnData(languageColumn, new ColumnWeightData(1,
MINIMUM_COLUMN_WIDTH, true));
tableParent.setLayout(layout);
Composite buttons = new Composite(composite, SWT.NONE);
buttons.setLayout(new GridLayout());
buttons.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false,
false));
Button addButton = new Button(buttons, SWT.PUSH);
addButton
.setText(PreferencesMessages.ProjectLanguagesPropertyPage_addMappingButton);
addButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
ContentTypeMappingDialog dialog = new ContentTypeMappingDialog(
getShell());
dialog.setContentTypeFilter(fMappings.getContentTypeMappings()
.keySet());
dialog.setBlockOnOpen(true);
if (dialog.open() == Window.OK) {
String contentType = dialog.getContentTypeID();
String language = dialog.getLanguageID();
fMappings.addContentTypeMapping(contentType, language);
refreshMappings();
Composite contents = new Composite(parent, SWT.NONE);
contents.setLayout(new GridLayout(1, false));
fetchMappings(getProject());
Composite contentTypeMappings = fMappingWidget.createContents(contents, PreferencesMessages.ProjectLanguagesPropertyPage_description);
contentTypeMappings.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Group group = new Group(contents, SWT.SHADOW_IN);
group.setText(PreferencesMessages.ProjectLanguagesPropertyPage_inheritedWorkspaceMappingsGroup);
group.setLayout(new FillLayout());
group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
fetchWorkspaceMappings();
fInheritedMappingWidget.createContents(group, null);
fInheritedMappingsChangeListener = new ILanguageMappingChangeListener() {
public void handleLanguageMappingChangeEvent(ILanguageMappingChangeEvent event) {
if (event.getType() == ILanguageMappingChangeEvent.TYPE_WORKSPACE) {
fetchWorkspaceMappings();
fInheritedMappingWidget.refreshMappings();
}
}
});
Button removeButton = new Button(buttons, SWT.PUSH);
removeButton
.setText(PreferencesMessages.ProjectLanguagesPropertyPage_removeMappingButton);
removeButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
TableItem[] selection = fTable.getSelection();
for (int i = 0; i < selection.length; i++) {
fMappings
.removeContentTypeMapping((String) fContentTypeNamesToIDsMap
.get(selection[i].getText(0)));
}
refreshMappings();
}
});
refreshMappings();
return composite;
};
LanguageManager.getInstance().registerLanguageChangeListener(fInheritedMappingsChangeListener);
return contents;
}
private void refreshMappings() {
fTable.removeAll();
Iterator mappings = fMappings.getContentTypeMappings().entrySet()
.iterator();
IContentTypeManager contentTypeManager = Platform
.getContentTypeManager();
while (mappings.hasNext()) {
Entry entry = (Entry) mappings.next();
TableItem item = new TableItem(fTable, SWT.NONE);
String contentTypeName = contentTypeManager.getContentType(
(String) entry.getKey()).getName();
String languageName = LanguageManager.getInstance().getLanguage(
(String) entry.getValue()).getName();
item.setText(0, contentTypeName);
item.setText(1, languageName);
private void fetchMappings(IProject project) {
try {
LanguageManager manager = LanguageManager.getInstance();
fMappings = manager.getLanguageConfiguration(project);
fMappingWidget.setMappings(fMappings.getContentTypeMappings());
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
private void fetchMappings() {
private void fetchWorkspaceMappings() {
try {
fMappings = LanguageManager.getInstance()
.getLanguageConfiguration(getProject());
LanguageManager manager = LanguageManager.getInstance();
WorkspaceLanguageConfiguration workspaceMappings = manager.getWorkspaceLanguageConfiguration();
fInheritedMappingWidget.setMappings(workspaceMappings.getWorkspaceMappings());
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
protected void performDefaults() {
fMappings = new ProjectLanguageConfiguration();
super.performDefaults();
fetchMappings(getProject());
fMappingWidget.refreshMappings();
}
public boolean performOk() {
try {
IContentType[] affectedContentTypes = null;
LanguageManager.getInstance().storeLanguageMappingConfiguration(
getProject(), affectedContentTypes);
fMappings.setContentTypeMappings(fMappingWidget.getContentTypeMappings());
IContentType[] affectedContentTypes = fMappingWidget.getAffectedContentTypes();
LanguageManager.getInstance().storeLanguageMappingConfiguration(getProject(), affectedContentTypes);
return true;
} catch (CoreException e) {
CCorePlugin.log(e);
return false;
}
}
public void dispose() {
super.dispose();
LanguageManager.getInstance().unregisterLanguageChangeListener(fInheritedMappingsChangeListener);
}
private IProject getProject() {
return (IProject) getElement().getAdapter(IProject.class);
}
}

View file

@ -0,0 +1,73 @@
/*******************************************************************************
* 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.ui.language;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.WorkspaceLanguageConfiguration;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.internal.ui.preferences.PreferencesMessages;
public class WorkspaceLanguageMappingPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
WorkspaceLanguageConfiguration fMappings;
LanguageMappingWidget fMappingWidget;
public WorkspaceLanguageMappingPreferencePage() {
fMappingWidget = new LanguageMappingWidget();
}
protected Control createContents(Composite parent) {
try {
fMappings = LanguageManager.getInstance().getWorkspaceLanguageConfiguration();
fMappingWidget.setMappings(fMappings.getWorkspaceMappings());
} catch (CoreException e) {
CCorePlugin.log(e);
}
return fMappingWidget.createContents(parent, PreferencesMessages.WorkspaceLanguagesPreferencePage_description);
}
public void init(IWorkbench workbench) {
}
public boolean performOk() {
try {
IContentType[] affectedContentTypes = fMappingWidget.getAffectedContentTypes();
LanguageManager manager = LanguageManager.getInstance();
WorkspaceLanguageConfiguration config = manager.getWorkspaceLanguageConfiguration();
config.setWorkspaceMappings(fMappingWidget.getContentTypeMappings());
manager.storeWorkspaceLanguageConfiguration(affectedContentTypes);
return true;
} catch (CoreException e) {
CCorePlugin.log(e);
return false;
}
}
protected void performDefaults() {
super.performDefaults();
try {
LanguageManager manager = LanguageManager.getInstance();
WorkspaceLanguageConfiguration config = manager.getWorkspaceLanguageConfiguration();
fMappingWidget.setMappings(config.getWorkspaceMappings());
} catch (CoreException e) {
CCorePlugin.log(e);
}
}
}

View file

@ -193,15 +193,28 @@ public final class PreferencesMessages extends NLS {
public static String CodeFormatterPreferencePage_title;
public static String CodeFormatterPreferencePage_description;
public static String WorkspaceLanguagesPreferencePage_description;
public static String ProjectLanguagesPropertyPage_description;
public static String ProjectLanguagesPropertyPage_contentTypeColumn;
public static String ProjectLanguagesPropertyPage_languageColumn;
public static String ProjectLanguagesPropertyPage_addMappingButton;
public static String ProjectLanguagesPropertyPage_removeMappingButton;
public static String ProjectLanguagesPropertyPage_inheritedWorkspaceMappingsGroup;
public static String ProjectLanguagesPropertyPage_overriddenContentType;
public static String ContentTypeMappingsDialog_title;
public static String ContentTypeMappingsDialog_contentType;
public static String ContentTypeMappingsDialog_language;
public static String FileLanguagesPropertyPage_languageLabel;
public static String FileLanguagesPropertyPage_inheritedProjectMappingsGroup;
public static String FileLanguagesPropertyPage_contentTypeLabel;
public static String FileLanguagesPropertyPage_inheritedFromSystem;
public static String FileLanguagesPropertyPage_inheritedFromProject;
public static String FileLanguagesPropertyPage_inheritedFromWorkspace;
public static String FileLanguagesPropertyPage_description;
static {
NLS.initializeMessages(BUNDLE_NAME, PreferencesMessages.class);
}

View file

@ -227,14 +227,27 @@ PathEntryVariablesBlock_removeVariableButton = &Remove
# Language settings
WorkspaceLanguagesPreferencePage_description = These settings are global to the entire workspace. They are overridden by project-specific language mappings.
ProjectLanguagesPropertyPage_description = These settings are project-specific. The mappings listed here override <a href="workspace">workspace-wide</a> language mappings.
ProjectLanguagesPropertyPage_contentTypeColumn = Content Type
ProjectLanguagesPropertyPage_languageColumn = Language
ProjectLanguagesPropertyPage_addMappingButton = &Add...
ProjectLanguagesPropertyPage_removeMappingButton = &Remove
ProjectLanguagesPropertyPage_inheritedWorkspaceMappingsGroup = Language settings inherited from the workspace
ProjectLanguagesPropertyPage_overriddenContentType = (Overridden) {0}
ContentTypeMappingsDialog_title = Add Mapping
ContentTypeMappingsDialog_contentType = Content type
ContentTypeMappingsDialog_language = Language
FileLanguagesPropertyPage_description = This language assignment overrides all <a href="project">project-wide</a> and <a href="workspace">workspace-wide</a> language mappings.
FileLanguagesPropertyPage_contentTypeLabel = Content Type:
FileLanguagesPropertyPage_languageLabel = Assigned Language:
FileLanguagesPropertyPage_inheritedProjectMappingsGroup = Language settings inherited from the project
FileLanguagesPropertyPage_inheritedFromSystem = Inherited from the system ({0})
FileLanguagesPropertyPage_inheritedFromProject = Inherited from the project ({0})
FileLanguagesPropertyPage_inheritedFromWorkspace = Inherited from the workspace ({0})
# Others
ProposalFilterPreferencesUtil_defaultFilterName=<Default Filter>