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); }
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); } }
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); }
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); }
/// <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); }
/// <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); }
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; }
public new AnalyzerConfigDocumentState UpdateText(SourceText text, PreservationMode mode) { return((AnalyzerConfigDocumentState)base.UpdateText(text, mode)); }
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)); }
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; }
/// <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)); }
/// <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)); }
protected virtual TextDocumentState UpdateText(ValueSource <TextAndVersion> newTextSource, PreservationMode mode, bool incremental) { return(new TextDocumentState( this.solutionServices, this.Services, this.Attributes, sourceText: null, textAndVersionSource: newTextSource)); }
// 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)); }
protected override TextDocumentState UpdateText(ValueSource <TextAndVersion> newTextSource, PreservationMode mode, bool incremental) { return(new AnalyzerConfigDocumentState( this.solutionServices, this.Services, this.Attributes, this.sourceText, newTextSource)); }
// 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)); }
/// <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)); }
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); } }
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; }
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); }
/// <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; }
/// <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)); }
public new AnalyzerConfigDocumentState UpdateText(TextLoader loader, PreservationMode mode) { return((AnalyzerConfigDocumentState)base.UpdateText(loader, mode)); }
/// <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); }
/// <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)); }
/// <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); }
/// <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)); }
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); } }
/// <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)); }
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); }
public static bool IsValid(this PreservationMode mode) => mode is >= PreservationMode.PreserveValue and <= PreservationMode.PreserveIdentity;
public new DocumentState UpdateText(TextLoader loader, PreservationMode mode) { return UpdateText(loader, textOpt: null, mode: mode); }
protected override TextDocumentState UpdateText(ValueSource <TextAndVersion> newTextSource, PreservationMode mode, bool incremental) { throw new NotSupportedException(WorkspacesResources.The_contents_of_a_SourceGeneratedDocument_may_not_be_changed); }
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)); }
public new DocumentState UpdateText(SourceText newText, PreservationMode mode) { return((DocumentState)base.UpdateText(newText, mode)); }
// 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); }
public new DocumentState UpdateText(TextAndVersion newTextAndVersion, PreservationMode mode) { return((DocumentState)base.UpdateText(newTextAndVersion, mode)); }
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); } }
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)); }
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); }
// 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)); }
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); }
/// <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); } }
// 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 <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 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); }
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)); } }
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); }
// 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)); }
/// <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); }
public new DocumentState UpdateText(TextLoader loader, PreservationMode mode) { return(UpdateText(loader, textOpt: null, mode: mode)); }
/// <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; }
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); }
/// <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); }
/// <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); }
/// <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; }
public new AnalyzerConfigDocumentState UpdateText( TextAndVersion newTextAndVersion, PreservationMode mode ) => (AnalyzerConfigDocumentState)base.UpdateText(newTextAndVersion, mode);