| Index: third_party/WebKit/Source/devtools/scripts/fix_comments.js
|
| diff --git a/third_party/WebKit/Source/devtools/scripts/fix_comments.js b/third_party/WebKit/Source/devtools/scripts/fix_comments.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e79a04134089aa4228cd1bac93bd4b670bcc26a2
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/devtools/scripts/fix_comments.js
|
| @@ -0,0 +1,316 @@
|
| +const fs = require('fs');
|
| +var escodegen = require('escodegen');
|
| +var esprima = require('esprima');
|
| +
|
| +String.prototype.rtrim = function() {
|
| + return this.replace(/\s+$/,"");
|
| +}
|
| +
|
| +String.prototype.replaceLineWithin = function(from, to, a, b) {
|
| + --from;
|
| + ++to;
|
| + var chunk = this.substring(from, to);
|
| + var newChunk = [];
|
| + for (var line of chunk.split("\n")) {
|
| + if (line.trim() === a)
|
| + newChunk.push(line.replace(a, b));
|
| + else
|
| + newChunk.push(line);
|
| + }
|
| + return this.substring(0, from) + newChunk.join("\n") + this.substring(to);
|
| +}
|
| +
|
| +String.prototype.replaceRange = function(range, replacement) {
|
| + return this.substring(0, range[0]) + replacement + this.substring(range[1]);
|
| +}
|
| +
|
| +class FileProcessor {
|
| +
|
| + constructor(filePath)
|
| + {
|
| + this._filePath = filePath;
|
| + this._classInfos = new Map();
|
| + this._content = fs.readFileSync(filePath).toString();
|
| +
|
| + var program;
|
| + try {
|
| + program = esprima.parse(this._content, {attachComment:true, range: true, loc: true});
|
| + } catch(e) {
|
| + console.log("FAILED TO PARSE: " + filePath);
|
| + return;
|
| + }
|
| +
|
| + this._definitions = new Map();
|
| +
|
| + this._walkAddParent(program, node => this._visit(node));
|
| + var newContent = this._content;
|
| +
|
| + for (var name of this._classInfos.keys()) {
|
| + var newDefinition = [];
|
| + var commentNode = this._classInfos.get(name).constructorCommentNode;
|
| + var constructorNode = this._classInfos.get(name).constructorNode;
|
| + var prototypeNode = this._classInfos.get(name).prototypeNode;
|
| + var comment = commentNode ? this._text(commentNode) : "";
|
| + if (!comment || !comment.includes("@constructor"))
|
| + continue;
|
| + var moduleName = filePath.replace(/front_end\/([^/]+)\/.*/, "$1");
|
| + if (moduleName.endsWith("_lazy"))
|
| + moduleName = moduleName.substring(0, moduleName.length - "_lazy".length);
|
| +
|
| + if (moduleName === "accessibility")
|
| + moduleName = "a11y";
|
| + if (moduleName === "resources")
|
| + moduleName = "storage";
|
| + if (moduleName === "heap_snapshot_worker")
|
| + moduleName = "heap_worker";
|
| + if (moduleName === "timeline")
|
| + moduleName = "timeline_ui";
|
| + if (moduleName === "timeline_module")
|
| + moduleName = "timeline";
|
| +
|
| + var newName = name.replace("WebInspector.", moduleName + ".");
|
| + var capModule = moduleName.substring(0, 1).toUpperCase() + moduleName.substring(1);
|
| + var prefix = moduleName + "." + capModule;
|
| + if (newName.startsWith(prefix) && newName.length > prefix.length)
|
| + newName = newName.replace(prefix, moduleName + ".");
|
| +
|
| + console.log(newName);
|
| +
|
| + var commentLines = comment.split("\n");
|
| + var implementsLines = [];
|
| + for (var commentLine of commentLines) {
|
| + var implementsMatch = commentLine.match(/@implements {(.*)}/);
|
| + if (implementsMatch)
|
| + implementsLines.push(` * @implements {${implementsMatch[1]}} `);
|
| + var templateMatch = commentLine.match(/@template/);
|
| + if (templateMatch)
|
| + implementsLines.push(commentLine);
|
| + }
|
| + implementsLines.push(" * @unrestricted");
|
| + newDefinition.push(`/**\n${implementsLines.join("\n")}\n*/\n`);
|
| +
|
| + if (constructorNode.type === "FunctionDeclaration")
|
| + newDefinition.push(`var ${name} = class `);
|
| + else
|
| + newDefinition.push(`${name} = class `);
|
| +
|
| + var extendsMatch = comment.match(/@extends {(.*)}/);
|
| + let superName;
|
| + if (extendsMatch)
|
| + superName = extendsMatch[1];
|
| +
|
| + if (superName)
|
| + newDefinition.push(`extends ${superName} {`);
|
| + else
|
| + newDefinition.push(`{`);
|
| +
|
| + if (comment) {
|
| + comment = comment.replace(/^/gm, " ").substring(2);
|
| + comment = comment.replace(/\s*@implements.*/g, "");
|
| + comment = comment.replace(/\s*@extends.*/, "");
|
| + comment = comment.replace(/\s*@constructor/, "");
|
| + comment = comment.replace(/\s*@template.*/g, "");
|
| + comment = comment.split("\n").filter(line => line.trim() !== "*").join("\n");
|
| + if (comment.replace(/[*/]/g, "").trim())
|
| + newDefinition.push(`\n ${comment}`);
|
| + }
|
| +
|
| + var constructorText = this._text(constructorNode).trim();
|
| + constructorText = constructorText.replace(/^/gm, " ");
|
| + var lines = constructorText.split("\n");
|
| + lines[0] = lines[0].replace(`function ${name}`, " constructor");
|
| + lines[0] = lines[0].replace(`function(`, " constructor(");
|
| + constructorText = lines.join("\n");
|
| + if (constructorText.includes(`${superName}.call`)) {
|
| + constructorText = constructorText.replace(`${superName}.call(this, `, "super(");
|
| + constructorText = constructorText.replace(`${superName}.call(this)`, "super()");
|
| + } else if (superName) {
|
| + constructorText = constructorText.replace("{", "{\n super();");
|
| + }
|
| +
|
| + if (constructorText.replace(/constructor[^{]+{/m, "").replace(/.*}/, "").trim()) {
|
| + newDefinition.push("\n");
|
| + newDefinition.push(constructorText);
|
| + }
|
| +
|
| + if (prototypeNode) {
|
| + // Remove block comma
|
| + var prototypeText = this._text(prototypeNode);
|
| + for (var i = 0; i < prototypeNode.properties.length; ++i) {
|
| + var previous = prototypeNode.properties[i - 1];
|
| + var property = prototypeNode.properties[i];
|
| + prototypeText = prototypeText.replaceLineWithin(previous ? previous.range[1] - prototypeNode.range[0] : 0, property.range[0] - prototypeNode.range[0], "},", "} ");
|
| + }
|
| + prototypeText = prototypeText.replaceLineWithin(property ? property.range[1] - prototypeNode.range[0] : prototypeNode.range[1] - prototypeNode.range[0], prototypeNode.range[1] - prototypeNode.range[0], "},", "} ");
|
| +
|
| + prototypeText = prototypeText.replace(/(^\s+[\w]+)\:\s?function/mg, "$1");
|
| + prototypeText = prototypeText.replace(new RegExp(`${superName}\.prototype\.([^.]+)\.call\\(this, `, 'g'), "super.$1(");
|
| + prototypeText = prototypeText.replace(new RegExp(`${superName}\.prototype\.([^.]+)\.call\\(this\\)`, 'g'), "super.$1()");
|
| + prototypeText = prototypeText.replace(new RegExp(`^\\s+__proto__\\s*:\\s*${superName}.*`, "m"), "");
|
| +
|
| + newDefinition.push("\n");
|
| + newDefinition.push(prototypeText.substring(1, prototypeText.length - 2));
|
| + }
|
| + newDefinition.push("\n}\n");
|
| + this._definitions.set(name, newDefinition.join(""));;
|
| + }
|
| +
|
| + var newContent = this._content;
|
| + for (var name of this._definitions.keys()) {
|
| + var classInfo = this._classInfos.get(name);
|
| +
|
| + newContent = this._replaceRange(newContent, classInfo.constructorCommentNode.range, "");
|
| + newContent = this._replaceRange(newContent, classInfo.constructorNode.range, this._definitions.get(name));
|
| +
|
| +
|
| + if (classInfo.prototypeNode)
|
| + newContent = this._replaceRange(newContent, classInfo.prototypeNode.range, "");
|
| + }
|
| +
|
| + for (var name of this._definitions.keys()) {
|
| + newContent = newContent.replace(`${name} = ${name} =`, `${name} =`);
|
| + newContent = newContent.replace(`${name} = /**`, `/**`);
|
| + newContent = newContent.replace(`${name}.prototype = ;`, "");
|
| + newContent = newContent.replace(`${name}.prototype =\n;`, "");
|
| + }
|
| + newContent = newContent.trim();
|
| + newContent = newContent.replace(/\n\n\n/g, "\n\n");
|
| + newContent = newContent.replace(/}\n;/g, "};");
|
| + newContent = newContent.split("\n").map(line => line.rtrim()).join("\n");
|
| + newContent = newContent.replace("\n\n", "\n") + "\n";
|
| + fs.writeFileSync(filePath, newContent);
|
| + }
|
| +
|
| + _replaceRange(text, range, newContent)
|
| + {
|
| + range = range.slice();
|
| + var result = text.substring(0, range[0]) + newContent + text.substring(range[1]);
|
| + var newLength = newContent.length;
|
| + for (var name of this._definitions.keys()) {
|
| + var classInfo = this._classInfos.get(name);
|
| + this._patchRange(classInfo.constructorCommentNode.range, range, newLength);
|
| + this._patchRange(classInfo.constructorNode.range, range, newLength);
|
| + if (classInfo.prototypeNode)
|
| + this._patchRange(classInfo.prototypeNode.range, range, newLength);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + _patchRange(range, shift, newLength)
|
| + {
|
| + var oldLength = shift[1] - shift[0];
|
| + if (shift[0] > range[1])
|
| + return;
|
| + if (shift[1] < range[0]) {
|
| + range[0] += newLength - oldLength;
|
| + range[1] += newLength - oldLength;
|
| + return;
|
| + }
|
| + if (shift[0] == range[0] && shift[1] == range[1]) {
|
| + range[1] = range[0];
|
| + return;
|
| + }
|
| + console.error("POOR RANGE", this._filePath, range, shift);
|
| + }
|
| +
|
| + _classInfo(name) {
|
| + var result = this._classInfos.get(name);
|
| + if (!result) {
|
| + result = {};
|
| + this._classInfos.set(name, result);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + _log(title, node) {
|
| + if (node)
|
| + console.log(title + " : " + node.range[0] + ":" + node.range[1] + " " + this._text(node));
|
| + }
|
| +
|
| + _text(node) {
|
| + return this._content.substring(node.range[0], node.range[1]);
|
| + }
|
| +
|
| + _visit(node) {
|
| + var leadingComments = node.leadingComments || (node.parent && node.parent.leadingComments) || (node.parent && node.parent.parent && node.parent.parent.leadingComments);
|
| + var comment = null;
|
| + if (leadingComments) {
|
| + comment = leadingComments[leadingComments.length - 1];
|
| + var validComment = node.range[0] > comment.range[1] && this._content.substring(comment.range[1], node.range[0]).replace(/[^\n]/g, "").length < 2;
|
| + if (!validComment)
|
| + comment = null;
|
| + }
|
| +
|
| + if (node.type === "FunctionDeclaration") {
|
| + var classInfo = this._classInfo(node.id.name);
|
| + classInfo.constructorCommentNode = comment;
|
| + classInfo.constructorNode = node;
|
| + return;
|
| + }
|
| +
|
| + if (node.type === "FunctionExpression") {
|
| + if (!node.parent || !node.parent.left)
|
| + return;
|
| + var name = this._text(node.parent.left);
|
| + var classInfo = this._classInfo(name);
|
| + classInfo.constructorCommentNode = comment;
|
| + classInfo.constructorNode = node.parent.right;
|
| + return;
|
| + }
|
| +
|
| + if (node.type === "AssignmentExpression" && node.left.property && node.left.property.name === "prototype") {
|
| + var protoName = this._text(node.left);
|
| + var name = protoName.substring(0, protoName.length - ".prototype".length);
|
| + this._classInfo(name).prototypeNode = node.right;
|
| + return;
|
| + }
|
| + }
|
| +
|
| + _walkAddParent(ast, fn) {
|
| + var stack = [ast];
|
| + for (var i = 0; i < stack.length; i += 1) {
|
| + var node = stack[i];
|
| + fn(node);
|
| + for (var key in node) {
|
| + if (key !== 'parent') {
|
| + var child = node[key];
|
| + if (child instanceof Array) {
|
| + if (typeof child[0] === "number")
|
| + continue;
|
| + var len = child.length;
|
| + for (var j = 0; j < len; j += 1) {
|
| + var subchild = child[j];
|
| + subchild.parent = node;
|
| + stack.push(subchild);
|
| + }
|
| + } else if (child != void 0 && typeof child.type === 'string') {
|
| + child.parent = node;
|
| + stack.push(child);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +function walkSync(currentDirPath) {
|
| + var fs = require('fs'),
|
| + path = require('path');
|
| + fs.readdirSync(currentDirPath).forEach(function (name) {
|
| + var filePath = path.join(currentDirPath, name);
|
| + var stat = fs.statSync(filePath);
|
| + if (stat.isFile() && filePath.endsWith(".js")) {
|
| + if (filePath.includes("ExtensionAPI.js"))
|
| + return;
|
| + if (filePath.includes("externs.js"))
|
| + return;
|
| + if (filePath.includes("eslint") || filePath.includes("lighthouse-background.js") || filePath.includes("/cm/") || filePath.includes("/cm_modes/") || filePath.includes("/xterm.js/") || filePath.includes("/acorn/") || filePath.includes("/gonzales/"))
|
| + return;
|
| + new FileProcessor(filePath);
|
| + } else if (stat.isDirectory()) {
|
| + walkSync(filePath);
|
| + }
|
| + });
|
| +}
|
| +
|
| +walkSync('front_end');
|
|
|