| File: MetadataAsSource\MetadataAsSourceHelpers.cs | Web Access |
| Project: src\roslyn\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features) |
// 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.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.MetadataAsSource; /// <summary> /// Helpers shared by both the text service and the editor service /// </summary> internal sealed class MetadataAsSourceHelpers { #if false public static void ValidateSymbolArgument(ISymbol symbol, string parameterName) { if (symbol == null) { throw new ArgumentNullException(parameterName); } else if (!MetadataAsSourceHelpers.ValidSymbolKinds.Contains(symbol.Kind)) { throw new ArgumentException(FeaturesResources.generating_source_for_symbols_of_this_type_is_not_supported, parameterName); } } #endif public static string GetAssemblyInfo(IAssemblySymbol assemblySymbol) { return string.Format( "{0} {1}", FeaturesResources.Assembly, assemblySymbol.Identity.GetDisplayName()); } public static string GetAssemblyDisplay(Compilation compilation, IAssemblySymbol assemblySymbol) { // This method is only used to generate a comment at the top of Metadata-as-Source documents and // previous submissions are never viewed as metadata (i.e. we always have compilations) so there's no // need to consume compilation.ScriptCompilationInfo.PreviousScriptCompilation. var assemblyReference = compilation.GetMetadataReference(assemblySymbol); return assemblyReference?.Display ?? FeaturesResources.location_unknown; } public static INamedTypeSymbol GetTopLevelContainingNamedType(ISymbol symbol) => TryGetTopLevelContainingNamedType(symbol) ?? throw ExceptionUtilities.UnexpectedValue(symbol); public static INamedTypeSymbol? TryGetTopLevelContainingNamedType(ISymbol symbol) { // Traverse up until we find a named type that is parented by the namespace var topLevelNamedType = symbol; while (topLevelNamedType.ContainingSymbol != symbol.ContainingNamespace || topLevelNamedType.Kind != SymbolKind.NamedType) { topLevelNamedType = topLevelNamedType.ContainingSymbol; if (topLevelNamedType == null) { return null; } } return (INamedTypeSymbol)topLevelNamedType; } public static async Task<Location> GetLocationInGeneratedSourceAsync(SymbolKey symbolId, Document generatedDocument, CancellationToken cancellationToken) { var resolution = symbolId.Resolve( await generatedDocument.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false), ignoreAssemblyKey: true, cancellationToken: cancellationToken); var location = GetFirstSourceLocation(resolution); if (location == null) { // If we cannot find the location of the symbol. Just put the caret at the // beginning of the file. var tree = await generatedDocument.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); location = Location.Create(tree, new TextSpan(0, 0)); } return location; } private static Location? GetFirstSourceLocation(SymbolKeyResolution resolution) { foreach (var symbol in resolution) { foreach (var location in symbol.Locations) { if (location.IsInSource) { return location; } } } return null; } public static bool IsReferenceAssembly(IAssemblySymbol assemblySymbol) { foreach (var attribute in assemblySymbol.GetAttributes()) { if (attribute.AttributeClass?.Name == nameof(ReferenceAssemblyAttribute) && attribute.AttributeClass.ToNameDisplayString() == typeof(ReferenceAssemblyAttribute).FullName) { return true; } } return false; } }