better errors for non existent languages and categories
MODIFY
scripts/_utils.ts
scripts/_utils.ts
-import {AbsoluteFilePath, createAbsoluteFilePath} from "@internal/path";
-import {readFileText, writeFile as writeFileReal} from "@internal/fs";
+import {
+ AbsoluteFilePath,
+ AbsoluteFilePathSet,
+ createAbsoluteFilePath,
+} from "@internal/path";
+import {
+ lstat,
+ readDirectory,
+ readFileText,
+ writeFile as writeFileReal,
+} from "@internal/fs";
import {Reporter} from "@internal/cli-reporter";
import {createMockWorker} from "@internal/test-helpers";
@@ -256,3 +265,48 @@ export async function execDev(args: Array<string>): Promise<void> {
),
);
}
+
+async function getSubDirectories(
+ files: AbsoluteFilePathSet,
+): Promise<Array<string>> {
+ const subDirs: Array<string> = [];
+
+ for await (const file of files) {
+ if ((await lstat(file)).isDirectory()) {
+ subDirs.push(file.getBasename());
+ }
+ }
+
+ return subDirs;
+}
+
+export async function getLanguages(): Promise<Array<string>> {
+ const astPath = INTERNAL.append("ast");
+ const astDir = await readDirectory(astPath);
+
+ return getSubDirectories(astDir);
+}
+
+export async function getLanguageCategories(
+ language: string,
+): Promise<Array<string>> {
+ const languagePath = INTERNAL.append("ast", language);
+ const languageDir = await readDirectory(languagePath);
+
+ return getSubDirectories(languageDir);
+}
+
+export async function languageExists(language: string): Promise<boolean> {
+ const languages = await getLanguages();
+
+ return languages.includes(language);
+}
+
+export async function languageCategoryExists(
+ language: string,
+ category: string,
+): Promise<boolean> {
+ const categories = await getLanguageCategories(language);
+
+ return categories.includes(category);
+}

MODIFY
scripts/ast-create-node.ts
scripts/ast-create-node.ts
-import {INTERNAL, reporter, writeFile} from "./_utils";
+import {
+ INTERNAL,
+ getLanguageCategories,
+ getLanguages,
+ languageCategoryExists,
+ languageExists,
+ reporter,
+ writeFile,
+} from "./_utils";
import {exists} from "@internal/fs";
import {dedent, toCamelCase} from "@internal/string-utils";
import {markup} from "@internal/markup";
@@ -21,6 +29,32 @@ export async function main(
return 1;
}
+ if (!(await languageExists(language))) {
+ const languages = await getLanguages();
+
+ reporter.error(
+ markup`Language argument "${language}" is not a valid language`,
+ );
+
+ reporter.info(markup`The following languages are valid:`);
+
+ reporter.list(languages.map((languageName) => markup`${languageName}`));
+ return 1;
+ }
+
+ if (!(await languageCategoryExists(language, category))) {
+ const categories = await getLanguageCategories(language);
+
+ reporter.error(
+ markup`Category argument "${category}" is not a valid category for "${language}"`,
+ );
+
+ reporter.info(markup`The following categories are valid for ${language}:`);
+
+ reporter.list(categories.map((categoryName) => markup`${categoryName}`));
+ return 1;
+ }
+
const joined = `${language}/${category}/${nodeType}`;
// This will convert the pascal case to camel

better errors for non existent languages and categories (#1124)

Co-authored-by: Sebastian <853712+sebmck@users.noreply.github.com>