mirror of https://github.com/buggins/dlangide.git
toggle comment support
This commit is contained in:
parent
da9eafebaf
commit
4000298679
|
@ -89,7 +89,7 @@ class ArraySourceLines : SourceLines {
|
||||||
/// source file
|
/// source file
|
||||||
override @property SourceFile file() { return _file; }
|
override @property SourceFile file() { return _file; }
|
||||||
/// last read line
|
/// last read line
|
||||||
override @property uint line() { return _line; }
|
override @property uint line() { return _line + _firstLine; }
|
||||||
/// source encoding
|
/// source encoding
|
||||||
//@property EncodingType encoding() { return _encoding; }
|
//@property EncodingType encoding() { return _encoding; }
|
||||||
/// error code
|
/// error code
|
||||||
|
|
|
@ -928,6 +928,8 @@ class Token {
|
||||||
@property Keyword keyword() { return Keyword.NONE; }
|
@property Keyword keyword() { return Keyword.NONE; }
|
||||||
/// returns true if this is documentation comment token
|
/// returns true if this is documentation comment token
|
||||||
@property bool isDocumentationComment() { return false; }
|
@property bool isDocumentationComment() { return false; }
|
||||||
|
/// returns true if this is multiline
|
||||||
|
@property bool isMultilineComment() { return false; }
|
||||||
|
|
||||||
// error handling
|
// error handling
|
||||||
|
|
||||||
|
@ -1024,7 +1026,9 @@ class OpToken : Token {
|
||||||
super(TokenType.OP, file, line, pos);
|
super(TokenType.OP, file, line, pos);
|
||||||
}
|
}
|
||||||
override public Token clone() {
|
override public Token clone() {
|
||||||
return new OpToken(_file, _line, _pos);
|
OpToken res = new OpToken(_file, _line, _pos);
|
||||||
|
res._op = _op;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
public override @property string toString() {
|
public override @property string toString() {
|
||||||
return "Op:" ~ to!string(_op);
|
return "Op:" ~ to!string(_op);
|
||||||
|
@ -1043,7 +1047,9 @@ class KeywordToken : Token {
|
||||||
super(TokenType.KEYWORD, file, line, pos);
|
super(TokenType.KEYWORD, file, line, pos);
|
||||||
}
|
}
|
||||||
override public Token clone() {
|
override public Token clone() {
|
||||||
return new KeywordToken(_file, _line, _pos);
|
KeywordToken res = new KeywordToken(_file, _line, _pos);
|
||||||
|
res._keyword = _keyword;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
public override @property string toString() {
|
public override @property string toString() {
|
||||||
return "Keyword:" ~ to!string(_keyword);
|
return "Keyword:" ~ to!string(_keyword);
|
||||||
|
@ -1054,6 +1060,8 @@ class KeywordToken : Token {
|
||||||
class CommentToken : Token {
|
class CommentToken : Token {
|
||||||
protected dchar[] _text;
|
protected dchar[] _text;
|
||||||
protected bool _isDocumentationComment;
|
protected bool _isDocumentationComment;
|
||||||
|
protected bool _isMultilineComment;
|
||||||
|
|
||||||
|
|
||||||
override @property bool isDocumentationComment() {
|
override @property bool isDocumentationComment() {
|
||||||
return _isDocumentationComment;
|
return _isDocumentationComment;
|
||||||
|
@ -1063,6 +1071,15 @@ class CommentToken : Token {
|
||||||
_isDocumentationComment = f;
|
_isDocumentationComment = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns true if this is multiline
|
||||||
|
override @property bool isMultilineComment() {
|
||||||
|
return _isMultilineComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property void isMultilineComment(bool f) {
|
||||||
|
_isMultilineComment = f;
|
||||||
|
}
|
||||||
|
|
||||||
@property override dchar[] text() { return _text; }
|
@property override dchar[] text() { return _text; }
|
||||||
@property void text(dchar[] text) { _text = text; }
|
@property void text(dchar[] text) { _text = text; }
|
||||||
this() {
|
this() {
|
||||||
|
@ -1073,7 +1090,10 @@ class CommentToken : Token {
|
||||||
_text = text;
|
_text = text;
|
||||||
}
|
}
|
||||||
override public Token clone() {
|
override public Token clone() {
|
||||||
return new CommentToken(_file, _line, _pos, _text.dup);
|
CommentToken res = new CommentToken(_file, _line, _pos, _text.dup);
|
||||||
|
res._isDocumentationComment = _isDocumentationComment;
|
||||||
|
res._isMultilineComment = _isMultilineComment;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
public override @property string toString() {
|
public override @property string toString() {
|
||||||
return "Comment:" ~ to!string(_text);
|
return "Comment:" ~ to!string(_text);
|
||||||
|
@ -1413,7 +1433,7 @@ class Tokenizer
|
||||||
init(lineStream);
|
init(lineStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(SourceLines lineStream) {
|
void init(SourceLines lineStream, int pos = 0) {
|
||||||
_lineStream = lineStream;
|
_lineStream = lineStream;
|
||||||
SourceFile file = _lineStream.file;
|
SourceFile file = _lineStream.file;
|
||||||
_sharedWhiteSpaceToken.setFile(file);
|
_sharedWhiteSpaceToken.setFile(file);
|
||||||
|
@ -1432,6 +1452,7 @@ class Tokenizer
|
||||||
_prevLineLength = 0;
|
_prevLineLength = 0;
|
||||||
_lineText = null;
|
_lineText = null;
|
||||||
nextLine();
|
nextLine();
|
||||||
|
_pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(string code, string filename = "") {
|
this(string code, string filename = "") {
|
||||||
|
@ -1532,6 +1553,7 @@ class Tokenizer
|
||||||
protected Token processMultilineComment() {
|
protected Token processMultilineComment() {
|
||||||
_sharedCommentToken.setPos(_line, _pos - 1);
|
_sharedCommentToken.setPos(_line, _pos - 1);
|
||||||
_sharedCommentToken.isDocumentationComment = _pos + 1 < _lineText.length && _lineText[_pos + 1] == '*';
|
_sharedCommentToken.isDocumentationComment = _pos + 1 < _lineText.length && _lineText[_pos + 1] == '*';
|
||||||
|
_sharedCommentToken.isMultilineComment = true;
|
||||||
_commentAppender.reset();
|
_commentAppender.reset();
|
||||||
int textStart = _pos + 1;
|
int textStart = _pos + 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1566,6 +1588,7 @@ class Tokenizer
|
||||||
protected Token processNestedComment() {
|
protected Token processNestedComment() {
|
||||||
_sharedCommentToken.setPos(_line, _pos - 1);
|
_sharedCommentToken.setPos(_line, _pos - 1);
|
||||||
_sharedCommentToken.isDocumentationComment = _pos + 1 < _lineText.length && _lineText[_pos + 1] == '+';
|
_sharedCommentToken.isDocumentationComment = _pos + 1 < _lineText.length && _lineText[_pos + 1] == '+';
|
||||||
|
_sharedCommentToken.isMultilineComment = true;
|
||||||
_commentAppender.reset();
|
_commentAppender.reset();
|
||||||
dchar[] text;
|
dchar[] text;
|
||||||
int textStart = _pos + 1;
|
int textStart = _pos + 1;
|
||||||
|
|
|
@ -119,6 +119,9 @@ class SimpleDSyntaxHighlighter : SyntaxHighlighter {
|
||||||
|
|
||||||
/// return true if can toggle line comments for specified text range
|
/// return true if can toggle line comments for specified text range
|
||||||
override bool canToggleLineComment(TextRange range) {
|
override bool canToggleLineComment(TextRange range) {
|
||||||
|
TextRange r = content.fullLinesRange(range);
|
||||||
|
if (isInsideBlockComment(r.start) || isInsideBlockComment(r.end))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,9 +179,90 @@ class SimpleDSyntaxHighlighter : SyntaxHighlighter {
|
||||||
return cast(dstring)res;
|
return cast(dstring)res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// searches for neares token start before or equal to position
|
||||||
|
protected TextPosition tokenStart(TextPosition pos) {
|
||||||
|
TextPosition p = pos;
|
||||||
|
for (;;) {
|
||||||
|
TextPosition prevPos = content.prevCharPos(p);
|
||||||
|
if (p == prevPos)
|
||||||
|
return p; // begin of file
|
||||||
|
TokenProp prop = content.tokenProp(p);
|
||||||
|
TokenProp prevProp = content.tokenProp(prevPos);
|
||||||
|
if (prop && prop != prevProp)
|
||||||
|
return p;
|
||||||
|
p = prevPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct TokenWithRange {
|
||||||
|
Token token;
|
||||||
|
TextRange range;
|
||||||
|
@property string toString() {
|
||||||
|
return token.toString ~ range.toString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected TextPosition _lastTokenStart;
|
||||||
|
protected Token _lastToken;
|
||||||
|
protected bool initTokenizer(TextPosition startPos) {
|
||||||
|
const dstring[] lines = content.lines;
|
||||||
|
_lines.init(cast(dstring[])(lines[startPos.line .. $]), _file, startPos.line);
|
||||||
|
_tokenizer.init(_lines, startPos.pos);
|
||||||
|
_lastTokenStart = startPos;
|
||||||
|
_lastToken = null;
|
||||||
|
nextToken();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TokenWithRange nextToken() {
|
||||||
|
TokenWithRange res;
|
||||||
|
if (_lastToken && _lastToken.type == TokenType.EOF) {
|
||||||
|
// end of file
|
||||||
|
res.range.start = _lastTokenStart;
|
||||||
|
res.range.end = content.endOfFile();
|
||||||
|
res.token = null;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
res.range.start = _lastTokenStart;
|
||||||
|
res.token = _lastToken;
|
||||||
|
_lastToken = _tokenizer.nextToken();
|
||||||
|
if (_lastToken)
|
||||||
|
_lastToken = _lastToken.clone();
|
||||||
|
_lastTokenStart = _lastToken ? TextPosition(_lastToken.line - 1, _lastToken.pos - 1) : content.endOfFile();
|
||||||
|
res.range.end = _lastTokenStart;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TokenWithRange getPositionToken(TextPosition pos) {
|
||||||
|
Log.d("getPositionToken for ", pos);
|
||||||
|
TextPosition start = tokenStart(pos);
|
||||||
|
Log.d("token start found: ", start);
|
||||||
|
initTokenizer(start);
|
||||||
|
for (;;) {
|
||||||
|
TokenWithRange tokenRange = nextToken();
|
||||||
|
Log.d("read token: ", tokenRange);
|
||||||
|
if (!tokenRange.token) {
|
||||||
|
Log.d("end of file");
|
||||||
|
return tokenRange;
|
||||||
|
}
|
||||||
|
if (pos >= tokenRange.range.start && pos < tokenRange.range.end) {
|
||||||
|
Log.d("found: ", pos, " in ", tokenRange);
|
||||||
|
return tokenRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool isInsideBlockComment(TextPosition pos) {
|
||||||
|
TokenWithRange tokenRange = getPositionToken(pos);
|
||||||
|
if (tokenRange.token && tokenRange.token.type == TokenType.COMMENT && tokenRange.token.isMultilineComment)
|
||||||
|
return pos > tokenRange.range.start && pos < tokenRange.range.end;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// toggle line comments for specified text range
|
/// toggle line comments for specified text range
|
||||||
override void toggleLineComment(TextRange range, Object source) {
|
override void toggleLineComment(TextRange range, Object source) {
|
||||||
TextRange r = content.fullLinesRange(range);
|
TextRange r = content.fullLinesRange(range);
|
||||||
|
if (isInsideBlockComment(r.start) || isInsideBlockComment(r.end))
|
||||||
|
return;
|
||||||
int lineCount = r.end.line - r.start.line;
|
int lineCount = r.end.line - r.start.line;
|
||||||
bool noEolAtEndOfRange = false;
|
bool noEolAtEndOfRange = false;
|
||||||
if (lineCount == 0 || r.end.pos > 0) {
|
if (lineCount == 0 || r.end.pos > 0) {
|
||||||
|
|
Loading…
Reference in New Issue