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());
        }
Пример #2
0
        // 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)));
        }
Пример #3
0
        // 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);
        }
Пример #4
0
        // 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);
        }
Пример #5
0
        // 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));
        }
Пример #6
0
        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);
            }
        }
Пример #7
0
        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);
            }
        }