|
@@ -1,452 +0,0 @@
|
|
|
-using System;
|
|
|
-using System.Diagnostics.CodeAnalysis;
|
|
|
-using System.Text;
|
|
|
-using System.Threading;
|
|
|
-using Microsoft.CodeAnalysis;
|
|
|
-using Microsoft.CodeAnalysis.Text;
|
|
|
-using Terminal.Gui.Analyzers.Internal.Attributes;
|
|
|
-using Terminal.Gui.Analyzers.Internal.Constants;
|
|
|
-
|
|
|
-namespace Terminal.Gui.Analyzers.Internal.Generators.EnumExtensions;
|
|
|
-
|
|
|
-/// <summary>
|
|
|
-/// Incremental code generator for enums decorated with <see cref="GenerateEnumExtensionMethodsAttribute"/>.
|
|
|
-/// </summary>
|
|
|
-[SuppressMessage ("CodeQuality", "IDE0079", Justification = "Suppressions here are intentional and the warnings they disable are just noise.")]
|
|
|
-[Generator (LanguageNames.CSharp)]
|
|
|
-public sealed class EnumExtensionMethodsIncrementalGenerator : IIncrementalGenerator
|
|
|
-{
|
|
|
- private const string ExtensionsForEnumTypeAttributeFullyQualifiedName = $"{Strings.AnalyzersAttributesNamespace}.{ExtensionsForEnumTypeAttributeName}";
|
|
|
- private const string ExtensionsForEnumTypeAttributeName = "ExtensionsForEnumTypeAttribute";
|
|
|
- private const string GeneratorAttributeFullyQualifiedName = $"{Strings.AnalyzersAttributesNamespace}.{GeneratorAttributeName}";
|
|
|
- private const string GeneratorAttributeName = nameof (GenerateEnumExtensionMethodsAttribute);
|
|
|
-
|
|
|
- /// <summary>Fully-qualified symbol name format without the "global::" prefix.</summary>
|
|
|
- private static readonly SymbolDisplayFormat _fullyQualifiedSymbolDisplayFormatWithoutGlobal =
|
|
|
- SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle (SymbolDisplayGlobalNamespaceStyle.Omitted);
|
|
|
-
|
|
|
- /// <inheritdoc/>
|
|
|
- /// <remarks>
|
|
|
- /// <para>
|
|
|
- /// Basically, this method is called once by the compiler, and is responsible for wiring up
|
|
|
- /// everything important about how source generation works.
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// See in-line comments for specifics of what's going on.
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// Note that <paramref name="context"/> is everything in the compilation,
|
|
|
- /// except for code generated by this generator or generators which have not yet executed.<br/>
|
|
|
- /// The methods registered to perform generation get called on-demand by the host (the IDE,
|
|
|
- /// compiler, etc), sometimes as often as every single keystroke.
|
|
|
- /// </para>
|
|
|
- /// </remarks>
|
|
|
- public void Initialize (IncrementalGeneratorInitializationContext context)
|
|
|
- {
|
|
|
- // Write out namespaces that may be used later. Harmless to declare them now and will avoid
|
|
|
- // additional processing and potential omissions later on.
|
|
|
- context.RegisterPostInitializationOutput (GenerateDummyNamespaces);
|
|
|
-
|
|
|
- // This executes the delegate given to it immediately after Roslyn gets all set up.
|
|
|
- //
|
|
|
- // As written, this will result in the GenerateEnumExtensionMethodsAttribute code
|
|
|
- // being added to the environment, so that it can be used without having to actually
|
|
|
- // be declared explicitly in the target project.
|
|
|
- // This is important, as it guarantees the type will exist and also guarantees it is
|
|
|
- // defined exactly as the generator expects it to be defined.
|
|
|
- context.RegisterPostInitializationOutput (GenerateAttributeSources);
|
|
|
-
|
|
|
- // Next up, we define our pipeline.
|
|
|
- // To do so, we create one or more IncrementalValuesProvider<T> objects, each of which
|
|
|
- // defines on stage of analysis or generation as needed.
|
|
|
- //
|
|
|
- // Critically, these must be as fast and efficient as reasonably possible because,
|
|
|
- // once the pipeline is registered, this stuff can get called A LOT.
|
|
|
- //
|
|
|
- // Note that declaring these doesn't really do much of anything unless they are given to the
|
|
|
- // RegisterSourceOutput method at the end of this method.
|
|
|
- //
|
|
|
- // The delegates are not actually evaluated right here. That is triggered by changes being
|
|
|
- // made to the source code.
|
|
|
-
|
|
|
- // This provider grabs attributes that pass our filter and then creates lightweight
|
|
|
- // metadata objects to be used in the final code generation step.
|
|
|
- // It also preemptively removes any nulls from the collection before handing things off
|
|
|
- // to the code generation logic.
|
|
|
- IncrementalValuesProvider<EnumExtensionMethodsGenerationInfo?> enumGenerationInfos =
|
|
|
- context
|
|
|
- .SyntaxProvider
|
|
|
-
|
|
|
- // This method is a highly-optimized (and highly-recommended) filter on the incoming
|
|
|
- // code elements that only bothers to present code that is annotated with the specified
|
|
|
- // attribute, by its fully-qualified name, as a string, which is the first parameter.
|
|
|
- //
|
|
|
- // Two delegates are passed to it, in the second and third parameters.
|
|
|
- //
|
|
|
- // The second parameter is a filter predicate taking each SyntaxNode that passes the
|
|
|
- // name filter above, and then refines that result.
|
|
|
- //
|
|
|
- // It is critical that the filter predicate be as simple and fast as possible, as it
|
|
|
- // will be called a ton, triggered by keystrokes or anything else that modifies code
|
|
|
- // in or even related to (in either direction) the pre-filtered code.
|
|
|
- // It should collect metadata only and not actually generate any code.
|
|
|
- // It must return a boolean indicating whether the supplied SyntaxNode should be
|
|
|
- // given to the transform delegate at all.
|
|
|
- //
|
|
|
- // The third parameter is the "transform" delegate.
|
|
|
- // That one only runs when code is changed that passed both the attribute name filter
|
|
|
- // and the filter predicate in the second parameter.
|
|
|
- // It will be called for everything that passes both of those, so it can still happen
|
|
|
- // a lot, but should at least be pretty close.
|
|
|
- // In our case, it should be 100% accurate, since we're using OUR attribute, which can
|
|
|
- // only be applied to enum types in the first place.
|
|
|
- //
|
|
|
- // That delegate is responsible for creating some sort of lightweight data structure
|
|
|
- // which can later be used to generate the actual source code for output.
|
|
|
- //
|
|
|
- // THIS DELEGATE DOES NOT GENERATE CODE!
|
|
|
- // However, it does need to return instances of the metadata class in use that are either
|
|
|
- // null or complete enough to generate meaningful code from, later on.
|
|
|
- //
|
|
|
- // We then filter out any that were null with the .Where call at the end, so that we don't
|
|
|
- // know or care about them when it's time to generate code.
|
|
|
- //
|
|
|
- // While the syntax of that .Where call is the same as LINQ, that is actually a
|
|
|
- // highly-optimized implementation specifically for this use.
|
|
|
- .ForAttributeWithMetadataName (
|
|
|
- GeneratorAttributeFullyQualifiedName,
|
|
|
- IsPotentiallyInterestingDeclaration,
|
|
|
- GatherMetadataForCodeGeneration
|
|
|
- )
|
|
|
- .WithTrackingName ("CollectEnumMetadata")
|
|
|
- .Where (static eInfo => eInfo is { });
|
|
|
-
|
|
|
- // Finally, we wire up any IncrementalValuesProvider<T> instances above to the appropriate
|
|
|
- // delegate that takes the SourceProductionContext that is current at run-time and an instance of
|
|
|
- // our metadata type and takes appropriate action.
|
|
|
- // Typically that means generating code from that metadata and adding it to the compilation via
|
|
|
- // the received context object.
|
|
|
- //
|
|
|
- // As with everything else , the delegate will be invoked once for each item that passed
|
|
|
- // all of the filters above, so we get to write that method from the perspective of a single
|
|
|
- // enum type declaration.
|
|
|
-
|
|
|
- context.RegisterSourceOutput (enumGenerationInfos, GenerateSourceFromGenerationInfo);
|
|
|
- }
|
|
|
-
|
|
|
- private static EnumExtensionMethodsGenerationInfo? GatherMetadataForCodeGeneration (
|
|
|
- GeneratorAttributeSyntaxContext context,
|
|
|
- CancellationToken cancellationToken
|
|
|
- )
|
|
|
- {
|
|
|
- var cts = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken);
|
|
|
- cancellationToken.ThrowIfCancellationRequested ();
|
|
|
-
|
|
|
- // If it's not an enum symbol, we don't care.
|
|
|
- // EnumUnderlyingType is null for non-enums, so this validates it's an enum declaration.
|
|
|
- if (context.TargetSymbol is not INamedTypeSymbol { EnumUnderlyingType: { } } namedSymbol)
|
|
|
- {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- INamespaceSymbol? enumNamespaceSymbol = namedSymbol.ContainingNamespace;
|
|
|
-
|
|
|
- if (enumNamespaceSymbol is null or { IsGlobalNamespace: true })
|
|
|
- {
|
|
|
- // Explicitly choosing not to support enums in the global namespace.
|
|
|
- // The corresponding analyzer will report this.
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- string enumName = namedSymbol.Name;
|
|
|
-
|
|
|
- string enumNamespace = enumNamespaceSymbol.ToDisplayString (_fullyQualifiedSymbolDisplayFormatWithoutGlobal);
|
|
|
-
|
|
|
- TypeCode enumTypeCode = namedSymbol.EnumUnderlyingType.Name switch
|
|
|
- {
|
|
|
- "UInt32" => TypeCode.UInt32,
|
|
|
- "Int32" => TypeCode.Int32,
|
|
|
- _ => TypeCode.Empty
|
|
|
- };
|
|
|
-
|
|
|
- EnumExtensionMethodsGenerationInfo info = new (
|
|
|
- enumNamespace,
|
|
|
- enumName,
|
|
|
- enumTypeCode
|
|
|
- );
|
|
|
-
|
|
|
- if (!info.TryConfigure (namedSymbol, cts.Token))
|
|
|
- {
|
|
|
- cts.Cancel ();
|
|
|
- cts.Token.ThrowIfCancellationRequested ();
|
|
|
- }
|
|
|
-
|
|
|
- return info;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- private static void GenerateAttributeSources (IncrementalGeneratorPostInitializationContext postInitializationContext)
|
|
|
- {
|
|
|
- postInitializationContext
|
|
|
- .AddSource (
|
|
|
- $"{nameof (IExtensionsForEnumTypeAttributes)}.g.cs",
|
|
|
- SourceText.From (
|
|
|
- $$"""
|
|
|
- // ReSharper disable All
|
|
|
- {{Strings.Templates.AutoGeneratedCommentBlock}}
|
|
|
- using System;
|
|
|
-
|
|
|
- namespace {{Strings.AnalyzersAttributesNamespace}};
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Interface to simplify general enumeration of constructed generic types for
|
|
|
- /// <see cref="ExtensionsForEnumTypeAttribute{TEnum}"/>
|
|
|
- /// </summary>
|
|
|
- {{Strings.Templates.AttributesForGeneratedInterfaces}}
|
|
|
- public interface IExtensionsForEnumTypeAttributes
|
|
|
- {
|
|
|
- System.Type EnumType { get; }
|
|
|
- }
|
|
|
-
|
|
|
- """,
|
|
|
- Encoding.UTF8));
|
|
|
-
|
|
|
- postInitializationContext
|
|
|
- .AddSource (
|
|
|
- $"{nameof (AssemblyExtendedEnumTypeAttribute)}.g.cs",
|
|
|
- SourceText.From (
|
|
|
- $$"""
|
|
|
- // ReSharper disable All
|
|
|
- #nullable enable
|
|
|
- {{Strings.Templates.AutoGeneratedCommentBlock}}
|
|
|
-
|
|
|
- namespace {{Strings.AnalyzersAttributesNamespace}};
|
|
|
-
|
|
|
- /// <summary>Assembly attribute declaring a known pairing of an <see langword="enum" /> type to an extension class.</summary>
|
|
|
- /// <remarks>This attribute should only be written by internal source generators for Terminal.Gui. No other usage of any kind is supported.</remarks>
|
|
|
- {{Strings.Templates.AttributesForGeneratedTypes}}
|
|
|
- [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true)]
|
|
|
- public sealed class {{nameof(AssemblyExtendedEnumTypeAttribute)}} : System.Attribute
|
|
|
- {
|
|
|
- /// <summary>Creates a new instance of <see cref="AssemblyExtendedEnumTypeAttribute" /> from the provided parameters.</summary>
|
|
|
- /// <param name="enumType">The <see cref="System.Type" /> of an <see langword="enum" /> decorated with a <see cref="GenerateEnumExtensionMethodsAttribute" />.</param>
|
|
|
- /// <param name="extensionClass">The <see cref="System.Type" /> of the <see langword="class" /> decorated with an <see cref="ExtensionsForEnumTypeAttribute{TEnum}" /> referring to the same type as <paramref name="enumType" />.</param>
|
|
|
- public AssemblyExtendedEnumTypeAttribute (System.Type enumType, System.Type extensionClass)
|
|
|
- {
|
|
|
- EnumType = enumType;
|
|
|
- ExtensionClass = extensionClass;
|
|
|
- }
|
|
|
- /// <summary>An <see langword="enum" /> type that has been extended by Terminal.Gui source generators.</summary>
|
|
|
- public System.Type EnumType { get; init; }
|
|
|
- /// <summary>A class containing extension methods for <see cref="EnumType"/>.</summary>
|
|
|
- public System.Type ExtensionClass { get; init; }
|
|
|
- /// <inheritdoc />
|
|
|
- public override string ToString () => $"{EnumType.Name},{ExtensionClass.Name}";
|
|
|
- }
|
|
|
-
|
|
|
- """,
|
|
|
- Encoding.UTF8));
|
|
|
-
|
|
|
- postInitializationContext
|
|
|
- .AddSource (
|
|
|
- $"{GeneratorAttributeFullyQualifiedName}.g.cs",
|
|
|
- SourceText.From (
|
|
|
- $$"""
|
|
|
- {{Strings.Templates.StandardHeader}}
|
|
|
-
|
|
|
- namespace {{Strings.AnalyzersAttributesNamespace}};
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Used to enable source generation of a common set of extension methods for enum types.
|
|
|
- /// </summary>
|
|
|
- {{Strings.Templates.AttributesForGeneratedTypes}}
|
|
|
- [{{Strings.DotnetNames.Types.AttributeUsageAttribute}} ({{Strings.DotnetNames.Types.AttributeTargets}}.Enum)]
|
|
|
- public sealed class {{GeneratorAttributeName}} : {{Strings.DotnetNames.Types.Attribute}}
|
|
|
- {
|
|
|
- /// <summary>
|
|
|
- /// The name of the generated static class.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// If unspecified, null, empty, or only whitespace, defaults to the name of the enum plus "Extensions".<br/>
|
|
|
- /// No other validation is performed, so illegal values will simply result in compiler errors.
|
|
|
- /// <para>
|
|
|
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
|
|
|
- /// </para>
|
|
|
- /// </remarks>
|
|
|
- public string? ClassName { get; set; }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// The namespace in which to place the generated static class containing the extension methods.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// If unspecified, null, empty, or only whitespace, defaults to the namespace of the enum.<br/>
|
|
|
- /// No other validation is performed, so illegal values will simply result in compiler errors.
|
|
|
- /// <para>
|
|
|
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
|
|
|
- /// </para>
|
|
|
- /// </remarks>
|
|
|
- public string? ClassNamespace { get; set; }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Whether to generate a fast, zero-allocation, non-boxing, and reflection-free alternative to the built-in
|
|
|
- /// <see cref="Enum.HasFlag"/> method.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// <para>
|
|
|
- /// Default: false
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// If the enum is not decorated with <see cref="Flags"/>, this option has no effect.
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// If multiple members have the same value, the first member with that value will be used and subsequent members
|
|
|
- /// with the same value will be skipped.
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// Overloads taking the enum type itself as well as the underlying type of the enum will be generated, enabling
|
|
|
- /// avoidance of implicit or explicit cast overhead.
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
|
|
|
- /// </para>
|
|
|
- /// </remarks>
|
|
|
- public bool FastHasFlags { get; set; }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Whether to generate a fast, zero-allocation, and reflection-free alternative to the built-in
|
|
|
- /// <see cref="Enum.IsDefined"/> method,
|
|
|
- /// using a switch expression as a hard-coded reverse mapping of numeric values to explicitly-named members.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// <para>
|
|
|
- /// Default: true
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// If multiple members have the same value, the first member with that value will be used and subsequent members
|
|
|
- /// with the same value will be skipped.
|
|
|
- /// </para>
|
|
|
- /// <para>
|
|
|
- /// As with <see cref="Enum.IsDefined"/> the source generator only considers explicitly-named members.<br/>
|
|
|
- /// Generation of values which represent valid bitwise combinations of members of enums decorated with
|
|
|
- /// <see cref="Flags"/> is not affected by this property.
|
|
|
- /// </para>
|
|
|
- /// </remarks>
|
|
|
- public bool FastIsDefined { get; init; } = true;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Gets a <see langword="bool"/> value indicating if this <see cref="GenerateEnumExtensionMethodsAttribute"/> instance
|
|
|
- /// contains default values only. See <see href="#remarks">remarks</see> of this method or documentation on properties of this type for details.
|
|
|
- /// </summary>
|
|
|
- /// <returns>
|
|
|
- /// A <see langword="bool"/> value indicating if all property values are default for this
|
|
|
- /// <see cref="GenerateEnumExtensionMethodsAttribute"/> instance.
|
|
|
- /// </returns>
|
|
|
- /// <remarks>
|
|
|
- /// Default values that will result in a <see langword="true"/> return value are:<br/>
|
|
|
- /// <see cref="FastIsDefined"/> && !<see cref="FastHasFlags"/> && <see cref="ClassName"/>
|
|
|
- /// <see langword="is"/> <see langword="null"/> && <see cref="ClassNamespace"/> <see langword="is"/>
|
|
|
- /// <see langword="null"/>
|
|
|
- /// </remarks>
|
|
|
- public override bool IsDefaultAttribute ()
|
|
|
- {
|
|
|
- return FastIsDefined
|
|
|
- && !FastHasFlags
|
|
|
- && ClassName is null
|
|
|
- && ClassNamespace is null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- """,
|
|
|
- Encoding.UTF8));
|
|
|
-
|
|
|
- postInitializationContext
|
|
|
- .AddSource (
|
|
|
- $"{ExtensionsForEnumTypeAttributeFullyQualifiedName}.g.cs",
|
|
|
- SourceText.From (
|
|
|
- $$"""
|
|
|
- // ReSharper disable RedundantNameQualifier
|
|
|
- // ReSharper disable RedundantNullableDirective
|
|
|
- // ReSharper disable UnusedType.Global
|
|
|
- {{Strings.Templates.AutoGeneratedCommentBlock}}
|
|
|
- #nullable enable
|
|
|
-
|
|
|
- namespace {{Strings.AnalyzersAttributesNamespace}};
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Attribute written by the source generator for enum extension classes, for easier analysis and reflection.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>
|
|
|
- /// Properties are just convenient shortcuts to properties of <typeparamref name="TEnum"/>.
|
|
|
- /// </remarks>
|
|
|
- {{Strings.Templates.AttributesForGeneratedTypes}}
|
|
|
- [System.AttributeUsageAttribute (System.AttributeTargets.Class | System.AttributeTargets.Interface)]
|
|
|
- public sealed class {{ExtensionsForEnumTypeAttributeName}}<TEnum>: System.Attribute, IExtensionsForEnumTypeAttributes where TEnum : struct, Enum
|
|
|
- {
|
|
|
- /// <summary>
|
|
|
- /// The namespace-qualified name of <typeparamref name="TEnum"/>.
|
|
|
- /// </summary>
|
|
|
- public string EnumFullName => EnumType.FullName!;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// The unqualified name of <typeparamref name="TEnum"/>.
|
|
|
- /// </summary>
|
|
|
- public string EnumName => EnumType.Name;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// The namespace containing <typeparamref name="TEnum"/>.
|
|
|
- /// </summary>
|
|
|
- public string EnumNamespace => EnumType.Namespace!;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// The <see cref="Type"/> given by <see langword="typeof"/>(<typeparamref name="TEnum"/>).
|
|
|
- /// </summary>
|
|
|
- public Type EnumType => typeof (TEnum);
|
|
|
- }
|
|
|
-
|
|
|
- """,
|
|
|
- Encoding.UTF8));
|
|
|
- }
|
|
|
-
|
|
|
- [SuppressMessage ("Roslynator", "RCS1267", Justification = "Intentionally used so that Spans are used.")]
|
|
|
- private static void GenerateDummyNamespaces (IncrementalGeneratorPostInitializationContext postInitializeContext)
|
|
|
- {
|
|
|
- postInitializeContext.AddSource (
|
|
|
- string.Concat (Strings.InternalAnalyzersNamespace, "Namespaces.g.cs"),
|
|
|
- SourceText.From (Strings.Templates.DummyNamespaceDeclarations, Encoding.UTF8));
|
|
|
- }
|
|
|
-
|
|
|
- private static void GenerateSourceFromGenerationInfo (SourceProductionContext context, EnumExtensionMethodsGenerationInfo? enumInfo)
|
|
|
- {
|
|
|
- // Just in case we still made it this far with a null...
|
|
|
- if (enumInfo is not { })
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- CodeWriter writer = new (enumInfo);
|
|
|
-
|
|
|
- context.AddSource ($"{enumInfo.FullyQualifiedClassName}.g.cs", writer.GenerateSourceText ());
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Returns true if <paramref name="syntaxNode"/> is an EnumDeclarationSyntax
|
|
|
- /// whose parent is a NamespaceDeclarationSyntax, FileScopedNamespaceDeclarationSyntax, or a
|
|
|
- /// (Class|Struct)DeclarationSyntax.<br/>
|
|
|
- /// Additional filtering is performed in later stages.
|
|
|
- /// </summary>
|
|
|
- private static bool IsPotentiallyInterestingDeclaration (SyntaxNode syntaxNode, CancellationToken cancellationToken)
|
|
|
- {
|
|
|
- cancellationToken.ThrowIfCancellationRequested ();
|
|
|
-
|
|
|
- return syntaxNode is
|
|
|
- {
|
|
|
- RawKind: 8858, //(int)SyntaxKind.EnumDeclaration,
|
|
|
- Parent.RawKind: 8845 //(int)SyntaxKind.FileScopedNamespaceDeclaration
|
|
|
- or 8842 //(int)SyntaxKind.NamespaceDeclaration
|
|
|
- or 8855 //(int)SyntaxKind.ClassDeclaration
|
|
|
- or 8856 //(int)SyntaxKind.StructDeclaration
|
|
|
- or 9068 //(int)SyntaxKind.RecordStructDeclaration
|
|
|
- or 9063 //(int)SyntaxKind.RecordDeclaration
|
|
|
- };
|
|
|
- }
|
|
|
-}
|