<commit_before>import chalk from "chalk"
import * as fs from "fs"
import * as json5 from "json5"
import * as klawSync from "klaw-sync"
import { flatten } from "lodash"
import { basename, relative } from "path"
import * as ts from "typescript"

function main() {
  if (process.argv.includes("--help") || process.argv.includes("-h")) {
    console.log(`
🔎  ${chalk.bold("find-unused-fields")} 🔍

USAGE

  ${chalk.cyan.bold("  yarn find-unused-fields")} ${chalk.cyan(
      "[fragment name]"
    )}

Add known exceptions in find-unused-fields.ts
`)
    return
  }
  const languageService = getLanguageService()
  const sources = getSources(languageService)
  findUnusedFields(sources, languageService)
}

interface Ignored {
  fields: string[]
}
/**
 * Temporary way to ignore false positives due to indirect referencing
 */
const ignoredFragments: Record<string, Ignored> = {
  ArtworkActions_artwork: {
    fields: ["dimensions", "image"],
  },
  ArtworkDetailsAboutTheWorkFromPartner_artwork: {
    fields: ["partner/locations/city", "partner/profile/id"],
  },
  ArtworkFilter_artist: {
    fields: [
      "name",
      "filtered_artworks/aggregations/counts/name",
      "filtered_artworks/aggregations/counts/id",
    ],
  },
  ArtworkImageBrowser_artwork: {
    fields: [
      "images/placeholder",
      "images/placeholder",
      "images/deepZoom/Image",
      "images/aspectRatio",
    ],
  },
}

function getLanguageService(): ts.LanguageService {
  const { options, ...others } = ts.convertCompilerOptionsFromJson(
    json5.parse(fs.readFileSync("./tsconfig.json").toString()).compilerOptions,
    "."
  )

  if (others.errors && others.errors.length > 0) {
    throw new Error(JSON.stringify(others.errors))
  }

  const sourceFiles = klawSync("./src", {
    traverseAll: true,
    filter(item) {
      return item.path.endsWith(".ts") || item.path.endsWith(".tsx")
    },
  }).map(item => item.path)

  // Create the language service files
  return ts.createLanguageService(
    {
      getScriptFileNames: () => sourceFiles,
      getScriptVersion: _ => "0",
      getScriptSnapshot: fileName => {
        if (!fs.existsSync(fileName)) {
          return undefined
        }

        return ts.ScriptSnapshot.fromString(
          fs.readFileSync(fileName).toString()
        )
      },
      getCurrentDirectory: () => process.cwd(),
      getCompilationSettings: () => options,
      getDefaultLibFileName: opts => ts.getDefaultLibFilePath(opts),
      fileExists: ts.sys.fileExists,
      readFile: ts.sys.readFile,
      readDirectory: ts.sys.readDirectory,
    },
    ts.createDocumentRegistry()
  )
}

const compare = (a, b) => (a < b ? -1 : a > b ? 1 : 0)

function getSources(languageService: ts.LanguageService): ts.SourceFile[] {
  let arg = process.argv[2]
  if (arg) {
    if (!fs.existsSync(arg)) {
      if (fs.existsSync(`src/__generated__/${arg}.graphql.ts`)) {
        arg = `src/__generated__/${arg}.graphql.ts`
      } else {
        console.error(chalk.red.bold("Bad argument"), chalk.bold("arg"))
        console.error(
          "Try a relay fragment name or the path of a generated relay typings file."
        )
        process.exit(1)
      }
    }
    return [
      languageService
        .getProgram()
        .getSourceFile(
          "src/__generated__/ArtworkImageBrowser_artwork.graphql.ts"
        ),
    ]
  } else {
    // get all files
    return languageService
      .getProgram()
      .getSourceFiles()
      .filter(
        f =>
          f.fileName.match("__generated__") &&
          !f.fileName.endsWith("Query.graphql.ts")
      )
      .sort((a, b) => compare(basename(a.fileName), basename(b.fileName)))
  }
}

class CheckContext {
  errors: string[] = []

  constructor(<commit_msg>fix args<commit_after>import chalk from "chalk"
import * as fs from "fs"
import * as json5 from "json5"
import * as klawSync from "klaw-sync"
import { flatten } from "lodash"
import { basename, relative } from "path"
import * as ts from "typescript"

function main() {
  if (process.argv.includes("--help") || process.argv.includes("-h")) {
    console.log(`
🔎  ${chalk.bold("find-unused-fields")} 🔍

USAGE

  ${chalk.cyan.bold("  yarn find-unused-fields")} ${chalk.cyan(
      "[fragment name]"
    )}

Add known exceptions in find-unused-fields.ts
`)
    return
  }
  const languageService = getLanguageService()
  const sources = getSources(languageService)
  findUnusedFields(sources, languageService)
}

interface Ignored {
  fields: string[]
}
/**
 * Temporary way to ignore false positives due to indirect referencing
 */
const ignoredFragments: Record<string, Ignored> = {
  ArtworkActions_artwork: {
    fields: ["dimensions", "image"],
  },
  ArtworkDetailsAboutTheWorkFromPartner_artwork: {
    fields: ["partner/locations/city", "partner/profile/id"],
  },
  ArtworkFilter_artist: {
    fields: [
      "name",
      "filtered_artworks/aggregations/counts/name",
      "filtered_artworks/aggregations/counts/id",
    ],
  },
  ArtworkImageBrowser_artwork: {
    fields: [
      "images/placeholder",
      "images/placeholder",
      "images/deepZoom/Image",
      "images/aspectRatio",
    ],
  },
}

function getLanguageService(): ts.LanguageService {
  const { options, ...others } = ts.convertCompilerOptionsFromJson(
    json5.parse(fs.readFileSync("./tsconfig.json").toString()).compilerOptions,
    "."
  )

  if (others.errors && others.errors.length > 0) {
    throw new Error(JSON.stringify(others.errors))
  }

  const sourceFiles = klawSync("./src", {
    traverseAll: true,
    filter(item) {
      return item.path.endsWith(".ts") || item.path.endsWith(".tsx")
    },
  }).map(item => item.path)

  // Create the language service files
  return ts.createLanguageService(
    {
      getScriptFileNames: () => sourceFiles,
      getScriptVersion: _ => "0",
      getScriptSnapshot: fileName => {
        if (!fs.existsSync(fileName)) {
          return undefined
        }

        return ts.ScriptSnapshot.fromString(
          fs.readFileSync(fileName).toString()
        )
      },
      getCurrentDirectory: () => process.cwd(),
      getCompilationSettings: () => options,
      getDefaultLibFileName: opts => ts.getDefaultLibFilePath(opts),
      fileExists: ts.sys.fileExists,
      readFile: ts.sys.readFile,
      readDirectory: ts.sys.readDirectory,
    },
    ts.createDocumentRegistry()
  )
}

const compare = (a, b) => (a < b ? -1 : a > b ? 1 : 0)

function getSources(languageService: ts.LanguageService): ts.SourceFile[] {
  let arg = process.argv[2]
  if (arg) {
    if (fs.existsSync(`src/__generated__/${arg}.graphql.ts`)) {
      arg = `src/__generated__/${arg}.graphql.ts`
    } else {
      console.error(chalk.red.bold("Bad argument"), chalk.bold("arg"))
      console.error("Try a relay fragment name like ArtworkActions_artwork.")
      process.exit(1)
    }
  } else {
    // get all files
    return languageService
      .getProgram()
      .getSourceFiles()
      .filter(
        f =>
          f.fileName.match("__generated__") &&
          !f.fileName.endsWith("Query.graphql.ts")
      )
      .sort((a, b) => compare(basename(a.fileName), basename(b.fileName)))
  }
}

class CheckContext {
  errors: string[] = []

  constructor(
{'fraction_non_alphanumeric': 0.14443676572218384, 'fraction_numerical': 0.0027643400138217, 'mean_word_length': 2.975824175824176, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, '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': '6620012', 'n_tokens_mistral': 2319, 'n_tokens_neox': 2295, 'n_words': 449}