From 74df98f55ea69e26aaf0a3e9f295b557762018e7 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 30 Aug 2022 08:25:44 -0700 Subject: [PATCH 1/3] Retain name and propertyName in declaration emit copies of binding patterns if property name is a keyword --- scripts/authors.js | 163 ++++++++++++++++++ src/compiler/checker.ts | 2 +- ...ationEmitBindingPatternWithReservedWord.js | 48 ++++++ ...EmitBindingPatternWithReservedWord.symbols | 78 +++++++++ ...onEmitBindingPatternWithReservedWord.types | 52 ++++++ ...ationEmitBindingPatternWithReservedWord.ts | 23 +++ 6 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 scripts/authors.js create mode 100644 tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.js create mode 100644 tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.symbols create mode 100644 tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.types create mode 100644 tests/cases/compiler/declarationEmitBindingPatternWithReservedWord.ts diff --git a/scripts/authors.js b/scripts/authors.js new file mode 100644 index 0000000000000..79f98634df4ad --- /dev/null +++ b/scripts/authors.js @@ -0,0 +1,163 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = require("fs"); +const path = require("path"); +const childProcess = require("child_process"); +const mailMapPath = path.resolve(__dirname, "../.mailmap"); +const authorsPath = path.resolve(__dirname, "../AUTHORS.md"); +function getKnownAuthors() { + const segmentRegExp = /\s?([^<]+)\s+<([^>]+)>/g; + const preferredNameRegeExp = /\s?#\s?([^#]+)$/; + const knownAuthors = []; + if (!fs.existsSync(mailMapPath)) { + throw new Error(`Could not load known users form .mailmap file at: ${mailMapPath}`); + } + const mailMap = fs.readFileSync(mailMapPath).toString(); + for (const line of mailMap.split("\r\n")) { + const author = { displayNames: [], emails: [] }; + let match; + while (match = segmentRegExp.exec(line)) { + author.displayNames.push(match[1]); + author.emails.push(match[2]); + } + if (match = preferredNameRegeExp.exec(line)) { + author.preferredName = match[1]; + } + if (!author.emails) + continue; + knownAuthors.push(author); + if (line.indexOf("#") > 0 && !author.preferredName) { + throw new Error("Could not match preferred name for: " + line); + } + // console.log("===> line: " + line); + // console.log(JSON.stringify(author, undefined, 2)); + } + return knownAuthors; +} +function getAuthorName(author) { + return author.preferredName || author.displayNames[0]; +} +function getKnownAuthorMaps() { + const knownAuthors = getKnownAuthors(); + const authorsByName = {}; + const authorsByEmail = {}; + knownAuthors.forEach(author => { + author.displayNames.forEach(n => authorsByName[n] = author); + author.emails.forEach(e => authorsByEmail[e.toLocaleLowerCase()] = author); + }); + return { + knownAuthors, + authorsByName, + authorsByEmail + }; +} +function deduplicate(array) { + const result = []; + if (array) { + for (const item of array) { + if (result.indexOf(item) < 0) { + result.push(item); + } + } + } + return result; +} +function log(s) { + console.log(` ${s}`); +} +function sortAuthors(a, b) { + if (a.charAt(0) === "@") + a = a.substr(1); + if (b.charAt(0) === "@") + b = b.substr(1); + if (a.toLocaleLowerCase() < b.toLocaleLowerCase()) { + return -1; + } + else { + return 1; + } +} +var Commands; +(function (Commands) { + Commands.writeAuthors = () => { + const output = deduplicate(getKnownAuthors().map(getAuthorName).filter(a => !!a)).sort(sortAuthors).join("\r\n* "); + fs.writeFileSync(authorsPath, "TypeScript is authored by:\r\n* " + output); + }; + Commands.writeAuthors.description = "Write known authors to AUTHORS.md file."; + Commands.listKnownAuthors = () => { + deduplicate(getKnownAuthors().map(getAuthorName)).filter(a => !!a).sort(sortAuthors).forEach(log); + }; + Commands.listKnownAuthors.description = "List known authors as listed in .mailmap file."; + Commands.listAuthors = (...specs) => { + const cmd = "git shortlog -se " + specs.join(" "); + console.log(cmd); + const outputRegExp = /\d+\s+([^<]+)<([^>]+)>/; + const authors = []; + const { output: [error, stdout, stderr] } = childProcess.spawnSync(`git`, ["shortlog", "-se", ...specs], { cwd: path.resolve(__dirname, "../") }); + if (error) { + console.log(stderr.toString()); + } + else { + const output = stdout.toString(); + const lines = output.split("\n"); + lines.forEach(line => { + if (line) { + let match; + if (match = outputRegExp.exec(line)) { + authors.push({ name: match[1], email: match[2] }); + } + else { + throw new Error("Could not parse output: " + line); + } + } + }); + const maps = getKnownAuthorMaps(); + const lookupAuthor = ({ name, email }) => { + return maps.authorsByEmail[email.toLocaleLowerCase()] || maps.authorsByName[name]; + }; + const knownAuthors = authors + .map(lookupAuthor) + .filter(a => !!a) + .map(getAuthorName); + const unknownAuthors = authors + .filter(a => !lookupAuthor(a)) + .map(a => `${a.name} <${a.email}>`); + if (knownAuthors.length) { + console.log("\r\n"); + console.log("Found known authors: "); + console.log("====================="); + deduplicate(knownAuthors).sort(sortAuthors).forEach(log); + } + if (unknownAuthors.length) { + console.log("\r\n"); + console.log("Found unknown authors: "); + console.log("====================="); + deduplicate(unknownAuthors).sort(sortAuthors).forEach(log); + } + const allAuthors = deduplicate([...knownAuthors, ...unknownAuthors].map(a => a.split("<")[0].trim())).sort(sortAuthors); + if (allAuthors.length) { + console.log("\r\n"); + console.log("Revised Authors.md: "); + console.log("====================="); + allAuthors.forEach(name => console.log(" - " + name)); + } + } + }; + Commands.listAuthors.description = "List known and unknown authors for a given spec, e.g. 'node authors.js listAuthors origin/release-2.6..origin/release-2.7'"; +})(Commands || (Commands = {})); +const args = process.argv.slice(2); +if (args.length < 1) { + console.log("Usage: node authors.js [command]"); + console.log("List of commands: "); + Object.keys(Commands).forEach(k => console.log(` ${k}: ${Commands[k].description}`)); +} +else { + const cmd = Commands[args[0]]; + if (cmd === undefined) { + console.log("Unknown command " + args[1]); + } + else { + cmd.apply(undefined, args.slice(1)); + } +} +//# sourceMappingURL=authors.js.map \ No newline at end of file diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 01fc87bae36a4..e911d7fe7d2a3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6122,7 +6122,7 @@ namespace ts { } let visited = visitEachChild(node, elideInitializerAndPropertyRenamingAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndPropertyRenamingAndSetEmitFlags)!; if (isBindingElement(visited)) { - if (visited.propertyName && isIdentifier(visited.propertyName) && isIdentifier(visited.name)) { + if (visited.propertyName && isIdentifier(visited.propertyName) && isIdentifier(visited.name) && !isStringAKeyword(idText(visited.propertyName))) { visited = factory.updateBindingElement( visited, visited.dotDotDotToken, diff --git a/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.js b/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.js new file mode 100644 index 0000000000000..efde38e3c6613 --- /dev/null +++ b/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.js @@ -0,0 +1,48 @@ +//// [declarationEmitBindingPatternWithReservedWord.ts] +type LocaleData = Record +type ConvertLocaleConfig = Record< + string, + T +>; +type LocaleConfig = Record>; + +export interface GetLocalesOptions { + app: unknown; + default: ConvertLocaleConfig; + config?: LocaleConfig | undefined; + name?: string; +} + +export const getLocales = ({ + app, + name, + default: defaultLocalesConfig, + config: userLocalesConfig = {}, +}: GetLocalesOptions): ConvertLocaleConfig => { + return defaultLocalesConfig; +}; + + +//// [declarationEmitBindingPatternWithReservedWord.js] +"use strict"; +exports.__esModule = true; +exports.getLocales = void 0; +var getLocales = function (_a) { + var app = _a.app, name = _a.name, defaultLocalesConfig = _a["default"], _b = _a.config, userLocalesConfig = _b === void 0 ? {} : _b; + return defaultLocalesConfig; +}; +exports.getLocales = getLocales; + + +//// [declarationEmitBindingPatternWithReservedWord.d.ts] +type LocaleData = Record; +type ConvertLocaleConfig = Record; +type LocaleConfig = Record>; +export interface GetLocalesOptions { + app: unknown; + default: ConvertLocaleConfig; + config?: LocaleConfig | undefined; + name?: string; +} +export declare const getLocales: ({ app, name, default: defaultLocalesConfig, config, }: GetLocalesOptions) => ConvertLocaleConfig; +export {}; diff --git a/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.symbols b/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.symbols new file mode 100644 index 0000000000000..fd535c190dbc1 --- /dev/null +++ b/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.symbols @@ -0,0 +1,78 @@ +=== tests/cases/compiler/declarationEmitBindingPatternWithReservedWord.ts === +type LocaleData = Record +>LocaleData : Symbol(LocaleData, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 0)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +type ConvertLocaleConfig = Record< +>ConvertLocaleConfig : Symbol(ConvertLocaleConfig, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 39)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 1, 25)) +>LocaleData : Symbol(LocaleData, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 0)) +>LocaleData : Symbol(LocaleData, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 0)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + + string, + T +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 1, 25)) + +>; +type LocaleConfig = Record>; +>LocaleConfig : Symbol(LocaleConfig, Decl(declarationEmitBindingPatternWithReservedWord.ts, 4, 2)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 5, 18)) +>LocaleData : Symbol(LocaleData, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 0)) +>LocaleData : Symbol(LocaleData, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 0)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 5, 18)) + +export interface GetLocalesOptions { +>GetLocalesOptions : Symbol(GetLocalesOptions, Decl(declarationEmitBindingPatternWithReservedWord.ts, 5, 82)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 7, 35)) +>LocaleData : Symbol(LocaleData, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 0)) + + app: unknown; +>app : Symbol(GetLocalesOptions.app, Decl(declarationEmitBindingPatternWithReservedWord.ts, 7, 58)) + + default: ConvertLocaleConfig; +>default : Symbol(GetLocalesOptions.default, Decl(declarationEmitBindingPatternWithReservedWord.ts, 8, 17)) +>ConvertLocaleConfig : Symbol(ConvertLocaleConfig, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 39)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 7, 35)) + + config?: LocaleConfig | undefined; +>config : Symbol(GetLocalesOptions.config, Decl(declarationEmitBindingPatternWithReservedWord.ts, 9, 36)) +>LocaleConfig : Symbol(LocaleConfig, Decl(declarationEmitBindingPatternWithReservedWord.ts, 4, 2)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 7, 35)) + + name?: string; +>name : Symbol(GetLocalesOptions.name, Decl(declarationEmitBindingPatternWithReservedWord.ts, 10, 41)) +} + +export const getLocales = ({ +>getLocales : Symbol(getLocales, Decl(declarationEmitBindingPatternWithReservedWord.ts, 14, 12)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 14, 27)) +>LocaleData : Symbol(LocaleData, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 0)) + + app, +>app : Symbol(app, Decl(declarationEmitBindingPatternWithReservedWord.ts, 14, 50)) + + name, +>name : Symbol(name, Decl(declarationEmitBindingPatternWithReservedWord.ts, 15, 8)) + + default: defaultLocalesConfig, +>default : Symbol(GetLocalesOptions.default, Decl(declarationEmitBindingPatternWithReservedWord.ts, 8, 17)) +>defaultLocalesConfig : Symbol(defaultLocalesConfig, Decl(declarationEmitBindingPatternWithReservedWord.ts, 16, 9)) + + config: userLocalesConfig = {}, +>config : Symbol(GetLocalesOptions.config, Decl(declarationEmitBindingPatternWithReservedWord.ts, 9, 36)) +>userLocalesConfig : Symbol(userLocalesConfig, Decl(declarationEmitBindingPatternWithReservedWord.ts, 17, 34)) + +}: GetLocalesOptions): ConvertLocaleConfig => { +>GetLocalesOptions : Symbol(GetLocalesOptions, Decl(declarationEmitBindingPatternWithReservedWord.ts, 5, 82)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 14, 27)) +>ConvertLocaleConfig : Symbol(ConvertLocaleConfig, Decl(declarationEmitBindingPatternWithReservedWord.ts, 0, 39)) +>T : Symbol(T, Decl(declarationEmitBindingPatternWithReservedWord.ts, 14, 27)) + + return defaultLocalesConfig; +>defaultLocalesConfig : Symbol(defaultLocalesConfig, Decl(declarationEmitBindingPatternWithReservedWord.ts, 16, 9)) + +}; + diff --git a/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.types b/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.types new file mode 100644 index 0000000000000..018026387e230 --- /dev/null +++ b/tests/baselines/reference/declarationEmitBindingPatternWithReservedWord.types @@ -0,0 +1,52 @@ +=== tests/cases/compiler/declarationEmitBindingPatternWithReservedWord.ts === +type LocaleData = Record +>LocaleData : { [x: string]: never; } + +type ConvertLocaleConfig = Record< +>ConvertLocaleConfig : ConvertLocaleConfig + + string, + T +>; +type LocaleConfig = Record>; +>LocaleConfig : LocaleConfig + +export interface GetLocalesOptions { + app: unknown; +>app : unknown + + default: ConvertLocaleConfig; +>default : ConvertLocaleConfig + + config?: LocaleConfig | undefined; +>config : LocaleConfig + + name?: string; +>name : string +} + +export const getLocales = ({ +>getLocales : ({ app, name, default: defaultLocalesConfig, config, }: GetLocalesOptions) => ConvertLocaleConfig +>({ app, name, default: defaultLocalesConfig, config: userLocalesConfig = {},}: GetLocalesOptions): ConvertLocaleConfig => { return defaultLocalesConfig;} : ({ app, name, default: defaultLocalesConfig, config, }: GetLocalesOptions) => ConvertLocaleConfig + + app, +>app : unknown + + name, +>name : string + + default: defaultLocalesConfig, +>default : any +>defaultLocalesConfig : ConvertLocaleConfig + + config: userLocalesConfig = {}, +>config : any +>userLocalesConfig : LocaleConfig +>{} : {} + +}: GetLocalesOptions): ConvertLocaleConfig => { + return defaultLocalesConfig; +>defaultLocalesConfig : ConvertLocaleConfig + +}; + diff --git a/tests/cases/compiler/declarationEmitBindingPatternWithReservedWord.ts b/tests/cases/compiler/declarationEmitBindingPatternWithReservedWord.ts new file mode 100644 index 0000000000000..be6fdc13ea0e8 --- /dev/null +++ b/tests/cases/compiler/declarationEmitBindingPatternWithReservedWord.ts @@ -0,0 +1,23 @@ +// @declaration: true +type LocaleData = Record +type ConvertLocaleConfig = Record< + string, + T +>; +type LocaleConfig = Record>; + +export interface GetLocalesOptions { + app: unknown; + default: ConvertLocaleConfig; + config?: LocaleConfig | undefined; + name?: string; +} + +export const getLocales = ({ + app, + name, + default: defaultLocalesConfig, + config: userLocalesConfig = {}, +}: GetLocalesOptions): ConvertLocaleConfig => { + return defaultLocalesConfig; +}; From 0a5096a8653c27b08e7260edfad4c85123a61f97 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 30 Aug 2022 08:35:48 -0700 Subject: [PATCH 2/3] Accept baselines --- .../destructuringParameterDeclaration6.types | 12 ++++++------ .../syntheticDefaultExportsWithDynamicImports.types | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/destructuringParameterDeclaration6.types b/tests/baselines/reference/destructuringParameterDeclaration6.types index 6b5085d21219c..d135f9cb8fdbf 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration6.types +++ b/tests/baselines/reference/destructuringParameterDeclaration6.types @@ -7,7 +7,7 @@ // Error function a({while}) { } ->a : ({ while }: { while: any; }) => void +>a : ({ while: }: { while: any; }) => void >while : any > : any @@ -42,32 +42,32 @@ function a7(...a: string) { } a({ while: 1 }); >a({ while: 1 }) : void ->a : ({ while }: { while: any; }) => void +>a : ({ while: }: { while: any; }) => void >{ while: 1 } : { while: number; } >while : number >1 : 1 // No Error function b1({public: x}) { } ->b1 : ({ public }: { public: any; }) => void +>b1 : ({ public: x }: { public: any; }) => void >public : any >x : any function b2({while: y}) { } ->b2 : ({ while }: { while: any; }) => void +>b2 : ({ while: y }: { while: any; }) => void >while : any >y : any b1({ public: 1 }); >b1({ public: 1 }) : void ->b1 : ({ public }: { public: any; }) => void +>b1 : ({ public: x }: { public: any; }) => void >{ public: 1 } : { public: number; } >public : number >1 : 1 b2({ while: 1 }); >b2({ while: 1 }) : void ->b2 : ({ while }: { while: any; }) => void +>b2 : ({ while: y }: { while: any; }) => void >{ while: 1 } : { while: number; } >while : number >1 : 1 diff --git a/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types b/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types index 3dc640792e075..3f1ef83a0ae9c 100644 --- a/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types +++ b/tests/baselines/reference/syntheticDefaultExportsWithDynamicImports.types @@ -13,7 +13,7 @@ import("package").then(({default: foo}) => foo(42)); >import("package") : Promise<{ default: (x: number) => string; }> >"package" : "package" >then : string; }, TResult2 = never>(onfulfilled?: (value: { default: (x: number) => string; }) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise ->({default: foo}) => foo(42) : ({ default }: { default: (x: number) => string; }) => string +>({default: foo}) => foo(42) : ({ default: foo }: { default: (x: number) => string; }) => string >default : any >foo : (x: number) => string >foo(42) : string From 9e0c039a605ac3b8765399a7fcdb3358b07486ba Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 30 Aug 2022 08:38:59 -0700 Subject: [PATCH 3/3] Remove out of date file --- scripts/authors.js | 163 --------------------------------------------- 1 file changed, 163 deletions(-) delete mode 100644 scripts/authors.js diff --git a/scripts/authors.js b/scripts/authors.js deleted file mode 100644 index 79f98634df4ad..0000000000000 --- a/scripts/authors.js +++ /dev/null @@ -1,163 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const fs = require("fs"); -const path = require("path"); -const childProcess = require("child_process"); -const mailMapPath = path.resolve(__dirname, "../.mailmap"); -const authorsPath = path.resolve(__dirname, "../AUTHORS.md"); -function getKnownAuthors() { - const segmentRegExp = /\s?([^<]+)\s+<([^>]+)>/g; - const preferredNameRegeExp = /\s?#\s?([^#]+)$/; - const knownAuthors = []; - if (!fs.existsSync(mailMapPath)) { - throw new Error(`Could not load known users form .mailmap file at: ${mailMapPath}`); - } - const mailMap = fs.readFileSync(mailMapPath).toString(); - for (const line of mailMap.split("\r\n")) { - const author = { displayNames: [], emails: [] }; - let match; - while (match = segmentRegExp.exec(line)) { - author.displayNames.push(match[1]); - author.emails.push(match[2]); - } - if (match = preferredNameRegeExp.exec(line)) { - author.preferredName = match[1]; - } - if (!author.emails) - continue; - knownAuthors.push(author); - if (line.indexOf("#") > 0 && !author.preferredName) { - throw new Error("Could not match preferred name for: " + line); - } - // console.log("===> line: " + line); - // console.log(JSON.stringify(author, undefined, 2)); - } - return knownAuthors; -} -function getAuthorName(author) { - return author.preferredName || author.displayNames[0]; -} -function getKnownAuthorMaps() { - const knownAuthors = getKnownAuthors(); - const authorsByName = {}; - const authorsByEmail = {}; - knownAuthors.forEach(author => { - author.displayNames.forEach(n => authorsByName[n] = author); - author.emails.forEach(e => authorsByEmail[e.toLocaleLowerCase()] = author); - }); - return { - knownAuthors, - authorsByName, - authorsByEmail - }; -} -function deduplicate(array) { - const result = []; - if (array) { - for (const item of array) { - if (result.indexOf(item) < 0) { - result.push(item); - } - } - } - return result; -} -function log(s) { - console.log(` ${s}`); -} -function sortAuthors(a, b) { - if (a.charAt(0) === "@") - a = a.substr(1); - if (b.charAt(0) === "@") - b = b.substr(1); - if (a.toLocaleLowerCase() < b.toLocaleLowerCase()) { - return -1; - } - else { - return 1; - } -} -var Commands; -(function (Commands) { - Commands.writeAuthors = () => { - const output = deduplicate(getKnownAuthors().map(getAuthorName).filter(a => !!a)).sort(sortAuthors).join("\r\n* "); - fs.writeFileSync(authorsPath, "TypeScript is authored by:\r\n* " + output); - }; - Commands.writeAuthors.description = "Write known authors to AUTHORS.md file."; - Commands.listKnownAuthors = () => { - deduplicate(getKnownAuthors().map(getAuthorName)).filter(a => !!a).sort(sortAuthors).forEach(log); - }; - Commands.listKnownAuthors.description = "List known authors as listed in .mailmap file."; - Commands.listAuthors = (...specs) => { - const cmd = "git shortlog -se " + specs.join(" "); - console.log(cmd); - const outputRegExp = /\d+\s+([^<]+)<([^>]+)>/; - const authors = []; - const { output: [error, stdout, stderr] } = childProcess.spawnSync(`git`, ["shortlog", "-se", ...specs], { cwd: path.resolve(__dirname, "../") }); - if (error) { - console.log(stderr.toString()); - } - else { - const output = stdout.toString(); - const lines = output.split("\n"); - lines.forEach(line => { - if (line) { - let match; - if (match = outputRegExp.exec(line)) { - authors.push({ name: match[1], email: match[2] }); - } - else { - throw new Error("Could not parse output: " + line); - } - } - }); - const maps = getKnownAuthorMaps(); - const lookupAuthor = ({ name, email }) => { - return maps.authorsByEmail[email.toLocaleLowerCase()] || maps.authorsByName[name]; - }; - const knownAuthors = authors - .map(lookupAuthor) - .filter(a => !!a) - .map(getAuthorName); - const unknownAuthors = authors - .filter(a => !lookupAuthor(a)) - .map(a => `${a.name} <${a.email}>`); - if (knownAuthors.length) { - console.log("\r\n"); - console.log("Found known authors: "); - console.log("====================="); - deduplicate(knownAuthors).sort(sortAuthors).forEach(log); - } - if (unknownAuthors.length) { - console.log("\r\n"); - console.log("Found unknown authors: "); - console.log("====================="); - deduplicate(unknownAuthors).sort(sortAuthors).forEach(log); - } - const allAuthors = deduplicate([...knownAuthors, ...unknownAuthors].map(a => a.split("<")[0].trim())).sort(sortAuthors); - if (allAuthors.length) { - console.log("\r\n"); - console.log("Revised Authors.md: "); - console.log("====================="); - allAuthors.forEach(name => console.log(" - " + name)); - } - } - }; - Commands.listAuthors.description = "List known and unknown authors for a given spec, e.g. 'node authors.js listAuthors origin/release-2.6..origin/release-2.7'"; -})(Commands || (Commands = {})); -const args = process.argv.slice(2); -if (args.length < 1) { - console.log("Usage: node authors.js [command]"); - console.log("List of commands: "); - Object.keys(Commands).forEach(k => console.log(` ${k}: ${Commands[k].description}`)); -} -else { - const cmd = Commands[args[0]]; - if (cmd === undefined) { - console.log("Unknown command " + args[1]); - } - else { - cmd.apply(undefined, args.slice(1)); - } -} -//# sourceMappingURL=authors.js.map \ No newline at end of file