|
7 | 7 | using System.Diagnostics.CodeAnalysis;
|
8 | 8 | using System.Globalization;
|
9 | 9 | using System.Linq;
|
| 10 | +using Microsoft.CodeAnalysis.Collections; |
10 | 11 | using Microsoft.CodeAnalysis.CSharp;
|
11 | 12 | using Microsoft.CodeAnalysis.CSharp.Syntax;
|
12 | 13 | using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
|
13 | 14 | using Microsoft.CodeAnalysis.PooledObjects;
|
14 | 15 | using Microsoft.CodeAnalysis.Text;
|
15 | 16 | using Microsoft.CodeAnalysis.Text.Shared.Extensions;
|
| 17 | +using Microsoft.VisualStudio.Debugger.Contracts.EditAndContinue.VsdbgIntegration; |
16 | 18 | using Microsoft.VisualStudio.Text;
|
17 | 19 |
|
18 | 20 | namespace Microsoft.CodeAnalysis.Editor.CSharp.StringCopyPaste;
|
@@ -497,19 +499,39 @@ static bool WillEscapeAnyCharacters(bool isInterpolated, string value)
|
497 | 499 | string? commonIndentPrefix = null;
|
498 | 500 | var first = true;
|
499 | 501 |
|
| 502 | + using var allLines = TemporaryArray<TextLine>.Empty; |
| 503 | + |
500 | 504 | foreach (var change in textChanges)
|
501 | 505 | {
|
502 | 506 | var text = SourceText.From(change.NewText);
|
503 | 507 | foreach (var line in text.Lines)
|
504 | 508 | {
|
505 |
| - if (first) |
506 |
| - { |
507 |
| - first = false; |
508 |
| - continue; |
509 |
| - } |
510 |
| - |
511 | 509 | var nonWhitespaceIndex = GetFirstNonWhitespaceIndex(text, line);
|
512 |
| - if (nonWhitespaceIndex >= 0) |
| 510 | + |
| 511 | + // For the first line, we only want to consider its indentation if it *has* any. That's because |
| 512 | + // people often copy by avoiding indentation on the first line and starting their selection on the |
| 513 | + // first real construct. e.g.: |
| 514 | + // |
| 515 | + // <ws>[|Goo |
| 516 | + // <ws >Bar |
| 517 | + // <ws >Baz|] |
| 518 | + // |
| 519 | + // In this case, we don't want to say that there is no common indentation to trim since there is |
| 520 | + // no indentation on the selection's first line. However, we do want to trim if the user selected |
| 521 | + // whitespace a-la: |
| 522 | + // |
| 523 | + // [|<ws>Goo |
| 524 | + // <ws >Bar |
| 525 | + // <ws >Baz|] |
| 526 | + // |
| 527 | + // In this case, we really only want to trim the common whitespace of all three lines, not the whitespace |
| 528 | + // of the second/third lines. If we do the latter, we'd end up with Goo and Bar being aligned, which |
| 529 | + // doesn't match the original intent. |
| 530 | + |
| 531 | + var minimumStartColumn = first ? 1 : 0; |
| 532 | + first = false; |
| 533 | + |
| 534 | + if (nonWhitespaceIndex >= minimumStartColumn) |
513 | 535 | commonIndentPrefix = GetCommonIndentationPrefix(commonIndentPrefix, text, TextSpan.FromBounds(line.Start, nonWhitespaceIndex));
|
514 | 536 | }
|
515 | 537 | }
|
@@ -554,6 +576,11 @@ public static bool RawContentMustBeMultiLine(SourceText text, ImmutableArray<Tex
|
554 | 576 | return true;
|
555 | 577 |
|
556 | 578 | // or contains a newline
|
| 579 | + return SpansContainsNewLine(text, spans); |
| 580 | + } |
| 581 | + |
| 582 | + public static bool SpansContainsNewLine(SourceText text, ImmutableArray<TextSpan> spans) |
| 583 | + { |
557 | 584 | foreach (var span in spans)
|
558 | 585 | {
|
559 | 586 | for (var i = span.Start; i < span.End; i++)
|
|
0 commit comments