-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Fix #3057: Toggle Block Comment doesn't work if the open/close delimiters are the same #3060
Changes from 6 commits
2d6039c
5fa487c
29d68d0
06e42b6
e6c2abf
a283618
4b9cc7e
bedec43
1038904
cbf893a
8c11ca7
3ec3cfa
851cfea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,6 +60,23 @@ define(function (require, exports, module) { | |
return lineExp; | ||
} | ||
|
||
/** | ||
* @private | ||
* Creates regular expressions for the block comment prefix and suffix | ||
* @param {!string} prefixes - the block comment prefix | ||
* @param {!string} prefixes - the block comment suffix | ||
* @return {Array.<RegExp>} | ||
*/ | ||
function _createBlockExpressions(prefix, suffix) { | ||
if (prefix) { | ||
return [ | ||
new RegExp("^" + StringUtils.regexEscape(prefix), "g"), | ||
new RegExp(StringUtils.regexEscape(suffix) + "$", "g") | ||
]; | ||
} | ||
return []; | ||
} | ||
|
||
/** | ||
* @private | ||
* Returns true if any regular expression matches the given string | ||
|
@@ -99,18 +116,19 @@ define(function (require, exports, module) { | |
* @param {!Editor} editor | ||
* @param {!number} startLine - valid line inside the document | ||
* @param {!number} endLine - valid line inside the document | ||
* @param {!Array.<string>} lineExp - an array of line comment prefixes regular expressions | ||
* @param {!Array.<RegExp>} lineExp - an array of line comment prefixes regular expressions | ||
* @param {!Array.<RegExp>} blockExp - a prefix and a suffix block comment regular expressions | ||
* @return {boolean} true if there is at least one uncommented line | ||
*/ | ||
function _containsUncommented(editor, startLine, endLine, lineExp) { | ||
function _containsUncommented(editor, startLine, endLine, lineExp, blockExp) { | ||
var containsUncommented = false; | ||
var i; | ||
var line; | ||
|
||
for (i = startLine; i <= endLine; i++) { | ||
line = editor.document.getLine(i); | ||
// A line is commented out if it starts with 0-N whitespace chars, then a line comment prefix | ||
if (line.match(/\S/) && !_matchExpressions(line, lineExp)) { | ||
if ((line.match(/\S/) && !_matchExpressions(line, lineExp)) || _matchExpressions(line.trim(), blockExp)) { | ||
containsUncommented = true; | ||
break; | ||
} | ||
|
@@ -128,13 +146,16 @@ define(function (require, exports, module) { | |
* | ||
* @param {!Editor} editor | ||
* @param {!Array.<string>} prefixes, e.g. ["//"] | ||
* @param {?string} blockPrefix, e.g. "<!--" | ||
* @param {?string} blockSuffix, e.g. "-->" | ||
*/ | ||
function lineCommentPrefix(editor, prefixes) { | ||
function lineCommentPrefix(editor, prefixes, blockPrefix, blockSuffix) { | ||
var doc = editor.document, | ||
sel = editor.getSelection(), | ||
startLine = sel.start.line, | ||
endLine = sel.end.line, | ||
lineExp = _createLineExpressions(prefixes); | ||
lineExp = _createLineExpressions(prefixes), | ||
blockExp = _createBlockExpressions(blockPrefix, blockSuffix); | ||
|
||
// Is a range of text selected? (vs just an insertion pt) | ||
var hasSelection = (startLine !== endLine) || (sel.start.ch !== sel.end.ch); | ||
|
@@ -147,7 +168,7 @@ define(function (require, exports, module) { | |
// Decide if we're commenting vs. un-commenting | ||
// Are there any non-blank lines that aren't commented out? (We ignore blank lines because | ||
// some editors like Sublime don't comment them out) | ||
var containsUncommented = _containsUncommented(editor, startLine, endLine, lineExp); | ||
var containsUncommented = _containsUncommented(editor, startLine, endLine, lineExp, blockExp); | ||
var i; | ||
var line; | ||
var prefix; | ||
|
@@ -191,59 +212,75 @@ define(function (require, exports, module) { | |
} | ||
|
||
|
||
/** | ||
* @private | ||
* Returns true if the token is a Block Comment | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be just a subset of a block comment -- might be worth clarifying that. (Unlike line comments, which are always a single token afaict). |
||
* @param {!{editor:{CodeMirror}, pos:{ch:{number}, line:{number}}, token:{object}}} ctx - token context | ||
* @param {!Array.<RegExp>} blockExp - a prefix and a suffix block comment regular expressions | ||
* @param {!Array.<RegExp>} lineExp - an array of line comment prefixes regular expressions | ||
* @return {boolean} | ||
*/ | ||
function _isBlockComment(ctx, blockExp, lineExp) { | ||
return ctx.token.className === "comment" && | ||
(_matchExpressions(ctx.token.string, blockExp) || !_matchExpressions(ctx.token.string, lineExp)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be good to explain why we need to check both (i.e. line comment delimiter may be a substring of block comment delimiter). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually I didn't do it for that reason, I was thinking of the case where a line comment would come after the block comment, but I didn't thought about the cases where the line comments could be inside the block comment, and thinking it better, maybe this last check isn't needed? I need to think more about it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, seems like we need to sort out what _findCommentStart()/End() actually need before deciding what this function should be checking for exactly. |
||
} | ||
|
||
/** | ||
* @private | ||
* Moves the token context to the token that starts the block-comment. Ctx starts in a block-comment. | ||
* Returns the position of the prefix or null if gets to the start of the document and didn't found it. | ||
* @param {!{editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}}} ctx - token context | ||
* @param {!RegExp} prefixExp - a valid regular expression | ||
* @param {!{editor:{CodeMirror}, pos:{ch:{number}, line:{number}}, token:{object}}} ctx - token context | ||
* @param {!Array.<RegExp>} blockExp - a prefix and a suffix block comment regular expressions | ||
* @param {!Array.<RegExp>} lineExp - an array of line comment prefixes regular expressions | ||
* @return {?{line: number, ch: number}} | ||
*/ | ||
function _findCommentStart(ctx, prefixExp) { | ||
var result = true; | ||
function _findCommentStart(ctx, blockExp, lineExp) { | ||
var result = _isBlockComment(ctx, blockExp, lineExp); | ||
|
||
while (result && !ctx.token.string.match(prefixExp)) { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx); | ||
while (result && !ctx.token.string.match(blockExp[0])) { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, ctx) && | ||
_isBlockComment(ctx, blockExp, lineExp); | ||
} | ||
return result ? {line: ctx.pos.line, ch: ctx.token.start} : null; | ||
} | ||
|
||
/** | ||
* @private | ||
* Moves the token context to the token that ends the block-comment. Ctx starts in a block-comment. | ||
* Returns the position of the sufix or null if gets to the end of the document and didn't found it. | ||
* @param {!{editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}}} ctx - token context | ||
* @param {!RegExp} suffixExp - a valid regular expression | ||
* Returns the position of the suffix or null if it gets to the end of the document and didn't found it. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should clarify that this returns the start of the suffix delimiter, so the actual comment end is a few chars later. At first glance, I would have incorrectly assumed that the range of the comment is _findCommentStart() - _findCommentEnd(). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, it actually tryes to find the Suffix, maybe the name is wrong too and should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That renaming sounds reasonable, but just clarifying the docs seems ok to me too. |
||
* @param {!{editor:{CodeMirror}, pos:{ch:{number}, line:{number}}, token:{object}}} ctx - token context | ||
* @param {!Array.<RegExp>} blockExp - a prefix and a suffix block comment regular expressions | ||
* @param {!Array.<RegExp>} lineExp - an array of line comment prefixes regular expressions | ||
* @param {!number} suffixLen - length of the suffix | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I forgot to update this JSDocs. Will do it on the next commit |
||
* @return {?{line: number, ch: number}} | ||
*/ | ||
function _findCommentEnd(ctx, suffixExp, suffixLen) { | ||
var result = true; | ||
function _findCommentEnd(ctx, blockExp, lineExp, suffixLen) { | ||
var result = _isBlockComment(ctx, blockExp, lineExp); | ||
|
||
while (result && !ctx.token.string.match(suffixExp)) { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx); | ||
while (result && !ctx.token.string.match(blockExp[1])) { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx) && | ||
_isBlockComment(ctx, blockExp, lineExp); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there's a line comment within a block comment, wouldn't this cause us to halt early and never find the end of the block comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And actually same about the reverse direction in _findCommentStart()... I wonder if it's actually enough just to have the one _isBlockComment() check at the top outside of the loop, and leave the loop code itself unchanged -- if the token we start from is inside a block comment, we shouldn't care about line comments we find in between there and the block comment delimiter. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Btw, we should add a couple unit tests for these nesting cases. E.g. try to block-uncomment a block comment containing a line comment -- right now that does nothing, I think because if the issues described above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I didn't thought about those cases, was trying to cover the line comments right before or after the block comment. That is a good idea, to leave it just outside, but it might still check the line comment inside the block comment, and break early or if we remove the line comment prefix check and the token starts in a line comment it could still confuse a block suffix with a block prefix as before. |
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The repeated checks for |
||
return result ? {line: ctx.pos.line, ch: ctx.token.end - suffixLen} : null; | ||
} | ||
|
||
/** | ||
* @private | ||
* Moves the token context to the next block-comment if there is one before end. | ||
* @param {!{editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}}} ctx - token context | ||
* Moves the token context to the next block-comment if there is one before the end. | ||
* @param {!{editor:{CodeMirror}, pos:{ch:{number}, line:{number}}, token:{object}}} ctx - token context | ||
* @param {!{line: number, ch: number}} end - where to stop searching | ||
* @param {!RegExp} prefixExp - a valid regular expression | ||
* @return {boolean} - true if it found a block-comment | ||
*/ | ||
function _findNextBlockComment(ctx, end, prefixExp) { | ||
var index = ctx.editor.indexFromPos(end), | ||
inside = ctx.editor.indexFromPos(ctx.pos) <= index, | ||
result = true; | ||
result = ctx.editor.indexFromPos(ctx.pos) <= index; | ||
|
||
while (result && inside && !ctx.token.string.match(prefixExp)) { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx); | ||
inside = ctx.editor.indexFromPos(ctx.pos) <= index; | ||
while (result && !ctx.token.string.match(prefixExp)) { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx) && | ||
ctx.editor.indexFromPos(ctx.pos) <= index; | ||
} | ||
return result && inside && !!ctx.token.string.match(prefixExp); | ||
return result && !!ctx.token.string.match(prefixExp); | ||
} | ||
|
||
/** | ||
|
@@ -255,9 +292,8 @@ define(function (require, exports, module) { | |
* Commenting out adds the prefix before the selection and the suffix after. | ||
* Uncommenting removes them. | ||
* | ||
* If slashComment is true and the start or end of the selection is inside a line-comment it | ||
* will try to do a line uncomment if is not actually inside a bigger block comment and all | ||
* the lines in the selection are line-commented. | ||
* If list of line comment prefixes is provided and all the lines inside the selection are line commented, | ||
* it will try to do a line uncomment if is not actually inside a bigger block comment. | ||
* | ||
* @param {!Editor} editor | ||
* @param {!string} prefix, e.g. "<!--" | ||
|
@@ -271,9 +307,8 @@ define(function (require, exports, module) { | |
ctx = TokenUtils.getInitialContext(editor._codeMirror, {line: sel.start.line, ch: sel.start.ch}), | ||
startCtx = TokenUtils.getInitialContext(editor._codeMirror, {line: sel.start.line, ch: sel.start.ch}), | ||
endCtx = TokenUtils.getInitialContext(editor._codeMirror, {line: sel.end.line, ch: sel.end.ch}), | ||
prefixExp = new RegExp("^" + StringUtils.regexEscape(prefix), "g"), | ||
suffixExp = new RegExp(StringUtils.regexEscape(suffix) + "$", "g"), | ||
lineExp = _createLineExpressions(linePrefixes), | ||
blockExp = _createBlockExpressions(prefix, suffix), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might make the following code easier to read if this was still broken out into prefixExp and suffixExp local vars |
||
prefixPos = null, | ||
suffixPos = null, | ||
canComment = false, | ||
|
@@ -283,13 +318,42 @@ define(function (require, exports, module) { | |
|
||
var result, text, line; | ||
|
||
/** | ||
* Intenal function that looks for the prefix and suffix position | ||
* @param {!{line: number, ch: number}} newPrefixPos | ||
*/ | ||
function findPrefixSuffix(newPrefixPos) { | ||
prefixPos = newPrefixPos || _findCommentStart(ctx, blockExp, lineExp); | ||
suffixPos = _findCommentEnd(ctx, blockExp, lineExp, suffix.length); | ||
|
||
// There are some languages like CoffeeScript where the block comment prefix and suffix are the same, so | ||
// when the prefix or suffix is alone in one line, both prefixPos and suffixPos might be the same. | ||
// In those cases we need to find the real prefix or suffix | ||
if (prefixPos && prefixPos.line === suffixPos.line && prefixPos.ch === suffixPos.ch) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suffixPos could be null here |
||
// Lets create a new Token context to look for the prefix so that ctx stays at the suffix position | ||
var newCtx = TokenUtils.getInitialContext(editor._codeMirror, {line: ctx.pos.line, ch: ctx.pos.ch }); | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.movePrevToken, newCtx); | ||
|
||
// The previows token is a block comment, so we found the suffix, we need to find the prefix | ||
if (result && _isBlockComment(newCtx, blockExp, lineExp)) { | ||
prefixPos = _findCommentStart(newCtx, blockExp, lineExp); | ||
// We found the prefix, we move to the next token and try to find the suffix | ||
} else { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx); | ||
suffixPos = result && _findCommentEnd(ctx, blockExp, lineExp, suffix.length); | ||
} | ||
} | ||
} | ||
|
||
|
||
// Move the context to the first non-empty token. | ||
if (!ctx.token.className && ctx.token.string.trim().length === 0) { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx); | ||
} | ||
|
||
// Check if we should just do a line uncomment (if all lines in the selection are commented). | ||
if (lineExp.length && (_matchExpressions(ctx.token.string, lineExp) || _matchExpressions(endCtx.token.string, lineExp))) { | ||
if (lineExp.length && (_matchExpressions(ctx.token.string, lineExp) || _matchExpressions(endCtx.token.string, lineExp)) && | ||
!ctx.token.string.match(blockExp[0])) { | ||
var startCtxIndex = editor.indexFromPos({line: ctx.pos.line, ch: ctx.token.start}); | ||
var endCtxIndex = editor.indexFromPos({line: endCtx.pos.line, ch: endCtx.token.start + endCtx.token.string.length}); | ||
|
||
|
@@ -300,7 +364,7 @@ define(function (require, exports, module) { | |
} | ||
|
||
// If we aren't in a block-comment. | ||
if (!result || ctx.token.className !== "comment" || ctx.token.string.match(suffixExp)) { | ||
if (!result || ctx.token.className !== "comment" || ctx.token.string.match(blockExp[1])) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like this logic (this diff plus the one just above it) wouldn't catch cases where a CoffeeScript-type block comment is embedded in between contiguous sets of line comments. The first line of the selection could be "#", and the while loop here could terminate on a "#", but some of the lines in between could be "###" -- the loop would continue past them because they do match lineExp too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The number of places where we have to catch this bug is high enough -- I've already lost count -- that I wonder whether we should be using a lineExp more like Edit: I guess the regexp might need to be a little trickier, e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line is trying to match the block prefix, not a line prefix. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, but the while loop just above here is matching on lineExp -- which without my suggested change to the regexp, would match block comments too. Hence the loop could fly past a block comment mixed in between line comments without realizing that it, and we'd erroneously decide the selection contained nothing but line comments. E.g. a case like this: # line 1
# line 2
###
block comment
###
# line 4
# line 5 |
||
// Is a range of text selected? (vs just an insertion pt) | ||
var hasSelection = (sel.start.line !== sel.end.line) || (sel.start.ch !== sel.end.ch); | ||
|
||
|
@@ -311,30 +375,27 @@ define(function (require, exports, module) { | |
} | ||
|
||
// Find if all the lines are line-commented. | ||
if (!_containsUncommented(editor, sel.start.line, endLine, lineExp)) { | ||
if (!_containsUncommented(editor, sel.start.line, endLine, lineExp, blockExp)) { | ||
lineUncomment = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure where in here the bug lies, but I'm also seeing problems with cases like this: ###
math =
root: Math.sqrt
cube: (x) -> x * square x
###
# foo
# bar Select the last two lines and invoke either of the Toggle Comment commands. The other block of commented-out code is uncommented instead. |
||
|
||
// Block-comment in all the other cases | ||
} else { | ||
canComment = true; | ||
} | ||
} else { | ||
prefixPos = _findCommentStart(startCtx, prefixExp); | ||
suffixPos = _findCommentEnd(startCtx, suffixExp, suffix.length); | ||
findPrefixSuffix(); | ||
} | ||
|
||
// If we are in a selection starting and ending in invalid tokens and with no content (not considering spaces), | ||
// find if we are inside a block-comment. | ||
} else if (startCtx.token.className === null && endCtx.token.className === null && | ||
!editor.posWithinRange(ctx.pos, startCtx.pos, endCtx.pos)) { | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, startCtx); | ||
|
||
// We found a comment, find the start and end and check if the selection is inside the block-comment. | ||
if (startCtx.token.className === "comment") { | ||
prefixPos = _findCommentStart(startCtx, prefixExp); | ||
suffixPos = _findCommentEnd(startCtx, suffixExp, suffix.length); | ||
if (ctx.token.className === "comment") { | ||
findPrefixSuffix(); | ||
|
||
if (prefixPos !== null && suffix !== null && !editor.posWithinRange(sel.start, prefixPos, suffixPos)) { | ||
if (prefixPos !== null && !editor.posWithinRange(sel.start, prefixPos, suffixPos)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently it's possible to have |
||
canComment = true; | ||
} | ||
} else { | ||
|
@@ -343,23 +404,19 @@ define(function (require, exports, module) { | |
|
||
// If the start is inside a comment, find the prefix and suffix positions. | ||
} else if (ctx.token.className === "comment") { | ||
prefixPos = _findCommentStart(ctx, prefixExp); | ||
suffixPos = _findCommentEnd(ctx, suffixExp, suffix.length); | ||
findPrefixSuffix(); | ||
|
||
// If not try to find the first comment inside the selection. | ||
} else { | ||
result = _findNextBlockComment(ctx, sel.end, prefixExp); | ||
result = _findNextBlockComment(ctx, sel.end, blockExp[0]); | ||
|
||
// If nothing was found is ok to comment. | ||
if (!result) { | ||
canComment = true; | ||
} else if (ctx.token.string.match(blockExp[0])) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at _findNextBlockComment(), it seems like this is always true if On the other hand, I'm not sure why the code in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought the same, but for some reason test where failing when I removed this case before, but now I tested it again, with a few other changes in the code, and it works good without it. |
||
findPrefixSuffix({line: ctx.pos.line, ch: ctx.token.start}); | ||
} else { | ||
if (!ctx.token.string.match(prefixExp)) { | ||
prefixPos = _findCommentStart(ctx, prefixExp); | ||
} else { | ||
prefixPos = {line: ctx.pos.line, ch: ctx.token.start}; | ||
} | ||
suffixPos = _findCommentEnd(ctx, suffixExp, suffix.length); | ||
findPrefixSuffix(); | ||
} | ||
} | ||
|
||
|
@@ -369,9 +426,10 @@ define(function (require, exports, module) { | |
if (editor.posWithinRange(start, sel.start, sel.end)) { | ||
// Start searching at the next token, if there is one. | ||
result = TokenUtils.moveSkippingWhitespace(TokenUtils.moveNextToken, ctx) && | ||
_findNextBlockComment(ctx, sel.end, prefixExp); | ||
_findNextBlockComment(ctx, sel.end, blockExp[0]); | ||
|
||
if (result) { | ||
console.log("invalid", ctx); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove |
||
invalidComment = true; | ||
} | ||
} | ||
|
@@ -543,7 +601,7 @@ define(function (require, exports, module) { | |
var language = editor.getLanguageForSelection(); | ||
|
||
if (language.hasLineCommentSyntax()) { | ||
lineCommentPrefix(editor, language.getLineCommentPrefixes()); | ||
lineCommentPrefix(editor, language.getLineCommentPrefixes(), language.getBlockCommentPrefix(), language.getBlockCommentSuffix()); | ||
} else if (language.hasBlockCommentSyntax()) { | ||
lineCommentPrefixSuffix(editor, language.getBlockCommentPrefix(), language.getBlockCommentSuffix()); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,7 +87,8 @@ | |
"name": "CoffeeScript", | ||
"mode": "coffeescript", | ||
"fileExtensions": ["coffee", "cf", "cson"], | ||
"fileNames": ["Cakefile"] | ||
"fileNames": ["Cakefile"], | ||
"blockComment": ["###", "###"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We want to add lineComment too, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do, since not having it can break stuff with out it, but since it was added in your pull request to add block and line comment for more languages, I did add it here. |
||
}, | ||
|
||
"clojure": { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the comment above this could use some updating. It's not immediately obvious why finding a block comment delimiter means there's an uncommented out line. Don't you need to know (a) whether it's an open vs. close delimiter, and (b) whether any non-blank lines exist on the "outside" side of the delimiter (and still within the startLine-endLine range)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And as a corollary, it seems like with symmetrical delimiters (like "###"), you can only know "(a)" by looking at the tokens...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just here so when you want to toggle line comment a line starting with 0-N whitespaces and then a block comment prefix or suffix where at least one line comment prefix is the prefix of either one, then it shouldn't remove part of the block comment prefix, and instead just comment it. This doesn't check block comments and try to to be smart about them.
The case I am trying to avoid is when you use toggle block comment in the first line of the next code:
that will turn into:
Which breaks the block comment and doesn't do either a line comment or uncomment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think that makes sense. In that case, maybe the name should be changed to _containsNotLineComment() -- since block comments will cause it to return true too, and since that's actually what the code calling it wants to know.
Or if that name is too awkward you could invert the sense of it and use a name like _isAllLineCommented().