Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Debugger.Contracts.EditAndContinue.VsdbgIntegration;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing this was accidental.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. can fixup later.

using Microsoft.VisualStudio.Text;

namespace Microsoft.CodeAnalysis.Editor.CSharp.StringCopyPaste;
Expand Down Expand Up @@ -497,19 +499,39 @@ static bool WillEscapeAnyCharacters(bool isInterpolated, string value)
string? commonIndentPrefix = null;
var first = true;

using var allLines = TemporaryArray<TextLine>.Empty;

foreach (var change in textChanges)
{
var text = SourceText.From(change.NewText);
foreach (var line in text.Lines)
{
if (first)
{
first = false;
continue;
}

var nonWhitespaceIndex = GetFirstNonWhitespaceIndex(text, line);
if (nonWhitespaceIndex >= 0)

// For the first line, we only want to consider its indentation if it *has* any. That's because
// people often copy by avoiding indentation on the first line and starting their selection on the
// first real construct. e.g.:
//
// <ws>[|Goo
// <ws >Bar
// <ws >Baz|]
//
// In this case, we don't want to say that there is no common indentation to trim since there is
// no indentation on the selection's first line. However, we do want to trim if the user selected
// whitespace a-la:
//
// [|<ws>Goo
// <ws >Bar
// <ws >Baz|]
//
// In this case, we really only want to trim the common whitespace of all three lines, not the whitespace
// of the second/third lines. If we do the latter, we'd end up with Goo and Bar being aligned, which
// doesn't match the original intent.

var minimumStartColumn = first ? 1 : 0;
first = false;

if (nonWhitespaceIndex >= minimumStartColumn)
commonIndentPrefix = GetCommonIndentationPrefix(commonIndentPrefix, text, TextSpan.FromBounds(line.Start, nonWhitespaceIndex));
}
}
Expand Down Expand Up @@ -554,6 +576,11 @@ public static bool RawContentMustBeMultiLine(SourceText text, ImmutableArray<Tex
return true;

// or contains a newline
return SpansContainsNewLine(text, spans);
}

public static bool SpansContainsNewLine(SourceText text, ImmutableArray<TextSpan> spans)
{
foreach (var span in spans)
{
for (var i = span.Start; i < span.End; i++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,15 @@ private void AdjustWhitespaceAndAddTextChangesForSingleLineRawStringLiteral(Arra
if (mustBeMultiLine)
edits.Add(new TextChange(new TextSpan(StringExpressionBeforePasteInfo.StartDelimiterSpan.End, 0), NewLine + IndentationWhitespace));

SourceText? textOfCurrentChange = null;
var commonIndentationPrefix = GetCommonIndentationPrefix(Changes) ?? "";
// Only if we're ending with a multi-line raw string do we want to consider the first line when determining
// the common indentation prefix to trim out. If we don't have a multi-line raw string, then that means we
// pasted a boring single-line string into a single-line raw string, and in that case, we don't want to touch
// the contents at all.
var commonIndentationPrefix = SpansContainsNewLine(TextAfterPaste, TextContentsSpansAfterPaste)
? GetCommonIndentationPrefix(Changes) ?? ""
: "";

SourceText? textOfCurrentChange = null;
foreach (var change in Changes)
{
// Create a text object around the change text we're making. This is a very simple way to get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,37 @@ public void TestNormalTextIntoMultiLineRawStringMultiLine13()
"""");
}

[WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/74661")]
public void TestNormalTextIntoMultiLineRawStringMultiLine14()
{
TestPasteUnknownSource(
pasteText: """
abc
def
ghi
""",
""""
var x = """
[||]
"""
"""",
""""
var x = """
abc
def
ghi[||]
"""
"""",
afterUndo:
""""
var x = """
abc
def
ghi[||]
"""
"""");
}

[WpfFact]
public void TestNormalTextIntoMultiLineRawStringHeader1()
{
Expand Down
Loading