TypeScript/scripts/processDiagnosticMessages.ts
Andy e53e56cf82
Enable '--strictNullChecks' (#22088)
* Enable '--strictNullChecks'

* Fix API baselines

* Make sys.getEnvironmentVariable non-nullable

* make properties optional instead of using `| undefined` in thier type

* reportDiagnostics should be required

* Declare firstAccessor as non-nullable

* Make `some` a type guard

* Fix `getEnvironmentVariable` definition in tests

* Pretend transformFlags are always defined

* Fix one more use of sys.getEnvironmentVariable

* `requiredResponse` accepts undefined, remove assertions

* Mark optional properties as optional instead of using `| undefined`

* Mark optional properties as optional instead of using ` | undefined`

* Remove unnecessary null assertions

* Put the bang on the declaration instead of every use

* Make `createMapFromTemplate` require a parameter

* Mark `EmitResult.emittedFiles` and `EmitResult.sourceMaps` as optional

* Plumb through undefined in emitLsit and EmitExpressionList

* `ElementAccessExpression.argumentExpression` can not be `undefined`

* Add overloads for `writeTokenText`

* Make `shouldWriteSeparatingLineTerminator` argument non-nullable

* Make `synthesizedNodeStartsOnNewLine` argument required

* `PropertyAssignment.initializer` cannot be undefined

* Use one `!` at declaration site instead of on every use site

* Capture host in a constant and avoid null assertions

* Remove few more unused assertions

* Update baselines

* Use parameter defaults

* Update baselines

* Fix lint

* Make Symbol#valueDeclaration and Symbol#declarations non-optional to reduce assertions

* Make Node#symbol and Type#symbol non-optional to reduce assertions

* Make `flags` non-nullable to reduce assertions

* Convert some asserts to type guards

* Make `isNonLocalAlias` a type guard

* Add overload for `getSymbolOfNode` for `Declaration`

* Some more `getSymbolOfNode` changes

* Push undefined suppression into `typeToTypeNodeHelper`

* `NodeBuilderContext.tracker` is never `undefined`

* use `Debug.assertDefined`

* Remove unnecessary tag

* Mark `LiteralType.freshType` and `LiteralTupe.regularType` as required
2018-05-22 14:46:57 -07:00

115 lines
4.5 KiB
TypeScript

interface DiagnosticDetails {
category: string;
code: number;
reportsUnnecessary?: {};
isEarly?: boolean;
}
type InputDiagnosticMessageTable = ts.Map<DiagnosticDetails>;
function main(): void {
const sys = ts.sys;
if (sys.args.length < 1) {
sys.write("Usage:" + sys.newLine);
sys.write("\tnode processDiagnosticMessages.js <diagnostic-json-input-file>" + sys.newLine);
return;
}
function writeFile(fileName: string, contents: string) {
const inputDirectory = ts.getDirectoryPath(inputFilePath);
const fileOutputPath = ts.combinePaths(inputDirectory, fileName);
sys.writeFile(fileOutputPath, contents);
}
const inputFilePath = sys.args[0].replace(/\\/g, "/");
const inputStr = sys.readFile(inputFilePath)!;
const diagnosticMessagesJson: { [key: string]: DiagnosticDetails } = JSON.parse(inputStr);
const diagnosticMessages: InputDiagnosticMessageTable = ts.createMapFromTemplate(diagnosticMessagesJson);
const outputFilesDir = ts.getDirectoryPath(inputFilePath);
const thisFilePathRel = ts.getRelativePathToDirectoryOrUrl(outputFilesDir, sys.getExecutingFilePath(),
sys.getCurrentDirectory(), ts.createGetCanonicalFileName(sys.useCaseSensitiveFileNames), /* isAbsolutePathAnUrl */ false);
const infoFileOutput = buildInfoFileOutput(diagnosticMessages, "./diagnosticInformationMap.generated.ts", thisFilePathRel);
checkForUniqueCodes(diagnosticMessages);
writeFile("diagnosticInformationMap.generated.ts", infoFileOutput);
const messageOutput = buildDiagnosticMessageOutput(diagnosticMessages);
writeFile("diagnosticMessages.generated.json", messageOutput);
}
function checkForUniqueCodes(diagnosticTable: InputDiagnosticMessageTable) {
const allCodes: { [key: number]: true | undefined } = [];
diagnosticTable.forEach(({ code }) => {
if (allCodes[code]) {
throw new Error(`Diagnostic code ${code} appears more than once.`);
}
allCodes[code] = true;
});
}
function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, inputFilePathRel: string, thisFilePathRel: string): string {
let result =
"// <auto-generated />\r\n" +
"// generated from '" + inputFilePathRel + "' by '" + thisFilePathRel + "'\r\n" +
"/* @internal */\r\n" +
"namespace ts {\r\n" +
" function diag(code: number, category: DiagnosticCategory, key: string, message: string, reportsUnnecessary?: {}): DiagnosticMessage {\r\n" +
" return { code, category, key, message, reportsUnnecessary };\r\n" +
" }\r\n" +
" // tslint:disable-next-line variable-name\r\n" +
" export const Diagnostics = {\r\n";
messageTable.forEach(({ code, category, reportsUnnecessary }, name) => {
const propName = convertPropertyName(name);
const argReportsUnnecessary = reportsUnnecessary ? `, /*reportsUnnecessary*/ ${reportsUnnecessary}` : "";
result += ` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}${argReportsUnnecessary}),\r\n`;
});
result += " };\r\n}";
return result;
}
function buildDiagnosticMessageOutput(messageTable: InputDiagnosticMessageTable): string {
let result = "{";
messageTable.forEach(({ code }, name) => {
const propName = convertPropertyName(name);
result += `\r\n "${createKey(propName, code)}" : "${name.replace(/[\"]/g, '\\"')}",`;
});
// Shave trailing comma, then add newline and ending brace
result = result.slice(0, result.length - 1) + "\r\n}";
// Assert that we generated valid JSON
JSON.parse(result);
return result;
}
function createKey(name: string, code: number): string {
return name.slice(0, 100) + "_" + code;
}
function convertPropertyName(origName: string): string {
let result = origName.split("").map(char => {
if (char === "*") { return "_Asterisk"; }
if (char === "/") { return "_Slash"; }
if (char === ":") { return "_Colon"; }
return /\w/.test(char) ? char : "_";
}).join("");
// get rid of all multi-underscores
result = result.replace(/_+/g, "_");
// remove any leading underscore, unless it is followed by a number.
result = result.replace(/^_([^\d])/, "$1");
// get rid of all trailing underscores.
result = result.replace(/_$/, "");
return result;
}
main();