// use static method so we don't capture references to this private static Tuple <ValueSource <TextAndVersion>, TreeAndVersion> CreateRecoverableTextAndTree( SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, Encoding encoding, DocumentInfo.DocumentAttributes attributes, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode, SolutionServices solutionServices) { string filePath = attributes.FilePath; SyntaxTree tree = null; ValueSource <TextAndVersion> lazyTextAndVersion = null; if ((mode == PreservationMode.PreserveIdentity) || !factory.CanCreateRecoverableTree(newRoot)) { // its okay to use a strong cached AsyncLazy here because the compiler layer SyntaxTree will also keep the text alive once its built. lazyTextAndVersion = new TreeTextSource( new AsyncLazy <SourceText>( c => tree.GetTextAsync(c), c => tree.GetText(c), cacheResult: true), textVersion, filePath); tree = factory.CreateSyntaxTree(GetSyntaxTreeFilePath(attributes), options, encoding, newRoot); } else { // uses CachedWeakValueSource so the document and tree will return the same SourceText instance across multiple accesses as long // as the text is referenced elsewhere. lazyTextAndVersion = new TreeTextSource( new CachedWeakValueSource <SourceText>( new AsyncLazy <SourceText>( c => BuildRecoverableTreeTextAsync(tree, encoding, c), c => BuildRecoverableTreeText(tree, encoding, c), cacheResult: false)), textVersion, filePath); tree = factory.CreateRecoverableTree(attributes.Id.ProjectId, GetSyntaxTreeFilePath(attributes), options, lazyTextAndVersion, encoding, newRoot); } return(Tuple.Create(lazyTextAndVersion, TreeAndVersion.Create(tree, treeVersion))); }
protected static TextAndVersion LoadTextSynchronously(TextLoader loader, DocumentId documentId, SolutionServices services, bool reportInvalidDataException, CancellationToken cancellationToken) { int retries = 0; while (true) { try { using (ExceptionHelpers.SuppressFailFast()) { var result = loader.LoadTextAndVersionSynchronously(services.Workspace, documentId, cancellationToken); return(result); } } catch (OperationCanceledException) { // if load text is failed due to a cancellation, make sure we propagate it out to the caller throw; } catch (IOException e) { if (++retries > MaxRetries) { services.Workspace.OnWorkspaceFailed(new DocumentDiagnostic(WorkspaceDiagnosticKind.Failure, e.Message, documentId)); return(TextAndVersion.Create(SourceText.From(string.Empty, Encoding.UTF8), VersionStamp.Default, documentId.GetDebuggerDisplay())); } // fall out to try again } catch (InvalidDataException e) { // TODO: Adjust this behavior in the future if we add support for non-text additional files if (reportInvalidDataException) { services.Workspace.OnWorkspaceFailed(new DocumentDiagnostic(WorkspaceDiagnosticKind.Failure, e.Message, documentId)); } return(TextAndVersion.Create(SourceText.From(string.Empty, Encoding.UTF8), VersionStamp.Default, documentId.GetDebuggerDisplay())); } // try again after a delay Thread.Sleep(RetryDelay); } }
protected static ValueSource <TextAndVersion> CreateRecoverableText(TextLoader loader, DocumentId documentId, SolutionServices services, bool reportInvalidDataException) { return(new RecoverableTextAndVersion( new AsyncLazy <TextAndVersion>( asynchronousComputeFunction: c => LoadTextAsync(loader, documentId, services, reportInvalidDataException, c), synchronousComputeFunction: c => LoadTextSynchronously(loader, documentId, services, reportInvalidDataException, c), cacheResult: false), services.TemporaryStorage)); }
protected static ValueSource <TextAndVersion> CreateRecoverableText(TextAndVersion text, SolutionServices services) { return(new RecoverableTextAndVersion(CreateStrongText(text), services.TemporaryStorage)); }
public ProjectState(ProjectInfo projectInfo, HostLanguageServices languageServices, SolutionServices solutionServices) { Contract.ThrowIfNull(projectInfo); Contract.ThrowIfNull(languageServices); Contract.ThrowIfNull(solutionServices); _languageServices = languageServices; _solutionServices = solutionServices; var projectInfoFixed = FixProjectInfo(projectInfo); _documentIds = projectInfoFixed.Documents.Select(d => d.Id).ToImmutableList(); _additionalDocumentIds = projectInfoFixed.AdditionalDocuments.Select(d => d.Id).ToImmutableList(); var parseOptions = projectInfoFixed.ParseOptions; var docStates = ImmutableSortedDictionary.CreateRange(DocumentIdComparer.Instance, projectInfoFixed.Documents.Select(d => new KeyValuePair <DocumentId, DocumentState>(d.Id, CreateDocument(d, parseOptions, languageServices, solutionServices)))); _documentStates = docStates; var additionalDocStates = ImmutableSortedDictionary.CreateRange(DocumentIdComparer.Instance, projectInfoFixed.AdditionalDocuments.Select(d => new KeyValuePair <DocumentId, TextDocumentState>(d.Id, TextDocumentState.Create(d, solutionServices)))); _additionalDocumentStates = additionalDocStates; _lazyLatestDocumentVersion = new AsyncLazy <VersionStamp>(c => ComputeLatestDocumentVersionAsync(docStates, additionalDocStates, c), cacheResult: true); _lazyLatestDocumentTopLevelChangeVersion = new AsyncLazy <VersionStamp>(c => ComputeLatestDocumentTopLevelChangeVersionAsync(docStates, additionalDocStates, c), cacheResult: true); // ownership of information on document has moved to project state. clear out documentInfo the state is // holding on. otherwise, these information will be held onto unnecesarily by projectInfo even after // the info has changed by DocumentState. // we hold onto the info so that we don't need to duplicate all information info already has in the state _projectInfo = ClearAllDocumentsFromProjectInfo(projectInfoFixed); _lazyChecksums = new AsyncLazy <ProjectStateChecksums>(ComputeChecksumsAsync, cacheResult: true); }
private static DocumentState CreateDocument(DocumentInfo documentInfo, ParseOptions parseOptions, HostLanguageServices languageServices, SolutionServices solutionServices) { var doc = DocumentState.Create(documentInfo, parseOptions, languageServices, solutionServices); if (doc.SourceCodeKind != documentInfo.SourceCodeKind) { doc = doc.UpdateSourceCodeKind(documentInfo.SourceCodeKind); } return(doc); }