Skip to content

Commit 2078632

Browse files
committedAug 30, 2018
Move the column marking functionality to the Highlighter framework
Summary: The syntax highlighting feature so far is mutually exclusive with the lldb feature that marks the current column in the line by underlining it via an ANSI color code. Meaning that if you enable one, the other is automatically disabled by LLDB. This was caused by the fact that both features inserted color codes into the the source code and were likely to interfere with each other (which would result in a broken source code printout to the user). This patch moves the cursor code into the highlighting framework, which provides the same feature to the user in normal non-C source code. For any source code that is highlighted by Clang, we now also have cursor marking for the whole token that is under the current source location. E.g., before we underlined only the '!' in the expression '1 != 2', but now the whole token '!=' is underlined. The same for function calls and so on. Below you can see two examples where we before only underlined the first character of the token, but now underline the whole token. {F7075400} {F7075414} It also simplifies the DisplaySourceLines method in the SourceManager as most of the code in there was essentially just for getting this column marker to work as a FormatEntity. Reviewers: aprantl Reviewed By: aprantl Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D51466 llvm-svn: 341003
1 parent db92a4a commit 2078632

File tree

10 files changed

+188
-105
lines changed

10 files changed

+188
-105
lines changed
 

‎lldb/include/lldb/Core/Debugger.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,9 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
277277

278278
lldb::StopShowColumn GetStopShowColumn() const;
279279

280-
const FormatEntity::Entry *GetStopShowColumnAnsiPrefix() const;
280+
llvm::StringRef GetStopShowColumnAnsiPrefix() const;
281281

282-
const FormatEntity::Entry *GetStopShowColumnAnsiSuffix() const;
282+
llvm::StringRef GetStopShowColumnAnsiSuffix() const;
283283

284284
uint32_t GetStopSourceLineCount(bool before) const;
285285

‎lldb/include/lldb/Core/Highlighter.h

+16-3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ struct HighlightStyle {
5353
void Set(llvm::StringRef prefix, llvm::StringRef suffix);
5454
};
5555

56+
/// The style for the token which is below the cursor of the user. Note that
57+
/// this style is overwritten by the SourceManager with the values of
58+
/// stop-show-column-ansi-prefix/stop-show-column-ansi-suffix.
59+
ColorStyle selected;
60+
5661
/// Matches identifiers to variable or functions.
5762
ColorStyle identifier;
5863
/// Matches any string or character literals in the language: "foo" or 'f'
@@ -106,32 +111,39 @@ class Highlighter {
106111
/// \param options
107112
/// \param line
108113
/// The user supplied line that needs to be highlighted.
114+
/// \param cursor_pos
115+
/// The cursor position of the user in this line, starting at 0 (which
116+
/// means the cursor is on the first character in 'line').
109117
/// \param previous_lines
110118
/// Any previous lines the user has written which we should only use
111119
/// for getting the context of the Highlighting right.
112120
/// \param s
113121
/// The stream to which the highlighted version of the user string should
114122
/// be written.
115123
virtual void Highlight(const HighlightStyle &options, llvm::StringRef line,
124+
llvm::Optional<size_t> cursor_pos,
116125
llvm::StringRef previous_lines, Stream &s) const = 0;
117126

118127
/// Utility method for calling Highlight without a stream.
119128
std::string Highlight(const HighlightStyle &options, llvm::StringRef line,
129+
llvm::Optional<size_t> cursor_pos,
120130
llvm::StringRef previous_lines = "") const;
121131
};
122132

123-
/// A default highlighter that does nothing. Used as a fallback.
124-
class NoHighlighter : public Highlighter {
133+
/// A default highlighter that only highlights the user cursor, but doesn't
134+
/// do any other highlighting.
135+
class DefaultHighlighter : public Highlighter {
125136
public:
126137
llvm::StringRef GetName() const override { return "none"; }
127138

128139
void Highlight(const HighlightStyle &options, llvm::StringRef line,
140+
llvm::Optional<size_t> cursor_pos,
129141
llvm::StringRef previous_lines, Stream &s) const override;
130142
};
131143

132144
/// Manages the available highlighters.
133145
class HighlighterManager {
134-
NoHighlighter m_no_highlighter;
146+
DefaultHighlighter m_default;
135147

136148
public:
137149
/// Queries all known highlighter for one that can highlight some source code.
@@ -145,6 +157,7 @@ class HighlighterManager {
145157
/// empty highlighter that does nothing.
146158
const Highlighter &getHighlighterFor(lldb::LanguageType language_type,
147159
llvm::StringRef path) const;
160+
const Highlighter &getDefaultHighlighter() const { return m_default; }
148161
};
149162

150163
} // namespace lldb_private

‎lldb/include/lldb/Core/SourceManager.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class SourceManager {
5252

5353
void UpdateIfNeeded();
5454

55-
size_t DisplaySourceLines(uint32_t line, uint32_t column,
55+
size_t DisplaySourceLines(uint32_t line, llvm::Optional<size_t> column,
5656
uint32_t context_before, uint32_t context_after,
5757
Stream *s);
5858
void FindLinesMatchingRegex(RegularExpression &regex, uint32_t start_line,

‎lldb/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def test_display_source_python_ansi_terminal(self):
113113
"""Test display of source using the SBSourceManager API, using a
114114
dumb terminal and thus no color support (the default)."""
115115
use_color = True
116-
underline_regex = ansi_underline_surround_regex(r".")
116+
underline_regex = ansi_underline_surround_regex(r"printf")
117117
self.do_display_source_python_api(use_color, underline_regex)
118118

119119
@add_test_categories(['pyapi'])
@@ -132,7 +132,8 @@ def test_display_source_python_ansi_terminal_syntax_highlighting(self):
132132
self.do_display_source_python_api(use_color, color_regex, syntax_highlighting)
133133

134134
# Test that we didn't color unrelated identifiers.
135-
self.do_display_source_python_api(use_color, r" printf\(", syntax_highlighting)
135+
self.do_display_source_python_api(use_color, r" main\(", syntax_highlighting)
136+
self.do_display_source_python_api(use_color, r"\);", syntax_highlighting)
136137

137138
def test_move_and_then_display_source(self):
138139
"""Test that target.source-map settings work by moving main.c to hidden/main.c."""

‎lldb/source/Core/Debugger.cpp

+8-11
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,6 @@ OptionEnumValueElement g_language_enumerators[] = {
177177
// args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-
178178
// without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}:
179179

180-
#define DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX "${ansi.underline}"
181-
#define DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX "${ansi.normal}"
182-
183180
static OptionEnumValueElement s_stop_show_column_values[] = {
184181
{eStopShowColumnAnsiOrCaret, "ansi-or-caret",
185182
"Highlight the stop column with ANSI terminal codes when color/ANSI mode "
@@ -239,13 +236,13 @@ static PropertyDefinition g_properties[] = {
239236
eStopShowColumnAnsiOrCaret, nullptr, s_stop_show_column_values,
240237
"If true, LLDB will use the column information from the debug info to "
241238
"mark the current position when displaying a stopped context."},
242-
{"stop-show-column-ansi-prefix", OptionValue::eTypeFormatEntity, true, 0,
243-
DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX, nullptr,
239+
{"stop-show-column-ansi-prefix", OptionValue::eTypeString, true, 0,
240+
"${ansi.underline}", nullptr,
244241
"When displaying the column marker in a color-enabled (i.e. ANSI) "
245242
"terminal, use the ANSI terminal code specified in this format at the "
246243
"immediately before the column to be marked."},
247-
{"stop-show-column-ansi-suffix", OptionValue::eTypeFormatEntity, true, 0,
248-
DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX, nullptr,
244+
{"stop-show-column-ansi-suffix", OptionValue::eTypeString, true, 0,
245+
"${ansi.normal}", nullptr,
249246
"When displaying the column marker in a color-enabled (i.e. ANSI) "
250247
"terminal, use the ANSI terminal code specified in this format "
251248
"immediately after the column to be marked."},
@@ -485,14 +482,14 @@ StopShowColumn Debugger::GetStopShowColumn() const {
485482
nullptr, idx, g_properties[idx].default_uint_value);
486483
}
487484

488-
const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiPrefix() const {
485+
llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
489486
const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
490-
return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
487+
return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
491488
}
492489

493-
const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiSuffix() const {
490+
llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
494491
const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
495-
return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
492+
return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
496493
}
497494

498495
uint32_t Debugger::GetStopSourceLineCount(bool before) const {

‎lldb/source/Core/Highlighter.cpp

+25-7
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,28 @@ void HighlightStyle::ColorStyle::Set(llvm::StringRef prefix,
2525
m_suffix = lldb_utility::ansi::FormatAnsiTerminalCodes(suffix);
2626
}
2727

28-
void NoHighlighter::Highlight(const HighlightStyle &options,
29-
llvm::StringRef line,
30-
llvm::StringRef previous_lines, Stream &s) const {
31-
// We just forward the input to the output and do no highlighting.
32-
s << line;
28+
void DefaultHighlighter::Highlight(const HighlightStyle &options,
29+
llvm::StringRef line,
30+
llvm::Optional<size_t> cursor_pos,
31+
llvm::StringRef previous_lines,
32+
Stream &s) const {
33+
// If we don't have a valid cursor, then we just print the line as-is.
34+
if (!cursor_pos || *cursor_pos >= line.size()) {
35+
s << line;
36+
return;
37+
}
38+
39+
// If we have a valid cursor, we have to apply the 'selected' style around
40+
// the character below the cursor.
41+
42+
// Split the line around the character which is below the cursor.
43+
size_t column = *cursor_pos;
44+
// Print the characters before the cursor.
45+
s << line.substr(0, column);
46+
// Print the selected character with the defined color codes.
47+
options.selected.Apply(s, line.substr(column, 1));
48+
// Print the rest of the line.
49+
s << line.substr(column + 1U);
3350
}
3451

3552
static HighlightStyle::ColorStyle GetColor(const char *c) {
@@ -50,14 +67,15 @@ HighlighterManager::getHighlighterFor(lldb::LanguageType language_type,
5067
Language *language = lldb_private::Language::FindPlugin(language_type, path);
5168
if (language && language->GetHighlighter())
5269
return *language->GetHighlighter();
53-
return m_no_highlighter;
70+
return m_default;
5471
}
5572

5673
std::string Highlighter::Highlight(const HighlightStyle &options,
5774
llvm::StringRef line,
75+
llvm::Optional<size_t> cursor_pos,
5876
llvm::StringRef previous_lines) const {
5977
StreamString s;
60-
Highlight(options, line, previous_lines, s);
78+
Highlight(options, line, cursor_pos, previous_lines, s);
6179
s.Flush();
6280
return s.GetString().str();
6381
}

‎lldb/source/Core/SourceManager.cpp

+26-69
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,6 @@ static bool should_show_stop_column_with_ansi(DebuggerSP debugger_sp) {
127127
if (!debugger_sp->GetUseColor())
128128
return false;
129129

130-
// Don't use terminal attributes when we have highlighting enabled. This
131-
// can mess up the command line.
132-
if (debugger_sp->GetHighlightSource())
133-
return false;
134-
135130
// We only use ANSI stop column formatting if we're either supposed to show
136131
// ANSI where available (which we know we have when we get to this point), or
137132
// if we're only supposed to use ANSI.
@@ -201,8 +196,16 @@ size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile(
201196
return_value +=
202197
s->Printf("%s%2.2s %-4u\t", prefix,
203198
line == curr_line ? current_line_cstr : "", line);
204-
size_t this_line_size = m_last_file_sp->DisplaySourceLines(
205-
line, line == curr_line ? column : 0, 0, 0, s);
199+
200+
// So far we treated column 0 as a special 'no column value', but
201+
// DisplaySourceLines starts counting columns from 0 (and no column is
202+
// expressed by passing an empty optional).
203+
llvm::Optional<size_t> columnToHighlight;
204+
if (line == curr_line && column)
205+
columnToHighlight = column - 1;
206+
207+
size_t this_line_size =
208+
m_last_file_sp->DisplaySourceLines(line, columnToHighlight, 0, 0, s);
206209
if (column != 0 && line == curr_line &&
207210
should_show_stop_column_with_caret(m_debugger_wp.lock())) {
208211
// Display caret cursor.
@@ -521,7 +524,8 @@ void SourceManager::File::UpdateIfNeeded() {
521524
}
522525
}
523526

524-
size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column,
527+
size_t SourceManager::File::DisplaySourceLines(uint32_t line,
528+
llvm::Optional<size_t> column,
525529
uint32_t context_before,
526530
uint32_t context_after,
527531
Stream *s) {
@@ -535,15 +539,24 @@ size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column,
535539

536540
size_t bytes_written = s->GetWrittenBytes();
537541

538-
std::string previous_content;
542+
auto debugger_sp = m_debugger_wp.lock();
543+
544+
HighlightStyle style;
545+
// Use the default Vim style if source highlighting is enabled.
546+
if (should_highlight_source(debugger_sp))
547+
style = HighlightStyle::MakeVimStyle();
548+
549+
// If we should mark the stop column with color codes, then copy the prefix
550+
// and suffix to our color style.
551+
if (should_show_stop_column_with_ansi(debugger_sp))
552+
style.selected.Set(debugger_sp->GetStopShowColumnAnsiPrefix(),
553+
debugger_sp->GetStopShowColumnAnsiSuffix());
539554

540-
HighlightStyle style = HighlightStyle::MakeVimStyle();
541555
HighlighterManager mgr;
542556
std::string path = GetFileSpec().GetPath(/*denormalize*/ false);
543557
// FIXME: Find a way to get the definitive language this file was written in
544558
// and pass it to the highlighter.
545-
auto &highlighter =
546-
mgr.getHighlighterFor(lldb::LanguageType::eLanguageTypeUnknown, path);
559+
const auto &h = mgr.getHighlighterFor(lldb::eLanguageTypeUnknown, path);
547560

548561
const uint32_t start_line =
549562
line <= context_before ? 1 : line - context_before;
@@ -560,64 +573,8 @@ size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column,
560573
const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
561574

562575
auto ref = llvm::StringRef(reinterpret_cast<const char *>(cstr), count);
563-
bool displayed_line = false;
564-
565-
auto debugger_sp = m_debugger_wp.lock();
566-
if (should_highlight_source(debugger_sp)) {
567-
highlighter.Highlight(style, ref, previous_content, *s);
568-
displayed_line = true;
569-
// Add the new line to the previous lines.
570-
previous_content += ref.str();
571-
}
572-
573-
if (!displayed_line && column && (column < count)) {
574-
if (should_show_stop_column_with_ansi(debugger_sp) && debugger_sp) {
575-
// Check if we have any ANSI codes with which to mark this column. If
576-
// not, no need to do this work.
577-
auto ansi_prefix_entry = debugger_sp->GetStopShowColumnAnsiPrefix();
578-
auto ansi_suffix_entry = debugger_sp->GetStopShowColumnAnsiSuffix();
579-
580-
// We only bother breaking up the line to format the marked column if
581-
// there is any marking specified on both sides of the marked column.
582-
// In ANSI-terminal-sequence land, there must be a post if there is a
583-
// pre format, and vice versa.
584-
if (ansi_prefix_entry && ansi_suffix_entry) {
585-
// Mark the current column with the desired escape sequence for
586-
// formatting the column (e.g. underline, inverse, etc.)
587-
588-
// First print the part before the column to mark.
589-
s->Write(cstr, column - 1);
590-
591-
// Write the pre escape sequence.
592-
const SymbolContext *sc = nullptr;
593-
const ExecutionContext *exe_ctx = nullptr;
594-
const Address addr = LLDB_INVALID_ADDRESS;
595-
ValueObject *valobj = nullptr;
596-
const bool function_changed = false;
597-
const bool initial_function = false;
598-
599-
FormatEntity::Format(*ansi_prefix_entry, *s, sc, exe_ctx, &addr,
600-
valobj, function_changed, initial_function);
601-
602-
s->Write(cstr + column - 1, 1);
603-
604-
// Write the post escape sequence.
605-
FormatEntity::Format(*ansi_suffix_entry, *s, sc, exe_ctx, &addr,
606-
valobj, function_changed, initial_function);
607-
608-
// And finish up with the rest of the line.
609-
s->Write(cstr + column, count - column);
610-
611-
// Keep track of the fact that we just wrote the line.
612-
displayed_line = true;
613-
}
614-
}
615-
}
616576

617-
// If we didn't end up displaying the line with ANSI codes for whatever
618-
// reason, display it now sans codes.
619-
if (!displayed_line)
620-
s->PutCString(ref);
577+
h.Highlight(style, ref, column, "", *s);
621578

622579
// Ensure we get an end of line character one way or another.
623580
if (!is_newline_char(ref.back()))

‎lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ determineClangStyle(const ClangHighlighter &highlighter,
130130

131131
void ClangHighlighter::Highlight(const HighlightStyle &options,
132132
llvm::StringRef line,
133+
llvm::Optional<size_t> cursor_pos,
133134
llvm::StringRef previous_lines,
134135
Stream &result) const {
135136
using namespace clang;
@@ -168,6 +169,8 @@ void ClangHighlighter::Highlight(const HighlightStyle &options,
168169
// True once we actually lexed the user provided line.
169170
bool found_user_line = false;
170171

172+
// True if we already highlighted the token under the cursor, false otherwise.
173+
bool highlighted_cursor = false;
171174
Token token;
172175
bool exit = false;
173176
while (!exit) {
@@ -204,11 +207,22 @@ void ClangHighlighter::Highlight(const HighlightStyle &options,
204207
if (tok_str.empty())
205208
continue;
206209

210+
// If the cursor is inside this token, we have to apply the 'selected'
211+
// highlight style before applying the actual token color.
212+
llvm::StringRef to_print = tok_str;
213+
StreamString storage;
214+
auto end = start + token.getLength();
215+
if (cursor_pos && end > *cursor_pos && !highlighted_cursor) {
216+
highlighted_cursor = true;
217+
options.selected.Apply(storage, tok_str);
218+
to_print = storage.GetString();
219+
}
220+
207221
// See how we are supposed to highlight this token.
208222
HighlightStyle::ColorStyle color =
209223
determineClangStyle(*this, token, tok_str, options, in_pp_directive);
210224

211-
color.Apply(result, tok_str);
225+
color.Apply(result, to_print);
212226
}
213227

214228
// If we went over the whole file but couldn't find our own file, then

‎lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.h

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class ClangHighlighter : public Highlighter {
2929
llvm::StringRef GetName() const override { return "clang"; }
3030

3131
void Highlight(const HighlightStyle &options, llvm::StringRef line,
32+
llvm::Optional<size_t> cursor_pos,
3233
llvm::StringRef previous_lines, Stream &s) const override;
3334

3435
/// Returns true if the given string represents a keywords in any Clang

‎lldb/unittests/Language/Highlighting/HighlighterTest.cpp

+91-9
Original file line numberDiff line numberDiff line change
@@ -99,31 +99,49 @@ TEST_F(HighlighterTest, FallbackHighlighter) {
9999
style.semicolons.Set("<", ">");
100100

101101
const char *code = "program Hello;";
102-
std::string output = h.Highlight(style, code);
102+
std::string output = h.Highlight(style, code, llvm::Optional<size_t>());
103103

104104
EXPECT_STREQ(output.c_str(), code);
105105
}
106106

107-
TEST_F(HighlighterTest, DefaultHighlighter) {
107+
static std::string
108+
highlightDefault(llvm::StringRef code, HighlightStyle style,
109+
llvm::Optional<size_t> cursor = llvm::Optional<size_t>()) {
108110
HighlighterManager mgr;
109-
const Highlighter &h = mgr.getHighlighterFor(lldb::eLanguageTypeC, "main.c");
110-
111-
HighlightStyle style;
111+
return mgr.getDefaultHighlighter().Highlight(style, code, cursor);
112+
}
112113

114+
TEST_F(HighlighterTest, DefaultHighlighter) {
113115
const char *code = "int my_main() { return 22; } \n";
114-
std::string output = h.Highlight(style, code);
115116

116-
EXPECT_STREQ(output.c_str(), code);
117+
HighlightStyle style;
118+
EXPECT_EQ(code, highlightDefault(code, style));
117119
}
118120

121+
TEST_F(HighlighterTest, DefaultHighlighterWithCursor) {
122+
HighlightStyle style;
123+
style.selected.Set("<c>", "</c>");
124+
EXPECT_EQ("<c>a</c> bc", highlightDefault("a bc", style, 0));
125+
EXPECT_EQ("a<c> </c>bc", highlightDefault("a bc", style, 1));
126+
EXPECT_EQ("a <c>b</c>c", highlightDefault("a bc", style, 2));
127+
EXPECT_EQ("a b<c>c</c>", highlightDefault("a bc", style, 3));
128+
}
129+
130+
TEST_F(HighlighterTest, DefaultHighlighterWithCursorOutOfBounds) {
131+
HighlightStyle style;
132+
style.selected.Set("<c>", "</c>");
133+
EXPECT_EQ("a bc", highlightDefault("a bc", style, 4));
134+
}
119135
//------------------------------------------------------------------------------
120136
// Tests highlighting with the Clang highlighter.
121137
//------------------------------------------------------------------------------
122138

123-
static std::string highlightC(llvm::StringRef code, HighlightStyle style) {
139+
static std::string
140+
highlightC(llvm::StringRef code, HighlightStyle style,
141+
llvm::Optional<size_t> cursor = llvm::Optional<size_t>()) {
124142
HighlighterManager mgr;
125143
const Highlighter &h = mgr.getHighlighterFor(lldb::eLanguageTypeC, "main.c");
126-
return h.Highlight(style, code);
144+
return h.Highlight(style, code, cursor);
127145
}
128146

129147
TEST_F(HighlighterTest, ClangEmptyInput) {
@@ -219,3 +237,67 @@ TEST_F(HighlighterTest, ClangIdentifiers) {
219237
EXPECT_EQ(" <id>foo</id> <id>c</id> = <id>bar</id>(); return 1;",
220238
highlightC(" foo c = bar(); return 1;", s));
221239
}
240+
241+
TEST_F(HighlighterTest, ClangCursorPos) {
242+
HighlightStyle s;
243+
s.selected.Set("<c>", "</c>");
244+
245+
EXPECT_EQ("<c> </c>foo c = bar(); return 1;",
246+
highlightC(" foo c = bar(); return 1;", s, 0));
247+
EXPECT_EQ(" <c>foo</c> c = bar(); return 1;",
248+
highlightC(" foo c = bar(); return 1;", s, 1));
249+
EXPECT_EQ(" <c>foo</c> c = bar(); return 1;",
250+
highlightC(" foo c = bar(); return 1;", s, 2));
251+
EXPECT_EQ(" <c>foo</c> c = bar(); return 1;",
252+
highlightC(" foo c = bar(); return 1;", s, 3));
253+
EXPECT_EQ(" foo<c> </c>c = bar(); return 1;",
254+
highlightC(" foo c = bar(); return 1;", s, 4));
255+
EXPECT_EQ(" foo <c>c</c> = bar(); return 1;",
256+
highlightC(" foo c = bar(); return 1;", s, 5));
257+
}
258+
259+
TEST_F(HighlighterTest, ClangCursorPosEndOfLine) {
260+
HighlightStyle s;
261+
s.selected.Set("<c>", "</c>");
262+
263+
EXPECT_EQ("f", highlightC("f", s, 1));
264+
}
265+
266+
TEST_F(HighlighterTest, ClangCursorOutOfBounds) {
267+
HighlightStyle s;
268+
s.selected.Set("<c>", "</c>");
269+
EXPECT_EQ("f", highlightC("f", s, 2));
270+
EXPECT_EQ("f", highlightC("f", s, 3));
271+
EXPECT_EQ("f", highlightC("f", s, 4));
272+
}
273+
274+
TEST_F(HighlighterTest, ClangCursorPosBeforeOtherToken) {
275+
HighlightStyle s;
276+
s.selected.Set("<c>", "</c>");
277+
s.identifier.Set("<id>", "</id>");
278+
279+
EXPECT_EQ("<c> </c><id>foo</id> <id>c</id> = <id>bar</id>(); return 1;",
280+
highlightC(" foo c = bar(); return 1;", s, 0));
281+
}
282+
283+
TEST_F(HighlighterTest, ClangCursorPosAfterOtherToken) {
284+
HighlightStyle s;
285+
s.selected.Set("<c>", "</c>");
286+
s.identifier.Set("<id>", "</id>");
287+
288+
EXPECT_EQ(" <id>foo</id><c> </c><id>c</id> = <id>bar</id>(); return 1;",
289+
highlightC(" foo c = bar(); return 1;", s, 4));
290+
}
291+
292+
TEST_F(HighlighterTest, ClangCursorPosInOtherToken) {
293+
HighlightStyle s;
294+
s.selected.Set("<c>", "</c>");
295+
s.identifier.Set("<id>", "</id>");
296+
297+
EXPECT_EQ(" <id><c>foo</c></id> <id>c</id> = <id>bar</id>(); return 1;",
298+
highlightC(" foo c = bar(); return 1;", s, 1));
299+
EXPECT_EQ(" <id><c>foo</c></id> <id>c</id> = <id>bar</id>(); return 1;",
300+
highlightC(" foo c = bar(); return 1;", s, 2));
301+
EXPECT_EQ(" <id><c>foo</c></id> <id>c</id> = <id>bar</id>(); return 1;",
302+
highlightC(" foo c = bar(); return 1;", s, 3));
303+
}

0 commit comments

Comments
 (0)
Please sign in to comment.