internal Document(Project project, DocumentState state) { Contract.ThrowIfNull(project); Contract.ThrowIfNull(state); this.Project = project; _state = state; }
/// <summary> /// Gets the documentId in this solution with the specified syntax tree. /// </summary> public DocumentId GetDocumentId(SyntaxTree syntaxTree, ProjectId projectId) { if (syntaxTree != null) { // is this tree known to be associated with a document? var documentId = DocumentState.GetDocumentIdForTree(syntaxTree); if (documentId != null && (projectId == null || documentId.ProjectId == projectId)) { // does this solution even have the document? if (this.ContainsDocument(documentId)) { return(documentId); } } } return(null); }
internal SyntaxTree GetSyntaxTreeSynchronously(CancellationToken cancellationToken) { if (!this.SupportsSyntaxTree) { return(null); } // if we already have a stask for getting this syntax tree, and the task // has completed, then we can just return that value. var syntaxTreeTask = GetExistingSyntaxTreeTask(); if (syntaxTreeTask?.Status == TaskStatus.RanToCompletion) { return(syntaxTreeTask.Result); } // Otherwise defer to our state to get this value. return(DocumentState.GetSyntaxTree(cancellationToken)); }
/// <summary> /// Gets the <see cref="SyntaxTree" /> for this document asynchronously. /// </summary> public Task <SyntaxTree> GetSyntaxTreeAsync(CancellationToken cancellationToken = default(CancellationToken)) { // If the language doesn't support getting syntax trees for a document, then bail out // immediately. if (!this.SupportsSyntaxTree) { return(SpecializedTasks.Default <SyntaxTree>()); } var syntaxTreeTask = GetExistingSyntaxTreeTask(); if (syntaxTreeTask != null) { return(syntaxTreeTask); } // we can't cache this result, since internally it uses AsyncLazy which // care about cancellation token return(DocumentState.GetSyntaxTreeAsync(cancellationToken)); }
private void GetLatestDependentVersions( ImmutableDictionary <DocumentId, DocumentState> newDocumentStates, DocumentState oldDocument, DocumentState newDocument, bool recalculateDependentVersions, bool textChanged, out AsyncLazy <VersionStamp> dependentDocumentVersion, out AsyncLazy <VersionStamp> dependentSemanticVersion) { var recalculateDocumentVersion = false; var recalculateSemanticVersion = false; if (recalculateDependentVersions) { VersionStamp oldVersion; if (oldDocument.TryGetTextVersion(out oldVersion)) { VersionStamp documentVersion; if (!this.lazyLatestDocumentVersion.TryGetValue(out documentVersion) || documentVersion == oldVersion) { recalculateDocumentVersion = true; } VersionStamp semanticVersion; if (!this.lazyLatestDocumentTopLevelChangeVersion.TryGetValue(out semanticVersion) || semanticVersion == oldVersion) { recalculateSemanticVersion = true; } } } dependentDocumentVersion = recalculateDocumentVersion ? new AsyncLazy <VersionStamp>(this.ComputeLatestDocumentVersionAsync, cacheResult: true) : textChanged ? new AsyncLazy <VersionStamp>(newDocument.GetTextVersionAsync, cacheResult: true) : this.lazyLatestDocumentVersion; dependentSemanticVersion = recalculateSemanticVersion ? new AsyncLazy <VersionStamp>(c => ComputeLatestDocumentTopLevelChangeVersionAsync(newDocumentStates, c), cacheResult: true) : textChanged? CreateLazyLatestDocumentTopLevelChangeVersion(newDocument, newDocumentStates) : this.lazyLatestDocumentTopLevelChangeVersion; }
/// <summary> /// Get the current syntax tree for the document if the text is already loaded and the tree is already parsed. /// In almost all cases, you should call <see cref="GetSyntaxTreeAsync"/> to fetch the tree, which will parse the tree /// if it's not already parsed. /// </summary> public bool TryGetSyntaxTree(out SyntaxTree syntaxTree) { // if we already have cache, use it if (_syntaxTreeResultTask != null) { syntaxTree = _syntaxTreeResultTask.Result; } if (!DocumentState.TryGetSyntaxTree(out syntaxTree)) { return(false); } // cache the result if it is not already cached if (_syntaxTreeResultTask == null) { var result = Task.FromResult(syntaxTree); Interlocked.CompareExchange(ref _syntaxTreeResultTask, result, null); } return(true); }
public ProjectState UpdateDocument(DocumentState newDocument, bool textChanged, bool recalculateDependentVersions) { Debug.Assert(this.ContainsDocument(newDocument.Id)); var oldDocument = this.GetDocumentState(newDocument.Id) !; if (oldDocument == newDocument) { return(this); } var newDocumentStates = _documentStates.SetItem(newDocument.Id, newDocument); GetLatestDependentVersions( newDocumentStates, _additionalDocumentStates, oldDocument, newDocument, recalculateDependentVersions, textChanged, out var dependentDocumentVersion, out var dependentSemanticVersion); return(this.With( documentStates: newDocumentStates, latestDocumentVersion: dependentDocumentVersion, latestDocumentTopLevelChangeVersion: dependentSemanticVersion)); }
internal Document GetDocument(SyntaxTree syntaxTree, ProjectId projectId) { if (syntaxTree != null) { // is this tree known to be associated with a document? var docId = DocumentState.GetDocumentIdForTree(syntaxTree); if (docId != null && (projectId == null || docId.ProjectId == projectId)) { // does this solution even have the document? var document = this.GetDocument(docId); if (document != null) { // does this document really have the syntax tree? if (document.TryGetSyntaxTree(out var documentTree) && documentTree == syntaxTree) { return(document); } } } } return(null); }
private SolutionState WithDocumentState(DocumentState newDocument, bool textChanged = false, bool recalculateDependentVersions = false) { if (newDocument == null) { throw new ArgumentNullException(nameof(newDocument)); } CheckContainsDocument(newDocument.Id); if (newDocument == this.GetDocumentState(newDocument.Id)) { // old and new documents are the same instance return this; } return this.TouchDocument(newDocument.Id, p => p.UpdateDocument(newDocument, textChanged, recalculateDependentVersions)); }
public TouchDocumentAction(DocumentState oldState, DocumentState newState) { _oldState = oldState; _newState = newState; }
/// <summary> /// True if the Text has changed /// </summary> public bool HasTextChanged(DocumentState oldState) { return(oldState.sourceTextOpt != this.sourceTextOpt || oldState.TextAndVersionSource != this.TextAndVersionSource); }
public ReuseVersionLoader(DocumentState oldDocumentState, SourceText newText) { _oldDocumentState = oldDocumentState; _newText = newText; }
public static CompilationTranslationAction RemoveDocument(DocumentState state) { return(new RemoveDocumentAction(state)); }
public CompilationTracker FreezePartialStateWithTree(SolutionState solution, DocumentState docState, SyntaxTree tree, CancellationToken cancellationToken) { GetPartialCompilationState(solution, docState.Id, out var inProgressProject, out var inProgressCompilation, cancellationToken); if (!inProgressCompilation.SyntaxTrees.Contains(tree)) { var existingTree = inProgressCompilation.SyntaxTrees.FirstOrDefault(t => t.FilePath == tree.FilePath); if (existingTree != null) { inProgressCompilation = inProgressCompilation.ReplaceSyntaxTree(existingTree, tree); inProgressProject = inProgressProject.UpdateDocument(docState, textChanged: false, recalculateDependentVersions: false); } else { inProgressCompilation = inProgressCompilation.AddSyntaxTrees(tree); Debug.Assert(!inProgressProject.DocumentIds.Contains(docState.Id)); inProgressProject = inProgressProject.AddDocuments(ImmutableArray.Create(docState)); } } // The user is asking for an in progress snap. We don't want to create it and then // have the compilation immediately disappear. So we force it to stay around with a ConstantValueSource. // As a policy, all partial-state projects are said to have incomplete references, since the state has no guarantees. return(new CompilationTracker(inProgressProject, new FinalState(new ConstantValueSource <Compilation>(inProgressCompilation), hasSuccessfullyLoaded: false))); }
private Solution AddDocument(DocumentState state) { if (state == null) { throw new ArgumentNullException(nameof(state)); } CheckContainsProject(state.Id.ProjectId); var oldProject = this.GetProjectState(state.Id.ProjectId); var newProject = oldProject.AddDocument(state); return this.ForkProject( newProject, CompilationTranslationAction.AddDocument(state), newLinkedFilesMap: CreateLinkedFilesMapWithAddedDocuments(newProject, SpecializedCollections.SingletonEnumerable(state.Id))); }
public bool HasTextChanged(DocumentState oldState) => HasTextChanged(oldState, ignoreUnchangeableDocument: false);
public bool HasContentChanged(DocumentState oldState) { return(oldState._treeSource != _treeSource || HasTextChanged(oldState, ignoreUnchangeableDocument: false)); }
/// <summary> /// Gets the version of the document's top level signature if it is already loaded and available. /// </summary> internal bool TryGetTopLevelChangeTextVersion(out VersionStamp version) { return(DocumentState.TryGetTopLevelChangeTextVersion(out version)); }
public bool HasTextChanged(DocumentState oldState) { return(HasTextChanged(oldState, ignoreUnchangeableDocument: false)); }
public ICompilationTracker FreezePartialStateWithTree(SolutionState solution, DocumentState docState, SyntaxTree tree, CancellationToken cancellationToken) { // Because we override SourceGeneratedDocument.WithFrozenPartialSemantics directly, we shouldn't be able to get here. throw ExceptionUtilities.Unreachable; }
public TouchDocumentAction(DocumentState oldState, DocumentState newState) { this.oldState = oldState; this.newState = newState; }
internal Document(Project project, DocumentState state) : base(project, state) { }
private static async Task<VersionStamp> ComputeTopLevelChangeTextVersionAsync(VersionStamp oldVersion, DocumentState newDocument, CancellationToken cancellationToken) { var newVersion = await newDocument.GetTopLevelChangeTextVersionAsync(cancellationToken).ConfigureAwait(false); return newVersion.GetNewerVersion(oldVersion); }
private Solution AddDocument(DocumentState state) { if (state == null) { throw new ArgumentNullException("document"); } CheckContainsProject(state.Id.ProjectId); var oldProject = this.GetProjectState(state.Id.ProjectId); var newProject = oldProject.AddDocument(state); return this.ForkProject(newProject, CompilationTranslationAction.AddDocument(state), withDocumentListChange: true); }
public ProjectState UpdateDocument(DocumentState newDocument, bool textChanged, bool recalculateDependentVersions) { Contract.Requires(this.ContainsDocument(newDocument.Id)); var oldDocument = this.GetDocumentState(newDocument.Id); if (oldDocument == newDocument) { return this; } var newDocumentStates = this.DocumentStates.SetItem(newDocument.Id, newDocument); AsyncLazy<VersionStamp> dependentDocumentVersion; AsyncLazy<VersionStamp> dependentSemanticVersion; GetLatestDependentVersions( newDocumentStates, oldDocument, newDocument, recalculateDependentVersions, textChanged, out dependentDocumentVersion, out dependentSemanticVersion); return this.With( documentStates: newDocumentStates, latestDocumentVersion: dependentDocumentVersion, latestDocumentTopLevelChangeVersion: dependentSemanticVersion); }
public bool HasContentChanged(DocumentState oldState) { return(oldState._treeSource != this._treeSource || oldState.sourceText != this.sourceText || oldState.TextAndVersionSource != this.TextAndVersionSource); }
public static CompilationTranslationAction RemoveDocument(DocumentState state) { return new RemoveDocumentAction(state); }
public static CompilationTranslationAction TouchDocument(DocumentState oldState, DocumentState newState) { return(new TouchDocumentAction(oldState, newState)); }
internal Document(Project project, DocumentState state) : base(project, state, TextDocumentKind.Document) { }
public CompilationTracker FreezePartialStateWithTree(Solution solution, DocumentState docState, SyntaxTree tree, CancellationToken cancellationToken) { ProjectState inProgressProject; Compilation inProgressCompilation; GetPartialCompilationState(solution, docState.Id, out inProgressProject, out inProgressCompilation, cancellationToken); if (!inProgressCompilation.SyntaxTrees.Contains(tree)) { var existingTree = inProgressCompilation.SyntaxTrees.FirstOrDefault(t => t.FilePath == tree.FilePath); if (existingTree != null) { inProgressCompilation = inProgressCompilation.ReplaceSyntaxTree(existingTree, tree); inProgressProject = inProgressProject.UpdateDocument(docState, textChanged: false, recalculateDependentVersions: false); } else { inProgressCompilation = inProgressCompilation.AddSyntaxTrees(tree); Debug.Assert(!inProgressProject.DocumentIds.Contains(docState.Id)); inProgressProject = inProgressProject.AddDocument(docState); } } // The user is asking for an in progress snap. We don't want to create it and then a // have the compilation immediately disappear. So we force it to stay around with a ConstantValueSource return new CompilationTracker(inProgressProject, new FinalState(new ConstantValueSource<Compilation>(inProgressCompilation))); }
private static async Task <VersionStamp> ComputeTopLevelChangeTextVersionAsync(VersionStamp oldVersion, DocumentState newDocument, CancellationToken cancellationToken) { var newVersion = await newDocument.GetTopLevelChangeTextVersionAsync(cancellationToken).ConfigureAwait(false); return(newVersion.GetNewerVersion(oldVersion)); }
private AsyncLazy<VersionStamp> CreateLazyLatestDocumentTopLevelChangeVersion(DocumentState newDocument, ImmutableDictionary<DocumentId, DocumentState> newDocumentStates) { VersionStamp oldVersion; if (this.lazyLatestDocumentTopLevelChangeVersion.TryGetValue(out oldVersion)) { return new AsyncLazy<VersionStamp>(c => ComputeTopLevelChangeTextVersionAsync(oldVersion, newDocument, c), cacheResult: true); } else { return new AsyncLazy<VersionStamp>(c => ComputeLatestDocumentTopLevelChangeVersionAsync(newDocumentStates, c), cacheResult: true); } }
internal DocumentBranch(SourceText text, DocumentState state) { this.Text = text; this.State = state; }
public ProjectState AddDocument(DocumentState document) { Contract.Requires(!this.DocumentStates.ContainsKey(document.Id)); return this.With( projectInfo: this.ProjectInfo.WithVersion(this.Version.GetNewerVersion()), documentIds: this.DocumentIds.Add(document.Id), documentStates: this.DocumentStates.Add(document.Id, document)); }
internal DocumentBranch(SourceText text, DocumentState state) { this.Text = text; this.State = state; }
private void GetLatestDependentVersions( ImmutableDictionary<DocumentId, DocumentState> newDocumentStates, DocumentState oldDocument, DocumentState newDocument, bool recalculateDependentVersions, bool textChanged, out AsyncLazy<VersionStamp> dependentDocumentVersion, out AsyncLazy<VersionStamp> dependentSemanticVersion) { var recalculateDocumentVersion = false; var recalculateSemanticVersion = false; if (recalculateDependentVersions) { VersionStamp oldVersion; if (oldDocument.TryGetTextVersion(out oldVersion)) { VersionStamp documentVersion; if (!this.lazyLatestDocumentVersion.TryGetValue(out documentVersion) || documentVersion == oldVersion) { recalculateDocumentVersion = true; } VersionStamp semanticVersion; if (!this.lazyLatestDocumentTopLevelChangeVersion.TryGetValue(out semanticVersion) || semanticVersion == oldVersion) { recalculateSemanticVersion = true; } } } dependentDocumentVersion = recalculateDocumentVersion ? new AsyncLazy<VersionStamp>(this.ComputeLatestDocumentVersionAsync, cacheResult: true) : textChanged ? new AsyncLazy<VersionStamp>(newDocument.GetTextVersionAsync, cacheResult: true) : this.lazyLatestDocumentVersion; dependentSemanticVersion = recalculateSemanticVersion ? new AsyncLazy<VersionStamp>(c => ComputeLatestDocumentTopLevelChangeVersionAsync(newDocumentStates, c), cacheResult: true) : textChanged ? CreateLazyLatestDocumentTopLevelChangeVersion(newDocument, newDocumentStates) : this.lazyLatestDocumentTopLevelChangeVersion; }
internal Document(Project project, DocumentState state) : base(project, state) { }
public static CompilationTranslationAction TouchDocument(DocumentState oldState, DocumentState newState) { return new TouchDocumentAction(oldState, newState); }
private static async Task<Compilation> UpdateDocumentInCompilationAsync( Compilation compilation, DocumentState oldDocument, DocumentState newDocument, CancellationToken cancellationToken) { return compilation.ReplaceSyntaxTree( await oldDocument.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false), await newDocument.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false)); }
internal Task <ImmutableDictionary <string, string> > GetAnalyzerOptionsAsync(CancellationToken cancellationToken) { return(DocumentState.GetAnalyzerOptionsAsync(Project.FilePath, cancellationToken)); }
private AsyncLazy <VersionStamp> CreateLazyLatestDocumentTopLevelChangeVersion(DocumentState newDocument, ImmutableDictionary <DocumentId, DocumentState> newDocumentStates) { VersionStamp oldVersion; if (this.lazyLatestDocumentTopLevelChangeVersion.TryGetValue(out oldVersion)) { return(new AsyncLazy <VersionStamp>(c => ComputeTopLevelChangeTextVersionAsync(oldVersion, newDocument, c), cacheResult: true)); } else { return(new AsyncLazy <VersionStamp>(c => ComputeLatestDocumentTopLevelChangeVersionAsync(newDocumentStates, c), cacheResult: true)); } }