private static (ValueSource <TextAndVersion>, TreeAndVersion) CreateRecoverableTextAndTree( SyntaxNode newRoot, string filePath, VersionStamp textVersion, VersionStamp treeVersion, Encoding?encoding, DocumentInfo.DocumentAttributes attributes, ParseOptions options, ImmutableDictionary <string, ReportDiagnostic>?treeDiagnosticReportingOptions, ISyntaxTreeFactoryService factory, PreservationMode mode) { SyntaxTree tree; ValueSource <TextAndVersion> lazyTextAndVersion; if (mode == PreservationMode.PreserveIdentity || !factory.CanCreateRecoverableTree(newRoot)) { tree = factory.CreateSyntaxTree(filePath, options, encoding, newRoot, treeDiagnosticReportingOptions); // its okay to use a strong cached AsyncLazy here because the compiler layer SyntaxTree will also keep the text alive once its built. lazyTextAndVersion = new TreeTextSource( new AsyncLazy <SourceText>( c => tree.GetTextAsync(c), c => tree.GetText(c), cacheResult: true), textVersion, filePath); } else { // There is a strange circularity here: the creation of lazyTextAndVersion reads this local, but will see it as non-null since it // only uses it through a lambda that won't have ran. The assignment exists to placate the definite-assignment analysis (which is // right to be suspicious of this). tree = null !; // Uses CachedWeakValueSource so the document and tree will return the same SourceText instance across multiple accesses as long // as the text is referenced elsewhere. lazyTextAndVersion = new TreeTextSource( new CachedWeakValueSource <SourceText>( new AsyncLazy <SourceText>( // Build text from root, so recoverable tree won't cycle. async cancellationToken => (await tree.GetRootAsync(cancellationToken).ConfigureAwait(false)).GetText(encoding), cancellationToken => tree.GetRoot(cancellationToken).GetText(encoding), cacheResult: false)), textVersion, filePath); tree = factory.CreateRecoverableTree(attributes.Id.ProjectId, filePath, options, lazyTextAndVersion, encoding, newRoot, treeDiagnosticReportingOptions); } return(lazyTextAndVersion, TreeAndVersion.Create(tree, treeVersion)); }
// use static method so we don't capture references to this private static Tuple <ValueSource <TextAndVersion>, TreeAndVersion> CreateRecoverableTextAndTree( SyntaxNode newRoot, string filePath, VersionStamp textVersion, VersionStamp treeVersion, Encoding encoding, DocumentInfo.DocumentAttributes attributes, ParseOptions options, ImmutableDictionary <string, ReportDiagnostic> treeDiagnosticReportingOptionsOpt, ISyntaxTreeFactoryService factory, PreservationMode mode) { SyntaxTree tree = null; ValueSource <TextAndVersion> lazyTextAndVersion = null; if ((mode == PreservationMode.PreserveIdentity) || !factory.CanCreateRecoverableTree(newRoot)) { // its okay to use a strong cached AsyncLazy here because the compiler layer SyntaxTree will also keep the text alive once its built. lazyTextAndVersion = new TreeTextSource( new AsyncLazy <SourceText>( c => tree.GetTextAsync(c), c => tree.GetText(c), cacheResult: true), textVersion, filePath); tree = factory.CreateSyntaxTree(filePath, options, encoding, newRoot, treeDiagnosticReportingOptionsOpt); } else { // uses CachedWeakValueSource so the document and tree will return the same SourceText instance across multiple accesses as long // as the text is referenced elsewhere. lazyTextAndVersion = new TreeTextSource( new CachedWeakValueSource <SourceText>( new AsyncLazy <SourceText>( c => BuildRecoverableTreeTextAsync(tree, encoding, c), c => BuildRecoverableTreeText(tree, encoding, c), cacheResult: false)), textVersion, filePath); tree = factory.CreateRecoverableTree(attributes.Id.ProjectId, filePath, options, lazyTextAndVersion, encoding, newRoot, treeDiagnosticReportingOptionsOpt); } return(Tuple.Create(lazyTextAndVersion, TreeAndVersion.Create(tree, treeVersion))); }
// use static method so we don't capture references to this private static Tuple<ValueSource<TextAndVersion>, TreeAndVersion> CreateRecoverableTextAndTree( SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, Encoding encoding, DocumentInfo info, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode, SolutionServices solutionServices) { string filePath = info.FilePath; SyntaxTree tree = null; ValueSource<TextAndVersion> lazyTextAndVersion = null; if ((mode == PreservationMode.PreserveIdentity) || !factory.CanCreateRecoverableTree(newRoot)) { // its okay to use a strong cached AsyncLazy here because the compiler layer SyntaxTree will also keep the text alive once its built. lazyTextAndVersion = new TreeTextSource( new AsyncLazy<SourceText>( c => tree.GetTextAsync(c), c => tree.GetText(c), cacheResult: true), textVersion, filePath); tree = factory.CreateSyntaxTree(GetSyntaxTreeFilePath(info), options, encoding, newRoot); } else { // uses CachedWeakValueSource so the document and tree will return the same SourceText instance across multiple accesses as long // as the text is referenced elsewhere. lazyTextAndVersion = new TreeTextSource( new CachedWeakValueSource<SourceText>( new AsyncLazy<SourceText>( c => BuildRecoverableTreeTextAsync(tree, encoding, c), c => BuildRecoverableTreeText(tree, encoding, c), cacheResult: false)), textVersion, filePath); tree = factory.CreateRecoverableTree(info.Id.ProjectId, GetSyntaxTreeFilePath(info), options, lazyTextAndVersion, encoding, newRoot); } return Tuple.Create(lazyTextAndVersion, TreeAndVersion.Create(tree, treeVersion)); }