Beispiel #1
0
        internal Document(Project project, DocumentState state)
        {
            Contract.ThrowIfNull(project);
            Contract.ThrowIfNull(state);

            this.Project = project;
            _state = state;
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
        /// <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));
        }
Beispiel #5
0
        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;
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        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));
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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;
 }
Beispiel #11
0
 /// <summary>
 /// True if the Text has changed
 /// </summary>
 public bool HasTextChanged(DocumentState oldState)
 {
     return(oldState.sourceTextOpt != this.sourceTextOpt ||
            oldState.TextAndVersionSource != this.TextAndVersionSource);
 }
Beispiel #12
0
 public ReuseVersionLoader(DocumentState oldDocumentState, SourceText newText)
 {
     _oldDocumentState = oldDocumentState;
     _newText          = newText;
 }
 public static CompilationTranslationAction RemoveDocument(DocumentState state)
 {
     return(new RemoveDocumentAction(state));
 }
Beispiel #14
0
            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)));
            }
Beispiel #15
0
        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)));
        }
Beispiel #16
0
 public bool HasTextChanged(DocumentState oldState)
 => HasTextChanged(oldState, ignoreUnchangeableDocument: false);
Beispiel #17
0
 public bool HasContentChanged(DocumentState oldState)
 {
     return(oldState._treeSource != _treeSource ||
            HasTextChanged(oldState, ignoreUnchangeableDocument: false));
 }
Beispiel #18
0
 /// <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));
 }
Beispiel #19
0
 public bool HasTextChanged(DocumentState oldState)
 {
     return(HasTextChanged(oldState, ignoreUnchangeableDocument: false));
 }
Beispiel #20
0
 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;
 }
Beispiel #22
0
 internal Document(Project project, DocumentState state) :
     base(project, state)
 {
 }
Beispiel #23
0
 private static async Task<VersionStamp> ComputeTopLevelChangeTextVersionAsync(VersionStamp oldVersion, DocumentState newDocument, CancellationToken cancellationToken)
 {
     var newVersion = await newDocument.GetTopLevelChangeTextVersionAsync(cancellationToken).ConfigureAwait(false);
     return newVersion.GetNewerVersion(oldVersion);
 }
Beispiel #24
0
        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);
        }
Beispiel #25
0
        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);
        }
Beispiel #26
0
 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));
 }
Beispiel #29
0
 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)));
            }
Beispiel #31
0
        private static async Task <VersionStamp> ComputeTopLevelChangeTextVersionAsync(VersionStamp oldVersion, DocumentState newDocument, CancellationToken cancellationToken)
        {
            var newVersion = await newDocument.GetTopLevelChangeTextVersionAsync(cancellationToken).ConfigureAwait(false);

            return(newVersion.GetNewerVersion(oldVersion));
        }
Beispiel #32
0
 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);
     }
 }
Beispiel #33
0
 internal DocumentBranch(SourceText text, DocumentState state)
 {
     this.Text = text;
     this.State = state;
 }
Beispiel #34
0
        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));
        }
Beispiel #35
0
 internal DocumentBranch(SourceText text, DocumentState state)
 {
     this.Text  = text;
     this.State = state;
 }
Beispiel #36
0
        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;
        }
Beispiel #37
0
 internal Document(Project project, DocumentState state) :
     base(project, state)
 {
 }
 public static CompilationTranslationAction TouchDocument(DocumentState oldState, DocumentState newState)
 {
     return new TouchDocumentAction(oldState, newState);
 }
Beispiel #39
0
 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));
 }
Beispiel #40
0
 internal Task <ImmutableDictionary <string, string> > GetAnalyzerOptionsAsync(CancellationToken cancellationToken)
 {
     return(DocumentState.GetAnalyzerOptionsAsync(Project.FilePath, cancellationToken));
 }
Beispiel #41
0
        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));
            }
        }