private static void TestSyntaxTreeFactoryService(ISyntaxTreeFactoryService service, string text, string fileName) { var parseOptions = service.GetDefaultParseOptions(); var workspaceServices = new TestWorkspaceServiceProvider(); var tree = service.ParseSyntaxTree( fileName, parseOptions, SourceText.From(text), CancellationToken.None); var textAndVersion = TextAndVersion.Create( tree.GetText(), VersionStamp.Create(), fileName); var valueSource = new AsyncLazy<TextAndVersion>(textAndVersion); var recoverableTree = service.CreateRecoverableTree( tree.FilePath, tree.Options, valueSource, tree.GetRoot()); workspaceServices.GetService<ISyntaxTreeCacheService>().Clear(); var trivia = tree.GetRoot().GetLeadingTrivia().First(); var actualTrivia = recoverableTree.GetRoot().GetLeadingTrivia().First(); Assert.Equal(trivia.ToFullString(), actualTrivia.ToFullString()); }
// 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.DocumentAttributes attributes, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode, SolutionServices solutionServices) { string filePath = attributes.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(attributes), 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(attributes.Id.ProjectId, GetSyntaxTreeFilePath(attributes), options, lazyTextAndVersion, encoding, newRoot); } return(Tuple.Create(lazyTextAndVersion, TreeAndVersion.Create(tree, treeVersion))); }
// use static method so we don't capture references to this private static Tuple<AsyncLazy<TextAndVersion>, AsyncLazy<TreeAndVersion>> CreateRecoverableTextAndTree( SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, DocumentInfo info, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode) { string filePath = info.FilePath; Encoding encoding = info.DefaultEncoding; AsyncLazy<TreeAndVersion> lazyTree = null; // this captures the lazyTree local var lazyText = new AsyncLazy<TextAndVersion>( c => GetTextAndVersionAsync(lazyTree, textVersion, encoding, filePath, c), c => GetTextAndVersion(lazyTree, textVersion, encoding, filePath, c), cacheResult: false); // this should be only called when we do forking, since there is no cheap way to figure out what has been changed, // we will always consider top level being changed by giving new version here. if (mode == PreservationMode.PreserveIdentity) { lazyTree = new AsyncLazy<TreeAndVersion>( TreeAndVersion.Create(factory.CreateSyntaxTree(GetSyntaxTreeFilePath(info), options, newRoot, encoding), treeVersion)); } else { lazyTree = new AsyncLazy<TreeAndVersion>( TreeAndVersion.Create(factory.CreateRecoverableTree(GetSyntaxTreeFilePath(info), options, lazyText, newRoot, reparse: false), treeVersion)); } return Tuple.Create(lazyText, lazyTree); }
// use static method so we don't capture references to this private static Tuple<AsyncLazy<TextAndVersion>, TreeAndVersion> CreateRecoverableTextAndTree( SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, DocumentInfo info, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode, SolutionServices solutionServices) { string filePath = info.FilePath; TreeAndVersion lazyTree = null; // Since this text will be created from a tree, it doesn't have an explicit encoding. // We'll check for this case when writing out the file, and look at the original file's // encoding. Encoding encoding = null; // this captures the lazyTree local var lazyText = new AsyncLazy<TextAndVersion>( c => GetTextAndVersionAsync(lazyTree, textVersion, encoding, filePath, c), c => GetTextAndVersion(lazyTree, textVersion, encoding, filePath, c), cacheResult: false); lazyTree = TreeAndVersion.Create( (mode == PreservationMode.PreserveIdentity) || !solutionServices.SupportsCachingRecoverableObjects ? factory.CreateSyntaxTree(GetSyntaxTreeFilePath(info), options, newRoot, encoding) : factory.CreateRecoverableTree(info.Id.ProjectId, GetSyntaxTreeFilePath(info), options, lazyText, newRoot), treeVersion); return Tuple.Create(lazyText, lazyTree); }
// 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)); }
public SyntaxNode Retrieve(SyntaxTree tree, ISyntaxTreeFactoryService service, CancellationToken cancellationToken) { ITemporaryStorage storage; if (!map.TryGetValue(tree, out storage)) { return null; } using (var stream = storage.ReadStream(cancellationToken)) { return service.DeserializeNodeFrom(stream, cancellationToken); } }
public async Task<SyntaxNode> RetrieveAsync(SyntaxTree tree, ISyntaxTreeFactoryService service, CancellationToken cancellationToken) { ITemporaryStorage storage; if (!map.TryGetValue(tree, out storage)) { return null; } using (var stream = await storage.ReadStreamAsync(cancellationToken).ConfigureAwait(false)) { return service.DeserializeNodeFrom(stream, cancellationToken); } }