diff options
| author | Neil <nyamatongwe@gmail.com> | 2019-12-22 22:43:28 +1100 | 
|---|---|---|
| committer | Neil <nyamatongwe@gmail.com> | 2019-12-22 22:43:28 +1100 | 
| commit | 651e4b440ad3019a63b10d972ee36a296020e2c8 (patch) | |
| tree | e3ad0055daf94ce00326e4bc34f97b80a154b8ea /lexilla/test/TestDocument.cxx | |
| parent | 0af155eae811e515b7d4fbad8e198cdf01f6ff2f (diff) | |
| download | scintilla-mirror-651e4b440ad3019a63b10d972ee36a296020e2c8.tar.gz | |
Lexilla testing framework.
Diffstat (limited to 'lexilla/test/TestDocument.cxx')
| -rw-r--r-- | lexilla/test/TestDocument.cxx | 222 | 
1 files changed, 222 insertions, 0 deletions
diff --git a/lexilla/test/TestDocument.cxx b/lexilla/test/TestDocument.cxx new file mode 100644 index 000000000..780265305 --- /dev/null +++ b/lexilla/test/TestDocument.cxx @@ -0,0 +1,222 @@ +// Scintilla source code edit control +/** @file TestDocument.cxx + ** Lexer testing. + **/ + // Copyright 2019 by Neil Hodgson <neilh@scintilla.org> + // The License.txt file describes the conditions under which this software may be distributed. + +#include <cassert> + +#include <string> +#include <string_view> +#include <vector> +#include <algorithm> + +#include <iostream> + +#include "ILexer.h" + +#include "TestDocument.h" + +namespace { + +	const unsigned char UTF8BytesOfLead[256] = { +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 00 - 0F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 1F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 2F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 3F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 4F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 50 - 5F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 6F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 70 - 7F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 8F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 - 9F +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A0 - AF +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B0 - BF +	1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0 - CF +	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D0 - DF +	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E0 - EF +	4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // F0 - FF +	}; + +	int UnicodeFromUTF8(const unsigned char *us) noexcept { +		switch (UTF8BytesOfLead[us[0]]) { +		case 1: +			return us[0]; +		case 2: +			return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F); +		case 3: +			return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F); +		default: +			return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F); +		} +	} + +} + +void TestDocument::Set(std::string_view sv) { +	text = sv; +	textStyles.resize(text.size()); +	lineStarts.clear(); +	endStyled = 0; +	lineStarts.push_back(0); +	for (size_t pos = 0; pos < text.length(); pos++) { +		if (text[pos] == '\n') { +			lineStarts.push_back(pos + 1); +		} +	} +	lineStarts.push_back(text.length()); +	lineStates.resize(lineStarts.size()); +} + +int SCI_METHOD TestDocument::Version() const { +	return Scintilla::dvRelease4; +} + +void SCI_METHOD TestDocument::SetErrorStatus(int) { +} + +Sci_Position SCI_METHOD TestDocument::Length() const { +	return text.length(); +} + +void SCI_METHOD TestDocument::GetCharRange(char *buffer, Sci_Position position, Sci_Position lengthRetrieve) const { +	text.copy(buffer, lengthRetrieve, position); +} + +char SCI_METHOD TestDocument::StyleAt(Sci_Position position) const { +	return textStyles.at(position); +} + +Sci_Position SCI_METHOD TestDocument::LineFromPosition(Sci_Position position) const { +	if (position >= static_cast<Sci_Position>(text.length())) { +		return lineStarts.size() - 1 - 1; +	} + +	std::vector<Sci_Position>::const_iterator it = std::lower_bound(lineStarts.begin(), lineStarts.end(), position); +	Sci_Position line = it - lineStarts.begin(); +	if (*it > position) +		line--; +	return line; +} + +Sci_Position SCI_METHOD TestDocument::LineStart(Sci_Position line) const { +	if (line >= static_cast<Sci_Position>(lineStarts.size())) { +		return text.length(); +	} +	return lineStarts.at(line); +} + +int SCI_METHOD TestDocument::GetLevel(Sci_Position) const { +	// Only for folding so not implemented yet +	return 0; +} + +int SCI_METHOD TestDocument::SetLevel(Sci_Position, int) { +	// Only for folding so not implemented yet +	return 0; +} + +int SCI_METHOD TestDocument::GetLineState(Sci_Position line) const { +	return lineStates.at(line); +} + +int SCI_METHOD TestDocument::SetLineState(Sci_Position line, int state) { +	return lineStates.at(line) = state; +} + +void SCI_METHOD TestDocument::StartStyling(Sci_Position position) { +	endStyled = position; +} + +bool SCI_METHOD TestDocument::SetStyleFor(Sci_Position length, char style) { +	for (Sci_Position i = 0; i < length; i++) { +		textStyles[endStyled] = style; +		endStyled++; +	} +	return true; +} + +bool SCI_METHOD TestDocument::SetStyles(Sci_Position length, const char *styles) { +	for (Sci_Position i = 0; i < length; i++) { +		textStyles[endStyled] = styles[i]; +		endStyled++; +	} +	return true; +} + +void SCI_METHOD TestDocument::DecorationSetCurrentIndicator(int) { +	// Not implemented as no way to read decorations +} + +void SCI_METHOD TestDocument::DecorationFillRange(Sci_Position, int, Sci_Position) { +	// Not implemented as no way to read decorations +} + +void SCI_METHOD TestDocument::ChangeLexerState(Sci_Position, Sci_Position) { +	// Not implemented as no watcher to trigger +} + +int SCI_METHOD TestDocument::CodePage() const { +	// Always UTF-8 for now +	return 65001; +} + +bool SCI_METHOD TestDocument::IsDBCSLeadByte(char) const { +	// Always UTF-8 for now +	return false; +} + +const char *SCI_METHOD TestDocument::BufferPointer() { +	return text.c_str(); +} + +int SCI_METHOD TestDocument::GetLineIndentation(Sci_Position) { +	// Never actually called - lexers use Accessor::IndentAmount +	return 0; +} + +Sci_Position SCI_METHOD TestDocument::LineEnd(Sci_Position line) const { +	Sci_Position position = LineStart(line + 1); +	position--; // Back over CR or LF +	// When line terminator is CR+LF, may need to go back one more +	if ((position > LineStart(line)) && (text.at(position - 1) == '\r')) { +		position--; +	} +	return position; +} + +Sci_Position SCI_METHOD TestDocument::GetRelativePosition(Sci_Position positionStart, Sci_Position characterOffset) const { +	// TODO: negative characterOffset +	assert(characterOffset >= 0); +	// TODO: invalid UTF-8 +	Sci_Position pos = positionStart; +	while (characterOffset > 0) { +		Sci_Position width = 0; +		GetCharacterAndWidth(pos, &width); +		pos += width; +		characterOffset--; +	} +	return pos; +} + +int SCI_METHOD TestDocument::GetCharacterAndWidth(Sci_Position position, Sci_Position *pWidth) const { +	// TODO: invalid UTF-8 +	if (position >= static_cast<Sci_Position>(text.length())) { +		// Return NULs after document end +		if (pWidth) { +			*pWidth = 1; +		} +		return '\0'; +	} +	const unsigned char leadByte = text.at(position); +	const int widthCharBytes = UTF8BytesOfLead[leadByte]; +	unsigned char charBytes[] = { leadByte,0,0,0 }; +	for (int b = 1; b < widthCharBytes; b++) +		charBytes[b] = text[position + b]; + +	if (pWidth) { +		*pWidth = widthCharBytes; +	} +	return UnicodeFromUTF8(charBytes); +}  | 
