diff --git a/src/language/HTMLUtils.js b/src/language/HTMLUtils.js
index c90a017d497..825a61dbd83 100644
--- a/src/language/HTMLUtils.js
+++ b/src/language/HTMLUtils.js
@@ -508,19 +508,16 @@ define(function (require, exports, module) {
*/
function findBlocks(editor, modeName) {
// Start scanning from beginning of file
- var blocks = [],
- cm = editor._codeMirror,
+ var ctx = TokenUtils.getInitialContext(editor._codeMirror, {line: 0, ch: 0}),
+ blocks = [],
currentBlock = null,
inBlock = false,
- line,
- lineCount = editor.lineCount(),
- outerMode = cm.getMode(),
- previousMode,
+ outerMode = editor._codeMirror.getMode(),
tokenModeName,
- tokens;
+ previousMode;
- function checkForBlock(ctx) {
- tokenModeName = CodeMirror.innerMode(outerMode, ctx.state).mode.name;
+ while (TokenUtils.moveNextToken(ctx, false)) {
+ tokenModeName = CodeMirror.innerMode(outerMode, ctx.token.state).mode.name;
if (inBlock) {
if (!currentBlock.end) {
// Handle empty blocks
@@ -532,13 +529,13 @@ define(function (require, exports, module) {
currentBlock.text = editor.document.getRange(currentBlock.start, currentBlock.end);
inBlock = false;
} else {
- currentBlock.end = { line: line, ch: ctx.end };
+ currentBlock.end = { line: ctx.pos.line, ch: ctx.pos.ch };
}
} else {
// Check for start of a block
if (tokenModeName === modeName) {
currentBlock = {
- start: { line: line, ch: ctx.end }
+ start: { line: ctx.pos.line, ch: ctx.pos.ch }
};
blocks.push(currentBlock);
inBlock = true;
@@ -549,12 +546,6 @@ define(function (require, exports, module) {
}
}
- for (line = 0; line < lineCount; line++) {
- tokens = cm.getLineTokens(line);
- tokens.forEach(checkForBlock);
- tokens = null; // Garbage collection - tokens can be pretty big
- }
-
return blocks;
}
diff --git a/src/utils/TokenUtils.js b/src/utils/TokenUtils.js
index 825dd23db81..f4243d1ff9d 100644
--- a/src/utils/TokenUtils.js
+++ b/src/utils/TokenUtils.js
@@ -33,20 +33,73 @@
define(function (require, exports, module) {
"use strict";
- var CodeMirror = require("thirdparty/CodeMirror2/lib/codemirror");
+ var _ = require("thirdparty/lodash"),
+ CodeMirror = require("thirdparty/CodeMirror2/lib/codemirror");
+
+ var cache;
+
+
+ function _clearCache(cm) {
+ cache = null;
+ if (cm) { // event handler
+ cm.off("changes", _clearCache);
+ }
+ }
+
+ /*
+ * Caches the tokens for the given editor/line if needed
+ * @param {!CodeMirror} cm
+ * @param {!number} line
+ * @return {Array.