|
12 | 12 | * QNX Software Systems - Initial API and implementation
|
13 | 13 | * Anton Leherbauer (Wind River Systems)
|
14 | 14 | * John Dallaway - Adapt for IBinaryFile (#413)
|
| 15 | + * John Dallaway - Fix object path processing (#630) |
15 | 16 | *******************************************************************************/
|
16 | 17 | package org.eclipse.cdt.internal.core.model;
|
17 | 18 |
|
18 | 19 | import java.util.Map;
|
| 20 | +import java.util.Optional; |
19 | 21 |
|
| 22 | +import org.eclipse.cdt.core.CCorePlugin; |
20 | 23 | import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive;
|
21 | 24 | import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
|
| 25 | +import org.eclipse.cdt.core.cdtvariables.CdtVariableException; |
| 26 | +import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; |
22 | 27 | import org.eclipse.cdt.core.model.CModelException;
|
| 28 | +import org.eclipse.cdt.core.model.CoreModel; |
23 | 29 | import org.eclipse.cdt.core.model.IArchive;
|
24 | 30 | import org.eclipse.cdt.core.model.IBinary;
|
25 | 31 | import org.eclipse.cdt.core.model.ICElement;
|
26 | 32 | import org.eclipse.cdt.core.model.ICProject;
|
| 33 | +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; |
| 34 | +import org.eclipse.cdt.core.settings.model.ICOutputEntry; |
| 35 | +import org.eclipse.cdt.core.settings.model.ICProjectDescription; |
| 36 | +import org.eclipse.cdt.core.settings.model.extension.CBuildData; |
| 37 | +import org.eclipse.cdt.core.settings.model.extension.CConfigurationData; |
| 38 | +import org.eclipse.cdt.core.settings.model.util.CDataUtil; |
27 | 39 | import org.eclipse.cdt.internal.core.util.MementoTokenizer;
|
28 | 40 | import org.eclipse.core.resources.IFile;
|
| 41 | +import org.eclipse.core.resources.IProject; |
29 | 42 | import org.eclipse.core.resources.IResource;
|
| 43 | +import org.eclipse.core.resources.ResourcesPlugin; |
30 | 44 | import org.eclipse.core.runtime.Assert;
|
31 | 45 | import org.eclipse.core.runtime.IPath;
|
32 | 46 | import org.eclipse.core.runtime.IProgressMonitor;
|
| 47 | +import org.eclipse.core.runtime.Path; |
33 | 48 |
|
34 | 49 | public class Archive extends Openable implements IArchive {
|
35 | 50 |
|
@@ -75,16 +90,30 @@ protected boolean buildStructure(OpenableInfo info, IProgressMonitor pm, Map<ICE
|
75 | 90 |
|
76 | 91 | public boolean computeChildren(OpenableInfo info, IResource res) {
|
77 | 92 | IBinaryArchive ar = getBinaryArchive();
|
78 |
| - if (ar != null) { |
79 |
| - IBinaryObject[] objects = ar.getObjects(); |
80 |
| - for (final IBinaryObject obj : objects) { |
81 |
| - Binary binary = new Binary(this, ar.getPath().append(obj.getName()), obj); |
| 93 | + IPath location = res.getLocation(); |
| 94 | + if (ar != null && location != null) { |
| 95 | + // find the build CWD for the archive file |
| 96 | + IPath buildCWD = Optional.ofNullable(findBuildConfiguration(res)).map(Archive::getBuildCWD) |
| 97 | + .orElse(location.removeLastSegments(1)); |
| 98 | + for (IBinaryObject obj : ar.getObjects()) { |
| 99 | + // assume object names are paths as specified on the archiver command line ("ar -P") |
| 100 | + IPath objPath = new Path(obj.getName()); |
| 101 | + if (!objPath.isAbsolute()) { |
| 102 | + // assume path is relative to the build CWD |
| 103 | + objPath = buildCWD.append(objPath); |
| 104 | + } |
| 105 | + IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(objPath); |
| 106 | + if (file == null) { // if object path is external to the workspace |
| 107 | + // fallback to legacy behaviour |
| 108 | + // TODO: support external paths in Binary class as we do in TranslationUnit |
| 109 | + objPath = ar.getPath().append(objPath.lastSegment()); |
| 110 | + } |
| 111 | + Binary binary = new Binary(this, objPath, obj); |
82 | 112 | info.addChild(binary);
|
83 | 113 | }
|
84 |
| - } else { |
85 |
| - return false; |
| 114 | + return true; |
86 | 115 | }
|
87 |
| - return true; |
| 116 | + return false; |
88 | 117 | }
|
89 | 118 |
|
90 | 119 | @Override
|
@@ -133,4 +162,50 @@ protected char getHandleMementoDelimiter() {
|
133 | 162 | return 0;
|
134 | 163 | }
|
135 | 164 |
|
| 165 | + private static ICConfigurationDescription findBuildConfiguration(IResource resource) { |
| 166 | + IPath location = resource.getLocation(); |
| 167 | + IProject project = resource.getProject(); |
| 168 | + ICProjectDescription projectDesc = CoreModel.getDefault().getProjectDescription(project, false); |
| 169 | + if (projectDesc == null) { |
| 170 | + return null; // not a CDT project |
| 171 | + } |
| 172 | + // for each build configuration of the project |
| 173 | + for (ICConfigurationDescription configDesc : projectDesc.getConfigurations()) { |
| 174 | + CConfigurationData configData = configDesc.getConfigurationData(); |
| 175 | + if (configData == null) { |
| 176 | + continue; // no configuration data |
| 177 | + } |
| 178 | + CBuildData buildData = configData.getBuildData(); |
| 179 | + if (buildData == null) { |
| 180 | + continue; // no build data |
| 181 | + } |
| 182 | + // for each build output directory of the build configuration |
| 183 | + for (ICOutputEntry dir : buildData.getOutputDirectories()) { |
| 184 | + IPath dirLocation = CDataUtil.makeAbsolute(project, dir).getLocation(); |
| 185 | + // if the build output directory is an ancestor of the resource |
| 186 | + if ((dirLocation != null) && dirLocation.isPrefixOf(location)) { |
| 187 | + return configDesc; // build configuration found |
| 188 | + } |
| 189 | + } |
| 190 | + } |
| 191 | + return null; |
| 192 | + } |
| 193 | + |
| 194 | + private static IPath getBuildCWD(ICConfigurationDescription configDesc) { |
| 195 | + IPath builderCWD = configDesc.getBuildSetting().getBuilderCWD(); |
| 196 | + if (builderCWD != null) { |
| 197 | + ICdtVariableManager manager = CCorePlugin.getDefault().getCdtVariableManager(); |
| 198 | + try { |
| 199 | + String cwd = builderCWD.toString(); |
| 200 | + cwd = manager.resolveValue(cwd, "", null, configDesc); //$NON-NLS-1$ |
| 201 | + if (!cwd.isEmpty()) { |
| 202 | + return new Path(cwd); |
| 203 | + } |
| 204 | + } catch (CdtVariableException e) { |
| 205 | + CCorePlugin.log(e); |
| 206 | + } |
| 207 | + } |
| 208 | + return null; |
| 209 | + } |
| 210 | + |
136 | 211 | }
|
0 commit comments