diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 0c06aff604f..589df5abce8 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,11 @@ +2005-02-10 Alain Magloire + Part of the fix for 79596 + * model/org/eclipse/cdt/core/model/CoreModel.java + * model/org/eclipse/cdt/core/model/IPathEntry.java + * model/org/eclipse/cdt/core/model/IPathEntryContainerExtension.java + * model/org/eclipse/cdt/internal/core/model/PathEntryManager.java + * src/org/eclipse/cdt/core/resources/ScannerProvider.java + 2005-01-29 Alain Magloire Copy the spaces and Newlines. * model/org/eclipse/cdt/internal/core/model/CopylementsOperation.java 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 2ed568bc3f6..6e560641257 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 @@ -706,7 +706,7 @@ public class CoreModel { } /** - * This method returs the resolved pathentries for the project All + * This method returns the resolved pathentries for the project All * pathEntry.CDT_CONTAINER entries in the project's will be replaced by the * entries they resolve to. *

@@ -724,6 +724,42 @@ public class CoreModel { return pathEntryManager.getResolvedPathEntries(cproject); } + /** + * This method returns the include entries associated with a translation unit + * if the path does not refer to a valid translation unit an empty is return. + *

+ * The resulting resolved entries are accurate for the given point in time. + * If the project's raw entries are later modified they can become out of + * date. Because of this, hanging on resolved pathentries is not + * recommended. + *

+ * + * @return the resolved entries for the project + * @exception CModelException + * @see IPathEntry + */ + public static IIncludeEntry[] getIncludeEntries(IPath path) throws CModelException { + return pathEntryManager.getIncludeEntries(path); + } + + /** + * This method returns the macro entries associated with a translation unit + * if the path does not refer to a valid translation unit an empty array is return. + *

+ * The resulting resolved entries are accurate for the given point in time. + * If the project's raw entries are later modified they can become out of + * date. Because of this, hanging on resolved pathentries is not + * recommended. + *

+ * + * @return the resolved entries for the project + * @exception CModelException + * @see IPathEntry + */ + public static IMacroEntry[] getMacroEntries(IPath path) throws CModelException { + return pathEntryManager.getMacroEntries(path); + } + /** * Helper method finding the pathentry container initializer registered for * a given container ID or null if none was found while diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPathEntry.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPathEntry.java index df6be99afa2..ef0091f9e0c 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPathEntry.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPathEntry.java @@ -74,15 +74,15 @@ public interface IPathEntry { *
  • CDT_OUTPUT - this entry describes output location */ int getEntryKind(); - + /** - * Returns the affected IPath - * - * @return IPath + * + * @return true if exported. */ boolean isExported(); /** + * Returns the affected IPath * * @return IPath */ diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPathEntryContainerExtension.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPathEntryContainerExtension.java new file mode 100644 index 00000000000..52a9336c274 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPathEntryContainerExtension.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.core.model; + +import org.eclipse.core.runtime.IPath; + +/** + * + */ +public interface IPathEntryContainerExtension extends IPathEntryContainer { + + /** + * Returns the set of include entries associated with the resource + * and empty array if none. + * + * @param path Workspace relative path. + * @return IIncludeEntry[] - the entries or empty set if none + * @see IPathEntry + */ + IIncludeEntry[] getIncludeEntries(IPath path); + + /** + * Returns the set of macro entries associated with the resource + * and empty array if none. + * + * @param path Workspace relative path. + * @return IMacroEntry[] - the entries or empty set if none + * @see IPathEntry + */ + IMacroEntry[] getMacroEntries(IPath path); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java index 4465cb0f97b..6f975bd24b4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryManager.java @@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.model; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; import java.util.List; @@ -39,8 +40,10 @@ import org.eclipse.cdt.core.model.IMacroEntry; import org.eclipse.cdt.core.model.IOutputEntry; import org.eclipse.cdt.core.model.IPathEntry; import org.eclipse.cdt.core.model.IPathEntryContainer; +import org.eclipse.cdt.core.model.IPathEntryContainerExtension; import org.eclipse.cdt.core.model.IProjectEntry; import org.eclipse.cdt.core.model.ISourceEntry; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.IWorkingCopy; import org.eclipse.cdt.core.model.PathEntryContainerInitializer; import org.eclipse.cdt.core.resources.IPathEntryStore; @@ -91,6 +94,10 @@ public class PathEntryManager implements IPathEntryStoreListener, IElementChange static final IPathEntry[] NO_PATHENTRIES = new IPathEntry[0]; + static final IIncludeEntry[] NO_INCLUDENTRIES = new IIncludeEntry[0]; + + static final IMacroEntry[] NO_MACROENTRIES = new IMacroEntry[0]; + // Synchronized the access of the cache entries. protected Map resolvedMap = new Hashtable(); @@ -152,6 +159,165 @@ public class PathEntryManager implements IPathEntryStoreListener, IElementChange return pathEntryManager; } + public IIncludeEntry[] getIncludeEntries(IPath resPath) throws CModelException { + ICElement celement = CoreModel.getDefault().create(resPath); + if (celement instanceof ITranslationUnit) { + return getIncludeEntries((ITranslationUnit)celement); + } + return NO_INCLUDENTRIES; + } + + public IIncludeEntry[] getIncludeEntries(ITranslationUnit cunit) throws CModelException { + ArrayList includeList = new ArrayList(); + ICProject cproject = cunit.getCProject(); + IPath resPath = cunit.getPath(); + // Do this first so the containers get inialized. + IPathEntry[] entries = getResolvedPathEntries(cproject); + for (int i = 0; i < entries.length; ++i) { + if (entries[i].getEntryKind() == IPathEntry.CDT_INCLUDE) { + includeList.add(entries[i]); + } + } + IPathEntryContainer[] containers = getPathEntryContainers(cproject); + if (containers != null) { + for (int i = 0; i < containers.length; ++i) { + if (containers[i] instanceof IPathEntryContainerExtension) { + IIncludeEntry[] incs = ((IPathEntryContainerExtension)containers[i]).getIncludeEntries(resPath); + includeList.addAll(Arrays.asList(incs)); + } + } + } + + IIncludeEntry[] includes = (IIncludeEntry[]) includeList.toArray(new IIncludeEntry[includeList.size()]); + // Clear the list since we are reusing it. + includeList.clear(); + + // We need to reorder the include/macros: + // includes with the closest match to the resource will come first + // /project/src/file.c --> /usr/local/include + // /project --> /usr/include + // + // /usr/local/include must come first. + // + int count = resPath.segmentCount(); + for (int i = 0; i < count; i++) { + IPath newPath = resPath.removeLastSegments(i); + for (int j = 0; j < includes.length; j++) { + IPath otherPath = includes[j].getPath(); + if (newPath.equals(otherPath)) { + includeList.add(includes[j]); + } + } + } + + // Since the include that comes from a project contribution are not + // tied to a resource they are added last. + for (int i = 0; i < entries.length; i++) { + IPathEntry entry = entries[i]; + if (entry != null && entry.getEntryKind() == IPathEntry.CDT_PROJECT) { + IResource res = cproject.getCModel().getWorkspace().getRoot().findMember(entry.getPath()); + if (res != null && res.getType() == IResource.PROJECT) { + ICProject refCProject = CoreModel.getDefault().create((IProject)res); + if (refCProject != null) { + IPathEntry[] projEntries = refCProject.getResolvedPathEntries(); + for (int j = 0; j < projEntries.length; j++) { + IPathEntry projEntry = projEntries[j]; + if (projEntry.isExported()) { + if (projEntry.getEntryKind() == IPathEntry.CDT_INCLUDE) { + IIncludeEntry include = (IIncludeEntry)projEntry; + includeList.add(include); + } + } + } + } + } + } + } + return (IIncludeEntry[])includeList.toArray(new IIncludeEntry[includeList.size()]); + } + + public IMacroEntry[] getMacroEntries(IPath resPath) throws CModelException { + ICElement celement = CoreModel.getDefault().create(resPath); + if (celement instanceof ITranslationUnit) { + return getMacroEntries((ITranslationUnit)celement); + } + return NO_MACROENTRIES; + } + + public IMacroEntry[] getMacroEntries(ITranslationUnit cunit) throws CModelException { + ArrayList macroList = new ArrayList(); + ICProject cproject = cunit.getCProject(); + IPath resPath = cunit.getPath(); + // Do this first so the containers get inialized. + IPathEntry[] entries = getResolvedPathEntries(cproject); + for (int i = 0; i < entries.length; ++i) { + if (entries[i].getEntryKind() == IPathEntry.CDT_MACRO) { + macroList.add(entries[i]); + } + } + IPathEntryContainer[] containers = getPathEntryContainers(cproject); + if (containers != null) { + for (int i = 0; i < containers.length; ++i) { + if (containers[i] instanceof IPathEntryContainerExtension) { + IMacroEntry[] incs = ((IPathEntryContainerExtension)containers[i]).getMacroEntries(resPath); + macroList.addAll(Arrays.asList(incs)); + } + } + } + + IMacroEntry[] macros = (IMacroEntry[]) macroList.toArray(new IMacroEntry[macroList.size()]); + macroList.clear(); + + // For the macros the closest symbol will override + // /projec/src/file.c --> NDEBUG=1 + // /project/src --> NDEBUG=0 + // + // We will use NDEBUG=1 only + int count = resPath.segmentCount(); + Map symbolMap = new HashMap(); + for (int i = 0; i < count; i++) { + IPath newPath = resPath.removeLastSegments(i); + for (int j = 0; j < macros.length; j++) { + IPath otherPath = macros[j].getPath(); + if (newPath.equals(otherPath)) { + String key = macros[j].getMacroName(); + if (!symbolMap.containsKey(key)) { + symbolMap.put(key, macros[j]); + } + } + } + } + + // Add the Project contributions last. + for (int i = 0; i < entries.length; i++) { + IPathEntry entry = entries[i]; + if (entry != null && entry.getEntryKind() == IPathEntry.CDT_PROJECT) { + IResource res = cproject.getCModel().getWorkspace().getRoot().findMember(entry.getPath()); + if (res != null && res.getType() == IResource.PROJECT) { + ICProject refCProject = CoreModel.getDefault().create((IProject)res); + if (refCProject != null) { + IPathEntry[] projEntries = refCProject.getResolvedPathEntries(); + for (int j = 0; j < projEntries.length; j++) { + IPathEntry projEntry = projEntries[j]; + if (projEntry.isExported()) { + if (projEntry.getEntryKind() == IPathEntry.CDT_MACRO) { + IMacroEntry macro = (IMacroEntry)entry; + String key = macro.getMacroName(); + if (!symbolMap.containsKey(key)) { + symbolMap.put(key, macro); + } + } + } + } + } + } + } + } + + return (IMacroEntry[])symbolMap.values().toArray(NO_MACROENTRIES); + + } + public IPathEntry[] getResolvedPathEntries(ICProject cproject) throws CModelException { boolean markers = cproject.getProject().getWorkspace().isTreeLocked(); return getResolvedPathEntries(cproject, !markers); @@ -549,6 +715,16 @@ public class PathEntryManager implements IPathEntryStoreListener, IElementChange } } + public synchronized IPathEntryContainer[] getPathEntryContainers(ICProject cproject) { + IPathEntryContainer[] pcs = null; + Map projectContainers = (Map)Containers.get(cproject); + if (projectContainers != null) { + Collection collection = projectContainers.values(); + pcs = (IPathEntryContainer[]) collection.toArray(new IPathEntryContainer[collection.size()]); + } + return pcs; + } + public IPathEntryContainer getPathEntryContainer(IContainerEntry entry, ICProject cproject) throws CModelException { return getPathEntryContainer(entry.getPath(), cproject); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/ScannerProvider.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/ScannerProvider.java index 216e2072186..ee36acce6da 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/ScannerProvider.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/resources/ScannerProvider.java @@ -18,15 +18,12 @@ import java.util.Map; import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.CoreModelUtil; import org.eclipse.cdt.core.model.ElementChangedEvent; 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.IElementChangedListener; import org.eclipse.cdt.core.model.IIncludeEntry; import org.eclipse.cdt.core.model.IMacroEntry; -import org.eclipse.cdt.core.model.IPathEntry; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; import org.eclipse.cdt.core.parser.IScannerInfoProvider; @@ -85,107 +82,19 @@ public class ScannerProvider extends AbstractCExtension implements IScannerInfoP */ public IScannerInfo getScannerInformation(IResource resource) { IPath resPath = resource.getFullPath(); - ICProject cproject = CoreModel.getDefault().create(resource.getProject()); + try { - if (cproject != null) { - IPathEntry[] entries = cproject.getResolvedPathEntries(); - - // First deal with the exclusion any entry that - // excludes the file should not be part of the list. - for (int k = 0; k < entries.length; k++) { - switch (entries[k].getEntryKind()) { - case IPathEntry.CDT_INCLUDE: - IIncludeEntry incEntry = (IIncludeEntry)entries[k]; - if (CoreModelUtil.isExcluded(resPath, incEntry.fullExclusionPatternChars())) { - entries[k] = null; - } - break; - case IPathEntry.CDT_MACRO: - IMacroEntry macEntry = (IMacroEntry)entries[k]; - if (CoreModelUtil.isExcluded(resPath, macEntry.fullExclusionPatternChars())) { - entries[k] = null; - } - break; - case IPathEntry.CDT_PROJECT: - // do nothing. - break; - default: - // not interrested in the other types. - entries[k] = null; - } - } - - // We need to reorder the include/macros: - // includes the closest match to the resource will come first - // /project/src/file.c --> /usr/local/include - // /project/src --> /usr/include - // - // /usr/local/include must come first. - // - // For the macros the closest symbol will override - // /projec/src/file.c --> NDEBUG=1 - // /project/src --> NDEBUG=0 - // - // We will use NDEBUG=1 only - - int count = resPath.segmentCount(); - ArrayList includeList = new ArrayList(); - Map symbolMap = new HashMap(); - for (int i = 0; i < count; i++) { - IPath newPath = resPath.removeLastSegments(i); - for (int j = 0; j < entries.length; j++) { - if (entries[j] != null) { - IPathEntry entry = entries[j]; - IPath otherPath = entry.getPath(); - if (newPath.equals(otherPath)) { - if (entry.getEntryKind() == IPathEntry.CDT_INCLUDE) { - IIncludeEntry include = (IIncludeEntry)entry; - includeList.add(include.getFullIncludePath().toOSString()); - } else if (entry.getEntryKind() == IPathEntry.CDT_MACRO) { - IMacroEntry macro = (IMacroEntry)entry; - String key = macro.getMacroName(); - if (!symbolMap.containsKey(key)) { - symbolMap.put(key, macro.getMacroValue()); - } - } - } - } - } - } - - // Add the Project contributions last. - for (int i = 0; i < entries.length; i++) { - IPathEntry entry = entries[i]; - if (entry != null && entry.getEntryKind() == IPathEntry.CDT_PROJECT) { - IResource res = resource.getWorkspace().getRoot().findMember(entry.getPath()); - if (res != null && res.getType() == IResource.PROJECT) { - ICProject refCProject = CoreModel.getDefault().create((IProject)res); - if (refCProject != null) { - IPathEntry[] projEntries = refCProject.getResolvedPathEntries(); - for (int j = 0; j < projEntries.length; j++) { - IPathEntry projEntry = projEntries[j]; - if (projEntry.isExported()) { - if (projEntry.getEntryKind() == IPathEntry.CDT_INCLUDE) { - IIncludeEntry include = (IIncludeEntry)projEntry; - includeList.add(include.getFullIncludePath().toOSString()); - } else if (projEntry.getEntryKind() == IPathEntry.CDT_MACRO) { - IMacroEntry macro = (IMacroEntry)entry; - String key = macro.getMacroName(); - if (!symbolMap.containsKey(key)) { - symbolMap.put(key, macro.getMacroValue()); - } - } - } - } - } - } - } - } - - String[] includes = new String[includeList.size()]; - includeList.toArray(includes); - return new ScannerInfo(includes, symbolMap); + IIncludeEntry[] includeEntries = CoreModel.getIncludeEntries(resPath); + String[] includes = new String[includeEntries.length]; + for (int i = 0; i < includes.length; ++i) { + includes[i] = includeEntries[i].getFullIncludePath().toOSString(); } + IMacroEntry[] macros = CoreModel.getMacroEntries(resPath); + Map symbolMap = new HashMap(); + for (int i = 0; i < macros.length; ++i) { + symbolMap.put(macros[i].getMacroName(), macros[i].getMacroValue()); + } + return new ScannerInfo(includes, symbolMap); } catch (CModelException e) { // }