diff --git a/browser/devtools/sourceeditor/source-editor-orion.jsm b/browser/devtools/sourceeditor/source-editor-orion.jsm index ea92d30b0422..d67dda9b3c60 100644 --- a/browser/devtools/sourceeditor/source-editor-orion.jsm +++ b/browser/devtools/sourceeditor/source-editor-orion.jsm @@ -1231,6 +1231,7 @@ SourceEditor.prototype = { // If the caret is not at the closing bracket "}", find the index of the // opening bracket "{" for the current code block. if (matchingIndex == -1 || matchingIndex > caretOffset) { + matchingIndex = -1; let text = this.getText(); let closingOffset = text.indexOf("}", caretOffset); while (closingOffset > -1) { @@ -1241,18 +1242,34 @@ SourceEditor.prototype = { } closingOffset = text.indexOf("}", closingOffset + 1); } + // Moving to the previous code block starting bracket if caret not inside + // any code block. + if (matchingIndex == -1) { + let lastClosingOffset = text.lastIndexOf("}", caretOffset); + while (lastClosingOffset > -1) { + let closingMatchingIndex = + this._getMatchingBracketIndex(lastClosingOffset); + if (closingMatchingIndex < caretOffset && + closingMatchingIndex != -1) { + matchingIndex = closingMatchingIndex; + break; + } + lastClosingOffset = text.lastIndexOf("}", lastClosingOffset - 1); + } + } } if (matchingIndex > -1) { - this.setCaretOffset(matchingIndex); + this.setCaretOffset(matchingIndex + 1); } return true; }, /** - * Moves the cursor to the matching closing bracket if at corresponding opening - * bracket, otherwise move to the closing bracket for the current block of code. + * Moves the cursor to the matching closing bracket if at corresponding + * opening bracket, otherwise move to the closing bracket for the current + * block of code. * * @private */ @@ -1271,6 +1288,7 @@ SourceEditor.prototype = { // If the caret is not at the opening bracket "{", find the index of the // closing bracket "}" for the current code block. if (matchingIndex == -1 || matchingIndex < caretOffset) { + matchingIndex = -1; let text = this.getText(); let openingOffset = text.lastIndexOf("{", caretOffset); while (openingOffset > -1) { @@ -1281,6 +1299,20 @@ SourceEditor.prototype = { } openingOffset = text.lastIndexOf("{", openingOffset - 1); } + // Moving to the next code block ending bracket if caret not inside + // any code block. + if (matchingIndex == -1) { + let nextOpeningIndex = text.indexOf("{", caretOffset + 1); + while (nextOpeningIndex > -1) { + let openingMatchingIndex = + this._getMatchingBracketIndex(nextOpeningIndex); + if (openingMatchingIndex > caretOffset) { + matchingIndex = openingMatchingIndex; + break; + } + nextOpeningIndex = text.indexOf("{", nextOpeningIndex + 1); + } + } } if (matchingIndex > -1) { diff --git a/browser/devtools/sourceeditor/test/Makefile.in b/browser/devtools/sourceeditor/test/Makefile.in index 75408aa038d6..92004b60aabc 100644 --- a/browser/devtools/sourceeditor/test/Makefile.in +++ b/browser/devtools/sourceeditor/test/Makefile.in @@ -30,6 +30,7 @@ MOCHITEST_BROWSER_FILES = \ browser_bug725430_comment_uncomment.js \ browser_bug731721_debugger_stepping.js \ browser_bug729960_block_bracket_jump.js \ + browser_bug744021_next_prev_bracket_jump.js \ head.js \ include $(topsrcdir)/config/rules.mk diff --git a/browser/devtools/sourceeditor/test/browser_bug729960_block_bracket_jump.js b/browser/devtools/sourceeditor/test/browser_bug729960_block_bracket_jump.js index fdafca08b1fd..534018e246d1 100644 --- a/browser/devtools/sourceeditor/test/browser_bug729960_block_bracket_jump.js +++ b/browser/devtools/sourceeditor/test/browser_bug729960_block_bracket_jump.js @@ -58,13 +58,13 @@ function test() { "JS : Jump to closing bracket of the code block when caret at block start"); EventUtils.synthesizeKey("[", {accelKey: true}, testWin); - is(editor.getCaretOffset(), 19, + is(editor.getCaretOffset(), 20, "JS : Jump to opening bracket of the code block when caret at block end"); // Setting caret at Line 10 start. editor.setCaretOffset(161); EventUtils.synthesizeKey("[", {accelKey: true}, testWin); - is(editor.getCaretOffset(), 19, + is(editor.getCaretOffset(), 20, "JS : Jump to opening bracket of code block when inside the function"); editor.setCaretOffset(161); @@ -80,7 +80,7 @@ function test() { editor.setCaretOffset(67); EventUtils.synthesizeKey("[", {accelKey: true}, testWin); - is(editor.getCaretOffset(), 61, + is(editor.getCaretOffset(), 62, "JS : Jump to opening bracket in a nested function with caret inside"); let CSSText = "#object {\n" + @@ -98,13 +98,13 @@ function test() { "CSS : Jump to closing bracket of the code block when caret at block start"); EventUtils.synthesizeKey("[", {accelKey: true}, testWin); - is(editor.getCaretOffset(), 8, + is(editor.getCaretOffset(), 9, "CSS : Jump to opening bracket of the code block when caret at block end"); // Setting caret at Line 3 start. editor.setCaretOffset(28); EventUtils.synthesizeKey("[", {accelKey: true}, testWin); - is(editor.getCaretOffset(), 8, + is(editor.getCaretOffset(), 9, "CSS : Jump to opening bracket of code block when inside the function"); editor.setCaretOffset(28); diff --git a/browser/devtools/sourceeditor/test/browser_bug744021_next_prev_bracket_jump.js b/browser/devtools/sourceeditor/test/browser_bug744021_next_prev_bracket_jump.js new file mode 100644 index 000000000000..72b7d45c6654 --- /dev/null +++ b/browser/devtools/sourceeditor/test/browser_bug744021_next_prev_bracket_jump.js @@ -0,0 +1,104 @@ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +function test() { + + let temp = {}; + Cu.import("resource:///modules/source-editor.jsm", temp); + let SourceEditor = temp.SourceEditor; + + waitForExplicitFinish(); + + let editor; + + const windowUrl = "data:text/xml;charset=utf8," + + ""; + const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable," + + "dialog=no"; + + let testWin = Services.ww.openWindow(null, windowUrl, "_blank", + windowFeatures, null); + testWin.addEventListener("load", function onWindowLoad() { + testWin.removeEventListener("load", onWindowLoad, false); + waitForFocus(initEditor, testWin); + }, false); + + function initEditor() + { + let hbox = testWin.document.querySelector("hbox"); + editor = new SourceEditor(); + editor.init(hbox, {showLineNumbers: true}, editorLoaded); + } + + function editorLoaded() + { + editor.focus(); + let JSText = "function foo() {\n" + + " \n" + + " function level2() {\n" + + " \n" + + " function level3() {\n" + + " \n" + + " }\n" + + " }\n" + + " function bar() { /* Block Level 2 */ }\n" + + "}\n" + + "function baz() {\n" + + " \n" + + "}"; + + editor.setMode(SourceEditor.MODES.JAVASCRIPT); + editor.setText(JSText); + + // Setting caret at end of line 11 (function baz() {). + editor.setCaretOffset(147); + EventUtils.synthesizeKey("[", {accelKey: true}, testWin); + is(editor.getCaretOffset(), 16, + "JS : Jump to opening bracket of previous sibling block when no parent"); + + EventUtils.synthesizeKey("]", {accelKey: true}, testWin); + is(editor.getCaretOffset(), 129, + "JS : Jump to closing bracket of same code block"); + + EventUtils.synthesizeKey("]", {accelKey: true}, testWin); + is(editor.getCaretOffset(), 151, + "JS : Jump to closing bracket of next sibling code block"); + + let CSSText = "#object1 {\n" + + " property: value;\n" + + " /* comment */\n" + + "}\n" + + ".class1 {\n" + + " property: value;\n" + + "}"; + + editor.setMode(SourceEditor.MODES.CSS); + editor.setText(CSSText); + + // Setting caret at Line 5 end (.class1 {). + editor.setCaretOffset(57); + EventUtils.synthesizeKey("[", {accelKey: true}, testWin); + is(editor.getCaretOffset(), 10, + "CSS : Jump to opening bracket of previous sibling code block"); + + EventUtils.synthesizeKey("]", {accelKey: true}, testWin); + is(editor.getCaretOffset(), 46, + "CSS : Jump to closing bracket of same code block"); + + EventUtils.synthesizeKey("]", {accelKey: true}, testWin); + is(editor.getCaretOffset(), 77, + "CSS : Jump to closing bracket of next sibling code block"); + + editor.destroy(); + + testWin.close(); + testWin = editor = null; + + waitForFocus(finish, window); + } +}