Bug 1312191 - Do not hardcode INDENT_LEVEL in xbl preprocessor. r?miker draft
authorPhilipp Kewisch <mozilla@kewis.ch>
Sun, 08 Oct 2017 14:40:16 +0200
changeset 676551 3e597ba49282e7e342a01add9c91d8266f4860bc
parent 676550 8dba4037f395ce60309ce9e9b1675152f240ff98
child 734963 54cdac883de9879b192bf2ef4efff003783a37a8
push id83522
push usermozilla@kewis.ch
push dateSun, 08 Oct 2017 15:25:16 +0000
reviewersmiker
bugs1312191
milestone58.0a1
Bug 1312191 - Do not hardcode INDENT_LEVEL in xbl preprocessor. r?miker MozReview-Commit-ID: EiufIKCNfSs
toolkit/content/widgets/datetimepicker.xml
toolkit/content/widgets/remote-browser.xml
tools/lint/eslint/eslint-plugin-mozilla/lib/processors/xbl-bindings.js
--- a/toolkit/content/widgets/datetimepicker.xml
+++ b/toolkit/content/widgets/datetimepicker.xml
@@ -179,17 +179,17 @@
             this._lastFocusedField = target;
         ]]>
       </handler>
 
       <handler event="keypress">
         <![CDATA[
           if (this._hasEntry && event.charCode &&
               this._currentField != this._fieldAMPM &&
-	            !(event.altKey || event.ctrlKey || event.metaKey) &&
+                !(event.altKey || event.ctrlKey || event.metaKey) &&
               (event.charCode < 48 || event.charCode > 57))
             event.preventDefault();
         ]]>
       </handler>
 
       <handler event="keypress" keycode="VK_UP">
         if (this._hasEntry)
           this._increaseOrDecrease(1);
--- a/toolkit/content/widgets/remote-browser.xml
+++ b/toolkit/content/widgets/remote-browser.xml
@@ -273,17 +273,17 @@
         <![CDATA[
           let id = this._permitUnloadId++;
           let mm = this.messageManager;
           mm.sendAsyncMessage("InPermitUnload", {id});
           mm.addMessageListener("InPermitUnload", function listener(msg) {
             if (msg.data.id != id) {
               return;
             }
-	    aCallback(msg.data.inPermitUnload);
+            aCallback(msg.data.inPermitUnload);
           });
         ]]>
         </body>
       </method>
 
       <method name="permitUnload">
         <body>
         <![CDATA[
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/processors/xbl-bindings.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/processors/xbl-bindings.js
@@ -104,22 +104,16 @@ XMLParser.prototype = {
     this._currentNode.comments.push(text);
   }
 };
 
 // -----------------------------------------------------------------------------
 // Processor Definition
 // -----------------------------------------------------------------------------
 
-const INDENT_LEVEL = 2;
-
-function indent(count) {
-  return " ".repeat(count * INDENT_LEVEL);
-}
-
 // Stores any XML parse error
 let xmlParseError = null;
 
 // Stores the lines of JS code generated from the XBL
 let scriptLines = [];
 // Stores a map from the synthetic line number to the real line number
 // and column offset.
 let lineMap = [];
@@ -145,51 +139,62 @@ function addNodeLines(node, reindent) {
   // Strip off any preceeding whitespace only lines. These are often used to
   // format the XML and CDATA blocks.
   while (lines.length && lines[0].trim() == "") {
     indentFirst = true;
     startLine++;
     lines.shift();
   }
 
+  // Remember the indent of the last blank line, which is the closing part of
+  // the CDATA block.
+  let lastIndent = 0;
+  if (lines.length && lines[lines.length - 1].trim() == "") {
+    lastIndent = lines[lines.length - 1].length;
+  }
+
+  // If the second to last line is also blank and has a higher indent than the
+  // last one, then the CDATA block doesn't close with the closing tag.
+  if (lines.length > 2 && lines[lines.length - 2].trim() == "" &&
+      lines[lines.length - 2].length > lastIndent) {
+    lastIndent = lines[lines.length - 2].length;
+  }
+
   // Strip off any whitespace lines at the end. These are often used to line
   // up the closing tags
   while (lines.length && lines[lines.length - 1].trim() == "") {
     lines.pop();
   }
 
   if (!indentFirst) {
     let firstLine = lines.shift();
-    firstLine = " ".repeat(reindent * INDENT_LEVEL) + firstLine;
     // ESLint counts columns starting at 1 rather than 0
-    lineMap[scriptLines.length] = {
-      line: startLine,
-      offset: reindent * INDENT_LEVEL - (startColumn - 1)
-    };
+    lineMap[scriptLines.length] = { line: startLine, offset: startColumn - 1 };
     scriptLines.push(firstLine);
     startLine++;
   }
 
   // Find the preceeding whitespace for all lines that aren't entirely
   // whitespace.
   let indents = lines.filter(s => s.trim().length > 0)
                      .map(s => s.length - s.trimLeft().length);
   // Find the smallest indent level in use
   let minIndent = Math.min.apply(null, indents);
+  let indent = Math.max(2, minIndent - lastIndent);
 
   for (let line of lines) {
     if (line.trim().length == 0) {
       // Don't offset lines that are only whitespace, the only possible JS error
       // is trailing whitespace and we want it to point at the right place
       lineMap[scriptLines.length] = { line: startLine, offset: 0 };
     } else {
-      line = " ".repeat(reindent * INDENT_LEVEL) + line.substring(minIndent);
+      line = " ".repeat(indent) + line.substring(minIndent);
       lineMap[scriptLines.length] = {
         line: startLine,
-        offset: reindent * INDENT_LEVEL - (minIndent - 1)
+        offset: 1 + indent - minIndent
       };
     }
 
     scriptLines.push(line);
     startLine++;
   }
 }
 
@@ -235,28 +240,27 @@ module.exports = {
 
     addSyntheticLine(`this.bindings = {`, bindings.textLine);
 
     for (let binding of bindings.children) {
       if (binding.local != "binding" || binding.namespace != NS_XBL) {
         continue;
       }
 
-      addSyntheticLine(indent(1) +
-        `"${binding.attributes.id}": {`, binding.textLine);
+      addSyntheticLine(`"${binding.attributes.id}": {`, binding.textLine);
 
       for (let part of binding.children) {
         if (part.namespace != NS_XBL) {
           continue;
         }
 
         if (part.local == "implementation") {
-          addSyntheticLine(indent(2) + `implementation: {`, part.textLine);
+          addSyntheticLine(`implementation: {`, part.textLine);
         } else if (part.local == "handlers") {
-          addSyntheticLine(indent(2) + `handlers: [`, part.textLine);
+          addSyntheticLine(`handlers: [`, part.textLine);
         } else {
           continue;
         }
 
         for (let item of part.children) {
           if (item.namespace != NS_XBL) {
             continue;
           }
@@ -265,94 +269,88 @@ module.exports = {
             case "field": {
               // Fields are something like lazy getter functions
 
               // Ignore empty fields
               if (item.textContent.trim().length == 0) {
                 continue;
               }
 
-              addSyntheticLine(indent(3) +
-                `get ${item.attributes.name}() {`, item.textLine);
-              addSyntheticLine(indent(4) +
-                `return (`, item.textLine);
+              addSyntheticLine(`get ${item.attributes.name}() {`, item.textLine);
+              addSyntheticLine(`return (`, item.textLine);
 
               // Remove trailing semicolons, as we are adding our own
               item.textContent = item.textContent.replace(/;(?=\s*$)/, "");
               addNodeLines(item, 5);
 
-              addSyntheticLine(indent(4) + `);`, item.textLine);
-              addSyntheticLine(indent(3) + `},`, item.textEndLine);
+              addSyntheticLine(`);`, item.textLine);
+              addSyntheticLine(`},`, item.textEndLine);
               break;
             }
             case "constructor":
             case "destructor": {
               // Constructors and destructors become function declarations
-              addSyntheticLine(indent(3) + `${item.local}() {`, item.textLine);
+              addSyntheticLine(`${item.local}() {`, item.textLine);
               addNodeLines(item, 4);
-              addSyntheticLine(indent(3) + `},`, item.textEndLine);
+              addSyntheticLine(`},`, item.textEndLine);
               break;
             }
             case "method": {
               // Methods become function declarations with the appropriate
               // params.
 
               let params = item.children.filter(n => {
                 return n.local == "parameter" && n.namespace == NS_XBL;
               })
                                         .map(n => n.attributes.name)
                                         .join(", ");
               let body = item.children.filter(n => {
                 return n.local == "body" && n.namespace == NS_XBL;
               })[0];
 
-              addSyntheticLine(indent(3) +
-                `${item.attributes.name}(${params}) {`, item.textLine);
+              addSyntheticLine(`${item.attributes.name}(${params}) {`, item.textLine);
               addNodeLines(body, 4);
-              addSyntheticLine(indent(3) + `},`, item.textEndLine);
+              addSyntheticLine(`},`, item.textEndLine);
               break;
             }
             case "property": {
               // Properties become one or two function declarations
               for (let propdef of item.children) {
                 if (propdef.namespace != NS_XBL) {
                   continue;
                 }
 
                 if (propdef.local == "setter") {
-                  addSyntheticLine(indent(3) +
-                    `set ${item.attributes.name}(val) {`, propdef.textLine);
+                  addSyntheticLine(`set ${item.attributes.name}(val) {`, propdef.textLine);
                 } else if (propdef.local == "getter") {
-                  addSyntheticLine(indent(3) +
-                    `get ${item.attributes.name}() {`, propdef.textLine);
+                  addSyntheticLine(`get ${item.attributes.name}() {`, propdef.textLine);
                 } else {
                   continue;
                 }
                 addNodeLines(propdef, 4);
-                addSyntheticLine(indent(3) + `},`, propdef.textEndLine);
+                addSyntheticLine(`},`, propdef.textEndLine);
               }
               break;
             }
             case "handler": {
               // Handlers become a function declaration with an `event`
               // parameter.
-              addSyntheticLine(indent(3) + `function(event) {`, item.textLine);
+              addSyntheticLine(`function(event) {`, item.textLine);
               addNodeLines(item, 4);
-              addSyntheticLine(indent(3) + `},`, item.textEndLine);
+              addSyntheticLine(`},`, item.textEndLine);
               break;
             }
             default:
               continue;
           }
         }
 
-        addSyntheticLine(indent(2) +
-          (part.local == "implementation" ? `},` : `],`), part.textEndLine);
+        addSyntheticLine((part.local == "implementation" ? `},` : `],`), part.textEndLine);
       }
-      addSyntheticLine(indent(1) + `},`, binding.textEndLine);
+      addSyntheticLine(`},`, binding.textEndLine);
     }
     addSyntheticLine(`};`, bindings.textEndLine);
 
     let script = scriptLines.join("\n") + "\n";
     return [script];
   },
 
   postprocess(messages, filename) {