|
// 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.Collections.Immutable;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis;
/// <summary>
/// Represents the set of symbols that are imported to a particular position in a source file. Each import has a
/// reference to the location the import directive was declared at. For the <see cref="IAliasSymbol"/> import, the
/// location can be found using either <see cref="ISymbol.Locations"/> or <see
/// cref="ISymbol.DeclaringSyntaxReferences"/> on the <see cref="IAliasSymbol"/> itself. For <see cref="Imports"/>
/// or <see cref="XmlNamespaces"/> the location is found through <see
/// cref="ImportedNamespaceOrType.DeclaringSyntaxReference"/> or <see
/// cref="ImportedXmlNamespace.DeclaringSyntaxReference"/> respectively.
/// </summary>
/// <remarks>
/// <list type="bullet">
/// <item>Scopes returned will always have at least one non-empty property value in them.</item>
/// <item>Symbols may be imported, but may not necessarily be available at that location (for example, an alias
/// symbol hidden by another symbol).</item>
/// <item>
/// In C# there will be an <see cref="IImportScope"/> for every containing namespace-declarations that include any
/// import directives. There will also be an <see cref="IImportScope"/> for the containing compilation-unit if it
/// includes any import directives or if there are global import directives pulled in from other files.
/// </item>
/// <item>
/// In Visual Basic there will commonly be one or two <see cref="IImportScope"/>s returned for any position. This will
/// commonly be a scope for the containing compilation unit if it includes any import directives. As well as a scope
/// representing any imports specified at the project level.
/// </item>
/// <item>
/// Elements of any property have no defined order. Even if they represent items from a single document, they are
/// not guaranteed to be returned in any specific file-oriented order.
/// </item>
/// <item>There is no guarantee that the same scope instances will be returned from successive calls to <see
/// cref="SemanticModel.GetImportScopes"/>.</item>
/// </list>
/// </remarks>
public interface IImportScope
{
/// <summary>
/// Aliases defined at this level of the chain. This corresponds to <c>using X = TypeOrNamespace;</c> in C# or
/// <c>Imports X = TypeOrNamespace</c> in Visual Basic. This will include global aliases if present for both
/// languages.
/// </summary>
/// <remarks>May be <see cref="ImmutableArray{T}.Empty"/>, will never be <see cref="ImmutableArray{T}.IsDefault"/>.</remarks>
ImmutableArray<IAliasSymbol> Aliases { get; }
/// <summary>
/// Extern aliases defined at this level of the chain. This corresponds to <c>extern alias X;</c> in C#. It
/// will be empty in Visual Basic.
/// </summary>
/// <remarks>May be <see cref="ImmutableArray{T}.Empty"/>, will never be <see cref="ImmutableArray{T}.IsDefault"/>.</remarks>
ImmutableArray<IAliasSymbol> ExternAliases { get; }
/// <summary>
/// Types or namespaces imported at this level of the chain. This corresponds to <c>using Namespace;</c> or
/// <c>using static Type;</c> in C#, or <c>Imports TypeOrNamespace</c> in Visual Basic. This will include
/// global namespace or type imports for both languages.
/// </summary>
/// <remarks>May be <see cref="ImmutableArray{T}.Empty"/>, will never be <see cref="ImmutableArray{T}.IsDefault"/>.</remarks>
ImmutableArray<ImportedNamespaceOrType> Imports { get; }
/// <summary>
/// Xml namespaces imported at this level of the chain. This corresponds to <c>Imports <xmlns:prefix =
/// "name"></c> in Visual Basic. It will be empty in C#.
/// </summary>
/// <remarks>May be <see cref="ImmutableArray{T}.Empty"/>, will never be <see cref="ImmutableArray{T}.IsDefault"/>.</remarks>
ImmutableArray<ImportedXmlNamespace> XmlNamespaces { get; }
}
/// <summary>
/// Represents an <see cref="INamespaceOrTypeSymbol"/> that has been imported, and the location the import was
/// declared at. This corresponds to <c>using Namespace;</c> or <c>using static Type;</c> in C#, or <c>Imports
/// TypeOrNamespace</c> in Visual Basic.
/// </summary>
public readonly struct ImportedNamespaceOrType
{
public INamespaceOrTypeSymbol NamespaceOrType { get; }
#pragma warning disable CA1200 // Avoid using cref tags with a prefix
/// <summary>
/// Location in source where the <c>using</c> directive or <c>Imports</c> clause was declared. May be null for
/// Visual Basic for a project-level import directive, or for a C# global using provided directly through <see
/// cref="P:Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions.Usings"/>.
/// </summary>
public SyntaxReference? DeclaringSyntaxReference { get; }
#pragma warning restore CA1200 // Avoid using cref tags with a prefix
internal ImportedNamespaceOrType(INamespaceOrTypeSymbol namespaceOrType, SyntaxReference? declaringSyntaxReference)
{
NamespaceOrType = namespaceOrType;
DeclaringSyntaxReference = declaringSyntaxReference;
}
}
/// <summary>
/// Represents an imported xml namespace name. This corresponds to <c>Imports <xmlns:prefix = "name"></c> in
/// Visual Basic. It does not exist for C#.
/// </summary>
public readonly struct ImportedXmlNamespace
{
public string XmlNamespace { get; }
/// <summary>
/// Location in source where the <c>Imports</c> clause was declared. May be null for a project-level import
/// directive.
/// </summary>
public SyntaxReference? DeclaringSyntaxReference { get; }
internal ImportedXmlNamespace(string xmlNamespace, SyntaxReference? declaringSyntaxReference)
{
XmlNamespace = xmlNamespace;
DeclaringSyntaxReference = declaringSyntaxReference;
}
}
/// <summary>
/// Simple POCO implementation of the import scope, usable by both C# and VB.
/// </summary>
internal sealed class SimpleImportScope : IImportScope
{
public SimpleImportScope(
ImmutableArray<IAliasSymbol> aliases,
ImmutableArray<IAliasSymbol> externAliases,
ImmutableArray<ImportedNamespaceOrType> imports,
ImmutableArray<ImportedXmlNamespace> xmlNamespaces)
{
Debug.Assert(!aliases.IsDefault);
Debug.Assert(!externAliases.IsDefault);
Debug.Assert(!imports.IsDefault);
Debug.Assert(!xmlNamespaces.IsDefault);
Debug.Assert(aliases.Length + externAliases.Length + imports.Length + xmlNamespaces.Length > 0);
// We make no guarantees about order of these arrays. So intentionally reorder them in debug to help find any
// cases where code may be depending on a particular order.
Aliases = aliases.ConditionallyDeOrder();
ExternAliases = externAliases.ConditionallyDeOrder();
Imports = imports.ConditionallyDeOrder();
XmlNamespaces = xmlNamespaces.ConditionallyDeOrder();
}
public ImmutableArray<IAliasSymbol> Aliases { get; }
public ImmutableArray<IAliasSymbol> ExternAliases { get; }
public ImmutableArray<ImportedNamespaceOrType> Imports { get; }
public ImmutableArray<ImportedXmlNamespace> XmlNamespaces { get; }
}
|