public void WriteUsingDirective_WithSource_WritesContentWithLinePragmaAndMapping() { // Arrange var writer = new DesignTimeNodeWriter(); var sourceDocument = TestRazorSourceDocument.Create("@using System;"); var context = TestCodeRenderingContext.CreateDesignTime(); var originalSpan = new SourceSpan("test.cshtml", 0, 0, 0, 6); var generatedSpan = new SourceSpan(null, 21 + Environment.NewLine.Length, 1, 0, 6); var expectedSourceMapping = new SourceMapping(originalSpan, generatedSpan); var node = new UsingDirectiveIntermediateNode() { Content = "System", Source = originalSpan, }; // Act writer.WriteUsingDirective(context, node); // Assert var mapping = Assert.Single(((DefaultCodeRenderingContext)context).SourceMappings); Assert.Equal(expectedSourceMapping, mapping); var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"#line 1 ""test.cshtml"" using System; #line default #line hidden ", csharp, ignoreLineEndingDifferences: true); }
public override void WriteUsingDirective(CodeRenderingContext context, UsingDirectiveIntermediateNode node) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (node == null) { throw new ArgumentNullException(nameof(node)); } if (node.Source.HasValue) { using (context.CodeWriter.BuildLinePragma(node.Source.Value)) { context.AddSourceMappingFor(node); context.CodeWriter.WriteUsing(node.Content); } } else { context.CodeWriter.WriteUsing(node.Content); } }
protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode) { if (documentNode.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind && documentNode.DocumentKind != MvcViewDocumentClassifierPass.MvcViewDocumentKind) { // Not a MVC file. Skip. return; } var visitor = new Visitor(); var modelType = GetModelType(documentNode, visitor); if (documentNode.Options.DesignTime) { // Alias the TModel token to a known type. // This allows design time compilation to succeed for Razor files where the token isn't replaced. var typeName = $"global::{typeof(object).FullName}"; var usingNode = new UsingDirectiveIntermediateNode() { Content = $"TModel = {typeName}" }; visitor.Namespace?.Children.Insert(0, usingNode); } var baseType = visitor.Class?.BaseType?.Replace("<TModel>", "<" + modelType + ">"); visitor.Class.BaseType = baseType; }
public void WriteUsingDirective_WithSource_WritesContentWithLinePragma() { // Arrange var codeWriter = new CodeWriter(); var writer = new RuntimeNodeWriter(); var context = TestCodeRenderingContext.CreateRuntime(); var node = new UsingDirectiveIntermediateNode() { Content = "System", Source = new SourceSpan("test.cshtml", 0, 0, 0, 3), }; // Act writer.WriteUsingDirective(context, node); // Assert var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @" #nullable restore #line 1 ""test.cshtml"" using System; #line default #line hidden #nullable disable ", csharp, ignoreLineEndingDifferences: true); }
public override void WriteUsingDirective(CodeRenderingContext context, UsingDirectiveIntermediateNode node) { if (node.Source.HasValue) { using (context.CodeWriter.BuildLinePragma(node.Source.Value, context)) { context.CodeWriter.WriteUsing(node.Content); } } else { context.CodeWriter.WriteUsing(node.Content); } }
public override void VisitUsingDirective(UsingDirectiveIntermediateNode node) { var children = _namespace.Current.Children; var i = children.Count - 1; for (; i >= 0; i--) { var child = children[i]; if (child is UsingDirectiveIntermediateNode) { break; } } _namespace.Insert(i + 1, node); }
public void WriteUsingDirective_NoSource_WritesContent() { // Arrange var writer = new DesignTimeNodeWriter(); var context = TestCodeRenderingContext.CreateDesignTime(); var node = new UsingDirectiveIntermediateNode() { Content = "System", }; // Act writer.WriteUsingDirective(context, node); // Assert var csharp = context.CodeWriter.GenerateCode(); Assert.Equal( @"using System; ", csharp, ignoreLineEndingDifferences: true); }
public virtual void VisitUsingDirective(UsingDirectiveIntermediateNode node) { VisitDefault(node); }
public override void VisitUsingDirective(UsingDirectiveIntermediateNode node) { WriteContentNode(node, node.Content); }
public override void VisitUsingDirective(UsingDirectiveIntermediateNode node) { Context.NodeWriter.WriteUsingDirective(Context, node); }
protected override void ExecuteCore(RazorCodeDocument codeDocument) { var syntaxTree = codeDocument.GetSyntaxTree(); ThrowForMissingDocumentDependency(syntaxTree); // This might not have been set if there are no tag helpers. var tagHelperContext = codeDocument.GetTagHelperContext(); var document = new DocumentIntermediateNode(); var builder = IntermediateNodeBuilder.Create(document); document.Options = _optionsFeature.GetOptions(); var namespaces = new Dictionary <string, SourceSpan?>(StringComparer.Ordinal); // The import documents should be inserted logically before the main document. var imports = codeDocument.GetImportSyntaxTrees(); if (imports != null) { var importsVisitor = new ImportsVisitor(document, builder, namespaces); for (var j = 0; j < imports.Count; j++) { var import = imports[j]; importsVisitor.FilePath = import.Source.FilePath; importsVisitor.VisitBlock(import.Root); } } var tagHelperPrefix = tagHelperContext?.Prefix; var visitor = new MainSourceVisitor(document, builder, namespaces, tagHelperPrefix) { FilePath = syntaxTree.Source.FilePath, }; visitor.VisitBlock(syntaxTree.Root); // In each lowering piece above, namespaces were tracked. We render them here to ensure every // lowering action has a chance to add a source location to a namespace. Ultimately, closest wins. var i = 0; foreach (var @namespace in namespaces) { var @using = new UsingDirectiveIntermediateNode() { Content = @namespace.Key, Source = @namespace.Value, }; builder.Insert(i++, @using); } ImportDirectives(document); // The document should contain all errors that currently exist in the system. This involves // adding the errors from the primary and imported syntax trees. for (i = 0; i < syntaxTree.Diagnostics.Count; i++) { document.Diagnostics.Add(syntaxTree.Diagnostics[i]); } if (imports != null) { for (i = 0; i < imports.Count; i++) { var import = imports[i]; for (var j = 0; j < import.Diagnostics.Count; j++) { document.Diagnostics.Add(import.Diagnostics[j]); } } } codeDocument.SetDocumentIntermediateNode(document); }
public abstract void WriteUsingDirective(CodeRenderingContext context, UsingDirectiveIntermediateNode node);
protected override void ExecuteCore(RazorCodeDocument codeDocument) { var syntaxTree = codeDocument.GetSyntaxTree(); ThrowForMissingDocumentDependency(syntaxTree); // This might not have been set if there are no tag helpers. var tagHelperContext = codeDocument.GetTagHelperContext(); var document = new DocumentIntermediateNode(); var builder = IntermediateNodeBuilder.Create(document); document.Options = codeDocument.GetCodeGenerationOptions() ?? _optionsFeature.GetOptions(); IReadOnlyList <UsingReference> importedUsings = Array.Empty <UsingReference>(); // The import documents should be inserted logically before the main document. var imports = codeDocument.GetImportSyntaxTrees(); if (imports != null) { var importsVisitor = new ImportsVisitor(document, builder, syntaxTree.Options.FeatureFlags); for (var j = 0; j < imports.Count; j++) { var import = imports[j]; importsVisitor.FilePath = import.Source.FilePath; importsVisitor.VisitBlock(import.Root); } importedUsings = importsVisitor.Usings; } var tagHelperPrefix = tagHelperContext?.Prefix; var visitor = new MainSourceVisitor(document, builder, tagHelperPrefix, syntaxTree.Options.FeatureFlags) { FilePath = syntaxTree.Source.FilePath, }; visitor.VisitBlock(syntaxTree.Root); // 1. Prioritize non-imported usings over imported ones. // 2. Don't import usings that already exist in primary document. // 3. Allow duplicate usings in primary document (C# warning). var usingReferences = new List <UsingReference>(visitor.Usings); for (var j = importedUsings.Count - 1; j >= 0; j--) { if (!usingReferences.Contains(importedUsings[j])) { usingReferences.Insert(0, importedUsings[j]); } } // In each lowering piece above, namespaces were tracked. We render them here to ensure every // lowering action has a chance to add a source location to a namespace. Ultimately, closest wins. var i = 0; foreach (var reference in usingReferences) { var @using = new UsingDirectiveIntermediateNode() { Content = reference.Namespace, Source = reference.Source, }; builder.Insert(i++, @using); } ImportDirectives(document); // The document should contain all errors that currently exist in the system. This involves // adding the errors from the primary and imported syntax trees. for (i = 0; i < syntaxTree.Diagnostics.Count; i++) { document.Diagnostics.Add(syntaxTree.Diagnostics[i]); } if (imports != null) { for (i = 0; i < imports.Count; i++) { var import = imports[i]; for (var j = 0; j < import.Diagnostics.Count; j++) { document.Diagnostics.Add(import.Diagnostics[j]); } } } codeDocument.SetDocumentIntermediateNode(document); }