/// <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,
                });
            }
        }