From 3b2085290f79e4a02d4011ec6cff09ff218ad1db Mon Sep 17 00:00:00 2001 From: Mikhail Sennikovsky Date: Tue, 5 Jun 2007 13:47:26 +0000 Subject: [PATCH] 1. language setting entries calculation fixes 2. test updates 3. CDt variables fixes --- .../plugin.xml | 2114 +++++++++++++++++ .../test40Projects/test_40/test_40.zip | Bin 0 -> 89845 bytes .../test_40_pathconverter.zip | Bin 0 -> 3086 bytes .../testplugin/BuildSystemTestHelper.java | 40 + .../testplugin/ManagedBuildTestHelper.java | 71 + .../tests/BidirectionalPathConverter.java | 34 + .../core/tests/BuildSystem40Tests.java | 566 +++++ .../core/tests/ManagedBuildCoreTests20.java | 18 +- .../tests/OneDirectionalPathConverter.java | 30 + .../core/OptionStringValue.java | 4 + .../internal/buildmodel/BuildDescription.java | 2 +- .../internal/buildmodel/BuildResource.java | 6 +- .../internal/buildmodel/BuildStep.java | 7 + .../internal/core/CommonBuilder.java | 1 + .../dataprovider/BuildEntryStorage.java | 365 ++- ...uildSystemSpecificVariableSubstitutor.java | 56 + .../internal/dataprovider/PathInfo.java | 110 + .../core/settings/model/util/SettingsSet.java | 9 + .../model/DescriptionScannerInfoProvider.java | 4 + .../SupplierBasedCdtVariableSubstitutor.java | 8 +- 20 files changed, 3377 insertions(+), 68 deletions(-) create mode 100644 build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/test_40.zip create mode 100644 build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40_pathconverter/test_40_pathconverter.zip create mode 100644 build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/BidirectionalPathConverter.java create mode 100644 build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/BuildSystem40Tests.java create mode 100644 build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/OneDirectionalPathConverter.java create mode 100644 build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/BuildSystemSpecificVariableSubstitutor.java create mode 100644 build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/PathInfo.java diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml b/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml index 9d362d9e054..f586cfa026d 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml @@ -6698,4 +6698,2118 @@ projectType="org.eclipse.cdt.managedbuilder.core.tests.projectType"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/test_40.zip b/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/test_40.zip new file mode 100644 index 0000000000000000000000000000000000000000..d08625764b59e52034fc2d7ea020b374d45088d4 GIT binary patch literal 89845 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 Gr}GfW?e6{n literal 0 HcmV?d00001 diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40_pathconverter/test_40_pathconverter.zip b/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40_pathconverter/test_40_pathconverter.zip new file mode 100644 index 0000000000000000000000000000000000000000..e9040f1517428416bcf8396a1d8ec930c217bb29 GIT binary patch literal 3086 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 aV*i)T@0cQWfGod1Vmv(Yhqp85@9tl=(Z1mT literal 0 HcmV?d00001 diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/BuildSystemTestHelper.java b/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/BuildSystemTestHelper.java index 4a94cda3045..88412320a5f 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/BuildSystemTestHelper.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/BuildSystemTestHelper.java @@ -10,6 +10,10 @@ *******************************************************************************/ package org.eclipse.cdt.managedbuilder.testplugin; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashSet; + import junit.framework.Assert; import org.eclipse.cdt.core.CCorePlugin; @@ -117,4 +121,40 @@ public class BuildSystemTestHelper { return project; } + + static public void checkDiff(Object[] arr1, Object[] arr2){ + LinkedHashSet set1 = new LinkedHashSet(Arrays.asList(arr1)); + LinkedHashSet set2 = new LinkedHashSet(Arrays.asList(arr2)); + LinkedHashSet set1Copy = new LinkedHashSet(set1); + set1.removeAll(set2); + set2.removeAll(set1Copy); + + String set1String = collectionToString(set1); + String set2String = collectionToString(set2); + String diffMsg = "array1 entries: " + set1String + ",\n array2 entries: " + set2String + "\n"; + Assert.assertEquals("arrays have different size\n" + diffMsg, arr1.length, arr2.length); + Assert.assertEquals("arrays have different contents\n" + diffMsg, 0, set1.size()); + Assert.assertEquals("arrays have different contents\n" + diffMsg, 0, set2.size()); + + if(!Arrays.equals(arr1, arr2)){ + Assert.fail("different element order, dumping..\n array1 entries: " + arrayToString(arr1) + "\n array2 entries: " + arrayToString(arr2) + "\n"); + } + } + + static public String collectionToString(Collection c){ + return arrayToString(c.toArray()); + } + + static public String arrayToString(Object[] arr){ + StringBuffer buf = new StringBuffer(); + buf.append('['); + for(int i = 0; i < arr.length; i++) { + if(i != 0) + buf.append(", "); + + buf.append(arr[i].toString()); + } + buf.append(']'); + return buf.toString(); + } } diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/ManagedBuildTestHelper.java b/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/ManagedBuildTestHelper.java index f0e688423d0..a48c1074016 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/ManagedBuildTestHelper.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/suite/org/eclipse/cdt/managedbuilder/testplugin/ManagedBuildTestHelper.java @@ -412,6 +412,74 @@ public class ManagedBuildTestHelper { return true; } + static public boolean compareBenchmarks(final IProject project, IPath testDir, String[] fileNames) { + return compareBenchmarks(project, testDir, new Path("benchmarks").append(testDir), fileNames); + } + + static public boolean compareBenchmarks(final IProject project, IPath testDir, IPath benchmarkDir, String[] fileNames) { + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IWorkspaceRunnable runnable = new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + project.refreshLocal(IResource.DEPTH_INFINITE, monitor); + } + }; + try { + NullProgressMonitor monitor = new NullProgressMonitor(); + workspace.run(runnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, monitor); + } catch (Exception e) { + Assert.fail("File " + fileNames[0] + " - project refresh failed."); + } + + IFolder testFolder = (IFolder)project.findMember(testDir); + IFolder bmFolder = (IFolder)project.findMember(benchmarkDir); + + return compareBenchmarks(testFolder, bmFolder, fileNames); + } + + static public boolean compareBenchmarks(IFolder testFolder, IFolder bmFolder, String[] fileNames) { + Assert.assertNotNull(testFolder); + Assert.assertNotNull(bmFolder); + + for (int i=0; i>>>>>>>>>>>>>>start diff: \n"); + String location1 = getFileLocation(bmFile.getProject(), bmFile.getProjectRelativePath()); + String location2 = getFileLocation(tFile.getProject(), tFile.getProjectRelativePath()); + String diff = DiffUtil.getInstance().diff(location1, location2); + if(diff == null) + diff = "!diff failed!"; + buffer.append(diff); + buffer.append("\n<<<<<<<<<< 0) { + if (i == 0) { + String configName = info.getDefaultConfiguration().getName(); + IPath buildDir = Path.fromOSString(configName); + if (compareBenchmark){ + succeeded = ManagedBuildTestHelper.compareBenchmarks(curProject, buildDir, files); + } +// else +// succeeded = ManagedBuildTestHelper.verifyFilesDoNotExist(curProject, buildDir, files); + } + } + } + } + +// if (succeeded) { // Otherwise leave the projects around for comparison +// for (int i = 0; i < projects.length; i++) +// ManagedBuildTestHelper.removeProject(projects[i].getName()); +// } + } + + private IProject[] createProjects(String projName, IPath location, String projectTypeId, boolean containsZip) { + + // In case the projects need to be updated... + IOverwriteQuery queryALL = new IOverwriteQuery(){ + public String queryOverwrite(String file) { + return ALL; + }}; + IOverwriteQuery queryNOALL = new IOverwriteQuery(){ + public String queryOverwrite(String file) { + return NO_ALL; + }}; + +// UpdateManagedProjectManager.setBackupFileOverwriteQuery(queryALL); +// UpdateManagedProjectManager.setUpdateProjectQuery(queryALL); + + IProject projects[] = createProject(projName, location, projectTypeId, containsZip); + return projects; + } + + private IProject[] createProject(String projName, IPath location, String projectTypeId, boolean containsZip){ + ArrayList projectList = null; + if (containsZip) { + File testDir = CTestPlugin.getFileInPlugin(new Path("resources/test40Projects/" + projName)); + if(testDir == null) { + fail("Test project directory " + projName + " is missing."); + return null; + } + + File projectZips[] = testDir.listFiles(new FileFilter(){ + public boolean accept(File pathname){ + if(pathname.isDirectory()) + return false; + return true; + } + }); + + projectList = new ArrayList(projectZips.length); + for(int i = 0; i < projectZips.length; i++){ + try{ + String projectName = projectZips[i].getName(); + if(!projectName.endsWith(".zip")) + continue; + + projectName = projectName.substring(0,projectName.length()-".zip".length()); + if(projectName.length() == 0) + continue; + IProject project = ManagedBuildTestHelper.createProject(projectName, projectZips[i], location, projectTypeId); + if(project != null) + projectList.add(project); + } + catch(Exception e){ + } + } + if(projectList.size() == 0) { + fail("No projects found in test project directory " + testDir.getName() + ". The .zip file may be missing or corrupt."); + return null; + } + } else { + try{ + IProject project = ManagedBuildTestHelper.createProject(projName, null, location, projectTypeId); + if(project != null) + projectList = new ArrayList(1); + projectList.add(project); + } catch(Exception e){} + } + + return (IProject[])projectList.toArray(new IProject[projectList.size()]); + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests20.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests20.java index e51da28f43d..dc71e3656c5 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests20.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/ManagedBuildCoreTests20.java @@ -45,7 +45,6 @@ import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.eclipse.cdt.managedbuilder.core.ManagedCProjectNature; -import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo; import org.eclipse.cdt.managedbuilder.internal.core.Option; import org.eclipse.cdt.managedbuilder.testplugin.ManagedBuildTestHelper; import org.eclipse.core.resources.IFile; @@ -235,15 +234,15 @@ public class ManagedBuildCoreTests20 extends TestCase { final String[] expectedPaths = new String[5]; // This first path is a built-in, so it will not be manipulated by build manager - expectedPaths[0] = (new Path("/usr/include")).toString(); - expectedPaths[1] = (new Path("/opt/gnome/include")).toString(); - IPath path = new Path("C:\\home\\tester/include"); + expectedPaths[0] = (new Path("\\usr\\include")).toOSString(); + expectedPaths[1] = (new Path("\\opt\\gnome\\include")).toOSString(); + IPath path = new Path("C:\\home\\tester\\include"); if(path.isAbsolute()) // for win32 path is treated as absolute - expectedPaths[2] = path.toString(); + expectedPaths[2] = path.toOSString(); else // for Linux path is relative - expectedPaths[2] = project.getLocation().append("Sub Config").append(path).toString(); - expectedPaths[3] = project.getLocation().append( "includes" ).toString(); - expectedPaths[4] = (new Path("/usr/gnu/include")).toString(); + expectedPaths[2] = project.getLocation().append("Sub Config").append(path).toOSString(); + expectedPaths[3] = project.getLocation().append( "includes" ).toOSString(); + expectedPaths[4] = (new Path("\\usr\\gnu\\include")).toOSString(); // Create a new managed project based on the sub project type IProjectType projType = ManagedBuildManager.getExtensionProjectType("test.sub"); @@ -323,9 +322,6 @@ public class ManagedBuildCoreTests20 extends TestCase { assertTrue(currentSymbols.containsKey("BUILTIN")); assertEquals((String)currentSymbols.get("BUILTIN"), ""); - //FIXME: - if(true) - return; String[] currentPaths = currentSettings.getIncludePaths(); assertTrue(Arrays.equals(expectedPaths, currentPaths)); diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/OneDirectionalPathConverter.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/OneDirectionalPathConverter.java new file mode 100644 index 00000000000..49e89304ca2 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/OneDirectionalPathConverter.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2007 Intel 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: + * Intel Corporation - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.core.tests; + +import org.eclipse.cdt.managedbuilder.core.IOption; +import org.eclipse.cdt.managedbuilder.core.IOptionPathConverter; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +public class OneDirectionalPathConverter implements IOptionPathConverter { + public static Path PREFIX = new Path("/test"); + + public IPath convertToPlatformLocation(String toolSpecificPath, + IOption option, ITool tool) { + IPath path = new Path(toolSpecificPath); + if(path.isAbsolute()) + return PREFIX.append(toolSpecificPath); + return path; + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/OptionStringValue.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/OptionStringValue.java index e81bed6968c..8d374801d5e 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/OptionStringValue.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/OptionStringValue.java @@ -190,4 +190,8 @@ public final class OptionStringValue { private static int code(String str){ return str != null ? str.hashCode() : 0; } + + public String toString() { + return new StringBuffer().append("ov:").append(value.toString()).toString(); + } } \ No newline at end of file diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildDescription.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildDescription.java index 577eb56aede..1475e2f626f 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildDescription.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildDescription.java @@ -759,7 +759,7 @@ public class BuildDescription implements IBuildDescription { synchRebuildState(); //TODO: trim(); } - + protected void processBuildState(){ IPath paths[] = fBuildState.getFullPathsForState(IRebuildState.NEED_REBUILD); processBuildState(IRebuildState.NEED_REBUILD, paths); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildResource.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildResource.java index d26189c49dc..819e886e8c9 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildResource.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildResource.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 Intel Corporation and others. + * Copyright (c) 2006, 2007 Intel 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 @@ -111,6 +111,10 @@ public class BuildResource implements IBuildResource { } else { if(fProducerArg == null){ fProducerArg = arg; + } else if(fProducerArg.getStep() == fInfo.getInputStep()) { + BuildStep inStep = (BuildStep)fInfo.getInputStep(); + inStep.removeResource(fProducerArg, this, true); + fProducerArg = arg; } else { String err = "ProducerArgument not null!!!\n"; //$NON-NLS-1$ if(DbgUtil.DEBUG){ diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java index 93cbcaf60c0..a00fcd1018e 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildStep.java @@ -144,6 +144,13 @@ public class BuildStep implements IBuildStep { return rcs; } + + public void removeResource(BuildIOType type, BuildResource rc, boolean rmTypeIfEmpty){ + type.removeResource(rc); + if(rmTypeIfEmpty && type.getResources().length == 0){ + removeIOType(type); + } + } public BuildIOType createIOType(boolean input, boolean primary, /*String ext,*/ IBuildObject ioType) { if(input){ diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java index b0c4e9af7be..90bb100000f 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java @@ -999,6 +999,7 @@ public class CommonBuilder extends ACBuilder { } } catch (Exception e) { + e.printStackTrace(); if(consoleOutStream != null){ StringBuffer buf = new StringBuffer(); String errorDesc = ManagedMakeMessages diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/BuildEntryStorage.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/BuildEntryStorage.java index 1edfc0b8522..db6f138a646 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/BuildEntryStorage.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/BuildEntryStorage.java @@ -11,10 +11,13 @@ package org.eclipse.cdt.managedbuilder.internal.dataprovider; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Set; +import org.eclipse.cdt.core.cdtvariables.CdtVariableException; import org.eclipse.cdt.core.settings.model.CMacroEntry; import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; import org.eclipse.cdt.core.settings.model.ICLanguageSettingPathEntry; @@ -25,31 +28,59 @@ import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.core.settings.model.util.SettingsSet; import org.eclipse.cdt.core.settings.model.util.SettingsSet.EntryInfo; import org.eclipse.cdt.core.settings.model.util.SettingsSet.SettingLevel; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IEnvVarBuildPath; import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.IOptionPathConverter; import org.eclipse.cdt.managedbuilder.core.IResourceInfo; import org.eclipse.cdt.managedbuilder.core.IReverseOptionPathConverter; import org.eclipse.cdt.managedbuilder.core.ITool; -import org.eclipse.cdt.managedbuilder.core.OptionStringValue; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; +import org.eclipse.cdt.managedbuilder.core.OptionStringValue; import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider; import org.eclipse.cdt.managedbuilder.internal.core.Option; +import org.eclipse.cdt.managedbuilder.internal.macros.DefaultMacroContextInfo; +import org.eclipse.cdt.managedbuilder.internal.macros.OptionContextData; +import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; +import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver; +import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; public class BuildEntryStorage extends AbstractEntryStorage { private BuildLanguageData fLangData; + private String fBuildDirName; private static class UserEntryInfo { private ICLanguageSettingEntry fEntry; - private OptionStringValue fOptionValue; + private OptionStringValue fOriginalValue; + private OptionStringValue fBsResolvedValue; + private List fSequense; - UserEntryInfo(ICLanguageSettingEntry entry, OptionStringValue optionValue){ + UserEntryInfo(ICLanguageSettingEntry entry, OptionStringValue originalValue, OptionStringValue bsResolvedValue, List sequense){ fEntry = entry; - fOptionValue = optionValue; + fOriginalValue = originalValue; + fBsResolvedValue = bsResolvedValue; + fSequense = sequense; + if(sequense != null) + sequense.add(this); } } + + private static class EmptyEntryInfo { + private OptionStringValue fOriginalValue; + private int fPosition; + + EmptyEntryInfo(OptionStringValue value, int position){ + fOriginalValue = value; + fPosition = position; + } + } + + public BuildEntryStorage(int kind, BuildLanguageData lData) { super(kind); fLangData = lData; @@ -83,6 +114,13 @@ public class BuildEntryStorage extends AbstractEntryStorage { return fLangData.getUndefOptionsForKind(getKind()).length != 0; } + private String getBuildDitName(){ + if(fBuildDirName == null){ + fBuildDirName = fLangData.getConfiguration().getName(); + } + return fBuildDirName; + } + protected void obtainEntriesFromLevel(int levelNum, SettingLevel level) { switch(levelNum){ case 0: @@ -92,9 +130,12 @@ public class BuildEntryStorage extends AbstractEntryStorage { EntryInfo infos[] = level.getInfos(); UserEntryInfo[] userInfos = new UserEntryInfo[infos.length]; for(int i = 0; i < infos.length; i++){ - userInfos[i] = new UserEntryInfo(infos[i].getEntry(), (OptionStringValue)infos[i].getCustomInfo()); + UserEntryInfo uei = (UserEntryInfo)infos[i].getCustomInfo(); + if(uei == null) + uei = new UserEntryInfo(infos[i].getEntry(), null, null, null); + userInfos[i] = uei; } - setUserEntries(userInfos); + setUserEntries(userInfos, (List)level.getContext()); setUserUndefinedStringSet(level.containsOverrideInfo() ? level.getOverrideSet() : null); } break; @@ -123,11 +164,14 @@ public class BuildEntryStorage extends AbstractEntryStorage { protected void putEntriesToLevel(int levelNum, SettingLevel level) { switch(levelNum){ case 0: - UserEntryInfo[] userEntries = getUserEntries(level.getFlags(0), true); + List emptyEntryInfos = new ArrayList(); + UserEntryInfo[] userEntries = getUserEntries(level.getFlags(0), true, emptyEntryInfos); for(int i = 0; i < userEntries.length; i++){ - level.addEntry(userEntries[i].fEntry, userEntries[i].fOptionValue); + level.addEntry(userEntries[i].fEntry, userEntries[i]); } level.addOverrideNameSet(getUserUndefinedStringSet()); + if(emptyEntryInfos.size() != 0) + level.setContext(emptyEntryInfos); break; case 1: ICLanguageSettingEntry[] envEntries = getEnvEntries(level.getFlags(0)); @@ -143,7 +187,7 @@ public class BuildEntryStorage extends AbstractEntryStorage { private ICLanguageSettingEntry[] getDiscoveredEntries(int flags){ ICLanguageSettingEntry[] entries = ProfileInfoProvider.getInstance().getEntryValues(fLangData, getKind(), flags); if(entries == null || entries.length == 0){ - UserEntryInfo[] infos = getUserEntries(flags, false); + UserEntryInfo[] infos = getUserEntries(flags, false, null); if(infos.length != 0){ entries = new ICLanguageSettingEntry[infos.length]; for(int i = 0; i < entries.length; i++){ @@ -154,7 +198,16 @@ public class BuildEntryStorage extends AbstractEntryStorage { return entries; } - private UserEntryInfo[] getUserEntries(int flags, boolean usr){ + private SupplierBasedCdtVariableSubstitutor createSubstitutor(IOption option, boolean bsVarsOnly){ + OptionContextData ocd = new OptionContextData(option, fLangData.getTool()); + DefaultMacroContextInfo ci = new DefaultMacroContextInfo(IBuildMacroProvider.CONTEXT_OPTION, ocd); + + return bsVarsOnly ? + new BuildSystemSpecificVariableSubstitutor(ci) + : new SupplierBasedCdtVariableSubstitutor(ci, "", " "); + } + + private UserEntryInfo[] getUserEntries(int flags, boolean usr, List emptyValuesInfos){ IOption options[] = fLangData.getOptionsForKind(getKind()); if(options.length > 0){ List entryList = new ArrayList(); @@ -163,13 +216,24 @@ public class BuildEntryStorage extends AbstractEntryStorage { List list = usr ? (List)option.getExactValue() : option.getExactBuiltinsList(); int size = list != null ? list.size() : 0; if(size > 0){ + SupplierBasedCdtVariableSubstitutor subst = createSubstitutor(option, false); + SupplierBasedCdtVariableSubstitutor bSVarsSubst = createSubstitutor(option, true); for(int j = 0; j < size; j++){ OptionStringValue ve = (OptionStringValue)list.get(j); -// if(value.indexOf('"') == 0 && value.lastIndexOf('"') == value.length() - 1 && value.length() != 1){ -// value = value.substring(1, value.length() - 1); -// } - ICLanguageSettingEntry entry = createUserEntry(option, ve, flags); - entryList.add(new UserEntryInfo(entry, ve)); + OptionStringValue[] rVes = resolve(ve, option, bSVarsSubst); + if(rVes.length == 0){ + if(emptyValuesInfos != null){ + emptyValuesInfos.add(new EmptyEntryInfo(ve, j)); + } + } else { + boolean isMultiple = rVes.length > 1; + List sequense = isMultiple ? new ArrayList(rVes.length) : null; + for(int k = 0; k < rVes.length; k++){ + OptionStringValue rVe = rVes[k]; + ICLanguageSettingEntry entry = createUserEntry(option, rVe, flags, subst); + entryList.add(new UserEntryInfo(entry, ve, rVe, sequense)); + } + } } } } @@ -179,13 +243,27 @@ public class BuildEntryStorage extends AbstractEntryStorage { return new UserEntryInfo[0]; } - private static String stripQuotes(String value){ +// private static OptionStringValue stripQuotes(OptionStringValue ov){ +// String value = ov.getValue(); +// value = stripQuotes(value, true); +// if(value != null){ +// value = value.substring(1, value.length() - 1); +// ov = substituteValue(ov, value); +// } +// return ov; +// } + + private static String stripQuotes(String value, boolean nullIfNone){ if(value.indexOf('"') == 0 && value.lastIndexOf('"') == value.length() - 1 && value.length() != 1){ - value = value.substring(1, value.length() - 1); + return value.substring(1, value.length() - 1); } - return value; + return nullIfNone ? null : value; + + } + + private static OptionStringValue substituteValue(OptionStringValue ov, String value){ + return new OptionStringValue(value, ov.isBuiltIn(), ov.getSourceAttachmentPath(), ov.getSourceAttachmentRootPath(), ov.getSourceAttachmentPrefixMapping()); } - private HashSet getUserUndefinedStringSet(){ HashSet set = null; @@ -203,6 +281,62 @@ public class BuildEntryStorage extends AbstractEntryStorage { } return set; } + + private PathInfo fromBuildToProj(PathInfo info){ + if(info.isAbsolute()) + return info; + + Path path = new Path(info.getUnresolvedPath()); + String projPath; + if(path.segmentCount() != 0 && "..".equals(path.segment(0))){ + projPath = path.removeFirstSegments(1).toString(); + } else { + StringBuffer buf = new StringBuffer(); + buf.append(getBuildDitName()).append('/').append(info.getUnresolvedPath()); + projPath = buf.toString(); + } + return new PathInfo(projPath, info.isWorkspacePath(), info.getSubstitutor()); + } + + private PathInfo fromProjToBuild(PathInfo info){ + if(info.isAbsolute()) + return info; + + Path path = new Path(info.getUnresolvedPath()); + String projPath; + if(path.segmentCount() != 0 && getBuildDitName().equals(path.segment(0))){ + projPath = path.removeFirstSegments(1).toString(); + } else { + StringBuffer buf = new StringBuffer(); + buf.append("../").append(info.getUnresolvedPath()); + projPath = buf.toString(); + } + return new PathInfo(projPath, info.isWorkspacePath(), info.getSubstitutor()); + } + +// private String[] resolve(String v, IOption option, IPath[] buildLocation){ +// +// } + + private String[] resolve(String v, IOption option, SupplierBasedCdtVariableSubstitutor sub){ + try { + return CdtVariableResolver.resolveToStringList(v, sub); + } catch (CdtVariableException e) { + ManagedBuilderCorePlugin.log(e); + } + return new String[0]; + } + + private OptionStringValue[] resolve(OptionStringValue ov, IOption option, SupplierBasedCdtVariableSubstitutor sub){ + String value = ov.getValue(); + value = stripQuotes(value, false); + String[] rValues = resolve(value, option, sub); + OptionStringValue[] result = new OptionStringValue[rValues.length]; + for(int i = 0; i < result.length; i++){ + result[i] = substituteValue(ov, stripQuotes(rValues[i], false)); + } + return result; + } private ICLanguageSettingEntry[] getEnvEntries(int flags){ String paths[] = null; @@ -231,7 +365,7 @@ public class BuildEntryStorage extends AbstractEntryStorage { return new ICLanguageSettingEntry[0]; } - private ICLanguageSettingEntry createUserEntry(Option option, OptionStringValue optionValue, int flags){ + private ICLanguageSettingEntry createUserEntry(Option option, OptionStringValue optionValue, int flags, SupplierBasedCdtVariableSubstitutor subst){ // private ICLanguageSettingEntry createUserEntry(Option option, String optionValue, int flags){ int kind = getKind(); @@ -264,32 +398,36 @@ public class BuildEntryStorage extends AbstractEntryStorage { //do not break default: IOptionPathConverter optionPathConverter = fLangData.getTool().getOptionPathConverter(); - Object[] v = optionPathValueToEntry(stripQuotes(optionValue.getValue())); + PathInfo pInfo = optionPathValueToEntry(optionValue.getValue(), subst); +// Object[] v = optionPathValueToEntry(stripQuotes(optionValue.getValue())); // Object[] v = optionPathValueToEntry(optionValue); - String name = (String)v[0]; - if(((Boolean)v[1]).booleanValue()){ + + if(pInfo.isWorkspacePath()){ flags |= ICLanguageSettingEntry.VALUE_WORKSPACE_PATH; } else if (optionPathConverter != null){ - IPath path = optionPathConverter.convertToPlatformLocation(name, option, fLangData.getTool()); - if(path != null) - name = path.toString(); + IPath path = optionPathConverter.convertToPlatformLocation(pInfo.getUnresolvedPath(), option, fLangData.getTool()); + if(path != null){ + pInfo = new PathInfo(path.toString(), false, subst); + } } - entry = (ICLanguageSettingEntry)CDataUtil.createEntry(kind, name, null, null, flags, srcPath, srcRootPath, srcPrefixMapping); + + pInfo = fromBuildToProj(pInfo); + + entry = (ICLanguageSettingEntry)CDataUtil.createEntry(kind, pInfo.getUnresolvedPath(), null, null, flags, srcPath, srcRootPath, srcPrefixMapping); break; - } return entry; } - private OptionStringValue createOptionValue(IOption option, UserEntryInfo info){ - if(info.fOptionValue != null) - return info.fOptionValue; + private OptionStringValue createOptionValue(IOption option, UserEntryInfo info, SupplierBasedCdtVariableSubstitutor subst){ + if(info.fOriginalValue != null) + return info.fOriginalValue; - return entryValueToOption(option, info.fEntry); + return entryValueToOption(option, info.fEntry, subst); } - private OptionStringValue entryValueToOption(IOption option, ICLanguageSettingEntry entry){ - String optionValue = entryValueToOptionStringValue(option, entry); + private OptionStringValue entryValueToOption(IOption option, ICLanguageSettingEntry entry, SupplierBasedCdtVariableSubstitutor subst){ + String optionValue = entryValueToOptionStringValue(option, entry, subst); if(entry.getKind() == ICSettingEntry.LIBRARY_FILE){ ICLibraryFileEntry libFile = (ICLibraryFileEntry)entry; return new OptionStringValue(optionValue, @@ -305,7 +443,7 @@ public class BuildEntryStorage extends AbstractEntryStorage { return path != null ? path.toString() : null; } - private String entryValueToOptionStringValue(IOption option, ICLanguageSettingEntry entry){ + private String entryValueToOptionStringValue(IOption option, ICLanguageSettingEntry entry, SupplierBasedCdtVariableSubstitutor subst){ String result; boolean checkQuote = true; if(entry.getKind() == ICLanguageSettingEntry.MACRO && entry.getValue().length() > 0){ @@ -317,23 +455,48 @@ public class BuildEntryStorage extends AbstractEntryStorage { checkQuote = false; } else { ICLanguageSettingPathEntry pathEntry = (ICLanguageSettingPathEntry)entry; - if(pathEntry.isValueWorkspacePath()){ - result = ManagedBuildManager.fullPathToLocation(pathEntry.getValue()); - } else { - result = entry.getName(); - } + result = doConvertToOptionValue(option, pathEntry, subst); } } else { result = entry.getName(); } if(checkQuote){ - result = doubleQuotePath(result); + result = doubleQuotePath(result, false); } return result; } - private String doubleQuotePath(String pathName) { + private String doConvertToOptionValue(IOption option, ICLanguageSettingPathEntry pathEntry, SupplierBasedCdtVariableSubstitutor subst){ + boolean isWsp = pathEntry.isValueWorkspacePath(); + PathInfo pInfo = new PathInfo(pathEntry.getName(), isWsp, subst); + String result; + if(isWsp){ + if(!pInfo.isAbsolute()){ + IConfiguration cfg = fLangData.getConfiguration(); + IResource rc = cfg.getOwner(); + if(rc != null){ + IProject proj = rc.getProject(); + String path = pInfo.getUnresolvedPath(); + IPath p = proj.getFullPath().append(path); + result = p.toString(); + } else { + result = pathEntry.getName(); + } + } else { + result = pathEntry.getName(); + } + + result = ManagedBuildManager.fullPathToLocation(result); + } else { + pInfo = fromProjToBuild(pInfo); + result = pInfo.getUnresolvedPath(); + } + + return result; + } + + private static String doubleQuotePath(String pathName, boolean nullIfNone) { /* Trim */ pathName = pathName.trim(); @@ -341,19 +504,27 @@ public class BuildEntryStorage extends AbstractEntryStorage { boolean bStartsWithQuote = pathName.indexOf('"') == 0; boolean bEndsWithQuote = pathName.lastIndexOf('"') == pathName.length() - 1; + boolean quoted = false; + /* Check for spaces, backslashes or macros */ int i = pathName.indexOf(' ') + pathName.indexOf('\\') //$NON-NLS-1$ //$NON-NLS-2$ + pathName.indexOf("${"); //$NON-NLS-1$ /* If indexof didn't fail all three times, double-quote path */ if (i != -3) { - if (!bStartsWithQuote) + if (!bStartsWithQuote){ pathName = "\"" + pathName; //$NON-NLS-1$ - if (!bEndsWithQuote) + quoted = true; + } + if (!bEndsWithQuote){ pathName = pathName + "\""; //$NON-NLS-1$ + quoted = true; + } } - return pathName; + if(quoted) + return pathName; + return nullIfNone ? null : pathName; } public static String[] macroNameValueFromValue(String value){ @@ -369,23 +540,44 @@ public class BuildEntryStorage extends AbstractEntryStorage { return nv; } - private static Object[] optionPathValueToEntry(String value){ - String wspPath = ManagedBuildManager.locationToFullPath(value); - if(wspPath != null) - return new Object[]{wspPath, Boolean.valueOf(true)}; - return new Object[]{value, Boolean.valueOf(false)}; +// private static Object[] optionPathValueToEntry(String value){ +// String wspPath = ManagedBuildManager.locationToFullPath(value); +// if(wspPath != null) +// return new Object[]{wspPath, Boolean.valueOf(true)}; +// return new Object[]{value, Boolean.valueOf(false)}; +// } + + private static PathInfo optionPathValueToEntry(String str, SupplierBasedCdtVariableSubstitutor subst){ + String unresolvedStr = ManagedBuildManager.locationToFullPath(str); + boolean isWorkspacePath; + if(unresolvedStr != null){ + isWorkspacePath = true; + } else { + unresolvedStr = str; + isWorkspacePath = false; + } + return new PathInfo(unresolvedStr, isWorkspacePath, subst); } - private void setUserEntries(UserEntryInfo[] entries){ + private void setUserEntries(UserEntryInfo[] entries, List emptyEntryInfos){ int kind = getKind(); IOption options[] = fLangData.getOptionsForKind(kind); if(options.length != 0){ IOption option = options[0]; - OptionStringValue optValue[] = new OptionStringValue[entries.length]; + OptionStringValue[] optValue; if(entries.length != 0){ + entries = combineSequenses(entries); + + entries = addEmptyEntries(entries, emptyEntryInfos); + + optValue = new OptionStringValue[entries.length]; + SupplierBasedCdtVariableSubstitutor subst = createSubstitutor(option, false); + for(int i = 0; i < entries.length; i++){ - optValue[i] = createOptionValue(option, entries[i]); + optValue[i] = createOptionValue(option, entries[i], subst); } + } else { + optValue = Option.EMPTY_LV_ARRAY; } ITool tool = fLangData.getTool(); @@ -398,6 +590,73 @@ public class BuildEntryStorage extends AbstractEntryStorage { } } } + + private UserEntryInfo[] addEmptyEntries(UserEntryInfo infos[], List emptyEntryInfos){ + if(emptyEntryInfos == null || emptyEntryInfos.size() == 0) + return infos; + + LinkedList list = new LinkedList(); + list.addAll(Arrays.asList(infos)); + for(int i = 0; i < emptyEntryInfos.size(); i++){ + EmptyEntryInfo ei = (EmptyEntryInfo)emptyEntryInfos.get(i); + int index = ei.fPosition; + if(index > list.size()) + index = list.size(); + + list.add(index, new UserEntryInfo(null, ei.fOriginalValue, ei.fOriginalValue, null)); + } + + return (UserEntryInfo[])list.toArray(new UserEntryInfo[list.size()]); + } + + private UserEntryInfo[] combineSequenses(UserEntryInfo infos[]){ + if(infos.length == 0) + return infos; + + List list = new ArrayList(infos.length); + + for(int i = 0; i < infos.length; i++){ + UserEntryInfo info = infos[i]; + if(info.fSequense != null) { + boolean match = true; + int seqSize = info.fSequense.size(); + if(seqSize > infos.length - i) + match = false; + else { + for(int k = 0; k < seqSize; k++){ + if(info.fSequense.get(k) != infos[i + k]){ + match = false; + break; + } + } + } + + if(match){ + i = i + seqSize - 1; + } else { + infos[i] = createDesecuencedEntry(info); + for(int k = i + 1; k < infos.length; k++){ + if(infos[k].fSequense == info.fSequense) + infos[k] = createDesecuencedEntry(infos[k]); + } + info = infos[i]; + } + } + list.add(info); + } + + return (UserEntryInfo[])list.toArray(new UserEntryInfo[list.size()]); + } + + private static UserEntryInfo createDesecuencedEntry(UserEntryInfo info){ + OptionStringValue resolvedValue = info.fBsResolvedValue; + if(resolvedValue != null){ + String v = doubleQuotePath(resolvedValue.getValue(), true); + if(v != null) + resolvedValue = substituteValue(resolvedValue, v); + } + return new UserEntryInfo(info.fEntry, resolvedValue, resolvedValue, null); + } private void setUserUndefinedStringSet(Set set){ int kind = getKind(); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/BuildSystemSpecificVariableSubstitutor.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/BuildSystemSpecificVariableSubstitutor.java new file mode 100644 index 00000000000..bb22e043ece --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/BuildSystemSpecificVariableSubstitutor.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2007 Intel 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: + * Intel Corporation - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.dataprovider; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.core.cdtvariables.CdtVariableException; +import org.eclipse.cdt.managedbuilder.internal.macros.MbsMacroSupplier; +import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; +import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver; +import org.eclipse.cdt.utils.cdtvariables.IVariableContextInfo; +import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor; + +public class BuildSystemSpecificVariableSubstitutor extends SupplierBasedCdtVariableSubstitutor{ + private static final Set fFileVarsSet = new HashSet(Arrays.asList(MbsMacroSupplier.getInstance().getMacroNames(IBuildMacroProvider.CONTEXT_FILE))); + private static final Set fOptionVarsSet = new HashSet(Arrays.asList(MbsMacroSupplier.getInstance().getMacroNames(IBuildMacroProvider.CONTEXT_OPTION))); + private static final Set fToolVarsSet = new HashSet(Arrays.asList(MbsMacroSupplier.getInstance().getMacroNames(IBuildMacroProvider.CONTEXT_TOOL))); + + public BuildSystemSpecificVariableSubstitutor( + IVariableContextInfo contextInfo, String inexistentMacroValue, + String listDelimiter, Map delimiterMap, + String incorrectlyReferencedMacroValue) { + super(contextInfo, inexistentMacroValue, listDelimiter, delimiterMap, + incorrectlyReferencedMacroValue); + } + + public BuildSystemSpecificVariableSubstitutor(IVariableContextInfo contextInfo){ + this(contextInfo, "", " "); + } + + public BuildSystemSpecificVariableSubstitutor( + IVariableContextInfo contextInfo, String inexistentMacroValue, + String listDelimiter) { + super(contextInfo, inexistentMacroValue, listDelimiter); + } + + protected ResolvedMacro resolveMacro(String macroName) + throws CdtVariableException { + if(fFileVarsSet.contains(macroName) + || fOptionVarsSet.contains(macroName) + || fToolVarsSet.contains(macroName)) + return super.resolveMacro(macroName); + return new ResolvedMacro(macroName, CdtVariableResolver.createVariableReference(macroName)); + } +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/PathInfo.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/PathInfo.java new file mode 100644 index 00000000000..86072a60096 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/PathInfo.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2007 Intel 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: + * Intel Corporation - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.dataprovider; + +import org.eclipse.cdt.core.cdtvariables.CdtVariableException; +import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; +import org.eclipse.cdt.utils.cdtvariables.SupplierBasedCdtVariableSubstitutor; +import org.eclipse.core.runtime.IPath; + +class PathInfo { + private String fUnresolvedStr; + private IPath fResolvedPath; + private boolean fIsWorkspacePath; + private String fAbsoluteInfoStr; + private Boolean fIsAbsolute; + private SupplierBasedCdtVariableSubstitutor fSubstitutor; + + public PathInfo(String str, boolean isWspPath, SupplierBasedCdtVariableSubstitutor subst){ + fUnresolvedStr = str; + fIsWorkspacePath = isWspPath; + fSubstitutor = subst; + } + + public String getUnresolvedPath(){ + return fUnresolvedStr; + } + + public boolean isWorkspacePath(){ + return fIsWorkspacePath; + } + + public boolean isAbsolute(){ + if(fIsAbsolute == null) + fIsAbsolute = Boolean.valueOf(checkIsAbsolute()); + return fIsAbsolute.booleanValue(); + } + + private boolean checkIsAbsolute(){ +// if(fIsWorkspacePath) +// return true; + + if(fResolvedPath != null) + return fResolvedPath.isAbsolute(); + + if(fAbsoluteInfoStr != null){ + return isAbsolute(fAbsoluteInfoStr, fSubstitutor, new String[1]); + } + + String str[] = new String[1]; + boolean isAbs = isAbsolute(fUnresolvedStr, fSubstitutor, str); + fAbsoluteInfoStr = str[0]; + return isAbs; + } + + private static boolean isAbsolute(String str, SupplierBasedCdtVariableSubstitutor subst, String[] out){ + int length = str.length(); + out[0] = str; + if(length == 0) + return false; + + char c0 = str.charAt(0); + if(c0 == '/' || c0 == '\\') + return true; + + if(length == 1) + return false; + + char c1 = str.charAt(1); + if(c1 == ':') + return true; + + if(length < 4) + return false; + + if(c0 == '$' && c1 == '{'){ + int indx = str.indexOf('}'); + if(indx != -1){ + String macroName = str.substring(2, indx); + if(macroName.length() != 0){ + String resolvedMacro; + try { + resolvedMacro = subst.resolveToString(macroName); + } catch (CdtVariableException e) { + ManagedBuilderCorePlugin.log(e); + resolvedMacro = null; + e.printStackTrace(); + } + String substr = str.substring(indx + 1); + String rStr = resolvedMacro == null || resolvedMacro.length() == 0 ? + substr : new StringBuffer().append(resolvedMacro).append(subst).toString(); + return isAbsolute(rStr, subst, out); + } + } + } + + return false; + } + + public SupplierBasedCdtVariableSubstitutor getSubstitutor(){ + return fSubstitutor; + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/SettingsSet.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/SettingsSet.java index 4c7af7a289f..86b0ff9a5c8 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/SettingsSet.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/SettingsSet.java @@ -33,6 +33,7 @@ public class SettingsSet { private boolean fIsOverrideSupported; private LinkedHashMap fEntries; HashSet fOverrideSet; + private Object fContext; private SettingLevel(){ fEntries = new LinkedHashMap(); @@ -172,6 +173,14 @@ public class SettingsSet { return list; } + + public Object getContext(){ + return fContext; + } + + public void setContext(Object context){ + fContext = context; + } } public static class EntryInfo { diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/DescriptionScannerInfoProvider.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/DescriptionScannerInfoProvider.java index 02dc568d47d..6b2682e2bd0 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/DescriptionScannerInfoProvider.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/DescriptionScannerInfoProvider.java @@ -240,6 +240,10 @@ public class DescriptionScannerInfoProvider implements IScannerInfoProvider, ICP if(rc != null){ path = rc.getLocation(); } + } else if (!path.isAbsolute()) { + IPath projLocation = fProject != null ? fProject.getLocation() : null; + if(projLocation != null) + path = projLocation.append(path); } if(path != null) values[num++] = path.toOSString(); diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/cdtvariables/SupplierBasedCdtVariableSubstitutor.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/cdtvariables/SupplierBasedCdtVariableSubstitutor.java index 3f83f988c54..2b6d9b9fe7e 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/cdtvariables/SupplierBasedCdtVariableSubstitutor.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/cdtvariables/SupplierBasedCdtVariableSubstitutor.java @@ -76,8 +76,12 @@ public class SupplierBasedCdtVariableSubstitutor implements IVariableSubstitutor public String[] getStringListValue() throws CdtVariableException { // if(!fIsDefined) // throw new BuildMacroException(BuildMacroException.TYPE_MACROS_UNDEFINED,fName); - if(!fIsList && fStringListValue == null) - fStringListValue = new String[]{fStringValue}; + if(!fIsList && fStringListValue == null){ + if(fStringValue != null && fStringValue.length() != 0) + fStringListValue = new String[]{fStringValue}; + else + fStringListValue = new String[0]; + } return fStringListValue; }