private void ApplySpaceAndWrappingOperations( FormattingContext context, TokenStream tokenStream, TokenPairWithOperations[] tokenOperations, OperationApplier applier, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Formatting_ApplySpaceAndLine, cancellationToken)) { // go through each token pairs and apply operations. operations don't need to be applied in order var partitioner = new Partitioner(context, tokenStream, tokenOperations); // always create task 1 more than current processor count var partitions = partitioner.GetPartitions(this.TaskExecutor == TaskExecutor.Synchronous ? 1 : Environment.ProcessorCount + 1); var tasks = new List <Task>( partitions.Select( partition => this.TaskExecutor.StartNew( () => { cancellationToken.ThrowIfCancellationRequested(); partition.Do(operationPair => ApplySpaceAndWrappingOperationsBody(context, tokenStream, operationPair, applier, cancellationToken)); }, cancellationToken))); Task.WaitAll(tasks.ToArray(), cancellationToken); } }
private void ApplySpecialOperations( FormattingContext context, NodeOperations nodeOperationsCollector, OperationApplier applier, CancellationToken cancellationToken) { // apply alignment operation using (Logger.LogBlock(FunctionId.Formatting_CollectAlignOperation, cancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); // TODO : figure out a way to run alignment operations in parallel. probably find // unions and run each chunk in separate tasks var previousChangesMap = new Dictionary <SyntaxToken, int>(); var alignmentOperations = nodeOperationsCollector.AlignmentOperation; alignmentOperations.Do(operation => { cancellationToken.ThrowIfCancellationRequested(); applier.ApplyAlignment(operation, previousChangesMap, cancellationToken); }); // go through all relative indent block operation, and see whether it is affected by previous operations context.GetAllRelativeIndentBlockOperations().Do(o => { cancellationToken.ThrowIfCancellationRequested(); applier.ApplyBaseTokenIndentationChangesFromTo(FindCorrectBaseTokenOfRelativeIndentBlockOperation(o, context.TokenStream), o.StartToken, o.EndToken, previousChangesMap, cancellationToken); }); } }
private void ApplyAnchorOperations( FormattingContext context, TokenStream tokenStream, TokenPairWithOperations[] tokenOperations, OperationApplier applier, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Formatting_ApplyAnchorOperation, cancellationToken)) { var tokenPairsToApplyAnchorOperations = this.TaskExecutor.Filter( tokenOperations, p => AnchorOperationCandidate(p), p => p.PairIndex, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); // TODO: find out a way to apply anchor operation concurrently if possible var previousChangesMap = new Dictionary <SyntaxToken, int>(); tokenPairsToApplyAnchorOperations.Do(pairIndex => { cancellationToken.ThrowIfCancellationRequested(); applier.ApplyAnchorIndentation(pairIndex, previousChangesMap, cancellationToken); }); // go through all relative indent block operation, and see whether it is affected by the anchor operation context.GetAllRelativeIndentBlockOperations().Do(o => { cancellationToken.ThrowIfCancellationRequested(); applier.ApplyBaseTokenIndentationChangesFromTo(FindCorrectBaseTokenOfRelativeIndentBlockOperation(o, tokenStream), o.StartToken, o.EndToken, previousChangesMap, cancellationToken); }); } }
private void ApplyTokenOperations( FormattingContext context, NodeOperations nodeOperations, SegmentedArray <TokenPairWithOperations> tokenOperations, CancellationToken cancellationToken) { var applier = new OperationApplier(context, _formattingRules); ApplySpaceAndWrappingOperations(context, tokenOperations, applier, cancellationToken); ApplyAnchorOperations(context, tokenOperations, applier, cancellationToken); ApplySpecialOperations(context, nodeOperations, applier, cancellationToken); }
private void ApplyTokenOperations( FormattingContext context, TokenStream tokenStream, NodeOperations nodeOperations, TokenPairWithOperations[] tokenOperations, CancellationToken cancellationToken) { var applier = new OperationApplier(context, tokenStream, _formattingRules); ApplySpaceAndWrappingOperations(context, tokenStream, tokenOperations, applier, cancellationToken); ApplyAnchorOperations(context, tokenStream, tokenOperations, applier, cancellationToken); ApplySpecialOperations(context, tokenStream, nodeOperations, applier, cancellationToken); }
private static void ApplySpaceAndWrappingOperationsBody( FormattingContext context, TokenStream tokenStream, TokenPairWithOperations operation, OperationApplier applier, CancellationToken cancellationToken) { var token1 = operation.Token1; var token2 = operation.Token2; // check whether one of tokens is missing (which means syntax error exist around two tokens) // in error case, we leave code as user wrote if (token1.IsMissing || token2.IsMissing) { return; } var triviaInfo = tokenStream.GetTriviaData(operation.PairIndex); var spanBetweenTokens = TextSpan.FromBounds(token1.Span.End, token2.SpanStart); if (operation.LineOperation != null) { if (!context.IsWrappingSuppressed(spanBetweenTokens)) { // TODO : need to revisit later for the case where line and space operations // are conflicting each other by forcing new lines and removing new lines. // // if wrapping operation applied, no need to run any other operation if (applier.Apply(operation.LineOperation, operation.PairIndex, cancellationToken)) { return; } } } if (operation.SpaceOperation != null) { if (!context.IsSpacingSuppressed(spanBetweenTokens)) { applier.Apply(operation.SpaceOperation, operation.PairIndex); } } }
private void ApplyTokenOperations( FormattingContext context, TokenStream tokenStream, Task anchorContextTask, NodeOperations nodeOperations, TokenPairWithOperations[] tokenOperations, CancellationToken cancellationToken) { var applier = new OperationApplier(context, tokenStream, this.formattingRules); ApplySpaceAndWrappingOperations(context, tokenStream, tokenOperations, applier, cancellationToken); // wait until anchor task to finish adding its information to context anchorContextTask.Wait(cancellationToken); ApplyAnchorOperations(context, tokenStream, tokenOperations, applier, cancellationToken); ApplySpecialOperations(context, tokenStream, nodeOperations, applier, cancellationToken); }
private async Task ApplyTokenOperationsAsync( FormattingContext context, TokenStream tokenStream, Task anchorContextTask, NodeOperations nodeOperations, TokenPairWithOperations[] tokenOperations, CancellationToken cancellationToken) { var applier = new OperationApplier(context, tokenStream, _formattingRules); ApplySpaceAndWrappingOperations(context, tokenStream, tokenOperations, applier, cancellationToken); // wait until anchor task to finish adding its information to context await anchorContextTask.ConfigureAwait(false); ApplyAnchorOperations(context, tokenStream, tokenOperations, applier, cancellationToken); await ApplySpecialOperationsAsync(context, tokenStream, nodeOperations, applier, cancellationToken).ConfigureAwait(false); }
private void ApplySpaceAndWrappingOperations( FormattingContext context, TokenPairWithOperations[] tokenOperations, OperationApplier applier, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Formatting_ApplySpaceAndLine, cancellationToken)) { // go through each token pairs and apply operations. operations don't need to be applied in order var partitioner = new Partitioner(context, tokenOperations); // always create task 1 more than current processor count var partitions = partitioner.GetPartitions(partitionCount: 1, cancellationToken); foreach (var partition in partitions) { cancellationToken.ThrowIfCancellationRequested(); partition.Do(operationPair => ApplySpaceAndWrappingOperationsBody(context, operationPair, applier, cancellationToken)); } } }
/// <summary> /// Retrieves, applies, and acknowledges each operation from the provided <paramref name="queue"/>. /// </summary> /// <param name="queue">The queue.</param> /// <param name="apply">The method used to apply each operation.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="initiated"> /// Optional completion to signify that the queue draining has begun. /// </param> /// <returns>A <see cref="Task"/> representing the work performed.</returns> private static async Task PumpOperations( IOperationStream queue, OperationApplier apply, CancellationToken cancellationToken, TaskCompletionSource <int> initiated = null) { var firstOperation = true; do { cancellationToken.ThrowIfCancellationRequested(); // Start retrieving the next operation. var nextOperation = queue.GetOperationAsync(cancellationToken); // If this is the first operation and the caller has requested to be notified that draining has begun, // notify the caller. if (firstOperation) { initiated?.TrySetResult(0); firstOperation = false; } // Wait for the operation to be retrieved. var operation = await nextOperation.ConfigureAwait(false); // A null operation signifies that the queue has been completely drained. if (operation == null) { return; } // Apply and acknowledge the operation. await apply(operation, cancellationToken).ConfigureAwait(false); operation.Acknowledge(); }while (true); }
/// <summary> /// Retrieves, applies, and acknowledges each operation from the provided <paramref name="queue"/>. /// </summary> /// <param name="queue">The queue.</param> /// <param name="apply">The method used to apply each operation.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="initiated"> /// Optional completion to signify that the queue draining has begun. /// </param> /// <returns>A <see cref="Task"/> representing the work performed.</returns> private static async Task PumpOperations( IOperationStream queue, OperationApplier apply, CancellationToken cancellationToken, TaskCompletionSource<int> initiated = null) { var firstOperation = true; do { cancellationToken.ThrowIfCancellationRequested(); // Start retrieving the next operation. var nextOperation = queue.GetOperationAsync(cancellationToken); // If this is the first operation and the caller has requested to be notified that draining has begun, // notify the caller. if (firstOperation) { initiated?.TrySetResult(0); firstOperation = false; } // Wait for the operation to be retrieved. var operation = await nextOperation.ConfigureAwait(false); // A null operation signifies that the queue has been completely drained. if (operation == null) { return; } // Apply and acknowledge the operation. await apply(operation, cancellationToken).ConfigureAwait(false); operation.Acknowledge(); } while (true); }