// This is the string used to represent the FilePath property on a SyntaxTree object. // if the document does not yet have a file path, use the document's name instead in regular code // or an empty string in script code. private static string GetSyntaxTreeFilePath(DocumentInfo.DocumentAttributes info) { if (info.FilePath != null) { return(info.FilePath); } return(info.SourceCodeKind == SourceCodeKind.Regular ? info.Name : ""); }
protected TextDocumentState( SolutionServices solutionServices, IDocumentServiceProvider documentServiceProvider, DocumentInfo.DocumentAttributes attributes, SourceText sourceTextOpt, ValueSource <TextAndVersion> textAndVersionSource, ValueSource <DocumentStateChecksums> lazyChecksums) { this.solutionServices = solutionServices; this.sourceTextOpt = sourceTextOpt; this.textAndVersionSource = textAndVersionSource; Attributes = attributes; Services = documentServiceProvider ?? DefaultTextDocumentServiceProvider.Instance; // for now, let it re-calculate if anything changed. // TODO: optimize this so that we only re-calcuate checksums that are actually changed _lazyChecksums = new AsyncLazy <DocumentStateChecksums>(ComputeChecksumsAsync, cacheResult: true); }
// 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))); }
private DocumentState( HostLanguageServices languageServices, SolutionServices solutionServices, IDocumentServiceProvider documentServiceProvider, DocumentInfo.DocumentAttributes attributes, ParseOptions options, SourceText sourceTextOpt, ValueSource <TextAndVersion> textSource, ValueSource <TreeAndVersion> treeSource, ValueSource <DocumentStateChecksums> lazyChecksums) : base(solutionServices, documentServiceProvider, attributes, sourceTextOpt, textSource, lazyChecksums) { _languageServices = languageServices; _options = options; // If this is document that doesn't support syntax, then don't even bother holding // onto any tree source. It will never be used to get a tree, and can only hurt us // by possibly holding onto data that might cause a slow memory leak. _treeSource = this.SupportsSyntaxTree ? treeSource : ValueSource <TreeAndVersion> .Empty; }