private void AddMultiLineRawStringLiteralLineContents( StringBuilder indentationWhitespace, StringBuilder currentLineWhitespace, bool firstContentLine) { Debug.Assert(SyntaxFacts.IsNewLine(TextWindow.PeekChar())); var newLineWidth = TextWindow.GetNewLineWidth(); for (var i = 0; i < newLineWidth; i++) { // the initial newline in `""" \r\n` is not added to the contents. if (!firstContentLine) { _builder.Append(TextWindow.PeekChar()); } TextWindow.AdvanceChar(); } var lineStartPosition = TextWindow.Position; currentLineWhitespace.Clear(); ConsumeWhitespace(currentLineWhitespace); if (!StartsWith(currentLineWhitespace, indentationWhitespace)) { // We have a line where the indentation of that line isn't a prefix of indentation // whitespace. // // If we're not on a blank line then this is bad. That's a content line that doesn't start // with the indentation whitespace. If we are on a blank line then it's ok if the whitespace // we do have is a prefix of the indentation whitespace. var isBlankLine = SyntaxFacts.IsNewLine(TextWindow.PeekChar()); var isLegalBlankLine = isBlankLine && StartsWith(indentationWhitespace, currentLineWhitespace); if (!isLegalBlankLine) { // Specialized error message if this is a spacing difference. if (CheckForSpaceDifference( currentLineWhitespace, indentationWhitespace, out var currentLineWhitespaceChar, out var indentationWhitespaceChar)) { this.AddError( lineStartPosition, width: TextWindow.Position - lineStartPosition, ErrorCode.ERR_LineContainsDifferentWhitespace, currentLineWhitespaceChar, indentationWhitespaceChar); } else { this.AddError( lineStartPosition, width: TextWindow.Position - lineStartPosition, ErrorCode.ERR_LineDoesNotStartWithSameWhitespace); } return; } }
private void ScanSingleLineRawStringLiteral(ref TokenInfo info, int startingQuoteCount) { info.Kind = SyntaxKind.SingleLineRawStringLiteralToken; while (true) { var currentChar = TextWindow.PeekChar(); // See if we reached the end of the line or file before hitting the end. if (SyntaxFacts.IsNewLine(currentChar)) { this.AddError(TextWindow.Position, width: TextWindow.GetNewLineWidth(), ErrorCode.ERR_UnterminatedRawString); return; } else if (IsAtEndOfText(currentChar)) { this.AddError(TextWindow.Position, width: 0, ErrorCode.ERR_UnterminatedRawString); return; } if (currentChar != '"') { // anything not a quote sequence just moves it forward. TextWindow.AdvanceChar(); continue; } var beforeEndDelimiter = TextWindow.Position; var currentQuoteCount = ConsumeQuoteSequence(); // A raw string literal starting with some number of quotes can contain a quote sequence with fewer quotes. if (currentQuoteCount < startingQuoteCount) { continue; } // A raw string could never be followed by another string. So once we've consumed all the closing quotes // if we have any more closing quotes then that's an error we can give a message for. if (currentQuoteCount > startingQuoteCount) { var excessQuoteCount = currentQuoteCount - startingQuoteCount; this.AddError( position: TextWindow.Position - excessQuoteCount, width: excessQuoteCount, ErrorCode.ERR_TooManyQuotesForRawString); } // We have enough quotes to finish this string at this point. var afterStartDelimiter = TextWindow.LexemeStartPosition + startingQuoteCount; var valueLength = beforeEndDelimiter - afterStartDelimiter; info.StringValue = TextWindow.GetText( position: afterStartDelimiter, length: valueLength, intern: true); return; } }