File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\Utilities\PathMetadataUtilities.cs
Web Access
Project: src\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// 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];
    }
}