UNPKG

derw

Version:

An Elm-inspired language that transpiles to TypeScript

197 lines (165 loc) 5.54 kB
import { allErrors, bothFlag, empty, help, longFlag, parse, parser, string, } from "@eeue56/baner"; import { withDefault } from "@eeue56/ts-core/build/main/lib/maybe"; import { Const, ContextModule, Export, Function, Import, ImportModule, TypeAlias, UnionType, } from "../types"; import { compileFiles } from "./compile"; const infoParser = parser([ longFlag( "file", "name of a particular file to get info about e.g src/Html.derw", string() ), bothFlag("h", "help", "This help text", empty()), ]); function showInfoHelp() { console.log(help(infoParser)); } function importModuleInfo(module: ImportModule): void { const aliasExtra = withDefault(module.name, module.alias); console.log(`Importing ${module.name} as ${aliasExtra}`); if (module.exposing.length > 0) { console.log(`Exposing ${module.exposing.join(", ")}`); } } function moduleInfo(fileName: string, module: ContextModule): void { console.log(`Analyizing ${fileName}...`); const imports = module.body.filter((b) => b.kind === "Import") as Import[]; console.log(`Imports ${imports.length} modules...`); for (const import_ of imports) { for (const module_ of import_.modules) { importModuleInfo(module_); console.log("------------------------"); } } const exportBlocks = module.body.filter( (b) => b.kind === "Export" ) as Export[]; let exportNames: string[] = [ ]; for (const export_ of exportBlocks) { exportNames = exportNames.concat(export_.names); } console.log(`Exports ${exportNames.length} values and functions...`); if (exportNames.length > 0) { console.log(`${exportNames.join(", ")}`); } console.log("------------------------"); const functionNames = ( module.body.filter((b) => b.kind === "Function") as Function[] ).map((f) => f.name); const nonExportedFunctionNames = functionNames.filter( (f) => exportNames.indexOf(f) === -1 ); console.log("Unexported functions"); console.log(nonExportedFunctionNames.join(", ")); console.log("------------------------"); const constNames = ( module.body.filter((b) => b.kind === "Const") as Const[] ).map((f) => f.name); const nonExportedConstNames = constNames.filter( (f) => exportNames.indexOf(f) === -1 ); console.log("Unexported consts"); console.log(nonExportedConstNames.join(", ")); console.log("------------------------"); const missingUnionTypes = [ ]; const unionTypes = module.body.filter( (b) => b.kind === "UnionType" ) as UnionType[]; for (const unionType of unionTypes) { const isRootTypeExported = exportNames.indexOf(unionType.type.name) > -1; const missingTagNames = [ ]; for (const tag of unionType.tags) { if (exportNames.indexOf(tag.name) === -1) { missingTagNames.push(tag.name); } } if (!isRootTypeExported || missingTagNames.length > 0) { if (isRootTypeExported) { missingUnionTypes.push( `Type ${ unionType.type.name } is exported but the constructors ${missingTagNames.join( ", " )} are not` ); } else { missingUnionTypes.push( `${unionType.type.name}(${missingTagNames.join(", ")})` ); } } } console.log("Unexported union types"); console.log(missingUnionTypes.join("\n ")); console.log("------------------------"); const typeAliasNames = ( module.body.filter((b) => b.kind === "TypeAlias") as TypeAlias[] ).map((f) => f.type.name); const nonExportedTypeAliasNames = typeAliasNames.filter( (f) => exportNames.indexOf(f) === -1 ); console.log("Unexported type aliases"); console.log(nonExportedTypeAliasNames.join(", ")); console.log("------------------------"); } export async function info( isInPackageDirectory: boolean, argv: string[] ): Promise<void> { const program = parse(infoParser, argv); if (program.flags["h/help"].isPresent) { showInfoHelp(); return; } const errors = allErrors(program); if (errors.length > 0) { console.log("Errors:"); console.log(errors.join("\n")); process.exit(1); } const fileNameToParse = program.flags.file.isPresent && program.flags.file.arguments.kind === "Ok" && (program.flags.file.arguments.value as string); if (!isInPackageDirectory && !fileNameToParse) { console.log( "No derw-package.json found. Maybe you need to run `derw init` first?" ); console.log("Or provide a file to analyize via --file."); process.exit(1); } let parsedFiles; if (fileNameToParse) { parsedFiles = await compileFiles(isInPackageDirectory, [ "--files", fileNameToParse, "--quiet", ]); } else { parsedFiles = await compileFiles(isInPackageDirectory, [ "--quiet" ]); } for (const fileName of Object.keys(parsedFiles)) { if (fileNameToParse && fileNameToParse !== fileName) { continue; } moduleInfo(fileName, parsedFiles[fileName]); } }