Skip to content

Commit

Permalink
Fix up bugs in parsing special chracters in EditorConfig (#54511)
Browse files Browse the repository at this point in the history
* Fix up bugs in parsing special chracters in EditorConfig

* Address feedback from peer review

* Update tests, clean  lexer logic, update method mdoifiers

* Fix method modifier
  • Loading branch information
captainsafia authored Jul 25, 2021
1 parent 0574a33 commit dc25977
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,28 @@ public void ConfigWithEscapedValues()
);
}

[Fact]
[WorkItem(52469, "https://github.com/dotnet/roslyn/issues/52469")]
public void CanGetSectionsWithSpecialCharacters()
{
var config = ParseConfigFile(@"is_global = true
[/home/foo/src/\{releaseid\}.cs]
build_metadata.Compile.ToRetrieve = abc123
[/home/foo/src/Pages/\#foo/HomePage.cs]
build_metadata.Compile.ToRetrieve = def456
");

var set = AnalyzerConfigSet.Create(ImmutableArray.Create(config));

var sectionOptions = set.GetOptionsForSourcePath("/home/foo/src/{releaseid}.cs");
Assert.Equal("abc123", sectionOptions.AnalyzerOptions["build_metadata.compile.toretrieve"]);

sectionOptions = set.GetOptionsForSourcePath("/home/foo/src/Pages/#foo/HomePage.cs");
Assert.Equal("def456", sectionOptions.AnalyzerOptions["build_metadata.compile.toretrieve"]);
}

[ConditionalFact(typeof(WindowsOnly))]
public void WindowsPath()
{
Expand Down
34 changes: 33 additions & 1 deletion src/Compilers/Core/MSBuildTask/GenerateMSBuildEditorConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
Expand Down Expand Up @@ -38,6 +39,10 @@ namespace Microsoft.CodeAnalysis.BuildTasks
/// </remarks>
public sealed class GenerateMSBuildEditorConfig : Task
{
/// <remarks>
/// Although this task does its own writing to disk, this
/// output parameter is here for testing purposes.
/// </remarks>
[Output]
public string ConfigFileContents { get; set; }

Expand All @@ -47,11 +52,14 @@ public sealed class GenerateMSBuildEditorConfig : Task
[Required]
public ITaskItem[] PropertyItems { get; set; }

public ITaskItem FileName { get; set; }

public GenerateMSBuildEditorConfig()
{
ConfigFileContents = string.Empty;
MetadataItems = Array.Empty<ITaskItem>();
PropertyItems = Array.Empty<ITaskItem>();
FileName = new TaskItem();
}

public override bool Execute()
Expand Down Expand Up @@ -98,7 +106,31 @@ public override bool Execute()
}

ConfigFileContents = builder.ToString();
return true;
return string.IsNullOrEmpty(FileName.ItemSpec) ? true : WriteMSBuildEditorConfig();
}

internal bool WriteMSBuildEditorConfig()
{
try
{
var targetFileName = FileName.ItemSpec;
if (File.Exists(targetFileName))
{
string existingContents = File.ReadAllText(targetFileName);
if (existingContents.Equals(ConfigFileContents))
{
return true;
}
}
var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
File.WriteAllText(targetFileName, ConfigFileContents, encoding);
return true;
}
catch (IOException ex)
{
Log.LogErrorFromException(ex);
return false;
}
}

/// <remarks>
Expand Down
8 changes: 2 additions & 6 deletions src/Compilers/Core/MSBuildTask/Microsoft.Managed.Core.targets
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,10 @@
<!-- Transform the collected properties and items into an editor config file -->
<GenerateMSBuildEditorConfig
PropertyItems="@(_GeneratedEditorConfigProperty)"
MetadataItems="@(_GeneratedEditorConfigMetadata)">

<Output TaskParameter="ConfigFileContents"
PropertyName="_GeneratedEditorConfigFileContent" />
MetadataItems="@(_GeneratedEditorConfigMetadata)"
FileName="$(GeneratedMSBuildEditorConfigFile)">
</GenerateMSBuildEditorConfig>

<!-- Write the output to the generated file, if it's changed -->
<WriteLinesToFile Lines="$(_GeneratedEditorConfigFileContent)" File="$(GeneratedMSBuildEditorConfigFile)" Overwrite="True" WriteOnlyWhenDifferent="True" />
</Target>

<!--
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;

Expand Down Expand Up @@ -351,5 +353,30 @@ public void ItemMetadataPathIsAdjustedOnWindows()
build_metadata.Compile.ToRetrieve = abc123
", result);
}

[Fact]
public void ConfigFileCanBeWrittenToDisk()
{
ITaskItem property1 = MSBuildUtil.CreateTaskItem("Property1", new Dictionary<string, string> { { "Value", "abc123" } });
ITaskItem property2 = MSBuildUtil.CreateTaskItem("Property2", new Dictionary<string, string> { { "Value", "def456" } });

var fileName = Path.Combine(TempRoot.Root, "ConfigFileCanBeWrittenToDisk.GenerateMSBuildEditorConfig.editorconfig");

GenerateMSBuildEditorConfig configTask = new GenerateMSBuildEditorConfig()
{
PropertyItems = new[] { property1, property2 },
FileName = new TaskItem(fileName)
};
configTask.Execute();

var expectedContents = @"is_global = true
build_property.Property1 = abc123
build_property.Property2 = def456
";

Assert.True(File.Exists(fileName));
Assert.True(configTask.WriteMSBuildEditorConfig());
Assert.Equal(expectedContents, File.ReadAllText(fileName));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,22 @@ public bool IsMatch(string s)
numberRangePairs.ToImmutableAndFree());
}

internal static bool TryUnescapeSectionName(string sectionName, out string? escapedSectionName)
{
var sb = new StringBuilder();
SectionNameLexer lexer = new SectionNameLexer(sectionName);
while (!lexer.IsDone)
{
var tokenKind = lexer.Lex();
if (tokenKind == TokenKind.SimpleCharacter)
{
sb.Append(lexer.EatCurrentCharacter());
}
}
escapedSectionName = sb.ToString();
return true;
}

/// <summary>
/// Test if a section name is an absolute path with no special chars
/// </summary>
Expand Down
3 changes: 2 additions & 1 deletion src/Compilers/Core/Portable/CommandLine/AnalyzerConfigSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ public AnalyzerConfigOptionsResult GetOptionsForSourcePath(string sourcePath)
// If we have a global config, add any sections that match the full path
foreach (var section in _globalConfig.NamedSections)
{
if (normalizedPath.Equals(section.Name, Section.NameComparer))
var escapedSectionName = TryUnescapeSectionName(section.Name, out var sectionName);
if (escapedSectionName && normalizedPath.Equals(sectionName, Section.NameComparer))
{
sectionKey.Add(section);
}
Expand Down

0 comments on commit dc25977

Please sign in to comment.