private static void CleanupSourceMappingEnd(FormattingContext context, Range sourceMappingRange, List <TextChange> changes) { // // We look through every source mapping that intersects with the affected range and // bring the content after the last line to its own line and adjust its indentation, // // E.g, // // @{ // if (true) // { <div></div> // } // } // // becomes, // // @{ // if (true) // { // </div></div> // } // } // var text = context.SourceText; var sourceMappingSpan = sourceMappingRange.AsTextSpan(text); var mappingEndLineIndex = sourceMappingRange.End.Line; if (!context.Indentations[mappingEndLineIndex].StartsInCSharpContext) { // For corner cases like (Position marked with |), // It is already in a separate line. It doesn't need cleaning up. // @{ // if (true} // { // |<div></div> // } // } // return; } var endSpan = TextSpan.FromBounds(sourceMappingSpan.End, sourceMappingSpan.End); if (!ShouldFormat(context, endSpan, allowImplicitStatements: false)) { // We don't want to run cleanup on this range. return; } var contentStartOffset = text.Lines[mappingEndLineIndex].GetFirstNonWhitespaceOffset(sourceMappingRange.End.Character); if (contentStartOffset == null) { // There is no content after the end of this source mapping. No need to clean up. return; } var spanToReplace = new TextSpan(sourceMappingSpan.End, 0); if (!context.TryGetIndentationLevel(spanToReplace.End, out var contentIndentLevel)) { // Can't find the correct indentation for this content. Leave it alone. return; } // At this point, `contentIndentLevel` should contain the correct indentation level for `}` in the above example. var replacement = context.NewLineString + context.GetIndentationLevelString(contentIndentLevel); // After the below change the above example should look like, // @{ // if (true) // { // <div></div> // } // } var change = new TextChange(spanToReplace, replacement); changes.Add(change); }
private SourceText CleanupDocument(FormattingContext context, Range range = null) { // // We look through every source mapping that intersects with the affected range and // adjust the indentation of the first line, // // E.g, // // @{ public int x = 0; // } // // becomes, // // @{ // public int x = 0; // } // var text = context.SourceText; range ??= TextSpan.FromBounds(0, text.Length).AsRange(text); var csharpDocument = context.CodeDocument.GetCSharpDocument(); var changes = new List <TextChange>(); foreach (var mapping in csharpDocument.SourceMappings) { var mappingSpan = new TextSpan(mapping.OriginalSpan.AbsoluteIndex, mapping.OriginalSpan.Length); var mappingRange = mappingSpan.AsRange(text); if (!range.LineOverlapsWith(mappingRange)) { // We don't care about this range. It didn't change. continue; } var mappingStartLineIndex = (int)mappingRange.Start.Line; if (context.Indentations[mappingStartLineIndex].StartsInCSharpContext) { // Doesn't need cleaning up. // For corner cases like (Range marked with |...|), // @{ // if (true} { <div></div>| }| // } // We want to leave it alone because tackling it here is really complicated. continue; } // @{ // if (true) // { // <div></div>| // // |} // } // We want to return the length of the range marked by |...| // var whitespaceLength = text.GetFirstNonWhitespaceOffset(mappingSpan); if (whitespaceLength == null) { // There was no content here. Skip. continue; } var spanToReplace = new TextSpan(mappingSpan.Start, whitespaceLength.Value); if (!context.TryGetIndentationLevel(spanToReplace.End, out var contentIndentLevel)) { // Can't find the correct indentation for this content. Leave it alone. continue; } // At this point, `contentIndentLevel` should contain the correct indentation level for `}` in the above example. var replacement = context.NewLineString + context.GetIndentationLevelString(contentIndentLevel); // After the below change the above example should look like, // @{ // if (true) // { // <div></div> // } // } var change = new TextChange(spanToReplace, replacement); changes.Add(change); } var changedText = text.WithChanges(changes); return(changedText); }
private static void CleanupSourceMappingStart(FormattingContext context, Range sourceMappingRange, List <TextChange> changes) { // // We look through every source mapping that intersects with the affected range and // bring the first line to its own line and adjust its indentation, // // E.g, // // @{ public int x = 0; // } // // becomes, // // @{ // public int x = 0; // } // var text = context.SourceText; var sourceMappingSpan = sourceMappingRange.AsTextSpan(text); if (!ShouldFormat(context, sourceMappingSpan, allowImplicitStatements: false)) { // We don't want to run cleanup on this range. return; } if (sourceMappingRange.Start.Character == 0) { // It already starts on a fresh new line which doesn't need cleanup. // E.g, (The mapping starts at | in the below case) // @{ // @: Some html // | var x = 123; // } // return; } // @{ // if (true) // { // <div></div>| // // |} // } // We want to return the length of the range marked by |...| // var whitespaceLength = text.GetFirstNonWhitespaceOffset(sourceMappingSpan, out var newLineCount); if (whitespaceLength == null) { // There was no content after the start of this mapping. Meaning it already is clean. // E.g, // @{| // ... // } return; } var spanToReplace = new TextSpan(sourceMappingSpan.Start, whitespaceLength.Value); if (!context.TryGetIndentationLevel(spanToReplace.End, out var contentIndentLevel)) { // Can't find the correct indentation for this content. Leave it alone. return; } // At this point, `contentIndentLevel` should contain the correct indentation level for `}` in the above example. // Make sure to preserve the same number of blank lines as the original string had var replacement = PrependLines(context.GetIndentationLevelString(contentIndentLevel), context.NewLineString, Math.Max(newLineCount, 1)); // After the below change the above example should look like, // @{ // if (true) // { // <div></div> // } // } var change = new TextChange(spanToReplace, replacement); changes.Add(change); }
private void CleanupSourceMappingStart(FormattingContext context, Range sourceMappingRange, List <TextChange> changes) { // // We look through every source mapping that intersects with the affected range and // bring the first line to its own line and adjust its indentation, // // E.g, // // @{ public int x = 0; // } // // becomes, // // @{ // public int x = 0; // } // if (!ShouldFormat(context, sourceMappingRange.Start, allowImplicitStatements: false)) { // We don't want to run cleanup on this range. return; } // @{ // if (true) // { // <div></div>| // // |} // } // We want to return the length of the range marked by |...| // var text = context.SourceText; var sourceMappingSpan = sourceMappingRange.AsTextSpan(text); var whitespaceLength = text.GetFirstNonWhitespaceOffset(sourceMappingSpan); if (whitespaceLength == null) { // There was no content here. Skip. return; } var spanToReplace = new TextSpan(sourceMappingSpan.Start, whitespaceLength.Value); if (!context.TryGetIndentationLevel(spanToReplace.End, out var contentIndentLevel)) { // Can't find the correct indentation for this content. Leave it alone. return; } // At this point, `contentIndentLevel` should contain the correct indentation level for `}` in the above example. var replacement = context.NewLineString + context.GetIndentationLevelString(contentIndentLevel); // After the below change the above example should look like, // @{ // if (true) // { // <div></div> // } // } var change = new TextChange(spanToReplace, replacement); changes.Add(change); }