|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.LanguageService;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Shared.Utilities;
internal static class PathMetadataUtilities
{
private static readonly char[] NamespaceSeparatorArray = ['.'];
/// <summary>
/// Given a set of folders from build the namespace that would match
/// the folder structure. If a document is located in { "Bat" , "Bar", "Baz" } then the namespace could be
/// "Bat.Bar.Baz". If a rootNamespace is provided, it is prepended to the generated namespace.
///
/// Returns null if the folders contain parts that are invalid identifiers for a namespace.
/// </summary>
public static string? TryBuildNamespaceFromFolders(IEnumerable<string> folders, ISyntaxFacts syntaxFacts, string? rootNamespace = null)
{
var parts = folders.SelectMany(folder => folder.Split(NamespaceSeparatorArray)).SelectAsArray(syntaxFacts.EscapeIdentifier);
// The root namespace can come directly from the project file name and/or
// editor config file, so if its not valid we don't want to use it.
if (rootNamespace is { Length: > 0 } &&
!rootNamespace.Split(NamespaceSeparatorArray).All(syntaxFacts.IsValidIdentifier))
{
rootNamespace = null;
}
if (parts.IsDefaultOrEmpty)
{
return rootNamespace;
}
var constructedNamespace = parts.All(syntaxFacts.IsValidIdentifier)
? string.Join(".", parts)
: null;
if (constructedNamespace is null)
{
return null;
}
if (string.IsNullOrEmpty(rootNamespace))
{
return constructedNamespace;
}
return $"{rootNamespace}.{constructedNamespace}";
}
public static ImmutableArray<string> BuildFoldersFromNamespace(string? @namespace, string? rootNamespace = null)
{
if (@namespace is null || @namespace == rootNamespace)
{
return [];
}
if (rootNamespace is not null && @namespace.StartsWith(rootNamespace + ".", StringComparison.OrdinalIgnoreCase))
{
// Add 1 to get rid of the starting "." as well
@namespace = @namespace[(rootNamespace.Length + 1)..];
}
var parts = @namespace.Split(NamespaceSeparatorArray, options: StringSplitOptions.RemoveEmptyEntries);
return [.. parts];
}
}
|