Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port case-sensitivity fixes from main #10104

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public CohostProjectSnapshot(Project project, DocumentSnapshotFactory documentSn

_importsToRelatedDocumentsLazy = new Lazy<ImmutableDictionary<string, ImmutableArray<string>>>(() =>
{
var importsToRelatedDocuments = ImmutableDictionary.Create<string, ImmutableArray<string>>(FilePathNormalizer.Comparer);
var importsToRelatedDocuments = ImmutableDictionary.Create<string, ImmutableArray<string>>(FilePathNormalizingComparer.Instance);
foreach (var document in DocumentFilePaths)
{
var importTargetPaths = ProjectState.GetImportDocumentTargetPaths(document, FileKinds.GetFileKindFromFilePath(document), _lazyProjectEngine.Value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.Razor;
Expand All @@ -14,15 +12,9 @@ namespace Microsoft.AspNetCore.Razor.Utilities;

internal static class FilePathNormalizer
{
private static Lazy<IEqualityComparer<string>> _lazyComparer = new Lazy<IEqualityComparer<string>>(() => new FilePathNormalizingComparer());
public static IEqualityComparer<string> Comparer => _lazyComparer.Value;

private class FilePathNormalizingComparer : IEqualityComparer<string>
{
public bool Equals(string? x, string? y) => FilePathNormalizer.FilePathsEquivalent(x, y);

public int GetHashCode([DisallowNull] string obj) => FilePathNormalizer.GetHashCode(obj);
}
private static readonly Func<char, char> s_charConverter = RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
? c => c
: char.ToLowerInvariant;

public static string NormalizeDirectory(string? directoryFilePath)
{
Expand Down Expand Up @@ -147,7 +139,7 @@ public static int GetHashCode(string filePath)

foreach (var ch in normalizedSpan)
{
hashCombiner.Add(ch);
hashCombiner.Add(s_charConverter(ch));
}

return hashCombiner.CombinedHash;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System.Collections.Generic;

namespace Microsoft.AspNetCore.Razor.Utilities;

internal sealed class FilePathNormalizingComparer : IEqualityComparer<string>
{
public static readonly FilePathNormalizingComparer Instance = new();

private FilePathNormalizingComparer()
{
}

public bool Equals(string? x, string? y) => FilePathNormalizer.FilePathsEquivalent(x, y);

public int GetHashCode(string obj) => FilePathNormalizer.GetHashCode(obj);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public ProjectSnapshot(ProjectState state)
State = state ?? throw new ArgumentNullException(nameof(state));

_lock = new object();
_documents = new Dictionary<string, DocumentSnapshot>(FilePathNormalizer.Comparer);
_documents = new Dictionary<string, DocumentSnapshot>(FilePathNormalizingComparer.Instance);
}

public ProjectKey Key => State.HostProject.Key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ internal class ProjectState
ProjectDifference.DocumentAdded |
ProjectDifference.DocumentRemoved;

private static readonly ImmutableDictionary<string, DocumentState> s_emptyDocuments = ImmutableDictionary.Create<string, DocumentState>(FilePathNormalizer.Comparer);
private static readonly ImmutableDictionary<string, ImmutableArray<string>> s_emptyImportsToRelatedDocuments = ImmutableDictionary.Create<string, ImmutableArray<string>>(FilePathNormalizer.Comparer);
private static readonly ImmutableDictionary<string, DocumentState> s_emptyDocuments = ImmutableDictionary.Create<string, DocumentState>(FilePathNormalizingComparer.Instance);
private static readonly ImmutableDictionary<string, ImmutableArray<string>> s_emptyImportsToRelatedDocuments = ImmutableDictionary.Create<string, ImmutableArray<string>>(FilePathNormalizingComparer.Instance);
private readonly object _lock;

private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider;
Expand Down Expand Up @@ -360,7 +360,7 @@ public ProjectState WithHostProject(HostProject hostProject)
return this;
}

var documents = Documents.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.WithConfigurationChange(), FilePathNormalizer.Comparer);
var documents = Documents.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.WithConfigurationChange(), FilePathNormalizingComparer.Instance);

// If the host project has changed then we need to recompute the imports map
var importsToRelatedDocuments = s_emptyImportsToRelatedDocuments;
Expand Down Expand Up @@ -388,7 +388,7 @@ public ProjectState WithProjectWorkspaceState(ProjectWorkspaceState projectWorks
}

var difference = ProjectDifference.ProjectWorkspaceStateChanged;
var documents = Documents.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.WithProjectWorkspaceStateChange(), FilePathNormalizer.Comparer);
var documents = Documents.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.WithProjectWorkspaceStateChange(), FilePathNormalizingComparer.Instance);
var state = new ProjectState(this, difference, HostProject, projectWorkspaceState, documents, ImportsToRelatedDocuments);
return state;
}
Expand Down Expand Up @@ -448,7 +448,7 @@ internal static List<string> GetImportDocumentTargetPaths(string targetPath, str
{
var itemTargetPath = importItem.FilePath.Replace('/', '\\').TrimStart('\\');

if (FilePathNormalizer.Comparer.Equals(itemTargetPath, targetPath))
if (FilePathNormalizingComparer.Instance.Equals(itemTargetPath, targetPath))
{
// We've normalized the original importItem.FilePath into the HostDocument.TargetPath. For instance, if the HostDocument.TargetPath
// was '/_Imports.razor' it'd be normalized down into '_Imports.razor'. The purpose of this method is to get the associated document
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Utilities;
using Xunit;
Expand Down Expand Up @@ -240,4 +241,22 @@ public void Normalize_ReplacesBackSlashesWithForwardSlashes()
// Assert
Assert.Equal("C:/path/to/document.cshtml", normalized);
}

[OSSkipConditionTheory(["OSX", "Linux"])]
[InlineData(@"C:\path\to\document.cshtml")]
[InlineData(@"c:\path\to\document.cshtml")]
[InlineData("C:/path/to/document.cshtml")]
[InlineData("c:/path/to/document.cshtml")]
public void Comparer_CaseInsensitiveDictionary(string fileName)
{
var dictionary = new Dictionary<string, bool>(FilePathNormalizingComparer.Instance)
{
{ "C:/path/to/document.cshtml", true },
{ "C:/path/to/document1.cshtml", true },
{ "C:/path/to/document2.cshtml", true }
};

Assert.True(dictionary.ContainsKey(fileName));
Assert.True(dictionary.TryGetValue(fileName, out _));
}
}