Change let into const (#457)

This patch:
- changes `let` into `const` throughout codebase
- adds eslint check to prefer const over let
This commit is contained in:
Eric Bidelman
2017-08-21 16:39:04 -07:00
committed by Andrey Lushnikov
parent 5d6d3e0a81
commit 1f9b4fb4c8
37 changed files with 495 additions and 494 deletions

View File

@@ -21,7 +21,7 @@ class Documentation {
constructor(classesArray) {
this.classesArray = classesArray;
this.classes = new Map();
for (let cls of classesArray)
for (const cls of classesArray)
this.classes.set(cls.name, cls);
}
}
@@ -38,7 +38,7 @@ Documentation.Class = class {
this.properties = new Map();
this.methods = new Map();
this.events = new Map();
for (let member of membersArray) {
for (const member of membersArray) {
this.members.set(member.name, member);
if (member.type === 'method')
this.methods.set(member.name, member);
@@ -65,7 +65,7 @@ Documentation.Member = class {
this.args = new Map();
this.hasReturn = hasReturn;
this.async = async;
for (let arg of argsArray)
for (const arg of argsArray)
this.args.set(arg.name, arg);
}

View File

@@ -36,13 +36,13 @@ class ESTreeWalker {
return;
}
let walkOrder = ESTreeWalker._walkOrder[node.type];
const walkOrder = ESTreeWalker._walkOrder[node.type];
if (!walkOrder)
return;
if (node.type === 'TemplateLiteral') {
let templateLiteral = /** @type {!ESTree.TemplateLiteralNode} */ (node);
let expressionsLength = templateLiteral.expressions.length;
const templateLiteral = /** @type {!ESTree.TemplateLiteralNode} */ (node);
const expressionsLength = templateLiteral.expressions.length;
for (let i = 0; i < expressionsLength; ++i) {
this._innerWalk(templateLiteral.quasis[i], templateLiteral);
this._innerWalk(templateLiteral.expressions[i], templateLiteral);
@@ -50,7 +50,7 @@ class ESTreeWalker {
this._innerWalk(templateLiteral.quasis[expressionsLength], templateLiteral);
} else {
for (let i = 0; i < walkOrder.length; ++i) {
let entity = node[walkOrder[i]];
const entity = node[walkOrder[i]];
if (Array.isArray(entity))
this._walkArray(entity, node);
else

View File

@@ -27,8 +27,8 @@ class JSOutline {
this._currentClassMembers = [];
this._text = text;
let ast = esprima.parseScript(this._text, {loc: true, range: true});
let walker = new ESTreeWalker(node => {
const ast = esprima.parseScript(this._text, {loc: true, range: true});
const walker = new ESTreeWalker(node => {
if (node.type === 'ClassDeclaration')
this._onClassDeclaration(node);
else if (node.type === 'MethodDefinition')
@@ -49,9 +49,9 @@ class JSOutline {
_onMethodDefinition(node) {
console.assert(this._currentClassName !== null);
console.assert(node.value.type === 'FunctionExpression');
let methodName = this._extractText(node.key);
const methodName = this._extractText(node.key);
if (node.kind === 'get') {
let property = Documentation.Member.createProperty(methodName);
const property = Documentation.Member.createProperty(methodName);
this._currentClassMembers.push(property);
return;
}
@@ -60,7 +60,7 @@ class JSOutline {
// Extract properties from constructor.
if (node.kind === 'constructor') {
// Extract properties from constructor.
let walker = new ESTreeWalker(node => {
const walker = new ESTreeWalker(node => {
if (node.type !== 'AssignmentExpression')
return;
node = node.left;
@@ -71,7 +71,7 @@ class JSOutline {
});
walker.walk(node);
} else if (!hasReturn) {
let walker = new ESTreeWalker(node => {
const walker = new ESTreeWalker(node => {
if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression')
return ESTreeWalker.SkipSubtree;
if (node.type === 'ReturnStatement')
@@ -80,7 +80,7 @@ class JSOutline {
walker.walk(node.value.body);
}
const args = [];
for (let param of node.value.params) {
for (const param of node.value.params) {
if (param.type === 'AssignmentPattern')
args.push(new Documentation.Argument(param.left.name));
else if (param.type === 'RestElement')
@@ -92,7 +92,7 @@ class JSOutline {
else
this.errors.push(`JS Parsing issue: unsupported syntax to define parameter in ${this._currentClassName}.${methodName}(): ${this._extractText(param)}`);
}
let method = Documentation.Member.createMethod(methodName, args, hasReturn, node.value.async);
const method = Documentation.Member.createMethod(methodName, args, hasReturn, node.value.async);
this._currentClassMembers.push(method);
return ESTreeWalker.SkipSubtree;
}
@@ -108,7 +108,7 @@ class JSOutline {
events = [];
this._eventsByClassName.set(className, events);
}
for (let property of node.right.properties) {
for (const property of node.right.properties) {
if (property.type !== 'Property' || property.key.type !== 'Identifier' || property.value.type !== 'Literal')
continue;
events.push(Documentation.Member.createEvent(property.value.value));
@@ -118,7 +118,7 @@ class JSOutline {
_flushClassIfNeeded() {
if (this._currentClassName === null)
return;
let jsClass = new Documentation.Class(this._currentClassName, this._currentClassMembers);
const jsClass = new Documentation.Class(this._currentClassName, this._currentClassMembers);
this.classes.push(jsClass);
this._currentClassName = null;
this._currentClassMembers = [];
@@ -126,8 +126,8 @@ class JSOutline {
_recreateClassesWithEvents() {
this.classes = this.classes.map(cls => {
let events = this._eventsByClassName.get(cls.name) || [];
let members = cls.membersArray.concat(events);
const events = this._eventsByClassName.get(cls.name) || [];
const members = cls.membersArray.concat(events);
return new Documentation.Class(cls.name, members);
});
}
@@ -135,7 +135,7 @@ class JSOutline {
_extractText(node) {
if (!node)
return null;
let text = this._text.substring(node.range[0], node.range[1]).trim();
const text = this._text.substring(node.range[0], node.range[1]).trim();
return text;
}
}
@@ -145,10 +145,10 @@ class JSOutline {
* @return {!Promise<{documentation: !Documentation, errors: !Array<string>}>}
*/
module.exports = async function(sources) {
let classes = [];
let errors = [];
for (let source of sources) {
let outline = new JSOutline(source.text());
const classes = [];
const errors = [];
for (const source of sources) {
const outline = new JSOutline(source.text());
classes.push(...outline.classes);
errors.push(...outline.errors);
}

View File

@@ -33,11 +33,11 @@ class MDOutline {
// Extract headings.
await page.setContent(html);
const {classes, errors} = await page.evaluate(() => {
let classes = [];
const classes = [];
let currentClass = {};
let member = {};
let errors = [];
for (let element of document.body.querySelectorAll('h3, h4, h4 + ul > li')) {
const errors = [];
for (const element of document.body.querySelectorAll('h3, h4, h4 + ul > li')) {
if (element.matches('h3')) {
currentClass = {
name: element.textContent,
@@ -82,22 +82,22 @@ class MDOutline {
let currentClassName = null;
let currentClassMembers = [];
for (const cls of classes) {
let match = cls.name.match(classHeading);
const match = cls.name.match(classHeading);
if (!match)
continue;
currentClassName = match[1];
for (let member of cls.members) {
for (const member of cls.members) {
if (constructorRegex.test(member.name)) {
let match = member.name.match(constructorRegex);
const match = member.name.match(constructorRegex);
handleMethod.call(this, member, match[1], 'constructor', match[2]);
} else if (methodRegex.test(member.name)) {
let match = member.name.match(methodRegex);
const match = member.name.match(methodRegex);
handleMethod.call(this, member, match[1], match[2], match[3]);
} else if (propertyRegex.test(member.name)) {
let match = member.name.match(propertyRegex);
const match = member.name.match(propertyRegex);
handleProperty.call(this, member, match[1], match[2]);
} else if (eventRegex.test(member.name)) {
let match = member.name.match(eventRegex);
const match = member.name.match(eventRegex);
handleEvent.call(this, member, match[1]);
}
}
@@ -112,8 +112,8 @@ class MDOutline {
parameters = parameters.trim().replace(/[\[\]]/g, '');
if (parameters !== member.args.join(', '))
this.errors.push(`Heading arguments for "${member.name}" do not match described ones, i.e. "${parameters}" != "${member.args.join(', ')}"`);
let args = member.args.map(arg => new Documentation.Argument(arg));
let method = Documentation.Member.createMethod(methodName, args, member.hasReturn, false);
const args = member.args.map(arg => new Documentation.Argument(arg));
const method = Documentation.Member.createMethod(methodName, args, member.hasReturn, false);
currentClassMembers.push(method);
}
@@ -149,10 +149,10 @@ class MDOutline {
* @return {!Promise<{documentation: !Documentation, errors: !Array<string>}>}
*/
module.exports = async function(page, sources) {
let classes = [];
let errors = [];
for (let source of sources) {
let outline = await MDOutline.create(page, source.text());
const classes = [];
const errors = [];
for (const source of sources) {
const outline = await MDOutline.create(page, source.text());
classes.push(...outline.classes);
errors.push(...outline.errors);
}

View File

@@ -58,21 +58,21 @@ const EXCLUDE_METHODS = new Set([
* @return {!Promise<!Array<!Message>>}
*/
module.exports = async function lint(page, mdSources, jsSources) {
let mdResult = await mdBuilder(page, mdSources);
let jsResult = await jsBuilder(jsSources);
let jsDocumentation = filterJSDocumentation(jsResult.documentation);
let mdDocumentation = mdResult.documentation;
const mdResult = await mdBuilder(page, mdSources);
const jsResult = await jsBuilder(jsSources);
const jsDocumentation = filterJSDocumentation(jsResult.documentation);
const mdDocumentation = mdResult.documentation;
let jsErrors = jsResult.errors;
const jsErrors = jsResult.errors;
jsErrors.push(...checkDuplicates(jsDocumentation));
let mdErrors = mdResult.errors;
const mdErrors = mdResult.errors;
mdErrors.push(...compareDocumentations(mdDocumentation, jsDocumentation));
mdErrors.push(...checkDuplicates(mdDocumentation));
mdErrors.push(...checkSorting(mdDocumentation));
// Push all errors with proper prefixes
let errors = jsErrors.map(error => '[JavaScript] ' + error);
const errors = jsErrors.map(error => '[JavaScript] ' + error);
errors.push(...mdErrors.map(error => '[MarkDown] ' + error));
return errors.map(error => Message.error(error));
};
@@ -83,8 +83,8 @@ module.exports = async function lint(page, mdSources, jsSources) {
*/
function checkSorting(doc) {
const errors = [];
for (let cls of doc.classesArray) {
let members = cls.membersArray;
for (const cls of doc.classesArray) {
const members = cls.membersArray;
// Events should go first.
let eventIndex = 0;
@@ -94,14 +94,14 @@ function checkSorting(doc) {
errors.push(`Events should go first. Event '${members[eventIndex].name}' in class ${cls.name} breaks order`);
// Constructor should be right after events and before all other members.
let constructorIndex = members.findIndex(member => member.type === 'method' && member.name === 'constructor');
const constructorIndex = members.findIndex(member => member.type === 'method' && member.name === 'constructor');
if (constructorIndex > 0 && members[constructorIndex - 1].type !== 'event')
errors.push(`Constructor of ${cls.name} should go before other methods`);
// Events should be sorted alphabetically.
for (let i = 0; i < members.length - 1; ++i) {
let member1 = cls.membersArray[i];
let member2 = cls.membersArray[i + 1];
const member1 = cls.membersArray[i];
const member2 = cls.membersArray[i + 1];
if (member1.type !== 'event' || member2.type !== 'event')
continue;
if (member1.name > member2.name)
@@ -110,8 +110,8 @@ function checkSorting(doc) {
// All other members should be sorted alphabetically.
for (let i = 0; i < members.length - 1; ++i) {
let member1 = cls.membersArray[i];
let member2 = cls.membersArray[i + 1];
const member1 = cls.membersArray[i];
const member2 = cls.membersArray[i + 1];
if (member1.type === 'event' || member2.type === 'event')
continue;
if (member1.type === 'method' && member1.name === 'constructor')
@@ -136,11 +136,11 @@ function checkSorting(doc) {
*/
function filterJSDocumentation(jsDocumentation) {
// Filter classes and methods.
let classes = [];
for (let cls of jsDocumentation.classesArray) {
const classes = [];
for (const cls of jsDocumentation.classesArray) {
if (EXCLUDE_CLASSES.has(cls.name))
continue;
let members = cls.membersArray.filter(member => {
const members = cls.membersArray.filter(member => {
if (member.name.startsWith('_'))
return false;
return !EXCLUDE_METHODS.has(`${cls.name}.${member.name}`);
@@ -156,19 +156,19 @@ function filterJSDocumentation(jsDocumentation) {
*/
function checkDuplicates(doc) {
const errors = [];
let classes = new Set();
const classes = new Set();
// Report duplicates.
for (let cls of doc.classesArray) {
for (const cls of doc.classesArray) {
if (classes.has(cls.name))
errors.push(`Duplicate declaration of class ${cls.name}`);
classes.add(cls.name);
let members = new Set();
for (let member of cls.membersArray) {
const members = new Set();
for (const member of cls.membersArray) {
if (members.has(member.name))
errors.push(`Duplicate declaration of method ${cls.name}.${member.name}()`);
members.add(member.name);
let args = new Set();
for (let arg of member.argsArray) {
const args = new Set();
for (const arg of member.argsArray) {
if (args.has(arg.name))
errors.push(`Duplicate declaration of argument ${cls.name}.${member.name} "${arg.name}"`);
args.add(arg.name);
@@ -188,24 +188,24 @@ function compareDocumentations(actual, expected) {
const actualClasses = Array.from(actual.classes.keys()).sort();
const expectedClasses = Array.from(expected.classes.keys()).sort();
let classesDiff = diff(actualClasses, expectedClasses);
for (let className of classesDiff.extra)
const classesDiff = diff(actualClasses, expectedClasses);
for (const className of classesDiff.extra)
errors.push(`Non-existing class found: ${className}`);
for (let className of classesDiff.missing)
for (const className of classesDiff.missing)
errors.push(`Class not found: ${className}`);
for (let className of classesDiff.equal) {
for (const className of classesDiff.equal) {
const actualClass = actual.classes.get(className);
const expectedClass = expected.classes.get(className);
const actualMethods = Array.from(actualClass.methods.keys()).sort();
const expectedMethods = Array.from(expectedClass.methods.keys()).sort();
const methodDiff = diff(actualMethods, expectedMethods);
for (let methodName of methodDiff.extra)
for (const methodName of methodDiff.extra)
errors.push(`Non-existing method found: ${className}.${methodName}()`);
for (let methodName of methodDiff.missing)
for (const methodName of methodDiff.missing)
errors.push(`Method not found: ${className}.${methodName}()`);
for (let methodName of methodDiff.equal) {
for (const methodName of methodDiff.equal) {
const actualMethod = actualClass.methods.get(methodName);
const expectedMethod = expectedClass.methods.get(methodName);
if (actualMethod.hasReturn !== expectedMethod.hasReturn) {
@@ -220,10 +220,10 @@ function compareDocumentations(actual, expected) {
const expectedArgs = Array.from(expectedMethod.args.keys());
const argDiff = diff(actualArgs, expectedArgs);
if (argDiff.extra.length || argDiff.missing.length) {
let text = [`Method ${className}.${methodName}() fails to describe its parameters:`];
for (let arg of argDiff.missing)
const text = [`Method ${className}.${methodName}() fails to describe its parameters:`];
for (const arg of argDiff.missing)
text.push(`- Argument not found: ${arg}`);
for (let arg of argDiff.extra)
for (const arg of argDiff.extra)
text.push(`- Non-existing argument found: ${arg}`);
errors.push(text.join('\n'));
}
@@ -231,17 +231,17 @@ function compareDocumentations(actual, expected) {
const actualProperties = Array.from(actualClass.properties.keys()).sort();
const expectedProperties = Array.from(expectedClass.properties.keys()).sort();
const propertyDiff = diff(actualProperties, expectedProperties);
for (let propertyName of propertyDiff.extra)
for (const propertyName of propertyDiff.extra)
errors.push(`Non-existing property found: ${className}.${propertyName}`);
for (let propertyName of propertyDiff.missing)
for (const propertyName of propertyDiff.missing)
errors.push(`Property not found: ${className}.${propertyName}`);
const actualEvents = Array.from(actualClass.events.keys()).sort();
const expectedEvents = Array.from(expectedClass.events.keys()).sort();
const eventsDiff = diff(actualEvents, expectedEvents);
for (let eventName of eventsDiff.extra)
for (const eventName of eventsDiff.extra)
errors.push(`Non-existing event found in class ${className}: '${eventName}'`);
for (let eventName of eventsDiff.missing)
for (const eventName of eventsDiff.missing)
errors.push(`Event not found in class ${className}: '${eventName}'`);
}
return errors;
@@ -261,8 +261,8 @@ function diff(actual, expected) {
return {extra: [], missing: expected.slice(), equal: []};
if (M === 0)
return {extra: actual.slice(), missing: [], equal: []};
let d = new Array(N);
let bt = new Array(N);
const d = new Array(N);
const bt = new Array(N);
for (let i = 0; i < N; ++i) {
d[i] = new Array(M);
bt[i] = new Array(M);
@@ -276,7 +276,7 @@ function diff(actual, expected) {
d[i][j] = left;
bt[i][j] = 'missing';
}
let diag = val(i - 1, j - 1);
const diag = val(i - 1, j - 1);
if (actual[i] === expected[j] && d[i][j] < diag + 1) {
d[i][j] = diag + 1;
bt[i][j] = 'eq';
@@ -286,9 +286,9 @@ function diff(actual, expected) {
// Backtrack results.
let i = N - 1;
let j = M - 1;
let missing = [];
let extra = [];
let equal = [];
const missing = [];
const extra = [];
const equal = [];
while (i >= 0 && j >= 0) {
switch (bt[i][j]) {
case 'extra':

View File

@@ -19,9 +19,9 @@ const Message = require('../Message');
const PUPPETEER_VERSION = require('../../../package.json').version;
module.exports = function(sources) {
let messages = [];
const messages = [];
let commands = [];
for (let source of sources) {
for (const source of sources) {
const text = source.text();
const commandStartRegex = /<!--\s*gen:([a-z]+)(?:\s*\(\s*([^)]*)\s*\))?\s*-->/ig;
const commandEndRegex = /<!--\s*gen:stop\s*-->/ig;
@@ -45,10 +45,10 @@ module.exports = function(sources) {
commands = validateCommands(commands, messages);
let changedSources = new Set();
const changedSources = new Set();
// Iterate commands in reverse order so that edits don't conflict.
commands.sort((a, b) => b.from - a.from);
for (let command of commands) {
for (const command of commands) {
let newText = command.source.text();
if (command.name === 'version')
newText = replaceInText(newText, command.from, command.to, PUPPETEER_VERSION);
@@ -67,7 +67,7 @@ module.exports = function(sources) {
*/
function validateCommands(commands, outMessages) {
// Filter sane commands
let goodCommands = commands.filter(command => {
const goodCommands = commands.filter(command => {
if (command.name === 'version')
return check(command, !command.arg, `"gen:version" should not have argument`);
check(command, false, `Unknown command: "gen:${command.name}"`);

View File

@@ -21,8 +21,8 @@ const VERSION = require('../../../package.json').version;
describe('preprocessor', function() {
it('should throw for unknown command', function() {
let source = factory.createForTest('doc.md', getCommand('unknownCommand()'));
let messages = preprocessor([source]);
const source = factory.createForTest('doc.md', getCommand('unknownCommand()'));
const messages = preprocessor([source]);
expect(source.hasUpdatedText()).toBe(false);
expect(messages.length).toBe(1);
expect(messages[0].type).toBe('error');
@@ -30,22 +30,22 @@ describe('preprocessor', function() {
});
describe('gen:version', function() {
it('should work', function() {
let source = factory.createForTest('doc.md', `Puppeteer v${getCommand('version')}`);
let messages = preprocessor([source]);
const source = factory.createForTest('doc.md', `Puppeteer v${getCommand('version')}`);
const messages = preprocessor([source]);
expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md');
expect(source.text()).toBe(`Puppeteer v${getCommand('version', VERSION)}`);
});
it('should tolerate different writing', function() {
let source = factory.createForTest('doc.md', `Puppeteer v<!-- gEn:version ( ) -->WHAT
const source = factory.createForTest('doc.md', `Puppeteer v<!-- gEn:version ( ) -->WHAT
<!-- GEN:stop -->`);
preprocessor([source]);
expect(source.text()).toBe(`Puppeteer v<!-- gEn:version ( ) -->${VERSION}<!-- GEN:stop -->`);
});
it('should not tolerate missing gen:stop', function() {
let source = factory.createForTest('doc.md', `<!--GEN:version-->`);
let messages = preprocessor([source]);
const source = factory.createForTest('doc.md', `<!--GEN:version-->`);
const messages = preprocessor([source]);
expect(source.hasUpdatedText()).toBe(false);
expect(messages.length).toBe(1);
expect(messages[0].type).toBe('error');

View File

@@ -23,7 +23,7 @@ const Message = require('./Message');
*/
module.exports = function(sources) {
const warnings = [];
for (let source of sources) {
for (const source of sources) {
const newText = markdownToc.insert(source.text());
if (source.setText(newText))
warnings.push('Regenerated table-of-contexts: ' + source.projectPath());