include-what-you-use/more_tests/iwyu_lexer_utils_test.cc

217 lines
8.0 KiB
C++

//===--- iwyu_lexer_utils_test.cc - test iwyu_lexer_utils.{cc,h} ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Tests for the iwyu_lexer_utils module. In addition, provides sample
// code for using Clang's Lexer.
#include "iwyu_lexer_utils.h"
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include "base/logging.h"
#include "iwyu_globals.h"
#include "testing/base/public/gunit.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Token.h"
using clang::LangOptions;
using clang::Lexer;
using clang::SourceLocation;
using clang::SourceRange;
using clang::Token;
namespace iwyu = include_what_you_use;
using iwyu::CharacterDataGetterInterface;
namespace {
// Hack. Work around the fact that only SourceManagers can create
// non-trivial SourceLocations.
SourceLocation CreateSourceLocationFromOffset(SourceLocation begin_loc,
unsigned offset) {
return SourceLocation::getFromRawEncoding(begin_loc.getRawEncoding()
+ offset);
}
class StringCharacterDataGetter : public CharacterDataGetterInterface {
public:
StringCharacterDataGetter(const string& str)
: str_("unused" + str) {
}
virtual const char* GetCharacterData(SourceLocation loc) const {
unsigned offset = loc.getRawEncoding();
CHECK_LE(offset, str_.size());
return str_.c_str() + offset;
}
SourceLocation BeginningOfString() {
// Returns an index into str that skips over the "unused" set in the ctor.
return CreateSourceLocationFromOffset(SourceLocation(), strlen("unused"));
}
private:
string str_;
};
TEST(GetSourceTextUntilEndOfLine, FullLine) {
const char text[] = "This is the full line.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
EXPECT_EQ("This is the full line.",
GetSourceTextUntilEndOfLine(begin_loc, data_getter));
}
TEST(GetSourceTextUntilEndOfLine, MultipleLines) {
const char text[] = "This is the full line.\nThis line should be ignored.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
EXPECT_EQ("This is the full line.",
GetSourceTextUntilEndOfLine(begin_loc, data_getter));
}
TEST(GetSourceTextUntilEndOfLine, PartialLine) {
const char text[] = "This is the full line.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation middle_loc = CreateSourceLocationFromOffset(begin_loc, 5);
EXPECT_EQ("is the full line.",
GetSourceTextUntilEndOfLine(middle_loc, data_getter));
}
TEST(GetSourceTextUntilEndOfLine, MiddleLine) {
const char text[] = "This is the full line.\nThis is the winning line.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation middle_loc = CreateSourceLocationFromOffset(begin_loc, 35);
EXPECT_EQ("winning line.",
GetSourceTextUntilEndOfLine(middle_loc, data_getter));
}
TEST(GetSourceTextUntilEndOfLine, NoNewline) {
const char text[] = "This is the full line.";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
EXPECT_EQ("This is the full line.",
GetSourceTextUntilEndOfLine(begin_loc, data_getter));
}
TEST(GetLocationAfter, FullLine) {
const char text[] = "This is the full line.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation after_loc = GetLocationAfter(begin_loc, "is the", data_getter);
EXPECT_TRUE(after_loc.isValid());
// We can't explore after_loc directly (it's opaque), so we use
// GetSourceTextUntilEndOfLine as a proxy.
EXPECT_EQ(" full line.", GetSourceTextUntilEndOfLine(after_loc, data_getter));
}
TEST(GetLocationAfter, FirstOfManyOccurrences) {
const char text[] = "This is the full line.\nThis is the full line too.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation after_loc = GetLocationAfter(begin_loc, "is the", data_getter);
EXPECT_TRUE(after_loc.isValid());
EXPECT_EQ(" full line.", GetSourceTextUntilEndOfLine(after_loc, data_getter));
}
TEST(GetLocationAfter, SecondOfManyOccurrences) {
const char text[] = "This is the full line.\nThis is the full line too.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation after_loc = GetLocationAfter(begin_loc, "is the", data_getter);
EXPECT_TRUE(after_loc.isValid());
after_loc = GetLocationAfter(after_loc, "is the", data_getter);
EXPECT_TRUE(after_loc.isValid());
EXPECT_EQ(" full line too.",
GetSourceTextUntilEndOfLine(after_loc, data_getter));
}
TEST(GetLocationAfter, NeedleNotFound) {
const char text[] = "This is the full line.\nThis is the full line too.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation after_loc = GetLocationAfter(begin_loc, "isthe", data_getter);
EXPECT_FALSE(after_loc.isValid());
}
TEST(GetLocationAfter, NeedleNotFoundTwice) {
const char text[] = "This is the full line.\nThis is the full line too.\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation after_loc = GetLocationAfter(begin_loc, "line.", data_getter);
EXPECT_TRUE(after_loc.isValid());
after_loc = GetLocationAfter(after_loc, "line.", data_getter);
EXPECT_FALSE(after_loc.isValid());
}
TEST(GetLocationAfter, EmptyNeedle) {
const char text[] = "This is the full line.";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation after_loc = GetLocationAfter(begin_loc, "", data_getter);
EXPECT_TRUE(after_loc.isValid());
EXPECT_EQ("This is the full line.",
GetSourceTextUntilEndOfLine(after_loc, data_getter));
}
TEST(GetLocationAfter, BeginAfterStartOfText) {
const char text[] = "This is the full line. This is the second 'this'.";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
begin_loc = CreateSourceLocationFromOffset(begin_loc, 1);
SourceLocation after_loc = GetLocationAfter(begin_loc, "This", data_getter);
EXPECT_TRUE(after_loc.isValid());
EXPECT_EQ(" is the second 'this'.",
GetSourceTextUntilEndOfLine(after_loc, data_getter));
}
TEST(GetIncludeNameAsWritten, SystemInclude) {
const char text[] = "#include <stdio.h>\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation inc_loc = CreateSourceLocationFromOffset(begin_loc, 9);
EXPECT_EQ("<stdio.h>",
GetIncludeNameAsWritten(inc_loc, data_getter));
}
TEST(GetIncludeNameAsWritten, NonsysytemInclude) {
const char text[] = "#include \"ads/util.h\"\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation inc_loc = CreateSourceLocationFromOffset(begin_loc, 9);
EXPECT_EQ("\"ads/util.h\"",
GetIncludeNameAsWritten(inc_loc, data_getter));
}
TEST(GetIncludeNameAsWritten, WithComments) {
const char text[] = "#include <stdio.h> // for printf\n";
StringCharacterDataGetter data_getter(text);
SourceLocation begin_loc = data_getter.BeginningOfString();
SourceLocation inc_loc = CreateSourceLocationFromOffset(begin_loc, 9);
EXPECT_EQ("<stdio.h>",
GetIncludeNameAsWritten(inc_loc, data_getter));
}
} // namespace
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
include_what_you_use::InitGlobalsAndFlagsForTesting();
return RUN_ALL_TESTS();
}