public void GetHierarchicalItems_Works()
    {
        // Arrange
        var projectSystem = new VirtualRazorProjectFileSystem();
        var viewImport1   = new TestRazorProjectItem("/_ViewImports.cshtml");
        var viewImport2   = new TestRazorProjectItem("/Views/Home/_ViewImports.cshtml");

        projectSystem.Add(viewImport1);
        projectSystem.Add(viewImport2);

        // Act
        var items = projectSystem.FindHierarchicalItems("/", "/Views/Home/Index.cshtml", "_ViewImports.cshtml");

        // Assert
        Assert.Collection(
            items,
            item => Assert.Same(viewImport2, item),
            item => Assert.False(item.Exists),
            item => Assert.Same(viewImport1, item));
    }
Exemple #2
0
        private static RazorCodeDocument GetCodeDocument(TestRazorProjectItem projectItem, TestRazorProjectItem imports = null)
        {
            var sourceDocument = RazorSourceDocument.ReadFrom(projectItem);
            var fileSystem     = new VirtualRazorProjectFileSystem();

            fileSystem.Add(projectItem);

            var codeDocument = RazorCodeDocument.Create(sourceDocument);

            if (imports != null)
            {
                fileSystem.Add(imports);
                codeDocument = RazorCodeDocument.Create(sourceDocument, new[] { RazorSourceDocument.ReadFrom(imports) });
            }

            var razorEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem).Engine;

            razorEngine.Process(codeDocument);
            return(codeDocument);
        }
    public void EnumerateItems_AtSubDirectory_ReturnsAllFilesUnderDirectoryHierarchy()
    {
        // Arrange
        var projectSystem = new VirtualRazorProjectFileSystem();
        var file1         = new TestRazorProjectItem("/subDirectory/dir2/file1.cshtml");
        var file2         = new TestRazorProjectItem("/file2.cshtml");
        var file3         = new TestRazorProjectItem("/dir3/file3.cshtml");
        var file4         = new TestRazorProjectItem("/subDirectory/file4.cshtml");

        projectSystem.Add(file1);
        projectSystem.Add(file2);
        projectSystem.Add(file3);
        projectSystem.Add(file4);

        // Act
        var result = projectSystem.EnumerateItems("/subDirectory");

        // Assert
        Assert.Equal(new[] { file4, file1 }, result);
    }
    public void AddHierarchicalImports_AddsViewImportSourceDocumentsNotOnDisk()
    {
        // Arrange
        var imports          = new List <RazorProjectItem>();
        var projectItem      = new TestRazorProjectItem("/Pages/Contact/Index.cshtml");
        var testFileSystem   = new TestRazorProjectFileSystem(new[] { projectItem });
        var mvcImportFeature = new MvcImportProjectFeature()
        {
            ProjectEngine = Mock.Of <RazorProjectEngine>(projectEngine => projectEngine.FileSystem == testFileSystem)
        };

        // Act
        mvcImportFeature.AddHierarchicalImports(projectItem, imports);

        // Assert
        Assert.Collection(imports,
                          import => Assert.Equal("/_ViewImports.cshtml", import.FilePath),
                          import => Assert.Equal("/Pages/_ViewImports.cshtml", import.FilePath),
                          import => Assert.Equal("/Pages/Contact/_ViewImports.cshtml", import.FilePath));
    }
        private static RazorSyntaxTree GetSyntaxTree(StringTextSnapshot source, IEnumerable <DirectiveDescriptor> directives = null)
        {
            directives = directives ?? Enumerable.Empty <DirectiveDescriptor>();
            var engine = RazorProjectEngine.Create(builder =>
            {
                foreach (var directive in directives)
                {
                    builder.AddDirective(directive);
                }
            });

            var sourceProjectItem = new TestRazorProjectItem("test.cshtml")
            {
                Content = source.GetText()
            };

            var codeDocument = engine.ProcessDesignTime(sourceProjectItem);

            return(codeDocument.GetSyntaxTree());
        }
Exemple #6
0
    public void ProcessDesignTime_SetsOptions_DesignTime()
    {
        // Arrange
        var projectItem = new TestRazorProjectItem("Index.cshtml");

        var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, TestRazorProjectFileSystem.Empty);

        // Act
        var codeDocument = projectEngine.ProcessDesignTime(projectItem);

        // Assert
        var parserOptions = codeDocument.GetParserOptions();

        Assert.True(parserOptions.DesignTime);

        var codeGenerationOptions = codeDocument.GetCodeGenerationOptions();

        Assert.True(codeGenerationOptions.DesignTime);
        Assert.True(codeGenerationOptions.SuppressChecksum);
        Assert.True(codeGenerationOptions.SuppressMetadataAttributes);
    }
        public void CSharpDocument_DesignTime_PreservesParserErrors()
        {
            // Arrange
            var projectEngine = CreateProjectEngine();
            var projectItem   = new TestRazorProjectItem("test.cshtml")
            {
                Content = "@{"
            };

            var expected = RazorDiagnosticFactory.CreateParsing_ExpectedEndOfBlockBeforeEOF(
                new SourceSpan(new SourceLocation("test.cshtml", 1, 0, 1), contentLength: 1), Resources.BlockName_Code, "}", "{");

            // Act
            var codeDocument = projectEngine.ProcessDesignTime(projectItem);

            // Assert
            var csharpDocument = codeDocument.GetCSharpDocument();
            var error          = Assert.Single(csharpDocument.Diagnostics);

            Assert.Equal(expected, error);
        }
Exemple #8
0
    public void GetCompilationFailedResult_ReadsContentFromImports()
    {
        // Arrange
        var viewPath       = "/Views/Home/Index.cshtml";
        var importsPath    = "/Views/_MyImports.cshtml";
        var fileContent    = "@ ";
        var importsContent = "@(abc";

        var projectItem    = new TestRazorProjectItem(viewPath, fileContent);
        var importsItem    = new TestRazorProjectItem(importsPath, importsContent);
        var codeDocument   = GetCodeDocument(projectItem, importsItem);
        var csharpDocument = codeDocument.GetCSharpDocument();

        // Act
        var compilationResult = CompilationFailedExceptionFactory.Create(codeDocument, csharpDocument.Diagnostics);

        // Assert
        Assert.Collection(
            compilationResult.CompilationFailures,
            failure =>
        {
            Assert.Equal(viewPath, failure.SourceFilePath);
            Assert.Collection(failure.Messages,
                              message =>
            {
                Assert.Equal(@"A space or line break was encountered after the ""@"" character.  Only valid identifiers, keywords, comments, ""("" and ""{"" are valid at the start of a code block and they must occur immediately following ""@"" with no space in between.",
                             message.Message);
            });
        },
            failure =>
        {
            Assert.Equal(importsPath, failure.SourceFilePath);
            Assert.Collection(failure.Messages,
                              message =>
            {
                Assert.Equal(@"The explicit expression block is missing a closing "")"" character.  Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.",
                             message.Message);
            });
        });
    }
Exemple #9
0
        public void GenerateCodeWithSetNamespace()
        {
            // Arrange
            var filePath    = Path.Combine(TestProjectRoot, $"{FileName}.cshtml");
            var content     = File.ReadAllText(filePath);
            var projectItem = new TestRazorProjectItem($"{FileName}.cshtml", "")
            {
                Content = content,
            };
            var project     = new TestRazorProject(new[] { projectItem });
            var razorEngine = RazorEngine.Create(engine =>
            {
                engine.SetNamespace("MyApp.Razor.Views");
            });
            var templateEngine = new RazorTemplateEngine(razorEngine, project);

            // Act
            var cSharpDocument = templateEngine.GenerateCode(projectItem.FilePath);

            // Assert
            AssertCSharpDocumentMatchesBaseline(cSharpDocument);
        }
        public void EnumerateItems_ReturnsResultsFromAllFileSystems()
        {
            // Arrange
            var basePath    = "base-path";
            var file1       = new TestRazorProjectItem("file1");
            var file2       = new TestRazorProjectItem("file2");
            var file3       = new TestRazorProjectItem("file3");
            var fileSystem1 = Mock.Of <RazorProjectFileSystem>(
                f => f.EnumerateItems(basePath) == new[] { file1 });
            var fileSystem2 = Mock.Of <RazorProjectFileSystem>(
                f => f.EnumerateItems(basePath) == Enumerable.Empty <RazorProjectItem>());
            var fileSystem3 = Mock.Of <RazorProjectFileSystem>(
                f => f.EnumerateItems(basePath) == new[] { file2, file3, });

            var compositeRazorProjectFileSystem = new CompositeRazorProjectFileSystem(new[] { fileSystem1, fileSystem2, fileSystem3 });

            // Act
            var result = compositeRazorProjectFileSystem.EnumerateItems(basePath);

            // Assert
            Assert.Equal(new[] { file1, file2, file3 }, result);
        }
Exemple #11
0
        public void CSharpDocument_Runtime_PreservesParserErrors()
        {
            // Arrange
            var projectEngine = CreateProjectEngine();
            var projectItem   = new TestRazorProjectItem("test.cshtml")
            {
                Content = "@!!!"
            };

            var expected = RazorDiagnosticFactory.CreateParsing_UnexpectedCharacterAtStartOfCodeBlock(
                new SourceSpan(new SourceLocation("test.cshtml", 1, 0, 1), contentLength: 1),
                "!");

            // Act
            var codeDocument = projectEngine.Process(projectItem);

            // Assert
            var csharpDocument = codeDocument.GetCSharpDocument();
            var error          = Assert.Single(csharpDocument.Diagnostics);

            Assert.Equal(expected, error);
        }
        public void GetItem_ReturnsFirstInstanceThatExists()
        {
            // Arrange
            var basePath = "base-path";
            var filePath = "file-path";
            var file1    = new NotFoundProjectItem(basePath, filePath, fileKind: null);
            var file2    = new TestRazorProjectItem(filePath);
            RazorProjectItem nullItem = null;
            var fileSystem1           = Mock.Of <RazorProjectFileSystem>(
                f => f.GetItem(filePath, null) == file1);
            var fileSystem2 = Mock.Of <RazorProjectFileSystem>(
                f => f.GetItem(filePath, null) == nullItem);
            var fileSystem3 = Mock.Of <RazorProjectFileSystem>(
                f => f.GetItem(filePath, null) == file2);

            var compositeRazorProjectFileSystem = new CompositeRazorProjectFileSystem(new[] { fileSystem1, fileSystem2, fileSystem3 });

            // Act
            var result = compositeRazorProjectFileSystem.GetItem(filePath, fileKind: null);

            // Assert
            Assert.Same(file2, result);
        }
Exemple #13
0
        private static RazorCodeDocument GetCodeDocument(string source)
        {
            var taghelper = TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly")
                            .BoundAttributeDescriptor(attr => attr.Name("show").TypeName("System.Boolean"))
                            .BoundAttributeDescriptor(attr => attr.Name("id").TypeName("System.Int32"))
                            .TagMatchingRuleDescriptor(rule => rule.RequireTagName("taghelper"))
                            .TypeName("TestTagHelper")
                            .Build();
            var engine = RazorProjectEngine.Create(builder =>
            {
                builder.AddTagHelpers(taghelper);
                builder.SetImportFeature(new TestImportProjectFeature());
            });

            var sourceProjectItem = new TestRazorProjectItem("test.cshtml")
            {
                Content = source
            };

            var codeDocument = engine.ProcessDesignTime(sourceProjectItem);

            return(codeDocument);
        }
Exemple #14
0
    public void ProcessDesignTime_WithImportsAndTagHelpers_SetsOnCodeDocument()
    {
        // Arrange
        var projectItem        = new TestRazorProjectItem("Index.cshtml");
        var importItem         = new TestRazorProjectItem("_import.cshtml");
        var expectedImports    = new[] { RazorSourceDocument.ReadFrom(importItem) };
        var expectedTagHelpers = new[]
        {
            TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build(),
            TagHelperDescriptorBuilder.Create("Test2TagHelper", "TestAssembly").Build(),
        };

        var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, TestRazorProjectFileSystem.Empty);

        // Act
        var codeDocument = projectEngine.ProcessDesignTime(RazorSourceDocument.ReadFrom(projectItem), "test", expectedImports, expectedTagHelpers);

        // Assert
        var tagHelpers = codeDocument.GetTagHelpers();

        Assert.Same(expectedTagHelpers, tagHelpers);
        Assert.Equal(expectedImports, codeDocument.Imports);
    }
Exemple #15
0
        public void CreateCodeDocument_SetsRelativePathOnOutput()
        {
            // Arrange
            var path = "/Views/Home/Index.cshtml";
            var item = new TestRazorProjectItem(path)
            {
                Content = "Hello world",
            };
            var project = new TestRazorProject(new List <RazorProjectItem>()
            {
                item,
            });

            var mvcRazorTemplateEngine = new MvcRazorTemplateEngine(
                RazorEngine.Create(),
                project);

            // Act
            var codeDocument = mvcRazorTemplateEngine.CreateCodeDocument(path);

            // Assert
            Assert.Equal(path, codeDocument.GetRelativePath());
        }
Exemple #16
0
        public void TagHelperAttributesAreLocatedAndAcceptChangesCorrectly(object editObject, object partialParseResultObject)
        {
            // Arrange
            var edit = (TestEdit)editObject;
            var partialParseResult = (PartialParseResultInternal)partialParseResultObject;
            var builder            = TagHelperDescriptorBuilder.Create("PTagHelper", "Test");

            builder.SetTypeName("PTagHelper");
            builder.TagMatchingRule(rule => rule.TagName = "p");
            builder.BindAttribute(attribute =>
            {
                attribute.Name     = "obj-attr";
                attribute.TypeName = typeof(object).FullName;
                attribute.SetPropertyName("ObjectAttribute");
            });
            builder.BindAttribute(attribute =>
            {
                attribute.Name     = "str-attr";
                attribute.TypeName = typeof(string).FullName;
                attribute.SetPropertyName("StringAttribute");
            });
            var descriptors    = new[] { builder.Build() };
            var projectEngine  = CreateProjectEngine(tagHelpers: descriptors);
            var sourceDocument = new TestRazorProjectItem("Index.cshtml")
            {
                Content = edit.OldSnapshot.GetText()
            };
            var codeDocument = projectEngine.Process(sourceDocument);
            var syntaxTree   = codeDocument.GetSyntaxTree();
            var parser       = new RazorSyntaxTreePartialParser(syntaxTree);

            // Act
            var result = parser.Parse(edit.Change);

            // Assert
            Assert.Equal(partialParseResult, result);
        }
    public void DirectoryNode_AddsFiles_ToSiblingDirectories()
    {
        // Arrange
        var root         = new DirectoryNode("/");
        var projectItem1 = new TestRazorProjectItem("/Pages/Products/Index.cshtml");
        var projectItem2 = new TestRazorProjectItem("/Pages/Accounts/About.cshtml");

        // Act
        root.AddFile(new FileNode(projectItem1.FilePath, projectItem1));
        root.AddFile(new FileNode(projectItem2.FilePath, projectItem2));

        // Assert
        Assert.Collection(
            root.Directories,
            directory =>
        {
            Assert.Equal("/Pages/", directory.Path);
            Assert.Empty(directory.Files);

            Assert.Collection(
                directory.Directories,
                subDirectory =>
            {
                Assert.Equal("/Pages/Products/", subDirectory.Path);
                Assert.Collection(
                    subDirectory.Files,
                    file => Assert.Same(projectItem1, file.ProjectItem));
            },
                subDirectory =>
            {
                Assert.Equal("/Pages/Accounts/", subDirectory.Path);
                Assert.Collection(
                    subDirectory.Files,
                    file => Assert.Same(projectItem2, file.ProjectItem));
            });
        });
    }
Exemple #18
0
            public IReadOnlyList <RazorProjectItem> GetImports(RazorProjectItem projectItem)
            {
                if (_inner is null)
                {
                    return(Array.Empty <RazorProjectItem>());
                }

                var normalizedImports = new List <RazorProjectItem>();
                var imports           = _inner.GetImports(projectItem);

                foreach (var import in imports)
                {
                    if (import.Exists)
                    {
                        var text = string.Empty;
                        using (var stream = import.Read())
                            using (var reader = new StreamReader(stream))
                            {
                                text = reader.ReadToEnd().Trim();
                            }

                        // It's important that we normalize the newlines in the default imports. The default imports will
                        // be created with Environment.NewLine, but we need to normalize to `\r\n` so that the indices
                        // are the same on xplat.
                        var normalizedText   = NormalizeNewLines(text, _lineEnding);
                        var normalizedImport = new TestRazorProjectItem(import.FilePath, import.PhysicalPath, import.RelativePhysicalPath, import.BasePath)
                        {
                            Content = normalizedText
                        };

                        normalizedImports.Add(normalizedImport);
                    }
                }

                return(normalizedImports);
            }
Exemple #19
0
    public void GetCompilationFailedResult_ReadsContentFromSourceDocuments()
    {
        // Arrange
        var viewPath    = "/Views/Home/Index.cshtml";
        var fileContent =
            @"
@if (User.IsAdmin)
{
    <span>
}
</span>";

        var projectItem    = new TestRazorProjectItem(viewPath, fileContent);
        var codeDocument   = GetCodeDocument(projectItem);
        var csharpDocument = codeDocument.GetCSharpDocument();

        // Act
        var compilationResult = CompilationFailedExceptionFactory.Create(codeDocument, csharpDocument.Diagnostics);

        // Assert
        var failure = Assert.Single(compilationResult.CompilationFailures);

        Assert.Equal(fileContent, failure.SourceFileContent);
    }
        private DocumentSnapshot CreateRazorDocumentSnapshot(RazorProjectEngine projectEngine, TestRazorProjectItem item, string rootNamespaceName, IReadOnlyList <TagHelperDescriptor> tagHelpers)
        {
            var codeDocument = projectEngine.ProcessDesignTime(item);

            var namespaceNode = (NamespaceDeclarationIntermediateNode)codeDocument
                                .GetDocumentIntermediateNode()
                                .FindDescendantNodes <IntermediateNode>()
                                .FirstOrDefault(n => n is NamespaceDeclarationIntermediateNode);

            namespaceNode.Content = rootNamespaceName;

            var sourceText            = SourceText.From(new string(item.Content));
            var projectWorkspaceState = new ProjectWorkspaceState(tagHelpers, LanguageVersion.Default);
            var projectSnapshot       = TestProjectSnapshot.Create("C:/project.csproj", projectWorkspaceState);
            var documentSnapshot      = Mock.Of <DocumentSnapshot>(d =>
                                                                   d.GetGeneratedOutputAsync() == Task.FromResult(codeDocument) &&
                                                                   d.FilePath == item.FilePath &&
                                                                   d.FileKind == FileKinds.Component &&
                                                                   d.GetTextAsync() == Task.FromResult(sourceText) &&
                                                                   d.Project == projectSnapshot, MockBehavior.Strict);

            return(documentSnapshot);
        }