Exemplo n.º 1
0
 private static ValueSource<TreeAndVersion> CreateLazyFullyParsedTree(
     ValueSource<TextAndVersion> newTextSource,
     string filePath,
     ParseOptions options,
     HostLanguageServices languageServices,
     PreservationMode mode = PreservationMode.PreserveValue)
 {
     return new AsyncLazy<TreeAndVersion>(
         c => FullyParseTreeAsync(newTextSource, filePath, options, languageServices, mode, c),
         cacheResult: true);
 }
Exemplo n.º 2
0
 public static Solution WithTextDocumentText(this Solution solution, DocumentId documentId, SourceText text, PreservationMode mode = PreservationMode.PreserveIdentity)
 {
     var document = solution.GetTextDocument(documentId);
     if (document is Document)
     {
         return solution.WithDocumentText(documentId, text, mode);
     }
     else
     {
         return solution.WithAdditionalDocumentText(documentId, text, mode);
     }
 }
Exemplo n.º 3
0
        public new DocumentState UpdateText(TextAndVersion newTextAndVersion, PreservationMode mode)
        {
            if (newTextAndVersion == null)
            {
                throw new ArgumentNullException(nameof(newTextAndVersion));
            }

            var newTextSource = mode == PreservationMode.PreserveIdentity
                ? CreateStrongText(newTextAndVersion)
                : CreateRecoverableText(newTextAndVersion, this.solutionServices);

            // always chain incremental parsing request, it will internally put 
            // appropriate request such as full parsing request if there are too many pending 
            // incremental parsing requests hanging around.
            //
            // However, don't bother with the chaining if this is a document that doesn't support
            // syntax trees.  The chaining will keep old data alive (like the old tree source,
            // which itself is keeping an old tree source which itself is keeping a ... alive),
            // causing a slow memory leak.
            var newTreeSource = !this.SupportsSyntaxTree
                ? ValueSource<TreeAndVersion>.Empty
                : CreateLazyIncrementallyParsedTree(_treeSource, newTextSource);

            return new DocumentState(
                this.LanguageServices,
                this.solutionServices,
                this.info,
                _options,
                sourceTextOpt: null,
                textSource: newTextSource,
                treeSource: newTreeSource);
        }
Exemplo n.º 4
0
        internal DocumentState UpdateText(TextLoader loader, SourceText textOpt, PreservationMode mode)
        {
            if (loader == null)
            {
                throw new ArgumentNullException(nameof(loader));
            }

            var newTextSource = mode == PreservationMode.PreserveIdentity
                ? CreateStrongText(loader, this.Id, this.solutionServices, reportInvalidDataException: true)
                : CreateRecoverableText(loader, this.Id, this.solutionServices, reportInvalidDataException: true);

            // Only create the ValueSource for creating the SyntaxTree if this is a Document that
            // supports SyntaxTrees.  There's no point in creating the async lazy and holding onto
            // this data otherwise.
            var newTreeSource = !this.SupportsSyntaxTree
                ? ValueSource<TreeAndVersion>.Empty
                : CreateLazyFullyParsedTree(
                    newTextSource,
                    this.Id.ProjectId,
                    GetSyntaxTreeFilePath(this.info),
                    _options,
                    _languageServices,
                    this.solutionServices,
                    mode);

            return new DocumentState(
                this.LanguageServices,
                this.solutionServices,
                this.info,
                _options,
                sourceTextOpt: textOpt,
                textSource: newTextSource,
                treeSource: newTreeSource);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates a new solution instance with the additional document specified updated to have the text
        /// supplied by the text loader.
        /// </summary>
        public SolutionState WithAdditionalDocumentTextLoader(DocumentId documentId, TextLoader loader, PreservationMode mode)
        {
            CheckContainsAdditionalDocument(documentId);

            var oldDocument = this.GetAdditionalDocumentState(documentId);

            // assumes that text has changed. user could have closed a doc without saving and we are loading text from closed file with
            // old content. also this should make sure we don't re-use latest doc version with data associated with opened document.
            return this.WithTextDocumentState(oldDocument.UpdateText(loader, mode), textChanged: true, recalculateDependentVersions: true);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates a new solution instance with all the documents specified updated to have the same specified text.
        /// </summary>
        public Solution WithDocumentText(IEnumerable<DocumentId> documentIds, SourceText text, PreservationMode mode = PreservationMode.PreserveValue)
        {
            var newState = _state.WithDocumentText(documentIds, text, mode);
            if (newState == _state)
            {
                return this;
            }

            return new Solution(newState);
        }
Exemplo n.º 7
0
        private VersionStamp GetNewTreeVersionForUpdatedTree(SyntaxNode newRoot, VersionStamp newTextVersion, PreservationMode mode)
        {
            if (mode != PreservationMode.PreserveIdentity)
            {
                return newTextVersion;
            }

            TreeAndVersion oldTreeAndVersion;
            SyntaxNode oldRoot;
            if (!this.treeSource.TryGetValue(out oldTreeAndVersion) || !oldTreeAndVersion.Tree.TryGetRoot(out oldRoot))
            {
                return newTextVersion;
            }

            return oldRoot.IsEquivalentTo(newRoot, topLevel: true) ? oldTreeAndVersion.Version : newTextVersion;
        }
Exemplo n.º 8
0
 public new AnalyzerConfigDocumentState UpdateText(SourceText text, PreservationMode mode)
 {
     return((AnalyzerConfigDocumentState)base.UpdateText(text, mode));
 }
Exemplo n.º 9
0
        internal Solution WithDocumentTextLoader(DocumentId documentId, TextLoader loader, SourceText textOpt, PreservationMode mode)
        {
            var newState = _state.WithDocumentTextLoader(documentId, loader, textOpt, mode);

            if (newState == _state)
            {
                return(this);
            }

            return(new Solution(newState));
        }
Exemplo n.º 10
0
        public DocumentState UpdateText(SourceText newText, PreservationMode mode)
        {
            if (newText == null)
            {
                throw new ArgumentNullException("newText");
            }

            // check to see if this docstate has already been branched before with the same text.
            // this helps reduce duplicate parsing when typing.
            if (mode == PreservationMode.PreserveIdentity)
            {
                var br = this.firstBranch;
                if (br != null && br.Text == newText)
                {
                    return br.State;
                }
            }

            var newVersion = this.GetNewerVersion();
            var newTextAndVersion = TextAndVersion.Create(newText, newVersion, this.FilePath);

            var newState = this.UpdateText(newTextAndVersion, mode);

            if (mode == PreservationMode.PreserveIdentity && this.firstBranch == null)
            {
                Interlocked.CompareExchange(ref this.firstBranch, new DocumentBranch(newText, newState), null);
            }

            return newState;
        }
Exemplo n.º 11
0
        /// <summary>
        /// Creates a new solution instance with the document specified updated to have a syntax tree
        /// rooted by the specified syntax node.
        /// </summary>
        public Solution WithDocumentSyntaxRoot(DocumentId documentId, SyntaxNode root, PreservationMode mode = PreservationMode.PreserveValue)
        {
            var newState = _state.WithDocumentSyntaxRoot(documentId, root, mode);

            if (newState == _state)
            {
                return(this);
            }

            return(new Solution(newState));
        }
Exemplo n.º 12
0
 /// <summary>
 /// Creates a new solution instance with the document specified updated to have the text
 /// supplied by the text loader.
 /// </summary>
 public Solution WithDocumentTextLoader(DocumentId documentId, TextLoader loader, PreservationMode mode)
 {
     return(WithDocumentTextLoader(documentId, loader, textOpt: null, mode: mode));
 }
Exemplo n.º 13
0
 protected virtual TextDocumentState UpdateText(ValueSource <TextAndVersion> newTextSource, PreservationMode mode, bool incremental)
 {
     return(new TextDocumentState(
                this.solutionServices,
                this.Services,
                this.Attributes,
                sourceText: null,
                textAndVersionSource: newTextSource));
 }
Exemplo n.º 14
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));
        }
Exemplo n.º 15
0
 protected override TextDocumentState UpdateText(ValueSource <TextAndVersion> newTextSource, PreservationMode mode, bool incremental)
 {
     return(new AnalyzerConfigDocumentState(
                this.solutionServices,
                this.Services,
                this.Attributes,
                this.sourceText,
                newTextSource));
 }
Exemplo n.º 16
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));
        }
Exemplo n.º 17
0
        /// <summary>
        /// Creates a new solution instance with the analyzer config document specified updated to have the text
        /// supplied by the text loader.
        /// </summary>
        public Solution WithAnalyzerConfigDocumentText(DocumentId documentId, SourceText text, PreservationMode mode = PreservationMode.PreserveValue)
        {
            var newState = _state.WithAnalyzerConfigDocumentText(documentId, text, mode);

            if (newState == _state)
            {
                return(this);
            }

            return(new Solution(newState));
        }
Exemplo n.º 18
0
        private static async Task<TreeAndVersion> FullyParseTreeAsync(
            ValueSource<TextAndVersion> newTextSource,
            ProjectId cacheKey,
            string filePath,
            ParseOptions options,
            HostLanguageServices languageServices,
            SolutionServices solutionServices,
            PreservationMode mode,
            CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.Workspace_Document_State_FullyParseSyntaxTree, cancellationToken))
            {
                var textAndVersion = await newTextSource.GetValueAsync(cancellationToken).ConfigureAwait(false);
                var text = textAndVersion.Text;

                var treeFactory = languageServices.GetService<ISyntaxTreeFactoryService>();

                var tree = treeFactory.ParseSyntaxTree(filePath, options, text, cancellationToken);

                if (mode == PreservationMode.PreserveValue && solutionServices.SupportsCachingRecoverableObjects)
                {
                    var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false);
                    tree = treeFactory.CreateRecoverableTree(cacheKey, tree.FilePath, tree.Options, newTextSource, root);
                }

                Contract.ThrowIfNull(tree);

                // text version for this document should be unique. use it as a starting point.
                return TreeAndVersion.Create(tree, textAndVersion.Version);
            }
        }
Exemplo n.º 19
0
        public TextDocumentState UpdateText(SourceText newText, PreservationMode mode)
        {
            if (newText == null)
            {
                throw new ArgumentNullException(nameof(newText));
            }

            var newVersion = this.GetNewerVersion();
            var newTextAndVersion = TextAndVersion.Create(newText, newVersion, this.FilePath);

            var newState = this.UpdateText(newTextAndVersion, mode);
            return newState;
        }
Exemplo n.º 20
0
        public DocumentState UpdateText(TextLoader loader, PreservationMode mode)
        {
            if (loader == null)
            {
                throw new ArgumentNullException("loader");
            }

            var newTextSource = (mode == PreservationMode.PreserveIdentity)
                ? CreateStrongText(loader, this.Id, this.solutionServices)
                : CreateRecoverableText(loader, this.Id, this.solutionServices);

            var newTreeSource = CreateLazyFullyParsedTree(
                newTextSource,
                GetSyntaxTreeFilePath(this.info),
                this.options,
                this.languageServices,
                mode);

            return new DocumentState(
                this.LanguageServices,
                this.solutionServices,
                this.info,
                this.options,
                textSource: newTextSource,
                treeSource: newTreeSource);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Creates a new solution instance with the document specified updated to have the text
        /// specified.
        /// </summary>
        public SolutionState WithDocumentText(DocumentId documentId, SourceText text, PreservationMode mode = PreservationMode.PreserveValue)
        {
            if (documentId == null)
            {
                throw new ArgumentNullException(nameof(documentId));
            }

            if (text == null)
            {
                throw new ArgumentNullException(nameof(text));
            }

            CheckContainsDocument(documentId);

            var oldDocument = this.GetDocumentState(documentId);

            SourceText oldText;
            if (oldDocument.TryGetText(out oldText) && text == oldText)
            {
                return this;
            }

            // check to see if this solution has already been branched before with the same doc & text changes.
            // this helps reduce duplicate parsing when typing, and separate services generating duplicate symbols.
            if (mode == PreservationMode.PreserveIdentity)
            {
                var branch = _firstBranch;
                if (branch != null && branch.Id == documentId && branch.Text == text)
                {
                    return branch.Solution;
                }
            }

            var newSolution = this.WithDocumentState(oldDocument.UpdateText(text, mode), textChanged: true);

            if (mode == PreservationMode.PreserveIdentity && _firstBranch == null)
            {
                Interlocked.CompareExchange(ref _firstBranch, new SolutionBranch(documentId, text, newSolution), null);
            }

            return newSolution;
        }
Exemplo n.º 22
0
        /// <summary>
        /// Creates a new solution instance with the analyzer config document specified updated to have the text
        /// supplied by the text loader.
        /// </summary>
        public Solution WithAnalyzerConfigDocumentTextLoader(DocumentId documentId, TextLoader loader, PreservationMode mode)
        {
            var newState = _state.WithAnalyzerConfigDocumentTextLoader(documentId, loader, mode);

            if (newState == _state)
            {
                return(this);
            }

            return(new Solution(newState));
        }
Exemplo n.º 23
0
 public new AnalyzerConfigDocumentState UpdateText(TextLoader loader, PreservationMode mode)
 {
     return((AnalyzerConfigDocumentState)base.UpdateText(loader, mode));
 }
Exemplo n.º 24
0
 /// <summary>
 /// Creates a new solution instance with the corresponding project updated to include a new
 /// document instance defined by its name and root <see cref="SyntaxNode"/>.
 /// </summary>
 public Solution AddDocument(DocumentId documentId, string name, SyntaxNode syntaxRoot, IEnumerable<string> folders = null, string filePath = null, bool isGenerated = false, PreservationMode preservationMode = PreservationMode.PreserveValue)
 {
     return AddDocument(documentId, name, SourceText.From(string.Empty), folders, filePath, isGenerated).WithDocumentSyntaxRoot(documentId, syntaxRoot, preservationMode);
 }
Exemplo n.º 25
0
        /// <summary>
        /// Creates a new solution instance with all the documents specified updated to have the same specified text.
        /// </summary>
        public Solution WithDocumentText(IEnumerable <DocumentId> documentIds, SourceText text, PreservationMode mode = PreservationMode.PreserveValue)
        {
            var newState = _state.WithDocumentText(documentIds, text, mode);

            if (newState == _state)
            {
                return(this);
            }

            return(new Solution(newState));
        }
Exemplo n.º 26
0
        /// <summary>
        /// Creates a new solution instance with the additional document specified updated to have the text
        /// and version specified.
        /// </summary>
        public SolutionState WithAdditionalDocumentText(DocumentId documentId, TextAndVersion textAndVersion, PreservationMode mode = PreservationMode.PreserveValue)
        {
            if (documentId == null)
            {
                throw new ArgumentNullException(nameof(documentId));
            }

            if (textAndVersion == null)
            {
                throw new ArgumentNullException(nameof(textAndVersion));
            }

            CheckContainsAdditionalDocument(documentId);

            var oldDocument = this.GetAdditionalDocumentState(documentId);

            return WithTextDocumentState(oldDocument.UpdateText(textAndVersion, mode), textChanged: true);
        }
Exemplo n.º 27
0
 /// <summary>
 /// Creates a new solution instance with the corresponding project updated to include a new
 /// document instance defined by its name and root <see cref="SyntaxNode"/>.
 /// </summary>
 public Solution AddDocument(DocumentId documentId, string name, SyntaxNode syntaxRoot, IEnumerable <string> folders = null, string filePath = null, bool isGenerated = false, PreservationMode preservationMode = PreservationMode.PreserveValue)
 {
     return(this.AddDocument(documentId, name, SourceText.From(string.Empty), folders, filePath, isGenerated).WithDocumentSyntaxRoot(documentId, syntaxRoot, preservationMode));
 }
Exemplo n.º 28
0
        public static Solution WithTextDocumentText(this Solution solution, DocumentId documentId, SourceText text, PreservationMode mode = PreservationMode.PreserveIdentity)
        {
            var documentKind = solution.GetDocumentKind(documentId);

            switch (documentKind)
            {
            case TextDocumentKind.Document:
                return(solution.WithDocumentText(documentId, text, mode));

            case TextDocumentKind.AnalyzerConfigDocument:
                return(solution.WithAnalyzerConfigDocumentText(documentId, text, mode));

            case TextDocumentKind.AdditionalDocument:
                return(solution.WithAdditionalDocumentText(documentId, text, mode));

            default:
                throw ExceptionUtilities.UnexpectedValue(documentKind);
            }
        }
Exemplo n.º 29
0
        /// <summary>
        /// Creates a new solution instance with the additional document specified updated to have the text
        /// and version specified.
        /// </summary>
        public Solution WithAdditionalDocumentText(DocumentId documentId, TextAndVersion textAndVersion, PreservationMode mode = PreservationMode.PreserveValue)
        {
            var newState = _state.WithAdditionalDocumentText(documentId, textAndVersion, mode);

            if (newState == _state)
            {
                return(this);
            }

            return(new Solution(newState));
        }
Exemplo n.º 30
0
        public TextDocumentState UpdateText(TextLoader loader, PreservationMode mode)
        {
            if (loader == null)
            {
                throw new ArgumentNullException("loader");
            }

            var newTextSource = (mode == PreservationMode.PreserveIdentity)
                ? CreateStrongText(loader, this.Id, this.solutionServices)
                : CreateRecoverableText(loader, this.Id, this.solutionServices);

            return new TextDocumentState(
                this.solutionServices,
                this.info,
                textSource: newTextSource);
        }
Exemplo n.º 31
0
 public static bool IsValid(this PreservationMode mode)
 => mode is >= PreservationMode.PreserveValue and <= PreservationMode.PreserveIdentity;
Exemplo n.º 32
0
 public new DocumentState UpdateText(TextLoader loader, PreservationMode mode)
 {
     return UpdateText(loader, textOpt: null, mode: mode);
 }
Exemplo n.º 33
0
 protected override TextDocumentState UpdateText(ValueSource <TextAndVersion> newTextSource, PreservationMode mode, bool incremental)
 {
     throw new NotSupportedException(WorkspacesResources.The_contents_of_a_SourceGeneratedDocument_may_not_be_changed);
 }
Exemplo n.º 34
0
        internal DocumentState UpdateTree(SyntaxNode newRoot, PreservationMode mode)
        {
            if (newRoot == null)
            {
                throw new ArgumentNullException(nameof(newRoot));
            }

            var newTextVersion = this.GetNewerVersion();
            var newTreeVersion = GetNewTreeVersionForUpdatedTree(newRoot, newTextVersion, mode);

            // determine encoding
            Encoding encoding;
            SyntaxTree priorTree;
            SourceText priorText;
            if (this.TryGetSyntaxTree(out priorTree))
            {
                // this is most likely available since UpdateTree is normally called after modifying the existing tree.
                encoding = priorTree.Encoding;
            }
            else if (this.TryGetText(out priorText))
            {
                encoding = priorText.Encoding;
            }
            else
            {
                // the existing encoding was never observed so is unknown.
                encoding = null;
            }

            var syntaxTreeFactory = _languageServices.GetService<ISyntaxTreeFactoryService>();

            var result = CreateRecoverableTextAndTree(newRoot, newTextVersion, newTreeVersion, encoding, this.info, _options, syntaxTreeFactory, mode, this.solutionServices);

            return new DocumentState(
                this.LanguageServices,
                this.solutionServices,
                this.info,
                _options,
                sourceTextOpt: null,
                textSource: result.Item1,
                treeSource: new ConstantValueSource<TreeAndVersion>(result.Item2));
        }
Exemplo n.º 35
0
 public new DocumentState UpdateText(SourceText newText, PreservationMode mode)
 {
     return((DocumentState)base.UpdateText(newText, mode));
 }
Exemplo n.º 36
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);
        }
Exemplo n.º 37
0
 public new DocumentState UpdateText(TextAndVersion newTextAndVersion, PreservationMode mode)
 {
     return((DocumentState)base.UpdateText(newTextAndVersion, mode));
 }
Exemplo n.º 38
0
        private static async Task<TreeAndVersion> FullyParseTreeAsync(
            ValueSource<TextAndVersion> newTextSource,
            string filePath,
            ParseOptions options,
            HostLanguageServices languageServices,
            PreservationMode mode,
            CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FeatureId.DocumentState, FunctionId.DocumentState_FullyParseSyntaxTree, cancellationToken))
            {
                var textAndVersion = await newTextSource.GetValueAsync(cancellationToken).ConfigureAwait(false);
                var text = textAndVersion.Text;

                var treeFactory = languageServices.GetService<ISyntaxTreeFactoryService>();

                var tree = treeFactory.ParseSyntaxTree(filePath, options, text, cancellationToken);

                if (mode == PreservationMode.PreserveValue)
                {
                    var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false);

                    // get a recoverable tree that reparses from the source text if it gets used after being kicked out of memory
                    tree = treeFactory.CreateRecoverableTree(tree.FilePath, tree.Options, newTextSource, root, reparse: true);
                }

                Contract.ThrowIfNull(tree);

                // text version for this document should be unique. use it as a starting point.
                return TreeAndVersion.Create(tree, textAndVersion.Version);
            }
        }
Exemplo n.º 39
0
        protected override TextDocumentState UpdateText(ValueSource <TextAndVersion> newTextSource, PreservationMode mode, bool incremental)
        {
            ValueSource <TreeAndVersion>?newTreeSource;

            if (_treeSource == null)
            {
                newTreeSource = null;
            }
            else if (incremental)
            {
                newTreeSource = CreateLazyIncrementallyParsedTree(_treeSource, newTextSource);
            }
            else
            {
                newTreeSource = CreateLazyFullyParsedTree(
                    newTextSource,
                    Id.ProjectId,
                    GetSyntaxTreeFilePath(Attributes),
                    _options !,
                    _analyzerConfigSetSource,
                    _languageServices,
                    mode); // TODO: understand why the mode is given here. If we're preserving text by identity, why also preserve the tree?
            }

            return(new DocumentState(
                       LanguageServices,
                       solutionServices,
                       Services,
                       Attributes,
                       _options,
                       _analyzerConfigSetSource,
                       sourceText: null,
                       textSource: newTextSource,
                       treeSource: newTreeSource));
        }
Exemplo n.º 40
0
        public DocumentState UpdateText(TextAndVersion newTextAndVersion, PreservationMode mode)
        {
            if (newTextAndVersion == null)
            {
                throw new ArgumentNullException("newTextAndVesion");
            }

            var newTextSource = mode == PreservationMode.PreserveIdentity
                ? CreateStrongText(newTextAndVersion)
                : CreateRecoverableText(newTextAndVersion, this.solutionServices);

            // always chain incremental parsing request, it will internally put 
            // appropriate request such as full parsing request if there are too many pending 
            // incremental parsing requests hanging around.
            var newTreeSource = CreateLazyIncrementallyParsedTree(this.treeSource, newTextSource);

            return new DocumentState(
                this.LanguageServices,
                this.solutionServices,
                this.info,
                this.options,
                newTextSource,
                newTreeSource);
        }
Exemplo n.º 41
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, Encoding encoding,
            DocumentInfo info, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode, SolutionServices solutionServices)
        {
            string         filePath = info.FilePath;
            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);

            lazyTree = TreeAndVersion.Create(
                (mode == PreservationMode.PreserveIdentity) || !solutionServices.SupportsCachingRecoverableObjects
                    ? factory.CreateSyntaxTree(GetSyntaxTreeFilePath(info), options, encoding, newRoot)
                    : factory.CreateRecoverableTree(info.Id.ProjectId, GetSyntaxTreeFilePath(info), options, lazyText, encoding, newRoot),
                treeVersion);

            return(Tuple.Create(lazyText, lazyTree));
        }
Exemplo n.º 42
0
        internal DocumentState UpdateTree(SyntaxNode newRoot, PreservationMode mode)
        {
            if (newRoot == null)
            {
                throw new ArgumentNullException("newRoot");
            }

            var newTextVersion = this.GetNewerVersion();
            var newTreeVersion = GetNewTreeVersionForUpdatedTree(newRoot, newTextVersion, mode);

            var syntaxTreeFactory = this.languageServices.GetService<ISyntaxTreeFactoryService>();
            
            var result = CreateRecoverableTextAndTree(newRoot, newTextVersion, newTreeVersion, this.info, this.options, syntaxTreeFactory, mode);

            return new DocumentState(
                this.LanguageServices,
                this.solutionServices,
                this.info,
                this.options,
                textSource: result.Item1,
                treeSource: result.Item2);
        }
Exemplo n.º 43
0
        /// <summary>
        /// Call this method when the text of a document is updated in the host environment.
        /// </summary>
        protected internal void OnDocumentTextChanged(DocumentId documentId, SourceText newText, PreservationMode mode)
        {
            using (this.serializationLock.DisposableWait())
            {
                CheckDocumentIsInCurrentSolution(documentId);

                var oldSolution = this.CurrentSolution;
                var newSolution = this.SetCurrentSolution(oldSolution.WithDocumentText(documentId, newText, mode));

                var newDocument = newSolution.GetDocument(documentId);
                this.OnDocumentTextChanged(newDocument);

                this.RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind.DocumentChanged, oldSolution, newSolution, documentId: documentId);
            }
        }
Exemplo n.º 44
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);
        }
Exemplo n.º 45
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)));
        }
Exemplo n.º 46
0
        public TextDocumentState UpdateText(TextAndVersion newTextAndVersion, PreservationMode mode)
        {
            if (newTextAndVersion == null)
            {
                throw new ArgumentNullException(nameof(newTextAndVersion));
            }

            var newTextSource = mode == PreservationMode.PreserveIdentity
                ? CreateStrongText(newTextAndVersion)
                : CreateRecoverableText(newTextAndVersion, this.solutionServices);

            return new TextDocumentState(
                this.solutionServices,
                this.info,
                newTextSource);
        }
Exemplo n.º 47
0
        public static Solution WithTextDocumentText(this Solution solution, DocumentId documentId, SourceText text, PreservationMode mode = PreservationMode.PreserveIdentity)
        {
            var document = solution.GetTextDocument(documentId);

            if (document is Document)
            {
                return(solution.WithDocumentText(documentId, text, mode));
            }
            else
            {
                return(solution.WithAdditionalDocumentText(documentId, text, mode));
            }
        }
Exemplo n.º 48
0
        public TextDocumentState UpdateText(TextLoader loader, PreservationMode mode)
        {
            if (loader == null)
            {
                throw new ArgumentNullException(nameof(loader));
            }

            // don't blow up on non-text documents.
            var newTextSource = (mode == PreservationMode.PreserveIdentity)
                ? CreateStrongText(loader, this.Id, this.solutionServices, reportInvalidDataException: false)
                : CreateRecoverableText(loader, this.Id, this.solutionServices, reportInvalidDataException: false);

            return new TextDocumentState(
                this.solutionServices,
                this.info,
                textSource: newTextSource);
        }
Exemplo n.º 49
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;
            AsyncLazy <TreeAndVersion> lazyTree = null;

            // this captures the lazyTree local
            var lazyText = new AsyncLazy <TextAndVersion>(
                c => GetTextAndVersionAsync(lazyTree, textVersion, filePath, c),
                c => GetTextAndVersion(lazyTree, textVersion, 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), treeVersion));
            }
            else
            {
                lazyTree = new AsyncLazy <TreeAndVersion>(
                    TreeAndVersion.Create(factory.CreateRecoverableTree(GetSyntaxTreeFilePath(info), options, lazyText, newRoot, reparse: false), treeVersion));
            }

            return(Tuple.Create(lazyText, lazyTree));
        }
Exemplo n.º 50
0
 /// <summary>
 /// Creates a new solution instance with the document specified updated to have the text
 /// supplied by the text loader.
 /// </summary>
 public Solution WithDocumentTextLoader(DocumentId documentId, TextLoader loader, PreservationMode mode)
 {
     return WithDocumentTextLoader(documentId, loader, textOpt: null, mode: mode);
 }
Exemplo n.º 51
0
 public new DocumentState UpdateText(TextLoader loader, PreservationMode mode)
 {
     return(UpdateText(loader, textOpt: null, mode: mode));
 }
Exemplo n.º 52
0
        /// <summary>
        /// Creates a new solution instance with the additional document specified updated to have the text
        /// specified.
        /// </summary>
        public SolutionState WithAdditionalDocumentText(DocumentId documentId, SourceText text, PreservationMode mode = PreservationMode.PreserveValue)
        {
            if (documentId == null)
            {
                throw new ArgumentNullException(nameof(documentId));
            }

            if (text == null)
            {
                throw new ArgumentNullException(nameof(text));
            }

            CheckContainsAdditionalDocument(documentId);

            var oldDocument = this.GetAdditionalDocumentState(documentId);

            SourceText oldText;
            if (oldDocument.TryGetText(out oldText) && text == oldText)
            {
                return this;
            }

            var newSolution = this.WithTextDocumentState(oldDocument.UpdateText(text, mode), textChanged: true);
            return newSolution;
        }
Exemplo n.º 53
0
        private VersionStamp GetNewTreeVersionForUpdatedTree(SyntaxNode newRoot, VersionStamp newTextVersion, PreservationMode mode)
        {
            if (mode != PreservationMode.PreserveIdentity)
            {
                return(newTextVersion);
            }

            if (!_treeSource.TryGetValue(out var oldTreeAndVersion) || !oldTreeAndVersion.Tree.TryGetRoot(out var oldRoot))
            {
                return(newTextVersion);
            }

            return(oldRoot.IsEquivalentTo(newRoot, topLevel: true) ? oldTreeAndVersion.Version : newTextVersion);
        }
Exemplo n.º 54
0
        /// <summary>
        /// Creates a new solution instance with the document specified updated to have a syntax tree
        /// rooted by the specified syntax node.
        /// </summary>
        public SolutionState WithDocumentSyntaxRoot(DocumentId documentId, SyntaxNode root, PreservationMode mode = PreservationMode.PreserveValue)
        {
            if (documentId == null)
            {
                throw new ArgumentNullException(nameof(documentId));
            }

            if (root == null)
            {
                throw new ArgumentNullException(nameof(root));
            }

            CheckContainsDocument(documentId);

            var oldDocument = this.GetDocumentState(documentId);

            SyntaxTree oldTree;
            SyntaxNode oldRoot;
            if (oldDocument.TryGetSyntaxTree(out oldTree) &&
                oldTree.TryGetRoot(out oldRoot) &&
                oldRoot == root)
            {
                return this;
            }

            return WithDocumentState(oldDocument.UpdateTree(root, mode), textChanged: true);
        }
Exemplo n.º 55
0
        /// <summary>
        /// Creates a new solution instance with the additional document specified updated to have the text
        /// supplied by the text loader.
        /// </summary>
        public Solution WithAdditionalDocumentTextLoader(DocumentId documentId, TextLoader loader, PreservationMode mode)
        {
            var newState = _state.WithAdditionalDocumentTextLoader(documentId, loader, mode);
            if (newState == _state)
            {
                return this;
            }

            return new Solution(newState);
        }
Exemplo n.º 56
0
        /// <summary>
        /// Creates a new solution instance with all the documents specified updated to have the same specified text.
        /// </summary>
        public SolutionState WithDocumentText(IEnumerable<DocumentId> documentIds, SourceText text, PreservationMode mode = PreservationMode.PreserveValue)
        {
            if (documentIds == null)
            {
                throw new ArgumentNullException(nameof(documentIds));
            }

            if (text == null)
            {
                throw new ArgumentNullException(nameof(text));
            }

            var solution = this;

            foreach (var documentId in documentIds)
            {
                var doc = solution.GetDocumentState(documentId);
                if (doc != null)
                {
                    SourceText existingText;
                    if (!doc.TryGetText(out existingText) || existingText != text)
                    {
                        solution = solution.WithDocumentText(documentId, text, mode);
                    }
                }
            }

            return solution;
        }
Exemplo n.º 57
0
 public new AnalyzerConfigDocumentState UpdateText(
     TextAndVersion newTextAndVersion,
     PreservationMode mode
     ) => (AnalyzerConfigDocumentState)base.UpdateText(newTextAndVersion, mode);