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