<commit_before>// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';

// Description: Scans for localizability violations in the DevTools front-end.
// Checks all .grdp files and reports messages without descriptions and placeholder examples.
// Audits all Common.UIString(), UI.formatLocalized(), and ls`` calls and
// checks for misuses of concatenation and conditionals. It also looks for
// specific arguments to functions that are expected to be a localized string.
// Since the check scans for common error patterns, it might misidentify something.
// In this case, add it to the excluded errors at the top of the script.

const path = require('path');
const localizationUtils = require('./localization_utils/localization_utils');
const esprimaTypes = localizationUtils.esprimaTypes;
const escodegen = localizationUtils.escodegen;
const esprima = localizationUtils.esprima;

// Exclude known errors
const excludeErrors = [
  'Common.UIString(view.title())', 'Common.UIString(setting.title() || \'\')', 'Common.UIString(option.text)',
  'Common.UIString(experiment.title)', 'Common.UIString(phase.message)',
  'Common.UIString(Help.latestReleaseNote().header)', 'Common.UIString(conditions.title)',
  'Common.UIString(extension.title())', 'Common.UIString(this._currentValueLabel, value)'
];

const usage = `Usage: node ${path.basename(process.argv[0])} [-a | <.js file path>*]

-a: If present, check all devtools frontend .js files
<.js file path>*: List of .js files with absolute paths separated by a space
`;

async function main() {
  if (process.argv.length < 3 || process.argv[2] === '--help') {
    console.log(usage);
    process.exit(0);
  }

  const errors = [];

  try {
    let filePaths = [];
    const frontendPath = path.resolve(__dirname, '..', 'front_end');
    let filePathPromises = [localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.grdp'])];
    if (process.argv[2] === '-a')
      filePathPromises.push(localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.js']));
    else
      filePaths = process.argv.slice(2).filter(localizationUtils.shouldParseDirectory);
    await Promise.all(filePathPromises);

    filePaths.push(localizationUtils.SHARED_STRINGS_PATH);
    const auditFilePromises = filePaths.map(filePath => auditFileForLocalizability(filePath, errors));
    await Promise.all(auditFilePromises);
  } catch (err) {
    console.log(err);
    process.exit(1);
  }

  if (errors.length > 0) {
    console.log(`DevTools localization checker detected errors!\n${errors.join('\n')}`);
    process.exit(1);
  }
  console.log('DevTools localization checker passed');
}

main();

function includesConditionalExpression(listOfElements) {
  return listOfElements.filter(ele => ele !== undefined && ele.type === esprimaTypes.COND_EXPR).length > 0;
}

function addError(error, errors) {
  if (!errors.includes(error))
    errors.push(error);
}

function buildConcatenatedNodesList(node, nodes) {
  if (!node)
    return;<commit_msg>Excluding JSON files from check_localizability.js.<commit_after>// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';

// Description: Scans for localizability violations in the DevTools front-end.
// Checks all .grdp files and reports messages without descriptions and placeholder examples.
// Audits all Common.UIString(), UI.formatLocalized(), and ls`` calls and
// checks for misuses of concatenation and conditionals. It also looks for
// specific arguments to functions that are expected to be a localized string.
// Since the check scans for common error patterns, it might misidentify something.
// In this case, add it to the excluded errors at the top of the script.

const path = require('path');
const localizationUtils = require('./localization_utils/localization_utils');
const esprimaTypes = localizationUtils.esprimaTypes;
const escodegen = localizationUtils.escodegen;
const esprima = localizationUtils.esprima;

// Exclude known errors
const excludeErrors = [
  'Common.UIString(view.title())', 'Common.UIString(setting.title() || \'\')', 'Common.UIString(option.text)',
  'Common.UIString(experiment.title)', 'Common.UIString(phase.message)',
  'Common.UIString(Help.latestReleaseNote().header)', 'Common.UIString(conditions.title)',
  'Common.UIString(extension.title())', 'Common.UIString(this._currentValueLabel, value)'
];

const usage = `Usage: node ${path.basename(process.argv[0])} [-a | <.js file path>*]

-a: If present, check all devtools frontend .js files
<.js file path>*: List of .js files with absolute paths separated by a space
`;

async function main() {
  if (process.argv.length < 3 || process.argv[2] === '--help') {
    console.log(usage);
    process.exit(0);
  }

  const errors = [];

  try {
    let filePaths = [];
    const frontendPath = path.resolve(__dirname, '..', 'front_end');
    let filePathPromises = [localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.grdp'])];
    if (process.argv[2] === '-a') {
      filePathPromises.push(localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.js']));
    } else {
      // esprima has a bug parsing a valid JSON format, so exclude them.
      filePaths = process.argv.slice(2).filter( file => {
        return (path.extname(file) !== '.json') && localizationUtils.shouldParseDirectory(file);
      });
    }
    await Promise.all(filePathPromises);

    filePaths.push(localizationUtils.SHARED_STRINGS_PATH);
    const auditFilePromises = filePaths.map(filePath => auditFileForLocalizability(filePath, errors));
    await Promise.all(auditFilePromises);
  } catch (err) {
    console.log(err);
    process.exit(1);
  }

  if (errors.length > 0) {
    console.log(`DevTools localization checker detected errors!\n${errors.join('\n')}`);
    process.exit(1);
  }
  console.log('DevTools localization checker passed');
}

main();

function includesConditionalExpression(listOfElements) {
  return listOfElements.filter(ele => ele !== undefined && ele.type === esprimaTypes.COND_EXPR).length > 0;
}

function addError(error, errors) {
  if (!errors.includes(error))
    errors.push(error);
}

function buildConcatenatedNodesList(node, nodes) {
  if (!node)
    return;
{'fraction_non_alphanumeric': 0.13221340799502254, 'fraction_numerical': 0.0043552652045419195, 'mean_word_length': 4.547886108714409, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5372729', 'n_tokens_mistral': 1919, 'n_tokens_neox': 1877, 'n_words': 526}