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);
            }
        }
示例#3
0
            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;
            }
示例#4
0
        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);
        }
示例#5
0
 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);
     }
 }
示例#6
0
        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);
 }
示例#9
0
 public override void VisitUsingDirective(UsingDirectiveIntermediateNode node)
 {
     WriteContentNode(node, node.Content);
 }
示例#10
0
 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);
        }
示例#12
0
 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);
        }