| File: Language\DefaultRazorParsingPhase.cs | Web Access |
| Project: src\roslyn\src\Razor\src\Compiler\Microsoft.CodeAnalysis.Razor.Compiler\src\Microsoft.CodeAnalysis.Razor.Compiler.csproj (Microsoft.CodeAnalysis.Razor.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Threading; using Microsoft.AspNetCore.Razor.PooledObjects; namespace Microsoft.AspNetCore.Razor.Language; internal class DefaultRazorParsingPhase : RazorEnginePhaseBase, IRazorParsingPhase { private static readonly ConditionalWeakTable<RazorSourceDocument, RazorSyntaxTree> s_importTrees = new(); #if !NET private static readonly object s_importTreesLock = new(); #endif protected override RazorCodeDocument ExecuteCore(RazorCodeDocument codeDocument, CancellationToken cancellationToken) { var options = codeDocument.ParserOptions; var syntaxTree = RazorSyntaxTree.Parse(codeDocument.Source, options, cancellationToken); using var importSyntaxTrees = new PooledArrayBuilder<RazorSyntaxTree>(codeDocument.Imports.Length); foreach (var import in codeDocument.Imports) { // Attempt to pull the parsed import tree from the CWT if (!TryGetCachedImportTree(import, options, out var tree)) { // We don't have a cached version, parse the import and add it to the CWT tree = RazorSyntaxTree.Parse(import, options, cancellationToken); #if NET s_importTrees.AddOrUpdate(import, tree); #else // NetStandard2.0 doesn't have a nice AddOrUpdate method, so we'll use our own locking to // ensure the CWT is updated correctly. lock (s_importTreesLock) { if (TryGetCachedImportTree(import, options, out var cachedTree)) { // Someone else added it while we were parsing, use theirs. tree = cachedTree; } else { if (cachedTree is not null) { // If there is a cachedTree, it must have different options. Remove it from the cache s_importTrees.Remove(import); } // Add the tree we created to the cache s_importTrees.Add(import, tree); } } #endif } importSyntaxTrees.Add(tree); } return codeDocument .WithSyntaxTree(syntaxTree) .WithImportSyntaxTrees(importSyntaxTrees.ToImmutableAndClear()); static bool TryGetCachedImportTree(RazorSourceDocument import, RazorParserOptions options, [NotNullWhen(true)] out RazorSyntaxTree? tree) => s_importTrees.TryGetValue(import, out tree) && tree.Options.Equals(options); } }