diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java index 15afacba49e..adfc62396e9 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java @@ -10,6 +10,7 @@ import org.eclipse.cdt.internal.core.model.BatchOperation; import org.eclipse.cdt.internal.core.model.CModelManager; import org.eclipse.cdt.internal.core.model.ContainerEntry; import org.eclipse.cdt.internal.core.model.IncludeEntry; +import org.eclipse.cdt.internal.core.model.LibraryEntry; import org.eclipse.cdt.internal.core.model.MacroEntry; import org.eclipse.cdt.internal.core.model.ProjectEntry; import org.eclipse.cdt.internal.core.model.SourceEntry; @@ -283,7 +284,7 @@ public class CoreModel { IPath sourceAttachmentRootPath, IPath sourceAttachmentPrefixMapping, boolean isExported) { - return newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, sourceAttachmentPrefixMapping, isExported); + return new LibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, sourceAttachmentPrefixMapping, isExported); } /** @@ -358,7 +359,31 @@ public class CoreModel { * @return a new source entry with the given exclusion patterns */ public static ISourceEntry newSourceEntry(IPath path, IPath outputLocation, IPath[] exclusionPatterns) { - return new SourceEntry(path, outputLocation, true, exclusionPatterns); + return newSourceEntry(path, outputLocation, true, exclusionPatterns); + } + + /** + * Creates and returns a new entry of kind CDT_SOURCE + * for the project's source folder identified by the given absolute + * workspace-relative path but excluding all source files with paths + * matching any of the given patterns. This specifies that all package + * fragments within the root will have children of type + * ICompilationUnit. + *

+ * The source folder is referred to using an absolute path relative to the + * workspace root, e.g. /Project/src. A project's source + * folders are located with that project. That is, a source + * entry specifying the path /P1/src is only usable for + * project P1. + *

+ * @param path the absolute workspace-relative path of a source folder + * @param exclusionPatterns the possibly empty list of exclusion patterns + * represented as relative paths + * @param specificOutputLocation the specific output location for this source entry (null if using project default ouput location) + * @return a new source entry with the given exclusion patterns + */ + public static ISourceEntry newSourceEntry(IPath path, IPath outputLocation, boolean isRecursive, IPath[] exclusionPatterns) { + return new SourceEntry(path, outputLocation, isRecursive, exclusionPatterns); } /** @@ -499,4 +524,5 @@ public class CoreModel { public IndexManager getIndexManager() { return manager.getIndexManager(); } + } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java index 93d9ce181de..b11ef9368c9 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java @@ -5,10 +5,11 @@ package org.eclipse.cdt.core.model; * All Rights Reserved. */ +import java.util.Map; + import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; - -import java.util.Map; +import org.eclipse.core.runtime.IProgressMonitor; /** * A C project represents a view of a project resource in terms of C @@ -48,12 +49,24 @@ public interface ICProject extends ICContainer { */ ILibraryReference[] getLibraryReferences() throws CModelException; + /** + * Returns the names of the projects that are directly required by this + * project. A project is required if it is in its cpath entries. + *

+ * The project names are returned in the order they appear on the cpathentries. + * + * @return the names of the projects that are directly required by this project + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + String[] getRequiredProjectNames() throws CModelException; + /** * * @return IProject */ IProject getProject(); - + /** * Helper method for returning one option value only. Equivalent to (String)this.getOptions(inheritCCoreOptions).get(optionName) * Note that it may answer null if this option does not exist, or if there is no custom value for it. @@ -82,7 +95,7 @@ public interface ICProject extends ICContainer { * @see CCorePlugin#getDefaultOptions */ Map getOptions(boolean inheritCCoreOptions); - + /** * Helper method for setting one option value only. Equivalent to Map options = this.getOptions(false); map.put(optionName, optionValue); this.setOptions(map) *

@@ -107,5 +120,30 @@ public interface ICProject extends ICContainer { * or null to flush all custom options (clients will automatically get the global CCorePlugin options). * @see CCorePlugin#getDefaultOptions */ - void setOptions(Map newOptions); + void setOptions(Map newOptions); + + /** + * Returns the list of entries for the project. This corresponds to the exact set + * of entries which were assigned using setCPathEntries. + *

+ * + * @return the list of entries for the project. + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + ICPathEntry[] getCPathEntries() throws CModelException; + + /** + * Sets the entries for this project. + * + * @param entries a list of ICPathEntry[] entries + * @param monitor the given progress monitor + * @exception CModelException if the entries could not be set. Reasons include: + *

+ */ + void setCPathEntries(ICPathEntry[] entries, IProgressMonitor monitor) throws CModelException; + } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Archive.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Archive.java index bdf98659cc3..9a745ae998b 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Archive.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Archive.java @@ -69,7 +69,7 @@ public class Archive extends Openable implements IArchive { IBinaryObject[] objects = ar.getObjects(); for (int i = 0; i < objects.length; i++) { final IBinaryObject obj = objects[i]; - Binary binary = new Binary(this, res.getLocation().append(obj.getName()), obj); + Binary binary = new Binary(this, ar.getPath().append(obj.getName()), obj); info.addChild(binary); } } else { diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java index 043108c2bdb..37ecafe5e44 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java @@ -40,6 +40,10 @@ public class Binary extends Openable implements IBinary { binaryFile = bin; } + protected IBinaryFile getBinaryFile() { + return binaryFile; + } + public boolean isSharedLib() { return getType() == IBinaryObject.SHARED; } @@ -58,65 +62,71 @@ public class Binary extends Openable implements IBinary { public boolean hasDebug() { if (isObject() || isExecutable() || isSharedLib()) { - return ((IBinaryObject)binaryFile).hasDebug(); + return ((IBinaryObject)getBinaryFile()).hasDebug(); } return false; } public String getCPU() { if (isObject() || isExecutable() || isSharedLib() || isCore()) { - return ((IBinaryObject)binaryFile).getCPU(); + return ((IBinaryObject)getBinaryFile()).getCPU(); } return ""; } public String[] getNeededSharedLibs() { if (isExecutable() || isSharedLib()) { - return ((IBinaryExecutable)binaryFile).getNeededSharedLibs(); + return ((IBinaryExecutable)getBinaryFile()).getNeededSharedLibs(); } return new String[0]; } protected int getType() { - IResource res = getResource(); - if (binaryFile != null && (fBinType == 0 || res.getModificationStamp() != fLastModification )) { - fLastModification = res.getModificationStamp(); - fBinType = binaryFile.getType(); + if (getBinaryFile() != null && (fBinType == 0 || getModificationStamp() != fLastModification )) { + fLastModification = getModificationStamp(); + fBinType = getBinaryFile().getType(); } return fBinType; } + protected long getModificationStamp() { + IResource res = getResource(); + if (res != null) + return res.getModificationStamp(); + return 0; + } + public long getText() { if (isObject() || isExecutable() || isSharedLib()) { - return ((IBinaryObject)binaryFile).getText(); + return ((IBinaryObject)getBinaryFile()).getText(); } return 0; } public long getData() { if (isObject() || isExecutable() || isSharedLib()) { - return ((IBinaryObject)binaryFile).getData(); + return ((IBinaryObject)getBinaryFile()).getData(); } return 0; } public long getBSS() { if (isObject() || isExecutable() || isSharedLib()) { - return ((IBinaryObject)binaryFile).getBSS(); + return ((IBinaryObject)getBinaryFile()).getBSS(); } return 0; } public String getSoname() { if (isSharedLib()) { - return ((IBinaryShared)binaryFile).getSoName(); + return ((IBinaryShared)getBinaryFile()).getSoName(); } return ""; } public boolean isLittleEndian() { if (isObject() || isExecutable() || isSharedLib() || isCore()) { - return ((IBinaryObject)binaryFile).isLittleEndian(); + return ((IBinaryObject)getBinaryFile()).isLittleEndian(); } return false; } @@ -145,7 +155,7 @@ public class Binary extends Openable implements IBinary { boolean computeChildren(OpenableInfo info, IResource res) { if (isObject() || isExecutable() || isSharedLib()) { Map hash = new HashMap(); - ISymbol[] symbols = ((IBinaryObject)binaryFile).getSymbols(); + ISymbol[] symbols = ((IBinaryObject)getBinaryFile()).getSymbols(); for (int i = 0; i < symbols.length; i++) { switch (symbols[i].getType()) { case ISymbol.FUNCTION : diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CPathEntry.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CPathEntry.java index 78e6a1b3d2d..51512920b57 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CPathEntry.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CPathEntry.java @@ -45,8 +45,8 @@ public class CPathEntry implements ICPathEntry { public boolean equals(Object object) { if (object instanceof ICPathEntry) { - return equals((ICPathEntry)object); - } + return equals((ICPathEntry) object); + } return super.equals(object); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java index 776cf0d3a65..896b0406f37 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java @@ -4,57 +4,81 @@ package org.eclipse.cdt.internal.core.model; * (c) Copyright QNX Software Systems Ltd. 2002. * All Rights Reserved. */ - + +import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.core.ICDescriptor; -import org.eclipse.cdt.core.ICPathEntry; +import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive; +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.IArchiveContainer; import org.eclipse.cdt.core.model.IBinaryContainer; import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICModelStatus; import org.eclipse.cdt.core.model.ICModelStatusConstants; +import org.eclipse.cdt.core.model.ICPathEntry; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IContainerEntry; +import org.eclipse.cdt.core.model.IIncludeEntry; +import org.eclipse.cdt.core.model.ILibraryEntry; import org.eclipse.cdt.core.model.ILibraryReference; +import org.eclipse.cdt.core.model.IMacroEntry; +import org.eclipse.cdt.core.model.IProjectEntry; +import org.eclipse.cdt.core.model.ISourceEntry; +import org.eclipse.cdt.internal.core.CharOperation; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.QualifiedName; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; public class CProject extends CContainer implements ICProject { - public CProject (ICElement parent, IProject project) { - super (parent, project, CElement.C_PROJECT); + /** + * An empty array of strings indicating that a project doesn't have any prerequesite projects. + */ + protected static final String[] NO_PREREQUISITES = new String[0]; + + public CProject(ICElement parent, IProject project) { + super(parent, project, CElement.C_PROJECT); } public IBinaryContainer getBinaryContainer() { - return ((CProjectInfo)getElementInfo()).getBinaryContainer(); + return ((CProjectInfo) getElementInfo()).getBinaryContainer(); } public IArchiveContainer getArchiveContainer() { - return ((CProjectInfo)getElementInfo()).getArchiveContainer(); + return ((CProjectInfo) getElementInfo()).getArchiveContainer(); } public IProject getProject() { return getUnderlyingResource().getProject(); } - - private static final String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$ + + private static final String CUSTOM_DEFAULT_OPTION_VALUE = "#\r\n\r#custom-non-empty-default-value#\r\n\r#"; //$NON-NLS-1$ public ICElement findElement(IPath path) throws CModelException { ICElement celem = null; if (path.isAbsolute()) { - celem = CModelManager.getDefault().create(path); + celem = CModelManager.getDefault().create(path); } else { IProject project = getProject(); - if (project != null) { + if (project != null) { IPath p = project.getFullPath().append(path); celem = CModelManager.getDefault().create(p); } @@ -66,7 +90,7 @@ public class CProject extends CContainer implements ICProject { return celem; } - public static boolean hasCNature (IProject p) { + public static boolean hasCNature(IProject p) { try { return p.hasNature(CProjectNature.C_NATURE_ID); } catch (CoreException e) { @@ -78,7 +102,7 @@ public class CProject extends CContainer implements ICProject { protected CElementInfo createElementInfo() { return new CProjectInfo(this); } - + // CHECKPOINT: CProjects will return the hash code of their underlying IProject public int hashCode() { return getProject().hashCode(); @@ -86,149 +110,195 @@ public class CProject extends CContainer implements ICProject { public ILibraryReference[] getLibraryReferences() throws CModelException { ArrayList list = new ArrayList(5); + IBinaryParser binParser = null; try { - ICDescriptor cdesc = CCorePlugin.getDefault().getCProjectDescription(getProject()); - ICPathEntry[] entries = cdesc.getPathEntries(); - for (int i = 0; i < entries.length; i++) { - if (entries[i].getEntryKind() == ICPathEntry.CDT_LIBRARY) { - ICPathEntry entry = entries[i]; - list.add(new LibraryReference(this, entry.getPath().lastSegment(),entry)); + binParser = CCorePlugin.getDefault().getBinaryParser(getProject()); + } catch (CoreException e) { + } + ICPathEntry[] entries = getCPathEntries(); + for (int i = 0; i < entries.length; i++) { + if (entries[i].getEntryKind() == ICPathEntry.CDT_LIBRARY) { + ILibraryEntry entry = (ILibraryEntry) entries[i]; + ILibraryReference lib = null; + if (binParser != null) { + IBinaryFile bin; + try { + bin = binParser.getBinary(entry.getLibraryPath()); + if (bin.getType() == IBinaryFile.ARCHIVE) { + lib = new LibraryReferenceArchive(this, entry, (IBinaryArchive)bin); + } else { + lib = new LibraryReferenceShared(this, entry, bin); + } + } catch (IOException e1) { + lib = new LibraryReference(this, entry); + } + } + if (lib != null) { + list.add(lib); } } - } catch (CoreException e) { - throw new CModelException(e); } - return (ILibraryReference[])list.toArray(new ILibraryReference[0]); + return (ILibraryReference[]) list.toArray(new ILibraryReference[0]); } - - /** - * @see org.eclipse.cdt.core.model.ICProject#getOption(String, boolean) - */ - public String getOption(String optionName, boolean inheritCCoreOptions) { - - if (CModelManager.OptionNames.contains(optionName)) { - Preferences preferences = getPreferences(); - - if (preferences == null || preferences.isDefault(optionName)) { - return inheritCCoreOptions ? CCorePlugin.getOption(optionName) : null; - } - - return preferences.getString(optionName).trim(); - } - - return null; - } - /** - * @see org.eclipse.cdt.core.model.ICProject#getOptions(boolean) - */ - public Map getOptions(boolean inheritCCoreOptions) { - // initialize to the defaults from CCorePlugin options pool - Map options = inheritCCoreOptions ? CCorePlugin.getOptions() : new HashMap(5); + /** + * @see ICProject#getRequiredProjectNames() + */ + public String[] getRequiredProjectNames() throws CModelException { + return projectPrerequisites(getCPathEntries()); + } - Preferences preferences = getPreferences(); - if (preferences == null) return options; - HashSet optionNames = CModelManager.OptionNames; - - // get preferences set to their default - if (inheritCCoreOptions){ - String[] defaultPropertyNames = preferences.defaultPropertyNames(); - for (int i = 0; i < defaultPropertyNames.length; i++){ - String propertyName = defaultPropertyNames[i]; - if (optionNames.contains(propertyName)){ - options.put(propertyName, preferences.getDefaultString(propertyName).trim()); - } - } - } - // get custom preferences not set to their default - String[] propertyNames = preferences.propertyNames(); - for (int i = 0; i < propertyNames.length; i++){ - String propertyName = propertyNames[i]; - if (optionNames.contains(propertyName)){ - options.put(propertyName, preferences.getString(propertyName).trim()); - } - } - return options; - } - - /** - * @see org.eclipse.cdt.core.model.ICProject#setOption(java.lang.String, java.lang.String) - */ - public void setOption(String optionName, String optionValue) { - if (!CModelManager.OptionNames.contains(optionName)) return; // unrecognized option - - Preferences preferences = getPreferences(); - preferences.setDefault(optionName, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251) - preferences.setValue(optionName, optionValue); - - savePreferences(preferences); - } + public String[] projectPrerequisites(ICPathEntry[] entries) throws CModelException { + ArrayList prerequisites = new ArrayList(); + for (int i = 0, length = entries.length; i < length; i++) { + if (entries[i].getEntryKind() == ICPathEntry.CDT_PROJECT) { + IProjectEntry entry = (IProjectEntry)entries[i]; + prerequisites.add(entry.getProjectPath().lastSegment()); + } + } + int size = prerequisites.size(); + if (size != 0) { + String[] result = new String[size]; + prerequisites.toArray(result); + return result; + } + return NO_PREREQUISITES; + } - /** - * @see org.eclipse.cdt.core.model.ICProject#setOptions(Map) - */ - public void setOptions(Map newOptions) - { - Preferences preferences = new Preferences(); - setPreferences(preferences); // always reset (26255) - - if (newOptions != null){ - Iterator keys = newOptions.keySet().iterator(); - - while (keys.hasNext()){ - String key = (String)keys.next(); - if (!CModelManager.OptionNames.contains(key)) continue; // unrecognized option - - // no filtering for encoding (custom encoding for project is allowed) - String value = (String)newOptions.get(key); - preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251) - preferences.setValue(key, value); - } - } - - // persist options - savePreferences(preferences); - } - - /** - * Returns the project custom preference pool. - * Project preferences may include custom encoding. - */ - private Preferences getPreferences() { - Preferences preferences = new Preferences(); - Iterator iter = CModelManager.OptionNames.iterator(); - - while (iter.hasNext()) { - String qualifiedName = (String)iter.next(); - String dequalifiedName = qualifiedName.substring(CCorePlugin.PLUGIN_ID.length()+1); - String value = null; - - try { - value = resource.getPersistentProperty(new QualifiedName(CCorePlugin.PLUGIN_ID, dequalifiedName)); - } catch (CoreException e) { - } - - if (value != null) preferences.setValue(qualifiedName, value); - } - - return preferences; - } - - /** - * Save project custom preferences to persistent properties - */ - private void savePreferences(Preferences preferences) { - if (preferences == null) return; + + + /** + * @see org.eclipse.cdt.core.model.ICProject#getOption(String, boolean) + */ + public String getOption(String optionName, boolean inheritCCoreOptions) { + + if (CModelManager.OptionNames.contains(optionName)) { + Preferences preferences = getPreferences(); + + if (preferences == null || preferences.isDefault(optionName)) { + return inheritCCoreOptions ? CCorePlugin.getOption(optionName) : null; + } + + return preferences.getString(optionName).trim(); + } + + return null; + } + + /** + * @see org.eclipse.cdt.core.model.ICProject#getOptions(boolean) + */ + public Map getOptions(boolean inheritCCoreOptions) { + // initialize to the defaults from CCorePlugin options pool + Map options = inheritCCoreOptions ? CCorePlugin.getOptions() : new HashMap(5); + + Preferences preferences = getPreferences(); + if (preferences == null) + return options; + HashSet optionNames = CModelManager.OptionNames; + + // get preferences set to their default + if (inheritCCoreOptions) { + String[] defaultPropertyNames = preferences.defaultPropertyNames(); + for (int i = 0; i < defaultPropertyNames.length; i++) { + String propertyName = defaultPropertyNames[i]; + if (optionNames.contains(propertyName)) { + options.put(propertyName, preferences.getDefaultString(propertyName).trim()); + } + } + } + // get custom preferences not set to their default + String[] propertyNames = preferences.propertyNames(); + for (int i = 0; i < propertyNames.length; i++) { + String propertyName = propertyNames[i]; + if (optionNames.contains(propertyName)) { + options.put(propertyName, preferences.getString(propertyName).trim()); + } + } + return options; + } + + /** + * @see org.eclipse.cdt.core.model.ICProject#setOption(java.lang.String, java.lang.String) + */ + public void setOption(String optionName, String optionValue) { + if (!CModelManager.OptionNames.contains(optionName)) + return; // unrecognized option + + Preferences preferences = getPreferences(); + preferences.setDefault(optionName, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251) + preferences.setValue(optionName, optionValue); + + savePreferences(preferences); + } + + /** + * @see org.eclipse.cdt.core.model.ICProject#setOptions(Map) + */ + public void setOptions(Map newOptions) { + Preferences preferences = new Preferences(); + setPreferences(preferences); // always reset (26255) + + if (newOptions != null) { + Iterator keys = newOptions.keySet().iterator(); + + while (keys.hasNext()) { + String key = (String) keys.next(); + if (!CModelManager.OptionNames.contains(key)) + continue; // unrecognized option + + // no filtering for encoding (custom encoding for project is allowed) + String value = (String) newOptions.get(key); + preferences.setDefault(key, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251) + preferences.setValue(key, value); + } + } + + // persist options + savePreferences(preferences); + } + + /** + * Returns the project custom preference pool. + * Project preferences may include custom encoding. + */ + private Preferences getPreferences() { + Preferences preferences = new Preferences(); Iterator iter = CModelManager.OptionNames.iterator(); - + while (iter.hasNext()) { - String qualifiedName = (String)iter.next(); - String dequalifiedName = qualifiedName.substring(CCorePlugin.PLUGIN_ID.length()+1); + String qualifiedName = (String) iter.next(); + String dequalifiedName = qualifiedName.substring(CCorePlugin.PLUGIN_ID.length() + 1); String value = null; - + + try { + value = resource.getPersistentProperty(new QualifiedName(CCorePlugin.PLUGIN_ID, dequalifiedName)); + } catch (CoreException e) { + } + + if (value != null) + preferences.setValue(qualifiedName, value); + } + + return preferences; + } + + /** + * Save project custom preferences to persistent properties + */ + private void savePreferences(Preferences preferences) { + if (preferences == null) + return; + Iterator iter = CModelManager.OptionNames.iterator(); + + while (iter.hasNext()) { + String qualifiedName = (String) iter.next(); + String dequalifiedName = qualifiedName.substring(CCorePlugin.PLUGIN_ID.length() + 1); + String value = null; + try { value = preferences.getString(qualifiedName); - + if (value != null && !value.equals(preferences.getDefaultString(qualifiedName))) { resource.setPersistentProperty(new QualifiedName(CCorePlugin.PLUGIN_ID, dequalifiedName), value); } else { @@ -237,12 +307,266 @@ public class CProject extends CContainer implements ICProject { } catch (CoreException e) { } } - } + } + + /* + * Set cached preferences, no preferences are saved, only info is updated + */ + private void setPreferences(Preferences preferences) { + // Do nothing + } + + + static String PATH_ENTRY = "cpathentry"; //$NON-NLS-1$ + static String PATH_ENTRY_ID = "org.eclipse.cdt.core.cpathentry"; //$NON-NLS-1$ + static String ATTRIBUTE_KIND = "kind"; //$NON-NLS-1$ + static String ATTRIBUTE_PATH = "path"; //$NON-NLS-1$ + static String ATTRIBUTE_EXPORTED = "exported"; //$NON-NLS-1$ + static String ATTRIBUTE_SOURCEPATH = "sourcepath"; //$NON-NLS-1$ + static String ATTRIBUTE_ROOTPATH = "roopath"; //$NON-NLS-1$ + static String ATTRIBUTE_PREFIXMAPPING = "prefixmapping"; //$NON-NLS-1$ + static String ATTRIBUTE_EXCLUDING = "excluding"; //$NON-NLS-1$ + static String ATTRIBUTE_RECUSIVE = "recusive"; //$NON-NLS-1$ + static String ATTRIBUTE_OUTPUT = "output"; //$NON-NLS-1$ + static String ATTRIBUTE_INCLUDE = "include"; //$NON-NLS-1$ + static String ATTRIBUTE_SYSTEM = "system"; //$NON-NLS-1$ + static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$ + static String ATTRIBUTE_VALUE = "value"; //$NON-NLS-1$ + static String ATTRIBUTE_ID = "id"; //$NON-NLS-1$ + static String VALUE_TRUE = "true"; //$NON-NLS-1$ + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.ICProject#getCPathEntries() + */ + public ICPathEntry[] getCPathEntries() throws CModelException { + ArrayList pathEntries = new ArrayList(); + try { + ICDescriptor cdesc = CCorePlugin.getDefault().getCProjectDescription(getProject()); + Element element = cdesc.getProjectData(PATH_ENTRY_ID); + NodeList list = element.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node childNode = list.item(i); + if (childNode.getNodeType() == Node.ELEMENT_NODE) { + if (childNode.getNodeName().equals(PATH_ENTRY)) { + pathEntries.add(decodeCPathEntry((Element) childNode)); + } + } + } + } catch (CoreException e) { + throw new CModelException(e); + } + return (ICPathEntry[]) pathEntries.toArray(new ICPathEntry[0]); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.ICProject#setCPathEntries(org.eclipse.cdt.core.model.ICPathEntry[], org.eclipse.core.runtime.IProgressMonitor) + */ + public void setCPathEntries(ICPathEntry[] newEntries, IProgressMonitor monitor) throws CModelException { + try { + SetCPathEntriesOperation op = new SetCPathEntriesOperation(this, getCPathEntries(), newEntries); + runOperation(op, monitor); + } catch (CoreException e) { + throw new CModelException(e); + } + + } + + ICPathEntry decodeCPathEntry(Element element) throws CModelException { + IPath projectPath = getProject().getFullPath(); + + // kind + String kindAttr = element.getAttribute(ATTRIBUTE_KIND); + int kind = CPathEntry.kindFromString(kindAttr); + + // exported flag + boolean isExported = false; + if (element.hasAttribute(ATTRIBUTE_EXPORTED)) { + isExported = element.getAttribute(ATTRIBUTE_EXPORTED).equals(VALUE_TRUE); + } + + // ensure path is absolute + String pathAttr = element.getAttribute(ATTRIBUTE_PATH); + IPath path = new Path(pathAttr); + if (kind != ICPathEntry.CDT_VARIABLE && !path.isAbsolute()) { + path = projectPath.append(path); + } + + // source attachment info (optional) + IPath sourceAttachmentPath = + element.hasAttribute(ATTRIBUTE_SOURCEPATH) ? new Path(element.getAttribute(ATTRIBUTE_SOURCEPATH)) : null; + IPath sourceAttachmentRootPath = + element.hasAttribute(ATTRIBUTE_ROOTPATH) ? new Path(element.getAttribute(ATTRIBUTE_ROOTPATH)) : null; + IPath sourceAttachmentPrefixMapping = + element.hasAttribute(ATTRIBUTE_PREFIXMAPPING) ? new Path(element.getAttribute(ATTRIBUTE_PREFIXMAPPING)) : null; + + // exclusion patterns (optional) + String exclusion = element.getAttribute(ATTRIBUTE_EXCLUDING); + IPath[] exclusionPatterns = ACPathEntry.NO_EXCLUSION_PATTERNS; + if (!exclusion.equals("")) { //$NON-NLS-1$ + char[][] patterns = CharOperation.splitOn('|', exclusion.toCharArray()); + int patternCount; + if ((patternCount = patterns.length) > 0) { + exclusionPatterns = new IPath[patternCount]; + for (int j = 0; j < patterns.length; j++) { + exclusionPatterns[j] = new Path(new String(patterns[j])); + } + } + } + + boolean isRecursive = false; + if (element.hasAttribute(ATTRIBUTE_RECUSIVE)) { + isRecursive = element.getAttribute(ATTRIBUTE_RECUSIVE).equals(VALUE_TRUE); + } + + // recreate the CP entry + + switch (kind) { + + case ICPathEntry.CDT_PROJECT : + return CoreModel.newProjectEntry(path, isExported); + + case ICPathEntry.CDT_LIBRARY : + return CoreModel.newLibraryEntry( + path, + sourceAttachmentPath, + sourceAttachmentRootPath, + sourceAttachmentPrefixMapping, + isExported); + + case ICPathEntry.CDT_SOURCE : + { + // custom output location + IPath outputLocation = element.hasAttribute(ATTRIBUTE_OUTPUT) ? projectPath.append(element.getAttribute(ATTRIBUTE_OUTPUT)) : null; //$NON-NLS-1$ //$NON-NLS-2$ + // must be an entry in this project or specify another project + String projSegment = path.segment(0); + if (projSegment != null && projSegment.equals(getElementName())) { // this project + return CoreModel.newSourceEntry(path, outputLocation, isRecursive, exclusionPatterns); + } else { // another project + return CoreModel.newProjectEntry(path, isExported); + } + } + + // case ICPathEntry.CDT_VARIABLE : + // return CoreModel.newVariableEntry(path, sourceAttachmentPath, sourceAttachmentRootPath); + + case ICPathEntry.CDT_INCLUDE : + { + // include path info (optional + IPath includePath = + element.hasAttribute(ATTRIBUTE_INCLUDE) ? new Path(element.getAttribute(ATTRIBUTE_INCLUDE)) : null; + // isSysteminclude + boolean isSystemInclude = false; + if (element.hasAttribute(ATTRIBUTE_SYSTEM)) { + isSystemInclude = element.getAttribute(ATTRIBUTE_SYSTEM).equals(VALUE_TRUE); + } + return CoreModel.newIncludeEntry( + path, + includePath, + isSystemInclude, + isRecursive, + exclusionPatterns, + isExported); + } + + case ICPathEntry.CDT_MACRO : + { + String macroName = element.getAttribute(ATTRIBUTE_NAME); //$NON-NLS-1$ + String macroValue = element.getAttribute(ATTRIBUTE_VALUE); //$NON-NLS-1$ + return CoreModel.newMacroEntry(path, macroName, macroValue, isRecursive, exclusionPatterns, isExported); + } + + case ICPathEntry.CDT_CONTAINER : + { + String id = element.getAttribute(ATTRIBUTE_ID); //$NON-NLS-1$ + return CoreModel.newContainerEntry(id, isExported); + } + + default : + { + ICModelStatus status = new CModelStatus(ICModelStatus.ERROR, "CPathEntry: unknown kind (" + kindAttr + ")"); //$NON-NLS-1$ + throw new CModelException(status); + } + } + } + + void encodeCPathEntries(Document doc, Element configRootElement, ICPathEntry[] entries) { + Element element; + IPath projectPath = getProject().getFullPath(); + for (int i = 0; i < entries.length; i++) { + element = doc.createElement(PATH_ENTRY); + configRootElement.appendChild(element); + int kind = entries[i].getEntryKind(); + + // Set the kind + element.setAttribute(ATTRIBUTE_KIND, CPathEntry.kindToString(kind)); + + // Save the exclusions attributes + if (entries[i] instanceof ACPathEntry) { + ACPathEntry entry = (ACPathEntry) entries[i]; + IPath[] exclusionPatterns = entry.getExclusionPatterns(); + if (exclusionPatterns.length > 0) { + StringBuffer excludeRule = new StringBuffer(10); + for (int j = 0, max = exclusionPatterns.length; j < max; j++) { + if (j > 0) { + excludeRule.append('|'); + } + excludeRule.append(exclusionPatterns[j]); + } + element.setAttribute(ATTRIBUTE_EXCLUDING, excludeRule.toString()); + } + if (entry.isRecursive()) { + element.setAttribute(ATTRIBUTE_RECUSIVE, VALUE_TRUE); + } + } + + if (kind == ICPathEntry.CDT_SOURCE) { + ISourceEntry source = (ISourceEntry) entries[i]; + IPath path = source.getSourcePath(); + element.setAttribute(ATTRIBUTE_PATH, path.toString()); + IPath output = source.getOutputLocation(); + if (output != null && output.isEmpty()) { + element.setAttribute(ATTRIBUTE_OUTPUT, output.toString()); + } + } else if (kind == ICPathEntry.CDT_LIBRARY) { + ILibraryEntry lib = (ILibraryEntry) entries[i]; + IPath path = lib.getLibraryPath(); + element.setAttribute(ATTRIBUTE_PATH, path.toString()); + if (lib.getSourceAttachmentPath() != null) { + element.setAttribute(ATTRIBUTE_SOURCEPATH, lib.getSourceAttachmentPath().toString()); + } + if (lib.getSourceAttachmentRootPath() != null) { + element.setAttribute(ATTRIBUTE_ROOTPATH, lib.getSourceAttachmentRootPath().toString()); + } + if (lib.getSourceAttachmentPrefixMapping() != null) { + element.setAttribute(ATTRIBUTE_PREFIXMAPPING, lib.getSourceAttachmentPrefixMapping().toString()); + } + } else if (kind == ICPathEntry.CDT_PROJECT) { + IProjectEntry pentry = (IProjectEntry) entries[i]; + IPath path = pentry.getProjectPath(); + element.setAttribute(ATTRIBUTE_PATH, path.toString()); + } else if (kind == ICPathEntry.CDT_INCLUDE) { + IIncludeEntry include = (IIncludeEntry) entries[i]; + IPath path = include.getResourcePath(); + element.setAttribute(ATTRIBUTE_PATH, path.toString()); + IPath includePath = include.getIncludePath(); + element.setAttribute(ATTRIBUTE_INCLUDE, includePath.toString()); + if (include.isSystemInclude()) { + element.setAttribute(ATTRIBUTE_SYSTEM, VALUE_TRUE); + } + } else if (kind == ICPathEntry.CDT_MACRO) { + IMacroEntry macro = (IMacroEntry) entries[i]; + IPath path = macro.getResourcePath(); + element.setAttribute(ATTRIBUTE_PATH, path.toString()); + element.setAttribute(ATTRIBUTE_NAME, macro.getMacroName()); + element.setAttribute(ATTRIBUTE_VALUE, macro.getMacroValue()); + } else if (kind == ICPathEntry.CDT_CONTAINER) { + IContainerEntry container = (IContainerEntry) entries[i]; + element.setAttribute(ATTRIBUTE_ID, container.getId()); + } + if (entries[i].isExported()) { + element.setAttribute(ATTRIBUTE_EXPORTED, VALUE_TRUE); + } + } + } - /* - * Set cached preferences, no preferences are saved, only info is updated - */ - private void setPreferences(Preferences preferences) { - // Do nothing - } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReference.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReference.java index c336e93e4b6..ee985a84d6a 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReference.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReference.java @@ -6,8 +6,8 @@ */ package org.eclipse.cdt.internal.core.model; -import org.eclipse.cdt.core.ICPathEntry; import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ILibraryEntry; import org.eclipse.cdt.core.model.ILibraryReference; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; @@ -17,9 +17,10 @@ import org.eclipse.core.runtime.IPath; */ public class LibraryReference extends Parent implements ILibraryReference { - ICPathEntry entry; - public LibraryReference(ICElement parent, String name, ICPathEntry e) { - super(parent, name, ICElement.C_VCONTAINER); + ILibraryEntry entry; + + public LibraryReference(ICElement parent, ILibraryEntry e) { + super(parent, e.getLibraryPath().lastSegment(), ICElement.C_VCONTAINER); entry = e; } @@ -27,7 +28,6 @@ public class LibraryReference extends Parent implements ILibraryReference { * @see org.eclipse.cdt.core.model.ICElement#getResource() */ public IResource getResource() { - // TODO Auto-generated method stub return null; } @@ -35,7 +35,6 @@ public class LibraryReference extends Parent implements ILibraryReference { * @see org.eclipse.cdt.internal.core.model.CElement#createElementInfo() */ protected CElementInfo createElementInfo() { - // TODO Auto-generated method stub return new CElementInfo(this); } @@ -43,7 +42,7 @@ public class LibraryReference extends Parent implements ILibraryReference { * @see org.eclipse.cdt.core.model.ICElement#getPath() */ public IPath getPath() { - return entry.getPath(); + return entry.getLibraryPath(); } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReferenceArchive.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReferenceArchive.java new file mode 100644 index 00000000000..d15a68c8115 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReferenceArchive.java @@ -0,0 +1,53 @@ +/* + * Created on Apr 2, 2003 + * + * To change this generated comment go to + * Window>Preferences>Java>Code Generation>Code Template + */ +package org.eclipse.cdt.internal.core.model; + +import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ILibraryEntry; +import org.eclipse.cdt.core.model.ILibraryReference; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; + +/** + * @author alain + */ +public class LibraryReferenceArchive extends Archive implements ILibraryReference { + + ILibraryEntry entry; + IBinaryArchive archive; + + public LibraryReferenceArchive(ICElement parent, ILibraryEntry e, IBinaryArchive ar) { + super(parent, e.getLibraryPath()); + setElementType(ICElement.C_VCONTAINER); + entry = e; + archive = ar; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.ICElement#getResource() + */ + public IResource getResource() { + return null; + } + + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.ICElement#getPath() + */ + public IPath getPath() { + return entry.getLibraryPath(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.model.Archive#getBinaryArchive(org.eclipse.core.resources.IResource) + */ + IBinaryArchive getBinaryArchive(IResource res) { + return archive; + } + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReferenceShared.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReferenceShared.java new file mode 100644 index 00000000000..ffa37133e05 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryReferenceShared.java @@ -0,0 +1,50 @@ +/* + * Created on Apr 2, 2003 + * + * To change this generated comment go to + * Window>Preferences>Java>Code Generation>Code Template + */ +package org.eclipse.cdt.internal.core.model; + +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ILibraryEntry; +import org.eclipse.cdt.core.model.ILibraryReference; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; + +/** + * @author alain + */ +public class LibraryReferenceShared extends Binary implements ILibraryReference { + + ILibraryEntry entry; + + public LibraryReferenceShared(ICElement parent, ILibraryEntry e, IBinaryFile bin) { + super(parent, e.getLibraryPath(), bin); + setElementType(ICElement.C_VCONTAINER); + entry = e; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.model.Binary#getModificationStamp() + */ + protected long getModificationStamp() { + return getPath().toFile().lastModified(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.ICElement#getResource() + */ + public IResource getResource() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.model.ICElement#getPath() + */ + public IPath getPath() { + return entry.getLibraryPath(); + } + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SetCPathEntriesOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SetCPathEntriesOperation.java new file mode 100644 index 00000000000..6b838f5ffe3 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/SetCPathEntriesOperation.java @@ -0,0 +1,144 @@ +/********************************************************************** + * Created on Mar 25, 2003 + * + * Copyright (c) 2002,2003 QNX Software Systems Ltd. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation +***********************************************************************/ + +package org.eclipse.cdt.internal.core.model; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.ICDescriptor; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICPathEntry; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + */ +public class SetCPathEntriesOperation extends CModelOperation { + + ICPathEntry[] oldEntries; + ICPathEntry[] newEntries; + CProject project; + + public SetCPathEntriesOperation(CProject project, ICPathEntry[] oldEntries, ICPathEntry[] newEntries) { + this.oldEntries = oldEntries; + this.newEntries = newEntries; + this.project = project; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.model.CModelOperation#executeOperation() + */ + protected void executeOperation() throws CModelException { + // project reference updated - may throw an exception if unable to write .cdtproject file + updateProjectReferencesIfNecessary(); + try { + + ICDescriptor descriptor = CCorePlugin.getDefault().getCProjectDescription(project.getProject()); + Element rootElement = descriptor.getProjectData(CProject.PATH_ENTRY_ID); + // Clear out all current children + Node child = rootElement.getFirstChild(); + while (child != null) { + rootElement.removeChild(child); + child = rootElement.getFirstChild(); + } + + // Save the entries + if (newEntries != null && newEntries.length > 0) { + // Serialize the include paths + Document doc = rootElement.getOwnerDocument(); + project.encodeCPathEntries(doc, rootElement, newEntries); + descriptor.saveProjectData(); + } + + generateCPathEntryDeltas(); + done(); + } catch (CoreException e) { + throw new CModelException(e); + } + } + + protected void updateProjectReferencesIfNecessary() throws CModelException { + String[] oldRequired = this.project.projectPrerequisites(oldEntries); + String[] newRequired = this.project.projectPrerequisites(newEntries); + + try { + IProject projectResource = project.getProject(); + IProjectDescription description = projectResource.getDescription(); + + IProject[] projectReferences = description.getReferencedProjects(); + + HashSet oldReferences = new HashSet(projectReferences.length); + for (int i = 0; i < projectReferences.length; i++) { + String projectName = projectReferences[i].getName(); + oldReferences.add(projectName); + } + HashSet newReferences = (HashSet) oldReferences.clone(); + + for (int i = 0; i < oldRequired.length; i++) { + String projectName = oldRequired[i]; + newReferences.remove(projectName); + } + for (int i = 0; i < newRequired.length; i++) { + String projectName = newRequired[i]; + newReferences.add(projectName); + } + + Iterator iter; + int newSize = newReferences.size(); + + checkIdentity : { + if (oldReferences.size() == newSize) { + iter = newReferences.iterator(); + while (iter.hasNext()) { + if (!oldReferences.contains(iter.next())) { + break checkIdentity; + } + } + return; + } + } + String[] requiredProjectNames = new String[newSize]; + int index = 0; + iter = newReferences.iterator(); + while (iter.hasNext()) { + requiredProjectNames[index++] = (String) iter.next(); + } + Arrays.sort(requiredProjectNames); // ensure that if changed, the order is consistent + + IProject[] requiredProjectArray = new IProject[newSize]; + IWorkspaceRoot wksRoot = projectResource.getWorkspace().getRoot(); + for (int i = 0; i < newSize; i++) { + requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]); + } + + description.setReferencedProjects(requiredProjectArray); + projectResource.setDescription(description, this.fMonitor); + + } catch (CoreException e) { + throw new CModelException(e); + } + } + + private void generateCPathEntryDeltas() { + } + + +}