protected override void OnDocumentStructureCreated(
            RazorCodeDocument codeDocument,
            NamespaceDeclarationIntermediateNode @namespace,
            ClassDeclarationIntermediateNode @class,
            MethodDeclarationIntermediateNode method)
        {
            base.OnDocumentStructureCreated(codeDocument, @namespace, @class, method);

            @namespace.Content = "AspNetCore";

            var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath;

            if (string.IsNullOrEmpty(filePath))
            {
                // It's possible for a Razor document to not have a file path.
                // Eg. When we try to generate code for an in memory document like default imports.
                var checksum = Checksum.BytesToString(codeDocument.Source.GetChecksum());
                @class.ClassName = $"AspNetCore_{checksum}";
            }
            else
            {
                @class.ClassName = GetClassNameFromPath(filePath);
            }

            @class.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>";
            @class.Modifiers.Clear();
            @class.Modifiers.Add("public");

            method.MethodName = "ExecuteAsync";
            method.Modifiers.Clear();
            method.Modifiers.Add("public");
            method.Modifiers.Add("async");
            method.Modifiers.Add("override");
            method.ReturnType = $"global::{typeof(System.Threading.Tasks.Task).FullName}";
        }
        public void WriteRazorSourceChecksumAttribute(CodeRenderingContext context, RazorSourceChecksumAttributeIntermediateNode node)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            // [global::...RazorSourceChecksum(@"{node.ChecksumAlgorithm}", @"{node.Checksum}", @"{node.Identifier}")]
            context.CodeWriter.Write("[");
            context.CodeWriter.Write(SourceChecksumAttributeName);
            context.CodeWriter.Write("(@\"");
            context.CodeWriter.Write(node.ChecksumAlgorithm);
            context.CodeWriter.Write("\", @\"");
            context.CodeWriter.Write(Checksum.BytesToString(node.Checksum));
            context.CodeWriter.Write("\", @\"");
            context.CodeWriter.Write(node.Identifier);
            context.CodeWriter.WriteLine("\")]");
        }
        /// <inheritdoc />
        protected override void OnDocumentStructureCreated(
            RazorCodeDocument codeDocument,
            NamespaceDeclarationIntermediateNode @namespace,
            ClassDeclarationIntermediateNode @class,
            MethodDeclarationIntermediateNode method)
        {
            if (!codeDocument.TryComputeNamespace(fallbackToRootNamespace: true, out var computedNamespace) ||
                !TryComputeClassName(codeDocument, out var computedClass))
            {
                // If we can't compute a nice namespace (no relative path) then just generate something
                // mangled.
                computedNamespace = FallbackRootNamespace;
                var checksum = Checksum.BytesToString(codeDocument.Source.GetChecksum());
                computedClass = $"AspNetCore_{checksum}";
            }

            var documentNode = codeDocument.GetDocumentIntermediateNode();

            if (char.IsLower(computedClass, 0))
            {
                // We don't allow component names to start with a lowercase character.
                documentNode.Diagnostics.Add(
                    ComponentDiagnosticFactory.Create_ComponentNamesCannotStartWithLowerCase(computedClass, documentNode.Source));
            }

            if (MangleClassNames)
            {
                computedClass = ComponentMetadata.MangleClassName(computedClass);
            }

            @namespace.Content = computedNamespace;
            @class.ClassName   = computedClass;
            @class.Modifiers.Clear();
            @class.Modifiers.Add("public");
            @class.Modifiers.Add("partial");

            if (FileKinds.IsComponentImport(codeDocument.GetFileKind()))
            {
                // We don't want component imports to be considered as real component.
                // But we still want to generate code for it so we can get diagnostics.
                @class.BaseType = typeof(object).FullName;

                method.ReturnType = "void";
                method.MethodName = "Execute";
                method.Modifiers.Clear();
                method.Modifiers.Add("protected");

                method.Parameters.Clear();
            }
            else
            {
                @class.BaseType = ComponentsApi.ComponentBase.FullTypeName;

                var typeParamReferences = documentNode.FindDirectiveReferences(ComponentTypeParamDirective.Directive);
                for (var i = 0; i < typeParamReferences.Count; i++)
                {
                    var typeParamNode = (DirectiveIntermediateNode)typeParamReferences[i].Node;
                    if (typeParamNode.HasDiagnostics)
                    {
                        continue;
                    }

                    @class.TypeParameters.Add(new TypeParameter()
                    {
                        ParameterName = typeParamNode.Tokens.First().Content,
                        Constraints   = typeParamNode.Tokens.Skip(1).FirstOrDefault()?.Content
                    });
                }

                method.ReturnType = "void";
                method.MethodName = ComponentsApi.ComponentBase.BuildRenderTree;
                method.Modifiers.Clear();
                method.Modifiers.Add("protected");
                method.Modifiers.Add("override");

                method.Parameters.Clear();
                method.Parameters.Add(new MethodParameter()
                {
                    ParameterName = ComponentsApi.RenderTreeBuilder.BuilderParameter,
                    TypeName      = ComponentsApi.RenderTreeBuilder.FullTypeName,
                });
            }
        }
            public override void VisitDocument(DocumentIntermediateNode node)
            {
                if (!Context.Options.SuppressChecksum)
                {
                    // See http://msdn.microsoft.com/en-us/library/system.codedom.codechecksumpragma.checksumalgorithmid.aspx
                    // And https://github.com/dotnet/roslyn/blob/614299ff83da9959fa07131c6d0ffbc58873b6ae/src/Compilers/Core/Portable/PEWriter/DebugSourceDocument.cs#L67
                    //
                    // We only support algorithms that the debugger understands, which is currently SHA1 and SHA256.

                    string algorithmId;
                    var    algorithm = Context.SourceDocument.GetChecksumAlgorithm();
                    if (string.Equals(algorithm, HashAlgorithmName.SHA256.Name, StringComparison.Ordinal))
                    {
                        algorithmId = "{8829d00f-11b8-4213-878b-770e8597ac16}";
                    }
                    else if (string.Equals(algorithm, HashAlgorithmName.SHA1.Name, StringComparison.Ordinal) ||

                             // In 2.0, we didn't actually expose the name of the algorithm, so it's possible we could get null here.
                             // If that's the case, we just assume SHA1 since that's the only thing we supported in 2.0.
                             algorithm == null)
                    {
                        algorithmId = "{ff1816ec-aa5e-4d10-87f7-6f4963833460}";
                    }
                    else
                    {
                        var supportedAlgorithms = string.Join(" ", new string[]
                        {
                            HashAlgorithmName.SHA1.Name,
                            HashAlgorithmName.SHA256.Name
                        });

                        var message = Resources.FormatUnsupportedChecksumAlgorithm(
                            algorithm,
                            supportedAlgorithms,
                            nameof(RazorCodeGenerationOptions) + "." + nameof(RazorCodeGenerationOptions.SuppressChecksum),
                            bool.TrueString);
                        throw new InvalidOperationException(message);
                    }

                    var sourceDocument = Context.SourceDocument;

                    var checksum = Checksum.BytesToString(sourceDocument.GetChecksum());
                    if (!string.IsNullOrEmpty(checksum))
                    {
                        Context.CodeWriter
                        .Write("#pragma checksum \"")
                        .Write(sourceDocument.FilePath)
                        .Write("\" \"")
                        .Write(algorithmId)
                        .Write("\" \"")
                        .Write(checksum)
                        .WriteLine("\"");
                    }
                }

                Context.CodeWriter
                .WriteLine("// <auto-generated/>")
                .WriteLine("#pragma warning disable 1591");

                VisitDefault(node);

                Context.CodeWriter.WriteLine("#pragma warning restore 1591");
            }
        protected override void OnDocumentStructureCreated(RazorCodeDocument codeDocument, NamespaceDeclarationIntermediateNode @namespace, ClassDeclarationIntermediateNode @class, MethodDeclarationIntermediateNode method)
        {
            base.OnDocumentStructureCreated(codeDocument, @namespace, @class, method);

            if (!TryComputeNamespaceAndClass(
                    codeDocument.Source.FilePath,
                    codeDocument.Source.RelativePath,
                    out var computedNamespace,
                    out var computedClass))
            {
                // If we can't compute a nice namespace (no relative path) then just generate something
                // mangled.
                computedNamespace = "AspNetCore";
                var checksum = Checksum.BytesToString(codeDocument.Source.GetChecksum());
                computedClass = $"AspNetCore_{checksum}";
            }

            @namespace.Content = computedNamespace;

            @class.ClassName = computedClass;
            @class.BaseType  = $"global::{CodeGenerationConstants.RazorComponent.FullTypeName}";
            var filePath = codeDocument.Source.RelativePath ?? codeDocument.Source.FilePath;

            if (string.IsNullOrEmpty(filePath))
            {
                // It's possible for a Razor document to not have a file path.
                // Eg. When we try to generate code for an in memory document like default imports.
                var checksum = Checksum.BytesToString(codeDocument.Source.GetChecksum());
                @class.ClassName = $"AspNetCore_{checksum}";
            }
            else
            {
                @class.ClassName = CSharpIdentifier.SanitizeIdentifier(Path.GetFileNameWithoutExtension(filePath));
            }

            @class.Modifiers.Clear();
            @class.Modifiers.Add("public");
            @class.Modifiers.Add("sealed");

            method.MethodName = CodeGenerationConstants.RazorComponent.BuildRenderTree;
            method.ReturnType = "void";
            method.Modifiers.Clear();
            method.Modifiers.Add("public");
            method.Modifiers.Add("override");

            method.Parameters.Clear();
            method.Parameters.Add(new MethodParameter()
            {
                TypeName      = CodeGenerationConstants.RenderTreeBuilder.FullTypeName,
                ParameterName = CodeGenerationConstants.RazorComponent.BuildRenderTreeParameter,
            });

            // We need to call the 'base' method as the first statement.
            var callBase = new CSharpCodeIntermediateNode();

            callBase.Annotations.Add(BuildRenderTreeBaseCallAnnotation, true);
            callBase.Children.Add(new IntermediateToken
            {
                Kind    = TokenKind.CSharp,
                Content = $"base.{CodeGenerationConstants.RazorComponent.BuildRenderTree}({CodeGenerationConstants.RazorComponent.BuildRenderTreeParameter});"
            });
            method.Children.Insert(0, callBase);
        }
        /// <inheritdoc />
        protected override void OnDocumentStructureCreated(
            RazorCodeDocument codeDocument,
            NamespaceDeclarationIntermediateNode @namespace,
            ClassDeclarationIntermediateNode @class,
            MethodDeclarationIntermediateNode method)
        {
            var options = codeDocument.GetDocumentIntermediateNode().Options;

            if (!TryComputeNamespaceAndClass(
                    options,
                    codeDocument.Source.FilePath,
                    codeDocument.Source.RelativePath,
                    out var computedNamespace,
                    out var computedClass))
            {
                // If we can't compute a nice namespace (no relative path) then just generate something
                // mangled.
                computedNamespace = FallbackRootNamespace;
                var checksum = Checksum.BytesToString(codeDocument.Source.GetChecksum());
                computedClass = $"AspNetCore_{checksum}";
            }

            if (MangleClassNames)
            {
                computedClass = "__" + computedClass;
            }

            @namespace.Content = computedNamespace;

            @class.BaseType  = ComponentsApi.ComponentBase.FullTypeName;
            @class.ClassName = computedClass;
            @class.Modifiers.Clear();
            @class.Modifiers.Add("public");

            var documentNode        = codeDocument.GetDocumentIntermediateNode();
            var typeParamReferences = documentNode.FindDirectiveReferences(ComponentTypeParamDirective.Directive);

            for (var i = 0; i < typeParamReferences.Count; i++)
            {
                var typeParamNode = (DirectiveIntermediateNode)typeParamReferences[i].Node;
                if (typeParamNode.HasDiagnostics)
                {
                    continue;
                }

                @class.TypeParameters.Add(new TypeParameter()
                {
                    ParameterName = typeParamNode.Tokens.First().Content,
                });
            }

            method.ReturnType = "void";
            method.MethodName = ComponentsApi.ComponentBase.BuildRenderTree;
            method.Modifiers.Clear();
            method.Modifiers.Add("protected");
            method.Modifiers.Add("override");

            method.Parameters.Clear();
            method.Parameters.Add(new MethodParameter()
            {
                ParameterName = "builder",
                TypeName      = ComponentsApi.RenderTreeBuilder.FullTypeName,
            });

            // We need to call the 'base' method as the first statement.
            var callBase = new CSharpCodeIntermediateNode();

            callBase.Annotations.Add(BuildRenderTreeBaseCallAnnotation, true);
            callBase.Children.Add(new IntermediateToken
            {
                Kind    = TokenKind.CSharp,
                Content = $"base.{ComponentsApi.ComponentBase.BuildRenderTree}(builder);"
            });
            method.Children.Insert(0, callBase);
        }