diff options
| -rw-r--r-- | test/lint/global-declarations.js | 105 | ||||
| -rw-r--r-- | test/yomichan-test.js | 21 | 
2 files changed, 126 insertions, 0 deletions
| diff --git a/test/lint/global-declarations.js b/test/lint/global-declarations.js new file mode 100644 index 00000000..2629cc5e --- /dev/null +++ b/test/lint/global-declarations.js @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2020  Alex Yatskov <alex@foosoft.net> + * Author: Alex Yatskov <alex@foosoft.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ + +const fs = require('fs'); +const path = require('path'); +const assert = require('assert'); +const {getAllFiles} = require('../yomichan-test'); + + +function countOccurences(string, pattern) { +    return (string.match(pattern) || []).length; +} + +function getNewline(string) { +    const count1 = countOccurences(string, /(?:^|[^\r])\n/g); +    const count2 = countOccurences(string, /\r\n/g); +    const count3 = countOccurences(string, /\r(?:[^\n]|$)/g); +    if (count2 > count1) { +        return (count3 > count2) ? '\r' : '\r\n'; +    } else { +        return (count3 > count1) ? '\r' : '\n'; +    } +} + + +function validateGlobals(fileName, fix) { +    const pattern = /\/\*\s*global\s+([\w\W]*?)\*\//g; +    const trimPattern = /^[\s,*]+|[\s,*]+$/g; +    const splitPattern = /[\s,*]+/; +    const source = fs.readFileSync(fileName, {encoding: 'utf8'}); +    let match; +    let first = true; +    let endIndex = 0; +    let newSource = ''; +    const newline = getNewline(source); +    while ((match = pattern.exec(source)) !== null) { +        if (!first) { +            console.error(`Encountered more than one global declaration in ${fileName}`); +            return false; +        } +        first = false; + +        const parts = match[1].replace(trimPattern, '').split(splitPattern); +        parts.sort(); + +        const actual = match[0]; +        const expected = `/* global${parts.map((v) => `${newline} * ${v}`).join('')}${newline} */`; + +        try { +            assert.strictEqual(actual, expected); +        } catch (e) { +            console.error(`Global declaration error encountered in ${fileName}:`); +            console.error(e.message); +            if (!fix) { +                return false; +            } +        } + +        newSource += source.substring(0, match.index); +        newSource += expected; +        endIndex = match.index + match[0].length; +    } + +    newSource += source.substring(endIndex); + +    if (fix) { +        fs.writeFileSync(fileName, newSource, {encoding: 'utf8'}); +    } + +    return true; +} + + +function main() { +    const fix = (process.argv.length >= 2 && process.argv[2] === '--fix'); +    const directory = path.resolve(__dirname, '..', '..', 'ext'); +    const pattern = /\.js$/; +    const ignorePattern = /[\\/]ext[\\/]mixed[\\/]lib[\\/]/; +    const fileNames = getAllFiles(directory, (f) => pattern.test(f) && !ignorePattern.test(f)); +    for (const fileName of fileNames) { +        if (!validateGlobals(fileName, fix)) { +            process.exit(-1); +            return; +        } +    } +    process.exit(0); +} + + +if (require.main === module) { main(); } diff --git a/test/yomichan-test.js b/test/yomichan-test.js index 0fc97b4b..5fa7730b 100644 --- a/test/yomichan-test.js +++ b/test/yomichan-test.js @@ -50,8 +50,29 @@ function createTestDictionaryArchive(dictionary, dictionaryName) {      return archive;  } +function getAllFiles(baseDirectory, predicate=null) { +    const results = []; +    const directories = [path.resolve(baseDirectory)]; +    while (directories.length > 0) { +        const directory = directories.shift(); +        for (const fileName of fs.readdirSync(directory)) { +            const fullFileName = path.resolve(directory, fileName); +            const stats = fs.statSync(fullFileName); +            if (stats.isFile()) { +                if (typeof predicate !== 'function' || predicate(fullFileName, directory, baseDirectory)) { +                    results.push(fullFileName); +                } +            } else if (stats.isDirectory()) { +                directories.push(fullFileName); +            } +        } +    } +    return results; +} +  module.exports = {      createTestDictionaryArchive, +    getAllFiles,      get JSZip() { return getJSZip(); }  }; |