未验证 提交 7b27ca3b 编写于 作者: T Tomáš Matoušek 提交者: GitHub

Fixes PathMap parsing to support all paths (#43706)

上级 b4973cd3
......@@ -72,7 +72,7 @@
| `/main`:*type* | Specify the type that contains the entry point (ignore all other possible entry points) (Short form: `/m`)
| `/fullpaths` | Compiler generates fully qualified paths
| `/filealign`:*n* | Specify the alignment used for output file sections
| `/pathmap:`*k1*=*v1*,*k2*=*v2*,... | Specify a mapping for source path names output by the compiler.
| `/pathmap:`*k1*=*v1*,*k2*=*v2*,... | Specify a mapping for source path names output by the compiler. Two consecutive separator characters are treated as a single character that is part of the key or value (i.e. `==` stands for `=` and `,,` for `,`).
| `/pdb:`*file* | Specify debug information file name (default: output file name with `.pdb` extension)
| `/errorendlocation` | Output line and column of the end location of each error
| `/preferreduilang` | Specify the preferred output language name.
......
......@@ -84,7 +84,7 @@
| `/moduleassemblyname:`*string* | Name of the assembly which this module will be a part of.
| `/netcf` | Target the .NET Compact Framework.
| `/nostdlib` | Do not reference standard libraries (`system.dll` and `VBC.RSP` file).
| `/pathmap:`*k1*=*v1*,*k2*=*v2*,... | Specify a mapping for source path names output by the compiler.
| `/pathmap:`*k1*=*v1*,*k2*=*v2*,... | Specify a mapping for source path names output by the compiler. Two consecutive separator characters are treated as a single character that is part of the key or value (i.e. `==` stands for `=` and `,,` for `,`).
| `/platform:`*string* | Limit which platforms this code can run on; must be `x86`, `x64`, `Itanium`, `arm`, `AnyCPU32BitPreferred` or `anycpu` (default).
| `/preferreduilang` | Specify the preferred output language name.
| `/sdkpath:`*path* | Location of the .NET Framework SDK directory (`mscorlib.dll`).
......
......@@ -10549,33 +10549,40 @@ public void ParseSeparatedPaths_QuotedComma()
paths);
}
[Fact]
[CompilerTrait(CompilerFeature.Determinism)]
[ConditionalFact(typeof(WindowsOnly), Reason = "https://github.com/dotnet/roslyn/issues/30289")]
public void PathMapParser()
{
var s = PathUtilities.DirectorySeparatorStr;
var parsedArgs = DefaultParse(new[] { "/pathmap:", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(ImmutableArray.Create<KeyValuePair<string, string>>(), parsedArgs.PathMap);
parsedArgs = DefaultParse(new[] { "/pathmap:K1=V1", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(KeyValuePairUtil.Create("K1\\", "V1\\"), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("K1" + s, "V1" + s), parsedArgs.PathMap[0]);
parsedArgs = DefaultParse(new[] { "/pathmap:C:\\goo\\=/", "a.cs" }, WorkingDirectory);
parsedArgs = DefaultParse(new[] { $"/pathmap:abc{s}=/", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(KeyValuePairUtil.Create("C:\\goo\\", "/"), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("abc" + s, "/"), parsedArgs.PathMap[0]);
parsedArgs = DefaultParse(new[] { "/pathmap:K1=V1,K2=V2", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(KeyValuePairUtil.Create("K1\\", "V1\\"), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("K2\\", "V2\\"), parsedArgs.PathMap[1]);
Assert.Equal(KeyValuePairUtil.Create("K1" + s, "V1" + s), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("K2" + s, "V2" + s), parsedArgs.PathMap[1]);
parsedArgs = DefaultParse(new[] { "/pathmap:,", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(ImmutableArray.Create<KeyValuePair<string, string>>(), parsedArgs.PathMap);
parsedArgs = DefaultParse(new[] { "/pathmap:,,", "a.cs" }, WorkingDirectory);
Assert.Equal(1, parsedArgs.Errors.Count());
Assert.Equal((int)ErrorCode.ERR_InvalidPathMap, parsedArgs.Errors[0].Code);
parsedArgs = DefaultParse(new[] { "/pathmap:,,,", "a.cs" }, WorkingDirectory);
Assert.Equal(4, parsedArgs.Errors.Count());
Assert.Equal(1, parsedArgs.Errors.Count());
Assert.Equal((int)ErrorCode.ERR_InvalidPathMap, parsedArgs.Errors[0].Code);
Assert.Equal((int)ErrorCode.ERR_InvalidPathMap, parsedArgs.Errors[1].Code);
Assert.Equal((int)ErrorCode.ERR_InvalidPathMap, parsedArgs.Errors[2].Code);
Assert.Equal((int)ErrorCode.ERR_InvalidPathMap, parsedArgs.Errors[3].Code);
parsedArgs = DefaultParse(new[] { "/pathmap:k=,=v", "a.cs" }, WorkingDirectory);
Assert.Equal(2, parsedArgs.Errors.Count());
......@@ -10586,19 +10593,46 @@ public void PathMapParser()
Assert.Equal(1, parsedArgs.Errors.Count());
Assert.Equal((int)ErrorCode.ERR_InvalidPathMap, parsedArgs.Errors[0].Code);
parsedArgs = DefaultParse(new[] { "/pathmap:k=", "a.cs" }, WorkingDirectory);
Assert.Equal(1, parsedArgs.Errors.Count());
Assert.Equal((int)ErrorCode.ERR_InvalidPathMap, parsedArgs.Errors[0].Code);
parsedArgs = DefaultParse(new[] { "/pathmap:=v", "a.cs" }, WorkingDirectory);
Assert.Equal(1, parsedArgs.Errors.Count());
Assert.Equal((int)ErrorCode.ERR_InvalidPathMap, parsedArgs.Errors[0].Code);
parsedArgs = DefaultParse(new[] { "/pathmap:\"supporting spaces=is hard\"", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(KeyValuePairUtil.Create("supporting spaces\\", "is hard\\"), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("supporting spaces" + s, "is hard" + s), parsedArgs.PathMap[0]);
parsedArgs = DefaultParse(new[] { "/pathmap:\"K 1=V 1\",\"K 2=V 2\"", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(KeyValuePairUtil.Create("K 1\\", "V 1\\"), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("K 2\\", "V 2\\"), parsedArgs.PathMap[1]);
Assert.Equal(KeyValuePairUtil.Create("K 1" + s, "V 1" + s), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("K 2" + s, "V 2" + s), parsedArgs.PathMap[1]);
parsedArgs = DefaultParse(new[] { "/pathmap:\"K 1\"=\"V 1\",\"K 2\"=\"V 2\"", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(KeyValuePairUtil.Create("K 1\\", "V 1\\"), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("K 2\\", "V 2\\"), parsedArgs.PathMap[1]);
Assert.Equal(KeyValuePairUtil.Create("K 1" + s, "V 1" + s), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("K 2" + s, "V 2" + s), parsedArgs.PathMap[1]);
parsedArgs = DefaultParse(new[] { "/pathmap:\"a ==,,b\"=\"1,,== 2\",\"x ==,,y\"=\"3 4\",", "a.cs" }, WorkingDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(KeyValuePairUtil.Create("a =,b" + s, "1,= 2" + s), parsedArgs.PathMap[0]);
Assert.Equal(KeyValuePairUtil.Create("x =,y" + s, "3 4" + s), parsedArgs.PathMap[1]);
}
[Theory]
[InlineData("", new string[0])]
[InlineData(",", new[] { "", "" })]
[InlineData(",,", new[] { "," })]
[InlineData(",,,", new[] { ",", "" })]
[InlineData(",,,,", new[] { ",," })]
[InlineData("a,", new[] { "a", "" })]
[InlineData("a,b", new[] { "a", "b" })]
[InlineData(",,a,,,,,b,,", new[] { ",a,,", "b," })]
public void SplitWithDoubledSeparatorEscaping(string str, string[] expected)
{
AssertEx.Equal(expected, CommandLineParser.SplitWithDoubledSeparatorEscaping(str, ','));
}
[ConditionalFact(typeof(WindowsOnly), Reason = "https://github.com/dotnet/roslyn/issues/30289")]
......
......@@ -159,7 +159,8 @@
-->
<Target Name="InitializeSourceRootMappedPaths"
DependsOnTargets="_InitializeSourceRootMappedPathsFromSourceControl">
DependsOnTargets="_InitializeSourceRootMappedPathsFromSourceControl"
Returns="@(SourceRoot)">
<ItemGroup Condition="'@(_MappedSourceRoot)' != ''">
<_MappedSourceRoot Remove="@(_MappedSourceRoot)" />
......@@ -207,26 +208,21 @@
Condition="'$(DeterministicSourcePaths)' == 'true'">
<ItemGroup>
<_TopLevelSourceRoot Include="@(SourceRoot)" Condition="'%(SourceRoot.NestedRoot)' == ''"/>
<_TopLevelSourceRoot Include="@(SourceRoot)" Condition="'%(SourceRoot.NestedRoot)' == ''">
<EscapedKey>$([MSBuild]::ValueOrDefault('%(Identity)', '').Replace(',', ',,').Replace('=', '=='))</EscapedKey>
<EscapedValue>$([MSBuild]::ValueOrDefault('%(MappedPath)', '').Replace(',', ',,').Replace('=', '=='))</EscapedValue>
</_TopLevelSourceRoot>
</ItemGroup>
<PropertyGroup Condition="'@(_TopLevelSourceRoot)' != ''">
<!-- TODO: Report error/warning if /pathmap doesn't cover all emitted source paths: https://github.com/dotnet/roslyn/issues/23969 -->
<!-- TODO: PathMap should accept and ignore empty mapping: https://github.com/dotnet/roslyn/issues/23523 -->
<PathMap Condition="'$(PathMap)' != ''">,$(PathMap)</PathMap>
<!--
Prepend the SourceRoot.MappedPath values to PathMap, if it already has a value.
For each emitted source path the compiler applies the first mapping that matches the path.
PathMap values set previously will thus only be applied if the mapping provided by
SourceRoot.MappedPath doesn't match. Since SourceRoot.MappedPath is also used by SourceLink
preferring it over manually set PathMap ensures that PathMap is consistent with SourceLink.
TODO: quote the paths to avoid misinterpreting ',' and '=' in them as separators,
but quoting doesn't currently work (see https://github.com/dotnet/roslyn/issues/22835).
-->
<PathMap>@(_TopLevelSourceRoot->'%(Identity)=%(MappedPath)', ',')$(PathMap)</PathMap>
<PathMap>@(_TopLevelSourceRoot->'%(EscapedKey)=%(EscapedValue)', ','),$(PathMap)</PathMap>
</PropertyGroup>
</Target>
......
......@@ -6,21 +6,24 @@
using System.IO;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.BuildTasks.UnitTests
{
public class DotNetSdkTests : DotNetSdkTestBase
{
[ConditionalFact(typeof(DotNetSdkAvailable))]
[WorkItem(22835, "https://github.com/dotnet/roslyn/issues/22835")]
public void TestSourceLink()
{
var sourcePackageDir = Temp.CreateDirectory();
// TODO: test escaping (https://github.com/dotnet/roslyn/issues/22835): .CreateDirectory("a=b, c");
var sourcePackageDir = Temp.CreateDirectory().CreateDirectory("a=b, c");
var libFile = sourcePackageDir.CreateFile("lib.cs").WriteAllText("class Lib { public void M() { } }");
var root1 = Path.GetFullPath(ProjectDir.Path + "\\");
var root2 = Path.GetFullPath(sourcePackageDir.Path + "\\");
var root1 = Path.GetFullPath(ProjectDir.Path + Path.DirectorySeparatorChar);
var root2 = Path.GetFullPath(sourcePackageDir.Path + Path.DirectorySeparatorChar);
var escapedRoot1 = root1.Replace(",", ",,").Replace("=", "==");
var escapedRoot2 = root2.Replace(",", ",,").Replace("=", "==");
var sourceLinkJsonPath = Path.Combine(ObjDir.Path, ProjectName + ".sourcelink.json");
......@@ -86,7 +89,7 @@ public void TestSourceLink()
$@"{root1}sub1\: /_/sub1/",
$@"{root1}sub2\: /_/sub2/",
"true",
$@"{root2}=/_1/,{root1}=/_/,PreviousPathMap",
$@"{escapedRoot2}=/_1/,{escapedRoot1}=/_/,PreviousPathMap",
"true"
});
......@@ -236,7 +239,7 @@ public void TestSourceLink()
$@"{root1}: /_/",
$@"{root2}: /_1/",
@"true",
$@"{root1}=/_/,{root2}=/_1/"
$@"{escapedRoot1}=/_/,{escapedRoot2}=/_1/,"
});
AssertEx.AssertEqualToleratingWhitespaceDifferences(
......@@ -274,7 +277,7 @@ public void TestSourceLink()
$@"{root1}: /_/",
$@"{root2}: /_1/",
@"true",
$@"{root1}=/_/,{root2}=/_1/"
$@"{escapedRoot1}=/_/,{escapedRoot2}=/_1/,"
});
AssertEx.AssertEqualToleratingWhitespaceDifferences(
......@@ -283,6 +286,48 @@ public void TestSourceLink()
File.ReadAllText(sourceLinkJsonPath));
}
[ConditionalTheory(typeof(DotNetSdkAvailable))]
[CombinatorialData]
[WorkItem(43476, "https://github.com/dotnet/roslyn/issues/43476")]
public void InitializeSourceRootMappedPathsReturnsSourceMap(bool deterministicSourcePaths)
{
ProjectDir.CreateFile("Project2.csproj").WriteAllText($@"
<Project Sdk='Microsoft.NET.Sdk'>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<DeterministicSourcePaths>{deterministicSourcePaths}</DeterministicSourcePaths>
</PropertyGroup>
<ItemGroup>
<SourceRoot Include=""X\""/>
<SourceRoot Include=""Y\"" ContainingRoot=""X\"" NestedRoot=""A""/>
<SourceRoot Include=""Z\"" ContainingRoot=""X\"" NestedRoot=""B""/>
</ItemGroup>
</Project>
");
VerifyValues(
customProps: $@"
<ItemGroup>
<ProjectReference Include=""Project2.csproj"" Targets=""InitializeSourceRootMappedPaths"" OutputItemType=""ReferencedProjectSourceRoots"" ReferenceOutputAssembly=""false"" />
</ItemGroup>
",
customTargets: null,
targets: new[]
{
"ResolveProjectReferences;_BeforeVBCSCoreCompile"
},
expressions: new[]
{
"@(ReferencedProjectSourceRoots)",
},
expectedResults: new[]
{
@"X\",
@"Y\",
@"Z\",
});
}
/// <summary>
/// Validates dependencies of _BeforeVBCSCoreCompile target.
/// </summary>
......
......@@ -261,20 +261,27 @@ internal static bool TryParseOption(string arg, [NotNullWhen(true)] out string?
protected ImmutableArray<KeyValuePair<string, string>> ParsePathMap(string pathMap, IList<Diagnostic> errors)
{
var pathMapBuilder = ArrayBuilder<KeyValuePair<string, string>>.GetInstance();
if (pathMap.IsEmpty())
{
return pathMapBuilder.ToImmutableAndFree();
return ImmutableArray<KeyValuePair<string, string>>.Empty;
}
foreach (var kEqualsV in pathMap.Split(','))
var pathMapBuilder = ArrayBuilder<KeyValuePair<string, string>>.GetInstance();
foreach (var kEqualsV in SplitWithDoubledSeparatorEscaping(pathMap, ','))
{
var kv = kEqualsV.Split('=');
if (kEqualsV.IsEmpty())
{
continue;
}
var kv = SplitWithDoubledSeparatorEscaping(kEqualsV, '=');
if (kv.Length != 2)
{
errors.Add(Diagnostic.Create(_messageProvider, _messageProvider.ERR_InvalidPathMap, kEqualsV));
continue;
}
var from = kv[0];
var to = kv[1];
......@@ -293,6 +300,49 @@ internal static bool TryParseOption(string arg, [NotNullWhen(true)] out string?
return pathMapBuilder.ToImmutableAndFree();
}
/// <summary>
/// Splits specified <paramref name="str"/> on <paramref name="separator"/>
/// treating two consecutive separators as if they were a single non-separating character.
/// E.g. "a,,b,c" split on ',' yields ["a,b", "c"].
/// </summary>
internal static string[] SplitWithDoubledSeparatorEscaping(string str, char separator)
{
if (str.Length == 0)
{
return Array.Empty<string>();
}
var result = ArrayBuilder<string>.GetInstance();
var pooledPart = PooledStringBuilder.GetInstance();
var part = pooledPart.Builder;
int i = 0;
while (i < str.Length)
{
char c = str[i++];
if (c == separator)
{
if (i < str.Length && str[i] == separator)
{
i++;
}
else
{
result.Add(part.ToString());
part.Clear();
continue;
}
}
part.Append(c);
}
result.Add(part.ToString());
pooledPart.Free();
return result.ToArrayAndFree();
}
internal void ParseOutputFile(
string value,
IList<Diagnostic> errors,
......
......@@ -3410,6 +3410,8 @@ print Goodbye, World"
<CompilerTrait(CompilerFeature.Determinism)>
<Fact>
Public Sub PathMapParser()
Dim s = PathUtilities.DirectorySeparatorStr
Dim parsedArgs = DefaultParse({"/pathmap:", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify(
Diagnostic(ERRID.WRN_BadSwitch).WithArguments("/pathmap:").WithLocation(1, 1)
......@@ -3418,23 +3420,28 @@ print Goodbye, World"
parsedArgs = DefaultParse({"/pathmap:K1=V1", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify()
Assert.Equal(KeyValuePairUtil.Create("K1\", "V1\"), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("K1" & s, "V1" & s), parsedArgs.PathMap(0))
parsedArgs = DefaultParse({"/pathmap:C:\goo\=/", "a.vb"}, _baseDirectory)
parsedArgs = DefaultParse({$"/pathmap:abc{s}=/", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify()
Assert.Equal(KeyValuePairUtil.Create("C:\goo\", "/"), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("abc" & s, "/"), parsedArgs.PathMap(0))
parsedArgs = DefaultParse({"/pathmap:K1=V1,K2=V2", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify()
Assert.Equal(KeyValuePairUtil.Create("K1\", "V1\"), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("K2\", "V2\"), parsedArgs.PathMap(1))
Assert.Equal(KeyValuePairUtil.Create("K1" & s, "V1" & s), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("K2" & s, "V2" & s), parsedArgs.PathMap(1))
parsedArgs = DefaultParse({"/pathmap:,", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify()
Assert.Equal(ImmutableArray.Create(Of KeyValuePair(Of String, String))(), parsedArgs.PathMap)
parsedArgs = DefaultParse({"/pathmap:,,", "a.vb"}, _baseDirectory)
Assert.Equal(1, parsedArgs.Errors.Count())
Assert.Equal(ERRID.ERR_InvalidPathMap, parsedArgs.Errors(0).Code)
parsedArgs = DefaultParse({"/pathmap:,,,", "a.vb"}, _baseDirectory)
Assert.Equal(4, parsedArgs.Errors.Count())
Assert.Equal(1, parsedArgs.Errors.Count())
Assert.Equal(ERRID.ERR_InvalidPathMap, parsedArgs.Errors(0).Code)
Assert.Equal(ERRID.ERR_InvalidPathMap, parsedArgs.Errors(1).Code)
Assert.Equal(ERRID.ERR_InvalidPathMap, parsedArgs.Errors(2).Code)
Assert.Equal(ERRID.ERR_InvalidPathMap, parsedArgs.Errors(3).Code)
parsedArgs = DefaultParse({"/pathmap:k=,=v", "a.vb"}, _baseDirectory)
Assert.Equal(2, parsedArgs.Errors.Count())
......@@ -3445,19 +3452,32 @@ print Goodbye, World"
Assert.Equal(1, parsedArgs.Errors.Count())
Assert.Equal(ERRID.ERR_InvalidPathMap, parsedArgs.Errors(0).Code)
parsedArgs = DefaultParse({"/pathmap:k=", "a.vb"}, _baseDirectory)
Assert.Equal(1, parsedArgs.Errors.Count())
Assert.Equal(ERRID.ERR_InvalidPathMap, parsedArgs.Errors(0).Code)
parsedArgs = DefaultParse({"/pathmap:=v", "a.vb"}, _baseDirectory)
Assert.Equal(1, parsedArgs.Errors.Count())
Assert.Equal(ERRID.ERR_InvalidPathMap, parsedArgs.Errors(0).Code)
parsedArgs = DefaultParse({"/pathmap:""supporting spaces=is hard""", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify()
Assert.Equal(KeyValuePairUtil.Create("supporting spaces\", "is hard\"), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("supporting spaces" & s, "is hard" & s), parsedArgs.PathMap(0))
parsedArgs = DefaultParse({"/pathmap:""K 1=V 1"",""K 2=V 2""", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify()
Assert.Equal(KeyValuePairUtil.Create("K 1\", "V 1\"), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("K 2\", "V 2\"), parsedArgs.PathMap(1))
Assert.Equal(KeyValuePairUtil.Create("K 1" & s, "V 1" & s), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("K 2" & s, "V 2" & s), parsedArgs.PathMap(1))
parsedArgs = DefaultParse({"/pathmap:""K 1""=""V 1"",""K 2""=""V 2""", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify()
Assert.Equal(KeyValuePairUtil.Create("K 1\", "V 1\"), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("K 2\", "V 2\"), parsedArgs.PathMap(1))
Assert.Equal(KeyValuePairUtil.Create("K 1" & s, "V 1" & s), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("K 2" & s, "V 2" & s), parsedArgs.PathMap(1))
parsedArgs = DefaultParse({"/pathmap:""a ==,,b""=""1,,== 2"",""x ==,,y""=""3 4"",", "a.vb"}, _baseDirectory)
parsedArgs.Errors.Verify()
Assert.Equal(KeyValuePairUtil.Create("a =,b" & s, "1,= 2" & s), parsedArgs.PathMap(0))
Assert.Equal(KeyValuePairUtil.Create("x =,y" & s, "3 4" & s), parsedArgs.PathMap(1))
End Sub
' PathMapKeepsCrossPlatformRoot and PathMapInconsistentSlashes should be in an
......@@ -3472,7 +3492,7 @@ print Goodbye, World"
<InlineData("/temp/", "C:\temp\", "/temp/", "C:\temp\")>
Public Sub PathMapKeepsCrossPlatformRoot(expectedFrom As String, expectedTo As String, sourceFrom As String, sourceTo As String)
Dim pathmapArg = $"/pathmap:{sourceFrom}={sourceTo}"
Dim parsedArgs = VisualBasicCommandLineParser.Default.Parse({pathmapArg, "a.cs"}, TempRoot.Root, RuntimeEnvironment.GetRuntimeDirectory(), Nothing)
Dim parsedArgs = VisualBasicCommandLineParser.Default.Parse({pathmapArg, "a.vb"}, TempRoot.Root, RuntimeEnvironment.GetRuntimeDirectory(), Nothing)
parsedArgs.Errors.Verify()
Dim expected = New KeyValuePair(Of String, String)(expectedFrom, expectedTo)
Assert.Equal(expected, parsedArgs.PathMap(0))
......@@ -3486,9 +3506,9 @@ print Goodbye, World"
Return parsedArgs
End Function
Dim sep = PathUtilities.DirectorySeparatorChar
Assert.Equal(New KeyValuePair(Of String, String)("C:\temp/goo" + sep, "/temp\goo" + sep), Parse({"/pathmap:C:\temp/goo=/temp\goo", "a.cs"}).PathMap(0))
Assert.Equal(New KeyValuePair(Of String, String)("noslash" + sep, "withoutslash" + sep), Parse({"/pathmap:noslash=withoutslash", "a.cs"}).PathMap(0))
Dim doublemap = Parse({"/pathmap:/temp=/goo,/temp/=/bar", "a.cs"}).PathMap
Assert.Equal(New KeyValuePair(Of String, String)("C:\temp/goo" + sep, "/temp\goo" + sep), Parse({"/pathmap:C:\temp/goo=/temp\goo", "a.vb"}).PathMap(0))
Assert.Equal(New KeyValuePair(Of String, String)("noslash" + sep, "withoutslash" + sep), Parse({"/pathmap:noslash=withoutslash", "a.vb"}).PathMap(0))
Dim doublemap = Parse({"/pathmap:/temp=/goo,/temp/=/bar", "a.vb"}).PathMap
Assert.Equal(New KeyValuePair(Of String, String)("/temp/", "/goo/"), doublemap(0))
Assert.Equal(New KeyValuePair(Of String, String)("/temp/", "/bar/"), doublemap(1))
End Sub
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册