Skip to content

Commit

Permalink
added local rule for banning forEach(), replace forEach() with for() …
Browse files Browse the repository at this point in the history
…loops in code
  • Loading branch information
Connum authored and yne committed Mar 9, 2023
1 parent 5c23f7d commit cb0f296
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 64 deletions.
23 changes: 23 additions & 0 deletions eslint-local-rules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

module.exports = {
'ban-foreach': {
meta: {
type: 'suggestion',
docs: {
description: 'Use `for()` loops instead of `.forEach()`',
category: 'Performance',
},
schema: [],
},
create(context) {
return {
CallExpression(node) {
if (node.callee.property && node.callee.property.name === 'forEach') {
context.report({node, message: 'Use for() loops instead of .forEach()'})
}
},
}
},
},
};
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"es2021": true,
"node": true
},
"plugins": ["eslint-plugin-local-rules"],
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2018,
Expand All @@ -78,7 +79,11 @@
"semi": [
"error",
"always"
]
],
"local-rules/ban-foreach": 2
}
},
"dependencies": {
"eslint-plugin-local-rules": "^1.3.2"
}
}
25 changes: 15 additions & 10 deletions src/bidi.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,15 @@ function tokenizeText() {
*/
function reverseArabicSentences() {
const ranges = this.tokenizer.getContextRanges('arabicSentence');
ranges.forEach(range => {
for(let i = 0; i < ranges.length; i++) {
const range = ranges[i];
let rangeTokens = this.tokenizer.getRangeTokens(range);
this.tokenizer.replaceRange(
range.startIndex,
range.endOffset,
rangeTokens.reverse()
);
});
}
}

/**
Expand Down Expand Up @@ -153,9 +154,10 @@ function applyArabicPresentationForms() {
if (!Object.prototype.hasOwnProperty.call(this.featuresTags, script)) return;
checkGlyphIndexStatus.call(this);
const ranges = this.tokenizer.getContextRanges('arabicWord');
ranges.forEach(range => {
for(let i = 0; i < ranges.length; i++) {
const range = ranges[i];
arabicPresentationForms.call(this, range);
});
}
}

/**
Expand All @@ -165,9 +167,10 @@ function applyArabicRequireLigatures() {
if (!this.hasFeatureEnabled('arab', 'rlig')) return;
checkGlyphIndexStatus.call(this);
const ranges = this.tokenizer.getContextRanges('arabicWord');
ranges.forEach(range => {
for(let i = 0; i < ranges.length; i++) {
const range = ranges[i];
arabicRequiredLigatures.call(this, range);
});
}
}

/**
Expand All @@ -177,16 +180,18 @@ function applyLatinLigatures() {
if (!this.hasFeatureEnabled('latn', 'liga')) return;
checkGlyphIndexStatus.call(this);
const ranges = this.tokenizer.getContextRanges('latinWord');
ranges.forEach(range => {
for(let i = 0; i < ranges.length; i++) {
const range = ranges[i];
latinLigature.call(this, range);
});
}
}

function applyUnicodeVariationSequences() {
const ranges = this.tokenizer.getContextRanges('unicodeVariationSequence');
ranges.forEach(range => {
for(let i = 0; i < ranges.length; i++) {
const range = ranges[i];
unicodeVariationSequences.call(this, range);
});
}
}

/**
Expand Down
7 changes: 4 additions & 3 deletions src/features/applySubstitution.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ function singleSubstitutionFormat2(action, tokens, index) {
* @param {number} index token index
*/
function chainingSubstitutionFormat3(action, tokens, index) {
action.substitution.forEach((subst, offset) => {
const token = tokens[index + offset];
for(let i = 0; i < action.substitution.length; i++) {
const subst = action.substitution[i];
const token = tokens[index + i];
token.setState(action.tag, subst);
});
}
}

/**
Expand Down
27 changes: 16 additions & 11 deletions src/features/arab/arabicPresentationForms.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ function arabicPresentationForms(range) {
const charContextParams = new ContextParams(
tokens.map(token => token.char
), 0);
tokens.forEach((token, index) => {
if (isTashkeelArabicChar(token.char)) return;
contextParams.setCurrentIndex(index);
charContextParams.setCurrentIndex(index);
for(let i = 0; i < tokens.length; i++) {
const token = tokens[i];
if (isTashkeelArabicChar(token.char)) continue;
contextParams.setCurrentIndex(i);
charContextParams.setCurrentIndex(i);
let CONNECT = 0; // 2 bits 00 (10: can connect next) (01: can connect prev)
if (willConnectPrev(charContextParams)) CONNECT |= 1;
if (willConnectNext(charContextParams)) CONNECT |= 2;
Expand All @@ -65,18 +66,22 @@ function arabicPresentationForms(range) {
case 2: (tag = 'init'); break;
case 3: (tag = 'medi'); break;
}
if (tags.indexOf(tag) === -1) return;
if (tags.indexOf(tag) === -1) continue;
let substitutions = this.query.lookupFeature({
tag, script, contextParams
});
if (substitutions instanceof Error) return console.info(substitutions.message);
substitutions.forEach((action, index) => {
if (substitutions instanceof Error) {
console.info(substitutions.message);
continue;
}
for(let j = 0; j < substitutions.length; j++) {
const action = substitutions[j];
if (action instanceof SubstitutionAction) {
applySubstitution(action, tokens, index);
contextParams.context[index] = action.substitution;
applySubstitution(action, tokens, j);
contextParams.context[j] = action.substitution;
}
});
});
}
}
}

export default arabicPresentationForms;
Expand Down
11 changes: 6 additions & 5 deletions src/features/arab/arabicRequiredLigatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@ function arabicRequiredLigatures(range) {
const script = 'arab';
let tokens = this.tokenizer.getRangeTokens(range);
let contextParams = getContextParams(tokens);
contextParams.context.forEach((glyphIndex, index) => {
for (let index = 0; index < contextParams.context.length; index++) {
contextParams.setCurrentIndex(index);
let substitutions = this.query.lookupFeature({
tag: 'rlig', script, contextParams
});
if (substitutions.length) {
substitutions.forEach(
action => applySubstitution(action, tokens, index)
);
for(let i = 0; i < substitutions.length; i++) {
const action = substitutions[i];
applySubstitution(action, tokens, index);
}
contextParams = getContextParams(tokens);
}
});
}
}

export default arabicRequiredLigatures;
Expand Down
11 changes: 6 additions & 5 deletions src/features/latn/latinLigatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@ function latinLigature(range) {
const script = 'latn';
let tokens = this.tokenizer.getRangeTokens(range);
let contextParams = getContextParams(tokens);
contextParams.context.forEach((glyphIndex, index) => {
for(let index = 0; index < contextParams.context.length; index++) {
contextParams.setCurrentIndex(index);
let substitutions = this.query.lookupFeature({
tag: 'liga', script, contextParams
});
if (substitutions.length) {
substitutions.forEach(
action => applySubstitution(action, tokens, index)
);
for(let i = 0; i < substitutions.length; i++) {
const action = substitutions[i];
applySubstitution(action, tokens, index);
}
contextParams = getContextParams(tokens);
}
});
}
}

export default latinLigature;
48 changes: 29 additions & 19 deletions src/tables/gsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,11 +282,12 @@ subtableMakers[5] = function makeLookup5(subtable) {
// ("glyphCount" in the spec) comes before seqLookupCount
[tableData[0], tableData[1]] = [tableData[1], tableData[0]];

sequenceRule.lookupRecords.forEach((record, i) => {
for(let i = 0; i < sequenceRule.lookupRecords.length; i++) {
const record = sequenceRule.lookupRecords[i];
tableData = tableData
.concat({name: 'sequenceIndex' + i, type: 'USHORT', value: record.sequenceIndex})
.concat({name: 'lookupListIndex' + i, type: 'USHORT', value: record.lookupListIndex});
});
}
return new table.Table('sequenceRuleTable', tableData);
}));
})));
Expand All @@ -302,12 +303,12 @@ subtableMakers[5] = function makeLookup5(subtable) {
return new table.Table('classSeqRuleSetTable', table.tableList('classSeqRule', classSeqRuleSet, function(classSeqRule) {
let tableData = table.ushortList('classes', classSeqRule.classes, classSeqRule.classes.length + 1)
.concat(table.ushortList('seqLookupCount', [], classSeqRule.lookupRecords.length));

classSeqRule.lookupRecords.forEach((record, i) => {
for(let i = 0; i < classSeqRule.lookupRecords.length; i++) {
const record = classSeqRule.lookupRecords[i];
tableData = tableData
.concat({name: 'sequenceIndex' + i, type: 'USHORT', value: record.sequenceIndex})
.concat({name: 'lookupListIndex' + i, type: 'USHORT', value: record.lookupListIndex});
});
}
return new table.Table('classSeqRuleTable', tableData);
}));
})));
Expand All @@ -318,15 +319,17 @@ subtableMakers[5] = function makeLookup5(subtable) {

tableData.push({name: 'inputGlyphCount', type: 'USHORT', value: subtable.coverages.length});
tableData.push({name: 'substitutionCount', type: 'USHORT', value: subtable.lookupRecords.length});
subtable.coverages.forEach((coverage, i) => {
for(let i = 0; i < subtable.coverages.length; i++) {
const coverage = subtable.coverages[i];
tableData.push({name: 'inputCoverage' + i, type: 'TABLE', value: new table.Coverage(coverage)});
});
}

subtable.lookupRecords.forEach((record, i) => {
for(let i = 0; i < subtable.lookupRecords.length; i++) {
const record = subtable.lookupRecords[i];
tableData = tableData
.concat({name: 'sequenceIndex' + i, type: 'USHORT', value: record.sequenceIndex})
.concat({name: 'lookupListIndex' + i, type: 'USHORT', value: record.lookupListIndex});
});
}

let returnTable = new table.Table('contextualSubstitutionTable', tableData);

Expand All @@ -348,11 +351,12 @@ subtableMakers[6] = function makeLookup6(subtable) {
.concat(table.ushortList('lookaheadGlyph', chainRule.lookahead, chainRule.lookahead.length))
.concat(table.ushortList('substitution', [], chainRule.lookupRecords.length));

chainRule.lookupRecords.forEach((record, i) => {
for(let i = 0; i < chainRule.lookupRecords.length; i++) {
const record = chainRule.lookupRecords[i];
tableData = tableData
.concat({name: 'sequenceIndex' + i, type: 'USHORT', value: record.sequenceIndex})
.concat({name: 'lookupListIndex' + i, type: 'USHORT', value: record.lookupListIndex});
});
}
return new table.Table('chainRuleTable', tableData);
}));
})));
Expand All @@ -365,24 +369,30 @@ subtableMakers[6] = function makeLookup6(subtable) {
];

tableData.push({name: 'backtrackGlyphCount', type: 'USHORT', value: subtable.backtrackCoverage.length});
subtable.backtrackCoverage.forEach((coverage, i) => {
for(let i = 0; i < subtable.backtrackCoverage.length; i++) {
const coverage = subtable.backtrackCoverage[i];
tableData.push({name: 'backtrackCoverage' + i, type: 'TABLE', value: new table.Coverage(coverage)});
});
}
tableData.push({name: 'inputGlyphCount', type: 'USHORT', value: subtable.inputCoverage.length});
subtable.inputCoverage.forEach((coverage, i) => {

for(let i = 0; i < subtable.inputCoverage.length; i++) {
const coverage = subtable.inputCoverage[i];
tableData.push({name: 'inputCoverage' + i, type: 'TABLE', value: new table.Coverage(coverage)});
});
}
tableData.push({name: 'lookaheadGlyphCount', type: 'USHORT', value: subtable.lookaheadCoverage.length});
subtable.lookaheadCoverage.forEach((coverage, i) => {

for(let i = 0; i < subtable.lookaheadCoverage.length; i++) {
const coverage = subtable.lookaheadCoverage[i];
tableData.push({name: 'lookaheadCoverage' + i, type: 'TABLE', value: new table.Coverage(coverage)});
});
}

tableData.push({name: 'substitutionCount', type: 'USHORT', value: subtable.lookupRecords.length});
subtable.lookupRecords.forEach((record, i) => {
for(let i = 0; i < subtable.lookupRecords.length; i++) {
const record = subtable.lookupRecords[i];
tableData = tableData
.concat({name: 'sequenceIndex' + i, type: 'USHORT', value: record.sequenceIndex})
.concat({name: 'lookupListIndex' + i, type: 'USHORT', value: record.lookupListIndex});
});
}

let returnTable = new table.Table('chainContextTable', tableData);

Expand Down
Loading

0 comments on commit cb0f296

Please sign in to comment.