public async Task <Solution> ProcessAsync( Document document, SyntaxNode syntaxRoot, CancellationToken cancellationToken) { if (m_unwrittenWritableFields == null) { using (await SemaphoreLock.GetAsync(m_processUsagesLock)) { // A global analysis must be run before we can do any actual processing, because a field might // be written in a different file than it is declared (even private ones may be split between // partial classes). // It's also quite expensive, which is why it's being done inside the lock, so // that the entire solution is not processed for each input file individually if (m_unwrittenWritableFields == null) { List <Document> allDocuments = document.Project.Solution.Projects.SelectMany(p => p.Documents).ToList(); HashSet <IFieldSymbol>[] fields = await Task.WhenAll( allDocuments .AsParallel() .Select( doc => WritableFieldScanner.Scan(doc, cancellationToken))); var writableFields = new ConcurrentDictionary <IFieldSymbol, bool>( fields.SelectMany(s => s).Select(f => new KeyValuePair <IFieldSymbol, bool>(f, true))); await Task.WhenAll( allDocuments.AsParallel() .Select( doc => WriteUsagesScanner.RemoveWrittenFields( doc, writableFields, cancellationToken))); m_unwrittenWritableFields = writableFields; } } } if (m_unwrittenWritableFields.Count == 0) { // If there are no unwritten writable fields, skip all the rewriting return(document.Project.Solution); } SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken); var application = new ReadonlyRewriter( m_unwrittenWritableFields, await document.GetSemanticModelAsync(cancellationToken)); return(document.Project.Solution.WithDocumentSyntaxRoot(document.Id, application.Visit(root))); }
public async Task<Solution> ProcessAsync( Document document, SyntaxNode syntaxRoot, CancellationToken cancellationToken) { if (_unwrittenWritableFields == null) { using (await SemaphoreLock.GetAsync(_processUsagesLock)) { // A global analysis must be run before we can do any actual processing, because a field might // be written in a different file than it is declared (even private ones may be split between // partial classes). // It's also quite expensive, which is why it's being done inside the lock, so // that the entire solution is not processed for each input file individually if (_unwrittenWritableFields == null) { List<Document> allDocuments = document.Project.Solution.Projects.SelectMany(p => p.Documents).ToList(); HashSet<IFieldSymbol>[] fields = await Task.WhenAll( allDocuments .AsParallel() .Select( doc => WritableFieldScanner.Scan(doc, cancellationToken))); var writableFields = new ConcurrentDictionary<IFieldSymbol, bool>( fields.SelectMany(s => s).Select(f => new KeyValuePair<IFieldSymbol, bool>(f, true))); await Task.WhenAll( allDocuments.AsParallel() .Select( doc => WriteUsagesScanner.RemoveWrittenFields( doc, writableFields, cancellationToken))); _unwrittenWritableFields = writableFields; } } } if (_unwrittenWritableFields.Count == 0) { // If there are no unwritten writable fields, skip all the rewriting return document.Project.Solution; } SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken); var application = new ReadonlyRewriter( _unwrittenWritableFields, await document.GetSemanticModelAsync(cancellationToken)); return document.Project.Solution.WithDocumentSyntaxRoot(document.Id, application.Visit(root)); }