Skip to content

Commit

Permalink
Fix up bugs in parsing special chracters in EditorConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
captainsafia committed Jul 1, 2021
1 parent 1b9f72f commit 2455390
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 11 deletions.
47 changes: 46 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,15 @@ public sealed class GenerateMSBuildEditorConfig : Task
[Required]
public ITaskItem[] PropertyItems { get; set; }

[Required]
public ITaskItem File { get; set; }

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

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

ConfigFileContents = builder.ToString();
return true;
return WriteMSBuildEditorConfig();
}

public bool WriteMSBuildEditorConfig()
{
try
{
var directoryPath = Path.GetDirectoryName(NormalizeWithForwardSlash(File.ItemSpec));
Directory.CreateDirectory(directoryPath);
try
{
if (System.IO.File.Exists(File.ItemSpec))
{
string existingContents = System.IO.File.ReadAllText(File.ItemSpec);
if (existingContents.Length == ConfigFileContents.Length)
{
if (existingContents.Equals(ConfigFileContents))
{
return true;
}
}
}
}
catch (IOException ex)
{
Log.LogErrorFromException(ex);
}

var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
System.IO.File.WriteAllText(File.ItemSpec, ConfigFileContents, encoding);
return true;
}
catch (Exception 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)"
File="$(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 @@ -114,15 +114,35 @@ public bool IsMatch(string s)
numberRangePairs.ToImmutableAndFree());
}

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

/// <summary>
/// Test if a section name is an absolute path with no special chars
/// Test if a section name is an absolute path
/// </summary>
internal static bool IsAbsoluteEditorConfigPath(string sectionName)
{
// NOTE: editorconfig paths must use '/' as a directory separator character on all OS.

// on all unix systems this is thus a simple test: does the path start with '/'
// and contain no special chars?

// on windows, a path can be either drive rooted or not (e.g. start with 'c:' or just '')
// in addition to being absolute or relative.
Expand All @@ -147,7 +167,7 @@ internal static bool IsAbsoluteEditorConfigPath(string sectionName)
int logicalIndex = 0;
while (!nameLexer.IsDone)
{
if (nameLexer.Lex() != TokenKind.SimpleCharacter)
if (nameLexer.Lex() == TokenKind.BadToken)
{
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Compilers/Core/Portable/CommandLine/AnalyzerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ public static AnalyzerConfig Parse(SourceText text, string? pathToFile)
{
addNewSection();

var sectionName = sectionMatches[0].Groups[1].Value;
var escapedSectionName = TryUnescapeSectionName(sectionMatches[0].Groups[1].Value, out var sectionName);
Debug.Assert(escapedSectionName == true);
Debug.Assert(!string.IsNullOrEmpty(sectionName));

activeSectionName = sectionName;
Expand Down

0 comments on commit 2455390

Please sign in to comment.