blob: 53736910311382e03ae32a304fafa58804294fc4 [file] [log] [blame]
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/Lexer.h"
#include "swift/Subsystems.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
using namespace swift;
using namespace swift::syntax;
using namespace llvm;
class LexerTriviaTest : public ::testing::Test {};
TEST_F(LexerTriviaTest, RestoreWithTrivia) {
using namespace swift::syntax;
StringRef SourceStr = "aaa \n bbb /*C*/ccc";
LangOptions LangOpts;
SourceManager SourceMgr;
unsigned BufferID = SourceMgr.addMemBufferCopy(SourceStr);
Lexer L(LangOpts, SourceMgr, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
CommentRetentionMode::AttachToNextToken,
TriviaRetentionMode::WithTrivia);
Token Tok;
Trivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia, Trivia());
ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia,
(Trivia{{TriviaPiece::newlines(1), TriviaPiece::spaces(1)}}));
ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
LexerState S = L.getStateForBeginningOfToken(Tok, LeadingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("ccc", Tok.getText());
ASSERT_FALSE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::blockComment("/*C*/")}}));
ASSERT_EQ(TrailingTrivia, Trivia());
L.restoreState(S);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia,
(Trivia{{TriviaPiece::newlines(1), TriviaPiece::spaces(1)}}));
ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
}
TEST_F(LexerTriviaTest, TriviaHashbang) {
StringRef SourceStr = "#!/bin/swift\naaa";
LangOptions LangOpts;
SourceManager SourceMgr;
unsigned BufferID = SourceMgr.addMemBufferCopy(SourceStr);
Lexer L(LangOpts, SourceMgr, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
CommentRetentionMode::AttachToNextToken,
TriviaRetentionMode::WithTrivia);
Token Tok;
Trivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia,
(Trivia{{TriviaPiece::garbageText("#!/bin/swift"),
TriviaPiece::newlines(1)}}));
}
TEST_F(LexerTriviaTest, TriviaHashbangAfterBOM) {
StringRef SourceStr = "\xEF\xBB\xBF" "#!/bin/swift\naaa";
LangOptions LangOpts;
SourceManager SourceMgr;
unsigned BufferID = SourceMgr.addMemBufferCopy(SourceStr);
Lexer L(LangOpts, SourceMgr, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
CommentRetentionMode::AttachToNextToken,
TriviaRetentionMode::WithTrivia);
Token Tok;
Trivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia,
(Trivia{{TriviaPiece::garbageText("\xEF\xBB\xBF"),
TriviaPiece::garbageText("#!/bin/swift"),
TriviaPiece::newlines(1)}}));
}
TEST_F(LexerTriviaTest, TriviaConflictMarker) {
using namespace swift::syntax;
StringRef SourceStr =
"aaa\n"
"<<<<<<< HEAD:conflict_markers.swift\n"
"new\n"
"=======\n"
"old\n"
">>>>>>> 18844bc65229786b96b89a9fc7739c0f:conflict_markers.swift\n"
"bbb\n";
LangOptions LangOpts;
SourceManager SourceMgr;
unsigned BufferID = SourceMgr.addMemBufferCopy(SourceStr);
Lexer L(LangOpts, SourceMgr, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
CommentRetentionMode::AttachToNextToken,
TriviaRetentionMode::WithTrivia);
Token Tok;
Trivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
StringRef expectedTrivia =
"<<<<<<< HEAD:conflict_markers.swift\n"
"new\n"
"=======\n"
"old\n"
">>>>>>> 18844bc65229786b96b89a9fc7739c0f:conflict_markers.swift";
ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::newlines(1),
TriviaPiece::garbageText(expectedTrivia),
TriviaPiece::newlines(1)}}));
}
TEST_F(LexerTriviaTest, TriviaCarriageReturn) {
using namespace swift::syntax;
StringRef SourceStr = "aaa\r\rbbb\r";
LangOptions LangOpts;
SourceManager SourceMgr;
unsigned BufferID = SourceMgr.addMemBufferCopy(SourceStr);
Lexer L(LangOpts, SourceMgr, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
CommentRetentionMode::AttachToNextToken,
TriviaRetentionMode::WithTrivia);
Token Tok;
Trivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia, Trivia());
ASSERT_EQ(TrailingTrivia, Trivia());
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::carriageReturns(2)}}));
ASSERT_EQ(TrailingTrivia, Trivia());
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::eof, Tok.getKind());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::carriageReturns(1)}}));
ASSERT_EQ(TrailingTrivia, Trivia());
}
TEST_F(LexerTriviaTest, TriviaNewLines) {
using namespace swift::syntax;
StringRef SourceStr = "\n\r\r\n\r\r\r\n\r\n\n\n"
"aaa"
"\n\r\r\n\r\r\r\n\r\n\n\n"
"bbb"
"\n\r\r\n\r\r\r\n\r\n\n\n";
LangOptions LangOpts;
SourceManager SourceMgr;
unsigned BufferID = SourceMgr.addMemBufferCopy(SourceStr);
Lexer L(LangOpts, SourceMgr, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
CommentRetentionMode::AttachToNextToken,
TriviaRetentionMode::WithTrivia);
Token Tok;
Trivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ((Trivia{{
TriviaPiece::newlines(1),
TriviaPiece::carriageReturns(1),
TriviaPiece::carriageReturnLineFeeds(1),
TriviaPiece::carriageReturns(2),
TriviaPiece::carriageReturnLineFeeds(2),
TriviaPiece::newlines(2)
}}), LeadingTrivia);
ASSERT_EQ(Trivia(), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ((Trivia{{
TriviaPiece::newlines(1),
TriviaPiece::carriageReturns(1),
TriviaPiece::carriageReturnLineFeeds(1),
TriviaPiece::carriageReturns(2),
TriviaPiece::carriageReturnLineFeeds(2),
TriviaPiece::newlines(2)
}}), LeadingTrivia);
ASSERT_EQ(Trivia(), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::eof, Tok.getKind());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ((Trivia{{
TriviaPiece::newlines(1),
TriviaPiece::carriageReturns(1),
TriviaPiece::carriageReturnLineFeeds(1),
TriviaPiece::carriageReturns(2),
TriviaPiece::carriageReturnLineFeeds(2),
TriviaPiece::newlines(2)
}}), LeadingTrivia);
ASSERT_EQ(Trivia(), TrailingTrivia);
}