private DisableNextLineDiagnosticsSyntaxTrivia GetDisableNextLineDiagnosticsSyntaxTrivia(List <Token> codes, int start, int length, string text) { if (codes.Any()) { var lastCodeSpan = codes.Last().Span; var lastCodeSpanEnd = lastCodeSpan.GetEndPosition(); // There could be whitespace following #disable-next-line directive, in which case we need to adjust the span and text. // E.g. #disable-next-line BCP226 // test if (length > lastCodeSpanEnd) { textWindow.Rewind(length - lastCodeSpanEnd); return(new DisableNextLineDiagnosticsSyntaxTrivia(SyntaxTriviaType.DisableNextLineDiagnosticsDirective, new TextSpan(start, lastCodeSpanEnd), text.Substring(0, lastCodeSpanEnd), codes)); } } return(new DisableNextLineDiagnosticsSyntaxTrivia(SyntaxTriviaType.DisableNextLineDiagnosticsDirective, new TextSpan(start, length), text, codes)); }
private TokenType ScanToken() { if (textWindow.IsAtEnd()) { return(TokenType.EndOfFile); } var nextChar = textWindow.Peek(); textWindow.Advance(); switch (nextChar) { case '{': if (templateStack.Any()) { // if we're inside a string interpolation hole, and we find an object open brace, // push it to the stack, so that we can match it up against an object close brace. // this allows us to determine whether we're terminating an object or closing an interpolation hole. templateStack.Push(TokenType.LeftBrace); } return(TokenType.LeftBrace); case '}': if (templateStack.Any()) { var prevTemplateToken = templateStack.Peek(); if (prevTemplateToken != TokenType.LeftBrace) { var stringToken = ScanStringSegment(false); if (stringToken == TokenType.StringRightPiece) { templateStack.Pop(); } return(stringToken); } } return(TokenType.RightBrace); case '(': return(TokenType.LeftParen); case ')': return(TokenType.RightParen); case '[': return(TokenType.LeftSquare); case ']': return(TokenType.RightSquare); case '@': return(TokenType.At); case ',': return(TokenType.Comma); case '.': return(TokenType.Dot); case '?': return(TokenType.Question); case ':': return(TokenType.Colon); case ';': return(TokenType.Semicolon); case '+': return(TokenType.Plus); case '-': return(TokenType.Minus); case '%': return(TokenType.Modulo); case '*': return(TokenType.Asterisk); case '/': return(TokenType.Slash); case '!': if (!textWindow.IsAtEnd()) { switch (textWindow.Peek()) { case '=': textWindow.Advance(); return(TokenType.NotEquals); case '~': textWindow.Advance(); return(TokenType.NotEqualsInsensitive); } } return(TokenType.Exclamation); case '<': if (!textWindow.IsAtEnd()) { switch (textWindow.Peek()) { case '=': textWindow.Advance(); return(TokenType.LessThanOrEqual); } } return(TokenType.LessThan); case '>': if (!textWindow.IsAtEnd()) { switch (textWindow.Peek()) { case '=': textWindow.Advance(); return(TokenType.GreaterThanOrEqual); } } return(TokenType.GreaterThan); case '=': if (!textWindow.IsAtEnd()) { switch (textWindow.Peek()) { case '=': textWindow.Advance(); return(TokenType.Equals); case '~': textWindow.Advance(); return(TokenType.EqualsInsensitive); } } return(TokenType.Assignment); case '&': if (!textWindow.IsAtEnd()) { switch (textWindow.Peek()) { case '&': textWindow.Advance(); return(TokenType.LogicalAnd); } } return(TokenType.Unrecognized); case '|': if (!textWindow.IsAtEnd()) { switch (textWindow.Peek()) { case '|': textWindow.Advance(); return(TokenType.LogicalOr); } } return(TokenType.Unrecognized); case '\'': var token = ScanStringSegment(true); if (token == TokenType.StringLeftPiece) { // if we're beginning a string interpolation statement, we need to keep track of it templateStack.Push(token); } return(token); case '\n': case '\r': if (templateStack.Any()) { // need to re-check the newline token on next pass textWindow.Rewind(); // do not consume the new line character // TODO: figure out a way to avoid returning this multiple times for nested interpolation AddDiagnostic(b => b.UnterminatedStringWithNewLine()); templateStack.Clear(); return(TokenType.StringRightPiece); } this.ScanNewLine(); return(TokenType.NewLine); default: if (IsDigit(nextChar)) { this.ScanNumber(); return(TokenType.Integer); } if (IsIdentifierStart(nextChar)) { return(this.ScanIdentifier()); } return(TokenType.Unrecognized); } }