private async Task <ViewCompilerWorkItem> CreateRuntimeCompilationWorkItem(string templateKey) { RazorLightProjectItem projectItem = null; if (_razorLightOptions.DynamicTemplates.TryGetValue(templateKey, out string templateContent)) { projectItem = new TextSourceRazorProjectItem(templateKey, templateContent); } else { string normalizedKey = GetNormalizedKey(templateKey); projectItem = await _razorProject.GetItemAsync(normalizedKey); } if (!projectItem.Exists) { throw new TemplateNotFoundException($"Project can not find template with key {projectItem.Key}"); } return(new ViewCompilerWorkItem() { SupportsCompilation = true, ProjectItem = projectItem, NormalizedKey = projectItem.Key, ExpirationToken = projectItem.ExpirationToken, }); }
protected virtual CompiledTemplateDescriptor CompileAndEmit(RazorLightProjectItem projectItem) { Assembly assembly = default(Assembly); if (_razorLightOptions.BinaryCache.TryGetValue($"{projectItem.Key}-Assembly", out var assemblyBinary) && _razorLightOptions.BinaryCache.TryGetValue($"{projectItem.Key}-Assembly", out var pdbBinary)) { assembly = _compiler.Emit(assemblyBinary, pdbBinary); } else { IGeneratedRazorTemplate generatedTemplate = _razorSourceGenerator.GenerateCodeAsync(projectItem).GetAwaiter().GetResult(); var compileResult = _compiler.Compile(generatedTemplate); _razorLightOptions.BinaryCache.CreateEntry($"{projectItem.Key}-Assembly", compileResult.AssemblyStream); _razorLightOptions.BinaryCache.CreateEntry($"{projectItem.Key}-Pdb", compileResult.PdbStream); assembly = _compiler.Emit(compileResult.AssemblyStream, compileResult.PdbStream); } // Anything we compile from source will use Razor 2.1 and so should have the new metadata. var loader = new RazorCompiledItemLoader(); var item = loader.LoadItems(assembly).SingleOrDefault(); var attribute = assembly.GetCustomAttribute <RazorLightTemplateAttribute>(); return(new CompiledTemplateDescriptor() { Item = item, TemplateKey = projectItem.Key, TemplateAttribute = attribute }); }
/// <summary> /// Parses the template specified by <paramref name="projectItem"/>. /// </summary> /// <param name="projectItem">The <see cref="RazorLightProjectItem"/>.</param> /// <returns>The <see cref="IGeneratedRazorTemplate"/>.</returns> public async Task <IGeneratedRazorTemplate> GenerateCodeAsync(RazorLightProjectItem projectItem) { if (projectItem == null) { throw new ArgumentNullException(nameof(projectItem)); } if (!projectItem.Exists) { throw new InvalidOperationException($"{nameof(RazorLightProjectItem)} of type " + $"{projectItem.GetType().FullName} with key {projectItem.Key} does not exist."); } RazorCodeDocument codeDocument = await CreateCodeDocumentAsync(projectItem); ProjectEngine.Process(codeDocument); RazorCSharpDocument document = codeDocument.GetCSharpDocument(); if (document.Diagnostics.Count > 0) { var builder = new StringBuilder(); builder.AppendLine("Failed to generate Razor template. See \"Diagnostics\" property for more details"); foreach (RazorDiagnostic d in document.Diagnostics) { builder.AppendLine($"- {d.GetMessage()}"); } throw new TemplateGenerationException(builder.ToString(), document.Diagnostics); } return(new GeneratedRazorTemplate(projectItem, document)); }
public async Task <TemplateFactoryResult> CreateFactoryAsync(RazorLightProjectItem projectItem) { if (projectItem == null) { throw new ArgumentNullException(nameof(projectItem)); } IGeneratedRazorTemplate razorTemplate = await sourceGenerator.GenerateCodeAsync(projectItem).ConfigureAwait(false); return(await CompileAsync(razorTemplate)); }
public GeneratedRazorTemplate(RazorLightProjectItem projectItem, RazorCSharpDocument cSharpDocument) { if (projectItem == null) { throw new ArgumentNullException(nameof(projectItem)); } if (cSharpDocument == null) { throw new ArgumentNullException(nameof(cSharpDocument)); } ProjectItem = projectItem; CSharpDocument = cSharpDocument; }
protected virtual CompiledTemplateDescriptor CompileAndEmit(RazorLightProjectItem projectItem) { IGeneratedRazorTemplate generatedTemplate = _razorSourceGenerator.GenerateCodeAsync(projectItem).GetAwaiter().GetResult(); Assembly assembly = _compiler.CompileAndEmit(generatedTemplate); // Anything we compile from source will use Razor 2.1 and so should have the new metadata. var loader = new RazorCompiledItemLoader(); var item = loader.LoadItems(assembly).SingleOrDefault(); var attribute = assembly.GetCustomAttribute <RazorLightTemplateAttribute>(); return(new CompiledTemplateDescriptor() { Item = item, TemplateKey = projectItem.Key, TemplateAttribute = attribute }); }
/// <summary> /// Parses the template specified by the project item <paramref name="key"/>. /// </summary> /// <param name="key">The template path.</param> /// <returns>The <see cref="IGeneratedRazorTemplate"/>.</returns> public async Task <IGeneratedRazorTemplate> GenerateCodeAsync(string key) { if (string.IsNullOrEmpty(key)) { throw new ArgumentException(); } if (Project == null) { string _message = $"Can not resolve a content for the template \"{key}\" as there is no project set. " + "You can only render a template by passing it's content directly via string using corresponding function overload"; throw new InvalidOperationException(_message); } RazorLightProjectItem projectItem = await Project.GetItemAsync(key).ConfigureAwait(false); return(await GenerateCodeAsync(projectItem)); }
private async Task <ViewCompilerWorkItem> CreateRuntimeCompilationWorkItem(string normalizedKey) { RazorLightProjectItem projectItem = null; if (_razorLightOptions.DynamicTemplates.TryGetValue(normalizedKey, out string templateContent)) { projectItem = new TextSourceRazorProjectItem(normalizedKey, templateContent); } else { projectItem = await _razorProject.GetItemAsync(normalizedKey); } if (!projectItem.Exists) { // If the file doesn't exist, we can't do compilation right now - we still want to cache // the fact that we tried. This will allow us to retrigger compilation if the view file // is added. return(new ViewCompilerWorkItem() { // We don't have enough information to compile SupportsCompilation = false, Descriptor = new CompiledTemplateDescriptor() { TemplateKey = normalizedKey, ExpirationToken = projectItem.ExpirationToken, }, // We can try again if the file gets created. ExpirationToken = projectItem.ExpirationToken, }); } return(new ViewCompilerWorkItem() { SupportsCompilation = true, ProjectItem = projectItem, NormalizedKey = normalizedKey, ExpirationToken = projectItem.ExpirationToken, }); }
/// <summary> /// Generates a <see cref="RazorCodeDocument"/> for the specified <paramref name="projectItem"/>. /// </summary> /// <param name="projectItem">The <see cref="RazorLightProjectItem"/>.</param> /// <returns>The created <see cref="RazorCodeDocument"/>.</returns> public virtual async Task <RazorCodeDocument> CreateCodeDocumentAsync(RazorLightProjectItem projectItem) { if (projectItem == null) { throw new ArgumentNullException(nameof(projectItem)); } if (!projectItem.Exists) { throw new InvalidOperationException($"Project can not find template with key {projectItem.Key}"); } using (var stream = projectItem.Read()) { RazorSourceDocument source = RazorSourceDocument.ReadFrom(stream, projectItem.Key); IEnumerable <RazorSourceDocument> imports = await GetImportsAsync(projectItem); return(RazorCodeDocument.Create(source, imports)); } }
/// <summary> /// Gets <see cref="RazorSourceDocument"/> that are applicable to the specified <paramref name="projectItem"/>. /// </summary> /// <param name="projectItem">The <see cref="RazorLightProjectItem"/>.</param> /// <returns>The sequence of applicable <see cref="RazorSourceDocument"/>.</returns> public virtual async Task <IEnumerable <RazorSourceDocument> > GetImportsAsync(RazorLightProjectItem projectItem) { if (projectItem == null) { throw new ArgumentNullException(nameof(projectItem)); } if (projectItem is TextSourceRazorProjectItem) { return(Enumerable.Empty <RazorSourceDocument>()); } var result = new List <RazorSourceDocument>(); IEnumerable <RazorLightProjectItem> importProjectItems = await Project.GetImportsAsync(projectItem.Key); foreach (var importItem in importProjectItems) { if (importItem.Exists) { using (var stream = importItem.Read()) { result.Insert(0, RazorSourceDocument.ReadFrom(stream, null)); } } } if (Namespaces != null) { RazorSourceDocument namespacesImports = GetNamespacesImports(); if (namespacesImports != null) { result.Insert(0, namespacesImports); } } if (DefaultImports != null) { result.Insert(0, DefaultImports); } return(result); }
internal async Task <TemplateNotFoundException> CreateTemplateNotFoundException(RazorLightProjectItem projectItem) { var msg = $"{nameof(RazorLightProjectItem)} of type {projectItem.GetType().FullName} with key {projectItem.Key} could not be found by the " + $"{ nameof(RazorLightProject)} of type { _razorProject.GetType().FullName} and does not exist in dynamic templates. "; var propNames = $"\"{nameof(TemplateNotFoundException.KnownDynamicTemplateKeys)}\" and \"{nameof(TemplateNotFoundException.KnownProjectTemplateKeys)}\""; if (_razorLightOptions.EnableDebugMode ?? false) { msg += $"See the {propNames} properties for known template keys."; var dynamicKeys = _razorLightOptions.DynamicTemplates.Keys.ToList(); var projectKeys = await _razorProject.GetKnownKeysAsync(); projectKeys = projectKeys == null?Enumerable.Empty <string>() : projectKeys.ToList(); return(new TemplateNotFoundException(msg, dynamicKeys, projectKeys)); } else { msg += $"Set {nameof(RazorLightOptions)}.{nameof(RazorLightOptions.EnableDebugMode)} to true to allow " + $"the {propNames} properties on this exception to be set."; return(new TemplateNotFoundException(msg)); } }