mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-01 06:05:24 +02:00
Made languages more dynamic. No more hard coding. The PDOM records and manages the mapping from language id used in the bindings to ILanguage instance. Added a LanguageManager to help with the mapping and move all access to the extension there.
This commit is contained in:
parent
d4bc99f45d
commit
df627e7739
11 changed files with 252 additions and 58 deletions
|
@ -17,7 +17,7 @@ import java.util.Map;
|
|||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ILanguage;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.LanguageManager;
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.IBuffer;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
|
@ -33,14 +33,9 @@ import org.eclipse.cdt.core.model.IWorkingCopy;
|
|||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IConfigurationElement;
|
||||
import org.eclipse.core.runtime.IExtension;
|
||||
import org.eclipse.core.runtime.IExtensionPoint;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.content.IContentType;
|
||||
import org.eclipse.core.runtime.content.IContentTypeManager;
|
||||
|
||||
|
@ -664,22 +659,7 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
|
|||
// content type string
|
||||
IContentTypeManager manager = Platform.getContentTypeManager();
|
||||
IContentType contentType = manager.getContentType(contentTypeId);
|
||||
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, ILanguage.KEY);
|
||||
IExtension[] extensions = point.getExtensions();
|
||||
for (int i = 0; i < extensions.length; ++i) {
|
||||
IConfigurationElement[] languages = extensions[i].getConfigurationElements();
|
||||
for (int j = 0; j < languages.length; ++j) {
|
||||
IConfigurationElement language = languages[j];
|
||||
IConfigurationElement[] contentTypes = language.getChildren("contentType"); //$NON-NLS-1$
|
||||
for (int k = 0; k < contentTypes.length; ++k) {
|
||||
IContentType langContType = manager.getContentType(contentTypes[k].getAttribute("id")); //$NON-NLS-1$
|
||||
if (contentType.equals(langContType)) {
|
||||
this.language = (ILanguage)language.createExecutableExtension("class"); //$NON-NLS-1$
|
||||
return this.language;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
language = LanguageManager.getInstance().getLanguage(contentType);
|
||||
}
|
||||
|
||||
return language;
|
||||
|
|
|
@ -48,21 +48,13 @@ public interface ILanguage {
|
|||
public static final int AST_SKIP_INDEXED_HEADERS = 4;
|
||||
|
||||
/**
|
||||
* Return the language id for this language. This is used in the PDOM database
|
||||
* to differentiate languages from eachother.
|
||||
* Return the language id for this language in the given PDOM.
|
||||
* This is to differentiate languages from eachother.
|
||||
*
|
||||
* @return
|
||||
* @return language id
|
||||
*/
|
||||
public int getId();
|
||||
public String getId();
|
||||
|
||||
// Language ID registry. This is here mainly to avoid languages trampling
|
||||
// over eachother. It is not critical that language ids be put here, but it
|
||||
// is critical that two languages in a given installion do not have the same
|
||||
// id.
|
||||
public static final int GCC_ID = 1; // gnu C
|
||||
public static final int GPP_ID = 2; // gnu C++
|
||||
public static final int GNAT_ID = 3; // gnu Ada
|
||||
|
||||
/**
|
||||
* Create the AST for the given translation unit with the given style.
|
||||
*
|
||||
|
@ -89,7 +81,7 @@ public interface ILanguage {
|
|||
* @param binding
|
||||
* @return
|
||||
*/
|
||||
public PDOMBinding getPDOMBinding(PDOMDatabase pdom, IASTName name) throws CoreException;
|
||||
public PDOMBinding getPDOMBinding(PDOMDatabase pdom, int languageId, IASTName name) throws CoreException;
|
||||
|
||||
/**
|
||||
* Creates a language specific binding given the generic binding extracted
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.core.dom;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IConfigurationElement;
|
||||
import org.eclipse.core.runtime.IExtension;
|
||||
import org.eclipse.core.runtime.IExtensionPoint;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.content.IContentType;
|
||||
import org.eclipse.core.runtime.content.IContentTypeManager;
|
||||
|
||||
/**
|
||||
* @author Doug Schaefer
|
||||
*
|
||||
*/
|
||||
public class LanguageManager {
|
||||
|
||||
private static LanguageManager instance;
|
||||
|
||||
public static LanguageManager getInstance() {
|
||||
if (instance == null)
|
||||
instance = new LanguageManager();
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ILanguage getLanguage(String id) throws CoreException {
|
||||
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, ILanguage.KEY);
|
||||
IExtension[] extensions = point.getExtensions();
|
||||
for (int i = 0; i < extensions.length; ++i) {
|
||||
IExtension extension = extensions[i];
|
||||
IConfigurationElement[] languages = extension.getConfigurationElements();
|
||||
for (int j = 0; j < languages.length; ++j) {
|
||||
IConfigurationElement language = languages[j];
|
||||
String langId = extension.getNamespace() + "." + language.getAttribute("id"); //$NON-NLS-1$ $NON-NLS-2$
|
||||
if (langId.equals(id))
|
||||
return (ILanguage)language.createExecutableExtension("class"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ILanguage getLanguage(IContentType contentType) throws CoreException {
|
||||
IContentTypeManager manager = Platform.getContentTypeManager();
|
||||
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, ILanguage.KEY);
|
||||
IExtension[] extensions = point.getExtensions();
|
||||
for (int i = 0; i < extensions.length; ++i) {
|
||||
IConfigurationElement[] languages = extensions[i].getConfigurationElements();
|
||||
for (int j = 0; j < languages.length; ++j) {
|
||||
IConfigurationElement language = languages[j];
|
||||
IConfigurationElement[] contentTypes = language.getChildren("contentType"); //$NON-NLS-1$
|
||||
for (int k = 0; k < contentTypes.length; ++k) {
|
||||
IContentType langContType = manager.getContentType(contentTypes[k].getAttribute("id")); //$NON-NLS-1$
|
||||
if (contentType.equals(langContType)) {
|
||||
return (ILanguage)language.createExecutableExtension("class"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -50,8 +50,9 @@ public class GCCLanguage implements ILanguage {
|
|||
|
||||
protected static final GCCScannerExtensionConfiguration C_GNU_SCANNER_EXTENSION = new GCCScannerExtensionConfiguration();
|
||||
|
||||
public int getId() {
|
||||
return GCC_ID;
|
||||
public String getId() {
|
||||
// Must match the id in the extension
|
||||
return CCorePlugin.PLUGIN_ID + ".gcc"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public IASTTranslationUnit getTranslationUnit(ITranslationUnit tu, int style) {
|
||||
|
@ -96,7 +97,7 @@ public class GCCLanguage implements ILanguage {
|
|||
return null;
|
||||
}
|
||||
|
||||
public PDOMBinding getPDOMBinding(PDOMDatabase pdom, IASTName name) throws CoreException {
|
||||
public PDOMBinding getPDOMBinding(PDOMDatabase pdom, int languageId, IASTName name) throws CoreException {
|
||||
IBinding binding = name.resolveBinding();
|
||||
if (binding == null)
|
||||
return null;
|
||||
|
|
|
@ -57,9 +57,9 @@ import org.eclipse.core.runtime.CoreException;
|
|||
public class GPPLanguage implements ILanguage {
|
||||
|
||||
protected static final GPPScannerExtensionConfiguration CPP_GNU_SCANNER_EXTENSION = new GPPScannerExtensionConfiguration();
|
||||
|
||||
public int getId() {
|
||||
return GPP_ID;
|
||||
|
||||
public String getId() {
|
||||
return CCorePlugin.PLUGIN_ID + ".g++"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public IASTTranslationUnit getTranslationUnit(ITranslationUnit tu, int style) {
|
||||
|
@ -107,7 +107,7 @@ public class GPPLanguage implements ILanguage {
|
|||
public static final int CPPVARIABLE = 1;
|
||||
public static final int CPPFUNCTION = 2;
|
||||
|
||||
public PDOMBinding getPDOMBinding(PDOMDatabase pdom, IASTName name) throws CoreException {
|
||||
public PDOMBinding getPDOMBinding(PDOMDatabase pdom, int languageId, IASTName name) throws CoreException {
|
||||
IBinding binding = name.resolveBinding();
|
||||
if (binding == null)
|
||||
return null;
|
||||
|
@ -117,11 +117,11 @@ public class GPPLanguage implements ILanguage {
|
|||
} else if (binding instanceof CPPVariable) {
|
||||
IScope scope = binding.getScope();
|
||||
if (!(scope instanceof CPPBlockScope))
|
||||
return new PDOMCPPVariable(pdom, name, (CPPVariable)binding);
|
||||
return new PDOMCPPVariable(pdom, languageId, name, (CPPVariable)binding);
|
||||
} else if (binding instanceof CPPMethod) {
|
||||
return null;
|
||||
} else if (binding instanceof CPPFunction) {
|
||||
return new PDOMCPPFunction(pdom, name, (CPPFunction)binding);
|
||||
return new PDOMCPPFunction(pdom, languageId, name, (CPPFunction)binding);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -10,10 +10,15 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.pdom;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ICodeReaderFactory;
|
||||
import org.eclipse.cdt.core.dom.ILanguage;
|
||||
import org.eclipse.cdt.core.dom.IPDOM;
|
||||
import org.eclipse.cdt.core.dom.LanguageManager;
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
|
@ -27,10 +32,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
|||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.QualifiedName;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
|
||||
/**
|
||||
* The PDOM Database.
|
||||
|
@ -43,11 +45,15 @@ public class PDOMDatabase implements IPDOM {
|
|||
private Database db;
|
||||
|
||||
private static final int VERSION = 0;
|
||||
|
||||
public static final int FILE_INDEX = Database.DATA_AREA + 1 * Database.INT_SIZE;
|
||||
private BTree fileIndex;
|
||||
|
||||
public static final int BINDING_INDEX = Database.DATA_AREA + 2 * Database.INT_SIZE;
|
||||
public static final int LANGUAGES = Database.DATA_AREA;
|
||||
public static final int FILE_INDEX = Database.DATA_AREA + 4;
|
||||
public static final int BINDING_INDEX = Database.DATA_AREA + 8;
|
||||
|
||||
private Map languageCache;
|
||||
private ILanguage[] languages;
|
||||
|
||||
private BTree fileIndex;
|
||||
private BTree bindingIndex;
|
||||
|
||||
private static final QualifiedName dbNameProperty
|
||||
|
@ -89,6 +95,7 @@ public class PDOMDatabase implements IPDOM {
|
|||
if (language == null)
|
||||
return;
|
||||
|
||||
final int languageId = getLanguageId(language);
|
||||
IASTTranslationUnit ast = language.getTranslationUnit(tu,
|
||||
ILanguage.AST_USE_INDEX |
|
||||
ILanguage.AST_SKIP_INDEXED_HEADERS);
|
||||
|
@ -102,7 +109,7 @@ public class PDOMDatabase implements IPDOM {
|
|||
public int visit(IASTName name) {
|
||||
try {
|
||||
if (name.toCharArray().length > 0) {
|
||||
PDOMBinding binding = language.getPDOMBinding(PDOMDatabase.this, name);
|
||||
PDOMBinding binding = language.getPDOMBinding(PDOMDatabase.this, languageId, name);
|
||||
if (binding != null)
|
||||
new PDOMName(PDOMDatabase.this, name, binding);
|
||||
}
|
||||
|
@ -155,4 +162,49 @@ public class PDOMDatabase implements IPDOM {
|
|||
return new IBinding[0];
|
||||
}
|
||||
|
||||
private void initLanguageMap() throws CoreException {
|
||||
// load in the languages
|
||||
languageCache = new HashMap();
|
||||
int record = db.getInt(LANGUAGES);
|
||||
PDOMLanguage lang = null;
|
||||
if (record != 0)
|
||||
lang = new PDOMLanguage(this, record);
|
||||
while (lang != null) {
|
||||
languageCache.put(lang.getName(), lang);
|
||||
lang = lang.getNext();
|
||||
}
|
||||
|
||||
// map language ids to ILanguage impls.
|
||||
languages = new ILanguage[languageCache.size() + 1]; // + 1 for the empty zero
|
||||
Iterator i = languageCache.values().iterator();
|
||||
while (i.hasNext()) {
|
||||
lang = (PDOMLanguage)i.next();
|
||||
languages[lang.getId()] = LanguageManager.getInstance().getLanguage(lang.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public int getLanguageId(ILanguage language) throws CoreException {
|
||||
if (languageCache == null)
|
||||
initLanguageMap();
|
||||
PDOMLanguage pdomLang = (PDOMLanguage)languageCache.get(language.getId());
|
||||
if (pdomLang == null) {
|
||||
// add it in
|
||||
int next = db.getInt(LANGUAGES);
|
||||
int id = next == 0 ? 1 : new PDOMLanguage(this, next).getId() + 1;
|
||||
pdomLang = new PDOMLanguage(this, language.getId(), id, next);
|
||||
db.putInt(LANGUAGES, pdomLang.getRecord());
|
||||
ILanguage[] oldlangs = languages;
|
||||
languages = new ILanguage[id + 1];
|
||||
System.arraycopy(oldlangs, 0, languages, 0, id);
|
||||
languages[id] = language;
|
||||
return id;
|
||||
} else
|
||||
return pdomLang.getId();
|
||||
}
|
||||
|
||||
public ILanguage getLanguage(int id) throws CoreException {
|
||||
if (languages == null)
|
||||
initLanguageMap();
|
||||
return languages[id];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.core.pdom;
|
||||
|
||||
import org.eclipse.cdt.internal.core.pdom.db.Database;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
/**
|
||||
* @author Doug Schaefer
|
||||
*
|
||||
*/
|
||||
public class PDOMLanguage {
|
||||
|
||||
private PDOMDatabase pdom;
|
||||
private int record;
|
||||
|
||||
private static final int NEXT = 0; // int
|
||||
private static final int ID = 4; // char
|
||||
private static final int NAME = 6; // string
|
||||
|
||||
public PDOMLanguage(PDOMDatabase pdom, int record) {
|
||||
this.pdom = pdom;
|
||||
this.record = record;
|
||||
}
|
||||
|
||||
public PDOMLanguage(PDOMDatabase pdom, String name, int id, int next) throws CoreException {
|
||||
this.pdom = pdom;
|
||||
Database db = pdom.getDB();
|
||||
record = db.malloc(6 + (name.length() + 1) * 2);
|
||||
db.putInt(record + NEXT, next);
|
||||
db.putChar(record + ID, (char)id);
|
||||
db.putString(record + NAME, name);
|
||||
}
|
||||
|
||||
public int getRecord() {
|
||||
return record;
|
||||
}
|
||||
|
||||
public int getId() throws CoreException {
|
||||
return pdom.getDB().getChar(record + ID);
|
||||
}
|
||||
|
||||
public String getName() throws CoreException {
|
||||
return pdom.getDB().getString(record + NAME);
|
||||
}
|
||||
|
||||
public PDOMLanguage getNext() throws CoreException {
|
||||
int nextrec = pdom.getDB().getInt(record + NEXT);
|
||||
return nextrec != 0 ? new PDOMLanguage(pdom, nextrec) : null;
|
||||
}
|
||||
|
||||
public boolean equals(String id) throws CoreException {
|
||||
return PDOMUtils.stringCompare(pdom.getDB(), record + NAME, id) == 0;
|
||||
}
|
||||
}
|
|
@ -70,4 +70,35 @@ public class PDOMUtils {
|
|||
return 1;
|
||||
|
||||
}
|
||||
|
||||
public static int stringCompare(Database db, int record1, String record2) throws CoreException {
|
||||
Chunk chunk1 = db.getChunk(record1);
|
||||
|
||||
int i1 = record1;
|
||||
int i2 = 0;
|
||||
int n2 = record2.length();
|
||||
char c1 = chunk1.getChar(i1);
|
||||
char c2 = i2 < n2 ? record2.charAt(i2) : 0;
|
||||
|
||||
while (c1 != 0 && c2 != 0) {
|
||||
if (c1 < c2)
|
||||
return -1;
|
||||
if (c1 > c2)
|
||||
return 1;
|
||||
|
||||
i1 += 2;
|
||||
++i2;
|
||||
c1 = chunk1.getChar(i1);
|
||||
c2 = i2 < n2 ? record2.charAt(i2) : 0;
|
||||
}
|
||||
|
||||
if (c1 == c2)
|
||||
return 0;
|
||||
else if (c1 == 0)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.pdom.dom;
|
|||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.dom.ILanguage;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
|
@ -136,8 +137,8 @@ public class PDOMBinding implements IBinding {
|
|||
return record;
|
||||
}
|
||||
|
||||
public int getLanguage() throws CoreException {
|
||||
return pdom.getDB().getChar(record + LANGUAGE_OFFSET);
|
||||
public ILanguage getLanguage() throws CoreException {
|
||||
return pdom.getLanguage(pdom.getDB().getChar(record + LANGUAGE_OFFSET));
|
||||
}
|
||||
|
||||
public int getBindingType() throws CoreException {
|
||||
|
|
|
@ -37,8 +37,8 @@ public class PDOMCPPFunction extends PDOMBinding implements ICPPFunction {
|
|||
* @param type
|
||||
* @throws CoreException
|
||||
*/
|
||||
public PDOMCPPFunction(PDOMDatabase pdom, IASTName name, CPPFunction binding) throws CoreException {
|
||||
super(pdom, name, GPPLanguage.GPP_ID, GPPLanguage.CPPFUNCTION);
|
||||
public PDOMCPPFunction(PDOMDatabase pdom, int languageId, IASTName name, CPPFunction binding) throws CoreException {
|
||||
super(pdom, name, languageId, GPPLanguage.CPPFUNCTION);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,9 +34,9 @@ public class PDOMCPPVariable extends PDOMBinding implements ICPPVariable {
|
|||
* @param binding
|
||||
* @throws CoreException
|
||||
*/
|
||||
public PDOMCPPVariable(PDOMDatabase pdom, IASTName name, CPPVariable binding)
|
||||
public PDOMCPPVariable(PDOMDatabase pdom, int languageId, IASTName name, CPPVariable binding)
|
||||
throws CoreException {
|
||||
super(pdom, name, GPPLanguage.GPP_ID, GPPLanguage.CPPVARIABLE);
|
||||
super(pdom, name, languageId, GPPLanguage.CPPVARIABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue