public void CompileCalculatesRootRelativePath(string appPath, string viewPath)
        {
            // Arrange
            var host = new Mock<IMvcRazorHost>();
            host.Setup(h => h.GenerateCode(@"Views\index\home.cshtml", It.IsAny<Stream>()))
                .Returns(GetGeneratorResult())
                .Verifiable();

            var fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.PhysicalPath).Returns(viewPath);
            fileInfo.Setup(f => f.CreateReadStream()).Returns(Stream.Null);

            var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");

            var compiler = new Mock<ICompilationService>();
            compiler.Setup(c => c.Compile(relativeFileInfo, It.IsAny<string>()))
                    .Returns(CompilationResult.Successful(typeof(RazorCompilationServiceTest)));

            var razorService = new RazorCompilationService(compiler.Object, host.Object);

            // Act
            razorService.Compile(relativeFileInfo);

            // Assert
            host.Verify();
        }
        public void Compile_ReturnsFailedResultIfParseFails()
        {
            // Arrange
            var errorSink = new ParserErrorSink();
            errorSink.OnError(new RazorError("some message", 1, 1, 1, 1));
            var generatorResult = new GeneratorResults(
                    new Block(new BlockBuilder { Type = BlockType.Comment }),
                    Enumerable.Empty<TagHelperDescriptor>(),
                    errorSink,
                    new CodeBuilderResult("", new LineMapping[0]),
                    new CodeTree());
            var host = new Mock<IMvcRazorHost>();
            host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>()))
                .Returns(generatorResult)
                .Verifiable();

            var fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.CreateReadStream())
                    .Returns(Stream.Null);

            var compiler = new Mock<ICompilationService>(MockBehavior.Strict);
            var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
            var razorService = new RazorCompilationService(compiler.Object, host.Object);

            // Act
            var result = razorService.Compile(relativeFileInfo);

            // Assert
            Assert.NotNull(result.CompilationFailure);
            var message = Assert.Single(result.CompilationFailure.Messages);
            Assert.Equal("some message", message.Message);
            host.Verify();
        }
        // Internal for unit testing
        internal CompilationResult GetCompilationFailedResult(RelativeFileInfo file, IEnumerable <RazorError> errors)
        {
            // If a SourceLocation does not specify a file path, assume it is produced
            // from parsing the current file.
            var messageGroups = errors
                                .GroupBy(razorError =>
                                         razorError.Location.FilePath ?? file.RelativePath,
                                         StringComparer.Ordinal);

            var failures = new List <CompilationFailure>();

            foreach (var group in messageGroups)
            {
                var filePath           = group.Key;
                var fileContent        = ReadFileContentsSafely(filePath);
                var compilationFailure = new CompilationFailure(
                    filePath,
                    fileContent,
                    compiledContent: string.Empty,
                    messages: group.Select(parserError => CreateDiagnosticMessage(parserError, filePath)));
                failures.Add(compilationFailure);
            }

            return(new CompilationResult(failures));
        }
Ejemplo n.º 4
0
        public void CompileCalculatesRootRelativePath(string appPath, string viewPath)
        {
            // Arrange
            var host = new Mock <IMvcRazorHost>();

            host.Setup(h => h.GenerateCode(@"views\index\home.cshtml", It.IsAny <Stream>()))
            .Returns(GetGeneratorResult())
            .Verifiable();

            var fileInfo = new Mock <IFileInfo>();

            fileInfo.Setup(f => f.PhysicalPath).Returns(viewPath);
            fileInfo.Setup(f => f.CreateReadStream()).Returns(Stream.Null);

            var compiler = new Mock <ICompilationService>();

            compiler.Setup(c => c.Compile(fileInfo.Object, It.IsAny <string>()))
            .Returns(CompilationResult.Successful(typeof(RazorCompilationServiceTest)));

            var razorService = new RazorCompilationService(compiler.Object, host.Object);

            var relativeFileInfo = new RelativeFileInfo()
            {
                FileInfo     = fileInfo.Object,
                RelativePath = @"views\index\home.cshtml",
            };

            // Act
            razorService.Compile(relativeFileInfo, isInstrumented: false);

            // Assert
            host.Verify();
        }
Ejemplo n.º 5
0
        public void GetOrAdd_IgnoresCache_IfCachedItemIsNotInstrumentedAndEnableInstrumentationIsTrue()
        {
            // Arrange
            var lastModified = DateTime.UtcNow;
            var cache        = new CompilerCache();
            var fileInfo     = new Mock <IFileInfo>();

            fileInfo.SetupGet(f => f.PhysicalPath)
            .Returns("test");
            fileInfo.SetupGet(f => f.LastModified)
            .Returns(lastModified);
            var type            = GetType();
            var uncachedResult1 = UncachedCompilationResult.Successful(type, "hello world");
            var uncachedResult2 = UncachedCompilationResult.Successful(typeof(object), "hello world");
            var uncachedResult3 = UncachedCompilationResult.Successful(typeof(Guid), "hello world");

            var runtimeFileInfo = new RelativeFileInfo()
            {
                FileInfo     = fileInfo.Object,
                RelativePath = "test",
            };

            // Act
            cache.GetOrAdd(runtimeFileInfo, false, () => uncachedResult1);
            var actual1 = cache.GetOrAdd(runtimeFileInfo, true, () => uncachedResult2);
            var actual2 = cache.GetOrAdd(runtimeFileInfo, false, () => uncachedResult3);

            // Assert
            Assert.Same(uncachedResult2, actual1);
            Assert.Same(typeof(object), actual1.CompiledType);

            Assert.NotSame(actual2, uncachedResult3);
            Assert.Same(typeof(object), actual2.CompiledType);
        }
Ejemplo n.º 6
0
        public void Compile_ReturnsGeneratedCodePath_IfLinePragmaIsNotAvailable()
        {
            // Arrange
            var fileContent = "file content";
            var content     = @"this should fail";

            var compilationService = new DefaultRoslynCompilationService(
                GetDependencyContext(),
                GetOptions(),
                GetFileProviderAccessor(),
                NullLoggerFactory.Instance);
            var relativeFileInfo = new RelativeFileInfo(
                new TestFileInfo {
                Content = fileContent
            },
                "some-relative-path");

            // Act
            var result = compilationService.Compile(relativeFileInfo, content);

            // Assert
            Assert.IsType <CompilationResult>(result);
            Assert.Null(result.CompiledType);

            var compilationFailure = Assert.Single(result.CompilationFailures);

            Assert.Equal("Generated Code", compilationFailure.SourceFilePath);
            Assert.Equal(content, compilationFailure.SourceFileContent);
        }
Ejemplo n.º 7
0
        public void Compile_SucceedsIfReferencesAreAddedInCallback()
        {
            // Arrange
            var options = GetOptions(context =>
            {
                var assemblyLocation = typeof(object).GetTypeInfo().Assembly.Location;

                context.Compilation = context
                                      .Compilation
                                      .AddReferences(MetadataReference.CreateFromFile(assemblyLocation));
            });
            var content            = "public class MyTestType  {}";
            var compilationService = new DefaultRoslynCompilationService(
                dependencyContext: null,
                viewEngineOptions: options,
                fileProviderAccessor: GetFileProviderAccessor(),
                loggerFactory: NullLoggerFactory.Instance);

            var relativeFileInfo = new RelativeFileInfo(
                new TestFileInfo {
                PhysicalPath = "SomePath"
            },
                "some-relative-path.cshtml");

            // Act
            var result = compilationService.Compile(relativeFileInfo, content);

            // Assert
            Assert.Null(result.CompilationFailures);
            Assert.NotNull(result.CompiledType);
        }
Ejemplo n.º 8
0
        public void Compile_DoesNotThrowIfReferencesWereClearedInCallback()
        {
            // Arrange
            var options = GetOptions(context =>
            {
                context.Compilation = context.Compilation.RemoveAllReferences();
            });
            var content            = "public class MyTestType  {}";
            var compilationService = new DefaultRoslynCompilationService(
                dependencyContext: GetDependencyContext(),
                viewEngineOptions: options,
                fileProviderAccessor: GetFileProviderAccessor(),
                loggerFactory: NullLoggerFactory.Instance);

            var relativeFileInfo = new RelativeFileInfo(
                new TestFileInfo {
                PhysicalPath = "SomePath"
            },
                "some-relative-path.cshtml");

            // Act
            var result = compilationService.Compile(relativeFileInfo, content);

            // Assert
            Assert.Single(result.CompilationFailures);
        }
Ejemplo n.º 9
0
        public void Compile_ThrowsIfDependencyContextReturnsNoReferencesAndTheApplicationFailsToCompile()
        {
            // Arrange
            var content           = "public class MyTestType  {}";
            var dependencyContext = new DependencyContext(
                new TargetInfo("framework", "runtime", "signature", isPortable: true),
                Extensions.DependencyModel.CompilationOptions.Default,
                new CompilationLibrary[0],
                new RuntimeLibrary[0],
                Enumerable.Empty <RuntimeFallbacks>());
            var compilationService = new DefaultRoslynCompilationService(
                dependencyContext: dependencyContext,
                viewEngineOptions: GetOptions(),
                fileProviderAccessor: GetFileProviderAccessor(),
                loggerFactory: NullLoggerFactory.Instance);

            var relativeFileInfo = new RelativeFileInfo(
                new TestFileInfo {
                PhysicalPath = "SomePath"
            },
                "some-relative-path.cshtml");

            var expected = "The Razor page 'some-relative-path.cshtml' failed to compile. Ensure that your "
                           + "application's project.json sets the 'preserveCompilationContext' compilation property.";

            // Act and Assert
            var ex = Assert.Throws <InvalidOperationException>(() =>
                                                               compilationService.Compile(relativeFileInfo, content));

            Assert.Equal(expected, ex.Message);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Gets the Razor page for an input document stream. This is roughly modeled on
        /// DefaultRazorPageFactory and CompilerCache. Note that we don't actually bother
        /// with caching the page if it's from a live stream.
        /// </summary>
        private IRazorPage GetPageFromStream(
            string relativePath,
            string viewStartLocation,
            string layoutLocation,
            Stream stream,
            IFileProvider rootFileProvider,
            IRazorCompilationService razorCompilationService)
        {
            if (relativePath.StartsWith("~/", StringComparison.Ordinal))
            {
                // For tilde slash paths, drop the leading ~ to make it work with the underlying IFileProvider.
                relativePath = relativePath.Substring(1);
            }

            // Get the file info by combining the stream content with info found at the document's original location (if any)
            IFileInfo        fileInfo         = new StreamFileInfo(rootFileProvider.GetFileInfo(relativePath), stream);
            RelativeFileInfo relativeFileInfo = new RelativeFileInfo(fileInfo, relativePath);

            // Try to get the compilation from the cache, but only if the stream is empty
            // Cache key is relative path if no explicit view start or layout OR either/both of those if specified
            CompilationResult compilationResult = stream.Length == 0
                ? _compilationCache.GetOrAdd(
                viewStartLocation == null
                        ? (layoutLocation ?? relativePath)
                        : (layoutLocation == null ? viewStartLocation : viewStartLocation + layoutLocation),
                _ => GetCompilation(relativeFileInfo, razorCompilationService))
                : GetCompilation(relativeFileInfo, razorCompilationService);

            // Create and return the page
            // We're not actually using the ASP.NET cache, but the CompilerCacheResult ctor contains the logic to create the page factory
            CompilerCacheResult compilerCacheResult = new CompilerCacheResult(relativePath, compilationResult, Array.Empty <IChangeToken>());

            return(compilerCacheResult.PageFactory());
        }
        /// <inheritdoc />
        public CompilationResult Compile(RelativeFileInfo file)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            GeneratorResults results;

            using (var inputStream = file.FileInfo.CreateReadStream())
            {
                _logger.RazorFileToCodeCompilationStart(file.RelativePath);

                var startTimestamp = _logger.IsEnabled(LogLevel.Debug) ? Stopwatch.GetTimestamp() : 0;

                results = GenerateCode(file.RelativePath, inputStream);

                _logger.RazorFileToCodeCompilationEnd(file.RelativePath, startTimestamp);
            }

            if (!results.Success)
            {
                return(GetCompilationFailedResult(file, results.ParserErrors));
            }

            return(_compilationService.Compile(file, results.GeneratedCode));
        }
Ejemplo n.º 12
0
        public void Compile_ReturnsFailedResultIfParseFails()
        {
            // Arrange
            var generatorResult = new GeneratorResults(
                new Block(new BlockBuilder {
                Type = BlockType.Comment
            }),
                Enumerable.Empty <TagHelperDescriptor>(),
                new RazorError[] { new RazorError("some message", 1, 1, 1, 1) },
                new CodeBuilderResult("", new LineMapping[0]),
                new CodeTree());
            var host = new Mock <IMvcRazorHost>();

            host.Setup(h => h.GenerateCode(It.IsAny <string>(), It.IsAny <Stream>()))
            .Returns(generatorResult)
            .Verifiable();

            var fileInfo = new Mock <IFileInfo>();

            fileInfo.Setup(f => f.CreateReadStream())
            .Returns(Stream.Null);

            var compiler         = new Mock <ICompilationService>(MockBehavior.Strict);
            var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");
            var razorService     = new RazorCompilationService(compiler.Object, host.Object);

            // Act
            var result = razorService.Compile(relativeFileInfo);

            // Assert
            var ex = Assert.Throws <CompilationFailedException>(() => result.CompiledType);

            Assert.Equal("some message", Assert.Single(ex.Messages).Message);
            host.Verify();
        }
Ejemplo n.º 13
0
        public void Compile_ReturnsGeneratedCodePath_IfLinePragmaIsNotAvailable()
        {
            // Arrange
            var fileContent = "file content";
            var content     = "this should fail";

            var compilationService = GetRoslynCompilationService();
            var relativeFileInfo   = new RelativeFileInfo(
                new TestFileInfo {
                Content = fileContent
            },
                "some-relative-path");

            // Act
            var result = compilationService.Compile(relativeFileInfo, content);

            // Assert
            Assert.IsType <CompilationResult>(result);
            Assert.Null(result.CompiledType);

            var compilationFailure = Assert.Single(result.CompilationFailures);

            Assert.Equal("Generated Code", compilationFailure.SourceFilePath);
            Assert.Equal(content, compilationFailure.SourceFileContent);
        }
Ejemplo n.º 14
0
        public void Compile_SucceedsIfReferencesAreAddedInCallback()
        {
            // Arrange
            var options = GetOptions(context =>
            {
                var assemblyLocation = typeof(object).GetTypeInfo().Assembly.Location;

                context.Compilation = context
                                      .Compilation
                                      .AddReferences(MetadataReference.CreateFromFile(assemblyLocation));
            });
            var content = "public class MyTestType  {}";
            var applicationPartManager = new ApplicationPartManager();
            var compilationService     = GetRoslynCompilationService(applicationPartManager, options);

            var relativeFileInfo = new RelativeFileInfo(
                new TestFileInfo {
                PhysicalPath = "SomePath"
            },
                "some-relative-path.cshtml");

            // Act
            var result = compilationService.Compile(relativeFileInfo, content);

            // Assert
            Assert.Null(result.CompilationFailures);
            Assert.NotNull(result.CompiledType);
        }
Ejemplo n.º 15
0
        public void Compile_ReturnsCompilationFailureWithPathsFromLinePragmas()
        {
            // Arrange
            var viewPath     = "some-relative-path";
            var fileContent  = "test file content";
            var content      = $@"
#line 1 ""{viewPath}""
this should fail";
            var fileProvider = new TestFileProvider();
            var fileInfo     = fileProvider.AddFile(viewPath, fileContent);

            var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
            var relativeFileInfo   = new RelativeFileInfo(fileInfo, "some-relative-path");

            // Act
            var result = compilationService.Compile(relativeFileInfo, content);

            // Assert
            Assert.IsType <CompilationResult>(result);
            Assert.Null(result.CompiledType);
            var compilationFailure = Assert.Single(result.CompilationFailures);

            Assert.Equal(relativeFileInfo.RelativePath, compilationFailure.SourceFilePath);
            Assert.Equal(fileContent, compilationFailure.SourceFileContent);
        }
Ejemplo n.º 16
0
        public void Compile_ThrowsIfDependencyContextIsNullAndTheApplicationFailsToCompileWithNoReferences()
        {
            // Arrange
            var content            = "public class MyTestType  {}";
            var compilationService = new DefaultRoslynCompilationService(
                dependencyContext: null,
                viewEngineOptions: GetOptions(),
                fileProviderAccessor: GetFileProviderAccessor(),
                loggerFactory: NullLoggerFactory.Instance);

            var relativeFileInfo = new RelativeFileInfo(
                new TestFileInfo {
                PhysicalPath = "SomePath"
            },
                "some-relative-path.cshtml");

            var expected = "The Razor page 'some-relative-path.cshtml' failed to compile. Ensure that your "
                           + "application's project.json sets the 'preserveCompilationContext' compilation property.";

            // Act and Assert
            var ex = Assert.Throws <InvalidOperationException>(() =>
                                                               compilationService.Compile(relativeFileInfo, content));

            Assert.Equal(expected, ex.Message);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Gets the Razor page for an input document stream. This is roughly modeled on
        /// DefaultRazorPageFactory and CompilerCache. Note that we don't actually bother
        /// with caching the page if it's from a live stream.
        /// </summary>
        private IRazorPage GetPageFromStream(IServiceProvider serviceProvider, RenderRequest request)
        {
            string relativePath = request.RelativePath;

            if (relativePath.StartsWith("~/", StringComparison.Ordinal))
            {
                // For tilde slash paths, drop the leading ~ to make it work with the underlying IFileProvider.
                relativePath = relativePath.Substring(1);
            }

            // Get the file info by combining the stream content with info found at the document's original location (if any)
            IHostingEnvironment hostingEnvironment = serviceProvider.GetRequiredService <IHostingEnvironment>();
            IFileInfo           fileInfo           = new StreamFileInfo(hostingEnvironment.WebRootFileProvider.GetFileInfo(relativePath), request.Input);
            RelativeFileInfo    relativeFileInfo   = new RelativeFileInfo(fileInfo, relativePath);

            // Compute a hash for the content since pipelines could have changed it from the underlying file
            // We have to pre-compute the hash (I.e., no CryptoStream) since we need to check for a hit before reading/compiling the view
            byte[] hash = MD5.Create().ComputeHash(request.Input);
            request.Input.Position = 0;

            CompilerCacheResult compilerCacheResult = CompilePage(serviceProvider, request, hash, relativeFileInfo, relativePath);

            IRazorPage result = compilerCacheResult.PageFactory();

            return(result);
        }
Ejemplo n.º 18
0
        private CompilationResult GetCompilation(RelativeFileInfo relativeFileInfo, IRazorCompilationService razorCompilationService)
        {
            CompilationResult compilationResult = razorCompilationService.Compile(relativeFileInfo);

            compilationResult.EnsureSuccessful();
            return(compilationResult);
        }
Ejemplo n.º 19
0
        public void CompileSetsEnableInstrumentationOnHost(bool enableInstrumentation)
        {
            // Arrange
            var host = new Mock <IMvcRazorHost>();

            host.SetupAllProperties();
            host.Setup(h => h.GenerateCode(It.IsAny <string>(), It.IsAny <Stream>()))
            .Returns(GetGeneratorResult());

            var compiler = new Mock <ICompilationService>();

            compiler.Setup(c => c.Compile(It.IsAny <IFileInfo>(), It.IsAny <string>()))
            .Returns(CompilationResult.Successful(GetType()));

            var razorService = new RazorCompilationService(compiler.Object, host.Object);

            var relativeFileInfo = new RelativeFileInfo()
            {
                FileInfo     = Mock.Of <IFileInfo>(),
                RelativePath = @"views\index\home.cshtml",
            };

            // Act
            razorService.Compile(relativeFileInfo, isInstrumented: enableInstrumentation);

            // Assert
            Assert.Equal(enableInstrumentation, host.Object.EnableInstrumentation);
        }
Ejemplo n.º 20
0
 public ViewCompilationInfo(
     RelativeFileInfo relativeFileInfo,
     GeneratorResults generatorResults)
 {
     RelativeFileInfo = relativeFileInfo;
     GeneratorResults = generatorResults;
 }
Ejemplo n.º 21
0
        public void GetOrAdd_ReturnsCompilationResultFromFactory()
        {
            // Arrange
            var cache    = new CompilerCache();
            var fileInfo = new Mock <IFileInfo>();

            fileInfo
            .SetupGet(i => i.LastModified)
            .Returns(DateTime.FromFileTimeUtc(10000));

            var type     = GetType();
            var expected = UncachedCompilationResult.Successful(type, "hello world");

            var runtimeFileInfo = new RelativeFileInfo()
            {
                FileInfo     = fileInfo.Object,
                RelativePath = "ab",
            };

            // Act
            var actual = cache.GetOrAdd(runtimeFileInfo, false, () => expected);

            // Assert
            Assert.Same(expected, actual);
            Assert.Equal("hello world", actual.CompiledContent);
            Assert.Same(type, actual.CompiledType);
        }
Ejemplo n.º 22
0
        public void CompileCalculatesRootRelativePath(string appPath, string viewPath)
        {
            // Arrange
            var host = new Mock <IMvcRazorHost>();

            host.Setup(h => h.GenerateCode(@"Views\index\home.cshtml", It.IsAny <Stream>()))
            .Returns(GetGeneratorResult())
            .Verifiable();

            var fileInfo = new Mock <IFileInfo>();

            fileInfo.Setup(f => f.PhysicalPath).Returns(viewPath);
            fileInfo.Setup(f => f.CreateReadStream()).Returns(Stream.Null);

            var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");

            var compiler = new Mock <ICompilationService>();

            compiler.Setup(c => c.Compile(relativeFileInfo, It.IsAny <string>()))
            .Returns(new CompilationResult(typeof(RazorCompilationServiceTest)));

            var razorService = new RazorCompilationService(compiler.Object, host.Object, GetFileProviderAccessor(), NullLoggerFactory.Instance);

            // Act
            razorService.Compile(relativeFileInfo);

            // Assert
            host.Verify();
        }
Ejemplo n.º 23
0
        public void Compile_DoesNotThrow_IfFileCannotBeRead()
        {
            // Arrange
            var path    = "some-relative-path";
            var content = $@"
#line 1 ""{path}""
this should fail";

            var mockFileInfo = new Mock <IFileInfo>();

            mockFileInfo.Setup(f => f.CreateReadStream())
            .Throws(new Exception());
            var fileProvider = new TestFileProvider();

            fileProvider.AddFile(path, mockFileInfo.Object);

            var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
            var relativeFileInfo   = new RelativeFileInfo(mockFileInfo.Object, path);

            // Act
            var result = compilationService.Compile(relativeFileInfo, content);

            // Assert
            Assert.IsType <CompilationResult>(result);
            Assert.Null(result.CompiledType);
            var compilationFailure = Assert.Single(result.CompilationFailures);

            Assert.Equal(path, compilationFailure.SourceFilePath);
            Assert.Null(compilationFailure.SourceFileContent);
        }
Ejemplo n.º 24
0
        public void Compile_UsesApplicationsCompilationSettings_ForParsingAndCompilation()
        {
            // Arrange
            var content = @"
#if MY_CUSTOM_DEFINE
public class MyCustomDefinedClass {}
#else
public class MyNonCustomDefinedClass {}
#endif
";
            var options = GetOptions();

            options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("MY_CUSTOM_DEFINE");
            var compilationService = GetRoslynCompilationService(options: options);
            var relativeFileInfo   = new RelativeFileInfo(
                new TestFileInfo {
                PhysicalPath = "SomePath"
            },
                "some-relative-path");

            // Act
            var result = compilationService.Compile(relativeFileInfo, content);

            // Assert
            Assert.NotNull(result.CompiledType);
            Assert.Equal("MyCustomDefinedClass", result.CompiledType.Name);
        }
        /// <inheritdoc />
        public CompilationResult Compile([NotNull] RelativeFileInfo fileInfo, [NotNull] string compilationContent)
        {
            var assemblyName        = Path.GetRandomFileName();
            var compilationSettings = _compilerOptionsProvider.GetCompilationSettings(_environment);
            var syntaxTree          = SyntaxTreeGenerator.Generate(compilationContent,
                                                                   assemblyName,
                                                                   compilationSettings);
            var references = _applicationReferences.Value;

            var compilationOptions = compilationSettings.CompilationOptions
                                     .WithOutputKind(OutputKind.DynamicallyLinkedLibrary);

            var compilation = CSharpCompilation.Create(assemblyName,
                                                       options: compilationOptions,
                                                       syntaxTrees: new[] { syntaxTree },
                                                       references: references);

            using (var ms = new MemoryStream()) {
                using (var pdb = new MemoryStream()) {
                    EmitResult result;

                    if (_supportsPdbGeneration.Value)
                    {
                        result = compilation.Emit(ms, pdbStream: pdb);
                    }
                    else
                    {
                        result = compilation.Emit(ms);
                    }

                    if (!result.Success)
                    {
                        return(GetCompilationFailedResult(
                                   fileInfo.RelativePath,
                                   compilationContent,
                                   assemblyName,
                                   result.Diagnostics));
                    }

                    Assembly assembly;
                    ms.Seek(0, SeekOrigin.Begin);

                    if (_supportsPdbGeneration.Value)
                    {
                        pdb.Seek(0, SeekOrigin.Begin);
                        assembly = _loader.LoadStream(ms, pdb);
                    }
                    else
                    {
                        assembly = _loader.LoadStream(ms, assemblySymbols: null);
                    }

                    var type = assembly.GetExportedTypes()
                               .First(t => t.Name.StartsWith(_classPrefix, StringComparison.Ordinal));

                    return(UncachedCompilationResult.Successful(type, compilationContent));
                }
            }
        }
Ejemplo n.º 26
0
        public CompilationResult Compile(RelativeFileInfo fileInfo)
        {
            var result = _inner.Compile(fileInfo);

            _log.Add(new CompileEntry {
                FileInfo = fileInfo, Result = result
            });
            return(result);
        }
        /// <inheritdoc />
        public CompilationResult Compile(RelativeFileInfo fileInfo, string compilationContent)
        {
            var assemblyName = Path.GetRandomFileName();
            var compilationSettings = _compilerOptionsProvider.GetCompilationSettings(_environment);
            var syntaxTree = SyntaxTreeGenerator.Generate(compilationContent,
                                                          assemblyName,
                                                          compilationSettings);
            var references = _applicationReferences.Value;

            var compilationOptions = compilationSettings.CompilationOptions
                                                        .WithOutputKind(OutputKind.DynamicallyLinkedLibrary);

            var compilation = CSharpCompilation.Create(assemblyName,
                        options: compilationOptions,
                        syntaxTrees: new[] { syntaxTree },
                        references: references);

            using (var ms = new MemoryStream()) {
                using (var pdb = new MemoryStream()) {
                    EmitResult result;

                    if (_supportsPdbGeneration.Value) {
                        result = compilation.Emit(ms, pdbStream: pdb);
                    }
                    else {
                        result = compilation.Emit(ms);
                    }

                    if (!result.Success) {
                        return GetCompilationFailedResult(
                            fileInfo.RelativePath,
                            compilationContent,
                            assemblyName,
                            result.Diagnostics);
                    }

                    Assembly assembly;
                    ms.Seek(0, SeekOrigin.Begin);

                    if (_supportsPdbGeneration.Value) {
                        pdb.Seek(0, SeekOrigin.Begin);
                        assembly = _loader.LoadStream(ms, pdb);
                    }
                    else {
                        assembly = _loader.LoadStream(ms, assemblySymbols: null);
                    }

                    var type = assembly.GetExportedTypes()
                                       .First(t => t.Name.StartsWith(_classPrefix, StringComparison.Ordinal));

                    return UncachedCompilationResult.Successful(type, compilationContent);
                }
            }
        }
Ejemplo n.º 28
0
        private MemoryCacheEntryOptions GetMemoryCacheEntryOptions(
            RelativeFileInfo fileInfo,
            PrecompilationCacheEntry cacheEntry)
        {
            var options = new MemoryCacheEntryOptions();

            options.AddExpirationToken(FileProvider.Watch(fileInfo.RelativePath));
            foreach (var path in ViewHierarchyUtility.GetViewImportsLocations(fileInfo.RelativePath))
            {
                options.AddExpirationToken(FileProvider.Watch(path));
            }
            return(options);
        }
        /// <inheritdoc />
        public CompilationResult Compile(RelativeFileInfo fileInfo, string compilationContent)
        {
            if (fileInfo == null)
            {
                throw new ArgumentNullException(nameof(fileInfo));
            }

            if (compilationContent == null)
            {
                throw new ArgumentNullException(nameof(compilationContent));
            }

            _logger.GeneratedCodeToAssemblyCompilationStart(fileInfo.RelativePath);
            var startTimestamp = _logger.IsEnabled(LogLevel.Debug) ? Stopwatch.GetTimestamp() : 0;

            var assemblyName = Path.GetRandomFileName();
            var compilation  = CreateCompilation(compilationContent, assemblyName);

            using (var assemblyStream = new MemoryStream())
            {
                using (var pdbStream = new MemoryStream())
                {
                    var result = compilation.Emit(
                        assemblyStream,
                        pdbStream,
                        options: _compiler.EmitOptions);

                    if (!result.Success)
                    {
                        return(GetCompilationFailedResult(
                                   fileInfo.RelativePath,
                                   compilationContent,
                                   assemblyName,
                                   result.Diagnostics));
                    }

                    assemblyStream.Seek(0, SeekOrigin.Begin);
                    pdbStream.Seek(0, SeekOrigin.Begin);

                    var assembly = LoadAssembly(assemblyStream, pdbStream);
                    var type     = assembly.GetExportedTypes().FirstOrDefault(a => !a.IsNested);

                    _logger.GeneratedCodeToAssemblyCompilationEnd(fileInfo.RelativePath, startTimestamp);

                    SaveAssembly(fileInfo, assemblyStream, pdbStream);

                    return(new CompilationResult(type));
                }
            }
        }
        public IRazorPage CreateInstance([NotNull] string relativePath, Stream stream)
        {
            if (relativePath.StartsWith("~/", StringComparison.Ordinal))
            {
                // For tilde slash paths, drop the leading ~ to make it work with the underlying IFileProvider.
                relativePath = relativePath.Substring(1);
            }

            // Code below is taken from CompilerCache (specifically OnCacheMiss) which is responsible for managing the compilation step in MVC

            // Check the file
            var fileProvider = stream == null ? (IFileProvider)_fileProvider : new WyamStreamFileProvider(_fileProvider, stream);
            var fileInfo     = fileProvider.GetFileInfo(relativePath);

            if (!fileInfo.Exists)
            {
                return(null);
            }

            // If relative path is the root, it probably means this isn't from reading a file so don't bother with caching
            IExecutionCache cache    = relativePath == "/" ? null : _executionContext.ExecutionCache;
            string          key      = null;
            Type            pageType = null;

            if (cache != null)
            {
                key = relativePath + " " + RazorFileHash.GetHash(fileInfo);
                if (!cache.TryGetValue(key, out pageType))
                {
                    pageType = null;
                }
            }

            // Compile and store in cache if not found
            if (pageType == null)
            {
                var relativeFileInfo = new RelativeFileInfo(fileInfo, relativePath);
                pageType = _razorcompilationService.Compile(relativeFileInfo);
                cache?.Set(key, pageType);
            }

            // Create an return a new page instance
            IRazorPage page = (IRazorPage)Activator.CreateInstance(pageType);

            page.Path = relativePath;
            return(page);
        }
Ejemplo n.º 31
0
        public void FileWithTheSameLengthAndDifferentTime_DoesNot_OverridesPrecompilation(
            Type resultViewType,
            long fileTimeUTC,
            bool swapsPreCompile)
        {
            // Arrange
            var instance = (View)Activator.CreateInstance(resultViewType);
            var length   = Encoding.UTF8.GetByteCount(instance.Content);

            var collection = new ViewCollection();
            var cache      = new CompilerCache(new[] { new ViewCollection() });

            var fileInfo = new Mock <IFileInfo>();

            fileInfo
            .SetupGet(i => i.Length)
            .Returns(length);
            fileInfo
            .SetupGet(i => i.LastModified)
            .Returns(DateTime.FromFileTimeUtc(fileTimeUTC));
            fileInfo.Setup(i => i.CreateReadStream())
            .Returns(GetMemoryStream(instance.Content));

            var preCompileType = typeof(PreCompile);

            var runtimeFileInfo = new RelativeFileInfo()
            {
                FileInfo     = fileInfo.Object,
                RelativePath = "ab",
            };

            // Act
            var actual = cache.GetOrAdd(runtimeFileInfo,
                                        enableInstrumentation: false,
                                        compile: () => CompilationResult.Successful(resultViewType));

            // Assert
            if (swapsPreCompile)
            {
                Assert.Equal(actual.CompiledType, resultViewType);
            }
            else
            {
                Assert.Equal(actual.CompiledType, typeof(PreCompile));
            }
        }
Ejemplo n.º 32
0
        protected virtual PrecompilationCacheEntry GetCacheEntry(RelativeFileInfo fileInfo)
        {
            if (fileInfo == null)
            {
                throw new ArgumentNullException(nameof(fileInfo));
            }

            using (var stream = fileInfo.FileInfo.CreateReadStream())
            {
                using (var host = GetRazorHost())
                {
                    var results = host.GenerateCode(fileInfo.RelativePath, stream);

                    if (results.Success)
                    {
                        var syntaxTree = SyntaxTreeGenerator.Generate(
                            results.GeneratedCode,
                            fileInfo.FileInfo.PhysicalPath,
                            CompilationSettings);
                        var fullTypeName = results.GetMainClassName(host, syntaxTree);

                        if (fullTypeName != null)
                        {
                            var razorFileInfo = new RazorFileInfo
                            {
                                RelativePath = fileInfo.RelativePath,
                                FullTypeName = fullTypeName
                            };

                            return(new PrecompilationCacheEntry(razorFileInfo, syntaxTree));
                        }
                    }
                    else
                    {
                        var diagnostics = results
                                          .ParserErrors
                                          .Select(error => error.ToDiagnostics(fileInfo.FileInfo.PhysicalPath))
                                          .ToList();

                        return(new PrecompilationCacheEntry(diagnostics));
                    }
                }
            }

            return(null);
        }
Ejemplo n.º 33
0
        protected virtual PrecompilationCacheEntry GetCacheEntry([NotNull] RelativeFileInfo fileInfo)
        {
            using (var stream = fileInfo.FileInfo.CreateReadStream())
            {
                var host    = GetRazorHost();
                var results = host.GenerateCode(fileInfo.RelativePath, stream);

                if (results.Success)
                {
                    var syntaxTree = SyntaxTreeGenerator.Generate(results.GeneratedCode,
                                                                  fileInfo.FileInfo.PhysicalPath,
                                                                  CompilationSettings);
                    var fullTypeName = results.GetMainClassName(host, syntaxTree);

                    if (fullTypeName != null)
                    {
                        var hashAlgorithmVersion = RazorFileHash.HashAlgorithmVersion1;
                        var hash          = RazorFileHash.GetHash(fileInfo.FileInfo, hashAlgorithmVersion);
                        var razorFileInfo = new RazorFileInfo
                        {
                            RelativePath         = fileInfo.RelativePath,
                            LastModified         = fileInfo.FileInfo.LastModified,
                            Length               = fileInfo.FileInfo.Length,
                            FullTypeName         = fullTypeName,
                            Hash                 = hash,
                            HashAlgorithmVersion = hashAlgorithmVersion
                        };

                        return(new PrecompilationCacheEntry(razorFileInfo, syntaxTree));
                    }
                }
                else
                {
                    var diagnostics = results.ParserErrors
                                      .Select(error => error.ToDiagnostics(fileInfo.FileInfo.PhysicalPath))
                                      .ToList();

                    return(new PrecompilationCacheEntry(diagnostics));
                }
            }

            return(null);
        }
        public void Compile_ReturnsResultFromCompilationServiceIfParseSucceeds()
        {
            // Arrange
            var code = "compiled-content";
            var generatorResult = new GeneratorResults(
                    new Block(new BlockBuilder { Type = BlockType.Comment }),
                    Enumerable.Empty<TagHelperDescriptor>(),
                    new ParserErrorSink(),
                    new CodeBuilderResult(code, new LineMapping[0]),
                    new CodeTree());
            var host = new Mock<IMvcRazorHost>();
            host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>()))
                .Returns(generatorResult);

            var fileInfo = new Mock<IFileInfo>();
            fileInfo.Setup(f => f.CreateReadStream())
                    .Returns(Stream.Null);
            var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml");

            var compilationResult = CompilationResult.Successful(typeof(object));
            var compiler = new Mock<ICompilationService>();
            compiler.Setup(c => c.Compile(relativeFileInfo, code))
                    .Returns(compilationResult)
                    .Verifiable();
            var razorService = new RazorCompilationService(compiler.Object, host.Object);

            // Act
            var result = razorService.Compile(relativeFileInfo);

            // Assert
            Assert.Same(compilationResult, result);
            compiler.Verify();
        }