From f70d9458e652ede123436cd2d0367012427399a0 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 17 Feb 2018 13:39:55 -0500 Subject: [PATCH 1/2] Apply 'no-unnecessary-initializer' lint rule Forbids `let`/`const` statements to be initialized to `undefined`, since that's the initial value by default anyway. The auto-fixer also happened to remove two unnecessary `as number` casts in `src/harness/parallel/worker.ts`. For historical data: to run with `--fix`, I modified the line in `Jakefile.js` that declared the `cmd` for running TSLint. --- src/compiler/checker.ts | 12 ++++++------ src/compiler/core.ts | 4 ++-- src/compiler/moduleNameResolver.ts | 2 +- src/compiler/parser.ts | 8 ++++---- src/compiler/transformers/utilities.ts | 2 +- src/harness/fourslash.ts | 6 +++--- src/harness/harness.ts | 6 +++--- src/harness/loggedIO.ts | 6 +++--- src/harness/parallel/worker.ts | 4 ++-- src/harness/projectsRunner.ts | 6 +++--- src/server/client.ts | 2 +- src/server/session.ts | 4 ++-- src/services/findAllReferences.ts | 4 ++-- src/services/patternMatcher.ts | 6 +++--- src/services/refactors/extractSymbol.ts | 22 +++++++++++----------- src/services/services.ts | 2 +- src/services/utilities.ts | 2 +- tslint.json | 1 - 18 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2768c142f5aad..21e9d395bd2ed 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3152,7 +3152,7 @@ namespace ts { } } - let entityName: EntityName = undefined; + let entityName: EntityName; const nameIdentifier = symbolToTypeReferenceName(type.symbol); if (qualifiedName) { Debug.assert(!qualifiedName.right); @@ -5636,7 +5636,7 @@ namespace ts { } return [signature]; } - let result: Signature[] = undefined; + let result: Signature[]; for (let i = 0; i < signatureLists.length; i++) { // Allow matching non-generic signatures to have excess parameters and different return types const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true); @@ -5654,7 +5654,7 @@ namespace ts { // type is the union of the constituent return types. function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] { const signatureLists = map(types, t => getSignaturesOfType(t, kind)); - let result: Signature[] = undefined; + let result: Signature[]; for (let i = 0; i < signatureLists.length; i++) { for (const signature of signatureLists[i]) { // Only process signatures with parameter lists that aren't already in the result list @@ -5790,7 +5790,7 @@ namespace ts { else { // Combinations of function, class, enum and module let members = emptySymbols; - let stringIndexInfo: IndexInfo = undefined; + let stringIndexInfo: IndexInfo; if (symbol.exports) { members = getExportsOfSymbol(symbol); } @@ -6332,7 +6332,7 @@ namespace ts { } const propTypes: Type[] = []; const declarations: Declaration[] = []; - let commonType: Type = undefined; + let commonType: Type; for (const prop of props) { if (prop.declarations) { addRange(declarations, prop.declarations); @@ -6613,7 +6613,7 @@ namespace ts { const parameters: Symbol[] = []; let hasLiteralTypes = false; let minArgumentCount = 0; - let thisParameter: Symbol = undefined; + let thisParameter: Symbol; let hasThisParameter: boolean; const iife = getImmediatelyInvokedFunctionExpression(declaration); const isJSConstructSignature = isJSDocConstructSignature(declaration); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 698824fa9b0fb..a4e024c7483a0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1584,7 +1584,7 @@ namespace ts { return text.replace(/{(\d+)}/g, (_match, index?) => args[+index + baseIndex]); } - export let localizedDiagnosticMessages: MapLike = undefined; + export let localizedDiagnosticMessages: MapLike; export function getLocaleSpecificMessage(message: DiagnosticMessage) { return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message; @@ -3043,7 +3043,7 @@ namespace ts { /** Return the object corresponding to the best pattern to match `candidate`. */ export function findBestPatternMatch(values: ReadonlyArray, getPattern: (value: T) => Pattern, candidate: string): T | undefined { - let matchedValue: T | undefined = undefined; + let matchedValue: T | undefined; // use length of prefix as betterness criteria let longestMatchPrefixLength = -1; diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 50181bb98e4f7..601556a5b7794 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -662,7 +662,7 @@ namespace ts { } // string is for exact match - let matchedPattern: Pattern | string | undefined = undefined; + let matchedPattern: Pattern | string | undefined; if (state.compilerOptions.paths) { if (state.traceEnabled) { trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 70ddb7b791df1..47d7b339a1058 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4763,7 +4763,7 @@ namespace ts { const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword); parseExpected(SyntaxKind.OpenParenToken); - let initializer: VariableDeclarationList | Expression = undefined; + let initializer: VariableDeclarationList | Expression; if (token() !== SyntaxKind.SemicolonToken) { if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) { initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); @@ -6090,7 +6090,7 @@ namespace ts { const typeReferenceDirectives: FileReference[] = []; const amdDependencies: { path: string; name: string }[] = []; let amdModuleName: string; - let checkJsDirective: CheckJsDirective = undefined; + let checkJsDirective: CheckJsDirective; // Keep scanning all the leading trivia in the file until we get to something that // isn't trivia. Any single line comment will be analyzed to see if it is a @@ -6313,7 +6313,7 @@ namespace ts { // Initially we can parse out a tag. We also have seen a starting asterisk. // This is so that /** * @type */ doesn't parse. let state = JSDocState.SawAsterisk; - let margin: number | undefined = undefined; + let margin: number | undefined; // + 4 for leading '/** ' let indent = start - Math.max(content.lastIndexOf("\n", start), 0) + 4; function pushComment(text: string) { @@ -7337,7 +7337,7 @@ namespace ts { } function getLastChildWorker(node: Node): Node | undefined { - let last: Node = undefined; + let last: Node; forEachChild(node, child => { if (nodeIsPresent(child)) { last = child; diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index f7d28d6b4fc3c..c64c1d169b8b8 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -48,7 +48,7 @@ namespace ts { const uniqueExports = createMap(); let exportedNames: Identifier[]; let hasExportDefault = false; - let exportEquals: ExportAssignment = undefined; + let exportEquals: ExportAssignment; let hasExportStarsToExportValues = false; let hasImportStarOrImportDefault = false; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index fa9bf124e5121..5c3ffdd46d91c 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3317,7 +3317,7 @@ ${code} const ranges: Range[] = []; // Stuff related to the subfile we're parsing - let currentFileContent: string = undefined; + let currentFileContent: string; let currentFileName = fileName; let currentFileSymlinks: string[] | undefined; let currentFileOptions: { [s: string]: string } = {}; @@ -3452,7 +3452,7 @@ ${code} } function recordObjectMarker(fileName: string, location: LocationInformation, text: string, markerMap: ts.Map, markers: Marker[]): Marker { - let markerValue: any = undefined; + let markerValue: any; try { // Attempt to parse the marker value as JSON markerValue = JSON.parse("{ " + text + " }"); @@ -3511,7 +3511,7 @@ ${code} let output = ""; /// The current marker (or maybe multi-line comment?) we're parsing, possibly - let openMarker: LocationInformation = undefined; + let openMarker: LocationInformation; /// A stack of the open range markers that are still unclosed const openRanges: RangeLocationInformation[] = []; diff --git a/src/harness/harness.ts b/src/harness/harness.ts index e35ecba2a04ca..eb41565f0d231 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -145,7 +145,7 @@ namespace Utils { path = "tests/" + path; } - let content: string = undefined; + let content: string; try { content = Harness.IO.readFile(Harness.userSpecifiedRoot + path); } @@ -1891,9 +1891,9 @@ namespace Harness { const lines = Utils.splitContentByNewlines(code); // Stuff related to the subfile we're parsing - let currentFileContent: string = undefined; + let currentFileContent: string; let currentFileOptions: any = {}; - let currentFileName: any = undefined; + let currentFileName: any; let refs: string[] = []; for (const line of lines) { diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 949c6e5d947c7..e87402ea14008 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -87,9 +87,9 @@ interface PlaybackControl { } namespace Playback { - let recordLog: IoLog = undefined; - let replayLog: IoLog = undefined; - let replayFilesRead: ts.Map | undefined = undefined; + let recordLog: IoLog; + let replayLog: IoLog; + let replayFilesRead: ts.Map | undefined; let recordLogFileNameBase = ""; interface Memoized { diff --git a/src/harness/parallel/worker.ts b/src/harness/parallel/worker.ts index 1902ff70b1933..00c86d4894c8e 100644 --- a/src/harness/parallel/worker.ts +++ b/src/harness/parallel/worker.ts @@ -55,7 +55,7 @@ namespace Harness.Parallel.Worker { retries() { return this; }, slow() { return this; }, timeout(n) { - timeout = n as number; + timeout = n; return this; }, }; @@ -127,7 +127,7 @@ namespace Harness.Parallel.Worker { const fakeContext: Mocha.ITestCallbackContext = { skip() { return this; }, timeout(n) { - timeout = n as number; + timeout = n; const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } }; process.send(timeoutMsg); return this; diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index f8d4d171f01df..7dbfe0c5a75f3 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -163,7 +163,7 @@ class ProjectRunner extends RunnerBase { } function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile { - let sourceFile: ts.SourceFile = undefined; + let sourceFile: ts.SourceFile; if (fileName === Harness.Compiler.defaultLibFileName) { sourceFile = Harness.Compiler.getDefaultLibrarySourceFile(Harness.Compiler.getDefaultLibFileName(compilerOptions)); } @@ -294,7 +294,7 @@ class ProjectRunner extends RunnerBase { } function getSourceFileText(fileName: string): string { - let text: string = undefined; + let text: string; try { text = Harness.IO.readFile(getFileNameInTheProjectTest(fileName)); } @@ -370,7 +370,7 @@ class ProjectRunner extends RunnerBase { allInputFiles.unshift({ emittedFileName: sourceFile.fileName, code: sourceFile.text }); } else if (!(compilerOptions.outFile || compilerOptions.out)) { - let emitOutputFilePathWithoutExtension: string = undefined; + let emitOutputFilePathWithoutExtension: string; if (compilerOptions.outDir) { let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program.getCurrentDirectory()); sourceFilePath = sourceFilePath.replace(compilerResult.program.getCommonSourceDirectory(), ""); diff --git a/src/server/client.ts b/src/server/client.ts index cee65c0e5a485..6ffe05790a017 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -617,7 +617,7 @@ namespace ts.server { const edits: FileTextChanges[] = this.convertCodeEditsToTextChanges(response.body.edits); const renameFilename: string | undefined = response.body.renameFilename; - let renameLocation: number | undefined = undefined; + let renameLocation: number | undefined; if (renameFilename !== undefined) { renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation); } diff --git a/src/server/session.ts b/src/server/session.ts index bff19d7bc232f..3b727ccadf69a 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1541,7 +1541,7 @@ namespace ts.server { } private extractPositionAndRange(args: protocol.FileLocationOrRangeRequestArgs, scriptInfo: ScriptInfo): { position: number, textRange: TextRange } { - let position: number = undefined; + let position: number; let textRange: TextRange; if (this.isLocation(args)) { position = getPosition(args); @@ -1657,7 +1657,7 @@ namespace ts.server { } private getStartAndEndPosition(args: protocol.FileRangeRequestArgs, scriptInfo: ScriptInfo) { - let startPosition: number = undefined, endPosition: number = undefined; + let startPosition: number, endPosition: number; if (args.startPosition !== undefined) { startPosition = args.startPosition; } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 8100a021fb8ba..af0fca5b0ea52 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -511,7 +511,7 @@ namespace ts.FindAllReferences.Core { // here appears to be intentional). const { text = stripQuotes(unescapeLeadingUnderscores((getLocalSymbolForExportDefault(symbol) || symbol).escapedName)), - allSearchSymbols = undefined, + allSearchSymbols, } = searchOptions; const escapedText = escapeLeadingUnderscores(text); const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); @@ -1148,7 +1148,7 @@ namespace ts.FindAllReferences.Core { } function getContainingTypeReference(node: Node): Node { - let topLevelTypeReference: Node = undefined; + let topLevelTypeReference: Node; while (node) { if (isTypeNode(node)) { diff --git a/src/services/patternMatcher.ts b/src/services/patternMatcher.ts index db957816146bb..14a9a73a9e1c5 100644 --- a/src/services/patternMatcher.ts +++ b/src/services/patternMatcher.ts @@ -336,7 +336,7 @@ namespace ts { // Only if all words have some sort of match is the pattern considered matched. const subWordTextChunks = segment.subWordTextChunks; - let matches: PatternMatch[] = undefined; + let matches: PatternMatch[]; for (const subWordTextChunk of subWordTextChunks) { // Try to match the candidate with this word @@ -393,8 +393,8 @@ namespace ts { let currentCandidate = 0; let currentChunkSpan = 0; - let firstMatch: number = undefined; - let contiguous: boolean = undefined; + let firstMatch: number; + let contiguous: boolean; while (true) { // Let's consider our termination cases diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 65c9fd6268c3e..25a243c93df92 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -274,7 +274,7 @@ namespace ts.refactor.extractSymbol { } else if (isVariableStatement(node)) { let numInitializers = 0; - let lastInitializer: Expression | undefined = undefined; + let lastInitializer: Expression | undefined; for (const declaration of node.declarationList.declarations) { if (declaration.initializer) { numInitializers++; @@ -730,12 +730,12 @@ namespace ts.refactor.extractSymbol { const functionName = createIdentifier(functionNameText); - let returnType: TypeNode = undefined; + let returnType: TypeNode; const parameters: ParameterDeclaration[] = []; const callArguments: Identifier[] = []; let writes: UsageEntry[]; usagesInScope.forEach((usage, name) => { - let typeNode: TypeNode = undefined; + let typeNode: TypeNode; if (!isJS) { let type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node); // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" @@ -1114,7 +1114,7 @@ namespace ts.refactor.extractSymbol { } function getContainingVariableDeclarationIfInList(node: Node, scope: Scope) { - let prevNode = undefined; + let prevNode; while (node !== undefined && node !== scope) { if (isVariableDeclaration(node) && node.initializer === prevNode && @@ -1161,7 +1161,7 @@ namespace ts.refactor.extractSymbol { } function getFirstDeclaration(type: Type): Declaration | undefined { - let firstDeclaration = undefined; + let firstDeclaration; const symbol = type.symbol; if (symbol && symbol.declarations) { @@ -1297,7 +1297,7 @@ namespace ts.refactor.extractSymbol { const members = scope.members; Debug.assert(members.length > 0); // There must be at least one child, since we extracted from one. - let prevMember: ClassElement | undefined = undefined; + let prevMember: ClassElement | undefined; let allProperties = true; for (const member of members) { if (member.pos > maxPos) { @@ -1322,7 +1322,7 @@ namespace ts.refactor.extractSymbol { function getNodeToInsertConstantBefore(node: Node, scope: Scope): Statement { Debug.assert(!isClassLike(scope)); - let prevScope: Scope | undefined = undefined; + let prevScope: Scope | undefined; for (let curr = node; curr !== scope; curr = curr.parent) { if (isScope(curr)) { prevScope = curr; @@ -1331,7 +1331,7 @@ namespace ts.refactor.extractSymbol { for (let curr = (prevScope || node).parent; ; curr = curr.parent) { if (isBlockLike(curr)) { - let prevStatement = undefined; + let prevStatement; for (const statement of curr.statements) { if (statement.pos > node.pos) { break; @@ -1432,7 +1432,7 @@ namespace ts.refactor.extractSymbol { const visibleDeclarationsInExtractedRange: NamedDeclaration[] = []; const exposedVariableSymbolSet = createMap(); // Key is symbol ID const exposedVariableDeclarations: VariableDeclaration[] = []; - let firstExposedNonVariableDeclaration: NamedDeclaration | undefined = undefined; + let firstExposedNonVariableDeclaration: NamedDeclaration | undefined; const expression = !isReadonlyArray(targetRange.range) ? targetRange.range @@ -1440,7 +1440,7 @@ namespace ts.refactor.extractSymbol { ? (targetRange.range[0] as ExpressionStatement).expression : undefined; - let expressionDiagnostic: Diagnostic | undefined = undefined; + let expressionDiagnostic: Diagnostic | undefined; if (expression === undefined) { const statements = targetRange.range as ReadonlyArray; const start = first(statements).getStart(); @@ -1542,7 +1542,7 @@ namespace ts.refactor.extractSymbol { } let hasWrite = false; - let readonlyClassPropertyWrite: Declaration | undefined = undefined; + let readonlyClassPropertyWrite: Declaration | undefined; usagesPerScope[i].usages.forEach(value => { if (value.usage === Usage.Write) { hasWrite = true; diff --git a/src/services/services.ts b/src/services/services.ts index 991b6c1060652..43a2b5cec250d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1979,7 +1979,7 @@ namespace ts { continue; } - let descriptor: TodoCommentDescriptor = undefined; + let descriptor: TodoCommentDescriptor; for (let i = 0; i < descriptors.length; i++) { if (matchArray[i + firstDescriptorCaptureIndex]) { descriptor = descriptors[i]; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 263ac0f4c3bb3..1a7cc97854acd 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1420,7 +1420,7 @@ namespace ts { function suppressTrailing(node: Node) { addEmitFlags(node, EmitFlags.NoTrailingComments); - let lastChild: Node = undefined; + let lastChild: Node; forEachChild( node, child => (lastChild = child, undefined), diff --git a/tslint.json b/tslint.json index bd06724edb8fc..ce2152a8e1f3e 100644 --- a/tslint.json +++ b/tslint.json @@ -103,7 +103,6 @@ "no-object-literal-type-assertion": false, "no-shadowed-variable": false, "no-submodule-imports": false, - "no-unnecessary-initializer": false, "no-var-requires": false, "ordered-imports": false, "prefer-conditional-expression": false, From 06cc81155ab521f153455a0b19aefa00ccfc572a Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 17 Feb 2018 13:58:16 -0500 Subject: [PATCH 2/2] Moved worker.ts type assertions to parameters --- src/harness/parallel/worker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/harness/parallel/worker.ts b/src/harness/parallel/worker.ts index 00c86d4894c8e..e0194815435f5 100644 --- a/src/harness/parallel/worker.ts +++ b/src/harness/parallel/worker.ts @@ -54,7 +54,7 @@ namespace Harness.Parallel.Worker { const fakeContext: Mocha.ISuiteCallbackContext = { retries() { return this; }, slow() { return this; }, - timeout(n) { + timeout(n: number) { timeout = n; return this; }, @@ -126,7 +126,7 @@ namespace Harness.Parallel.Worker { let timeout: number; const fakeContext: Mocha.ITestCallbackContext = { skip() { return this; }, - timeout(n) { + timeout(n: number) { timeout = n; const timeoutMsg: ParallelTimeoutChangeMessage = { type: "timeout", payload: { duration: timeout } }; process.send(timeoutMsg);