Skip to content

Commit 46d1426

Browse files
committed
Strict null checks (#60565)
1 parent 8ff2722 commit 46d1426

28 files changed

+248
-208
lines changed

Diff for: src/tsconfig.strictNullChecks.json

+15-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"include": [
88
"./typings",
99
"./vs/base/browser/browser.ts",
10+
"./vs/base/browser/dom.ts",
1011
"./vs/base/browser/event.ts",
1112
"./vs/base/browser/history.ts",
1213
"./vs/base/browser/iframe.ts",
@@ -92,8 +93,12 @@
9293
"./vs/code/electron-main/keyboard.ts",
9394
"./vs/code/electron-main/theme.ts",
9495
"./vs/code/node/shellEnv.ts",
96+
"./vs/editor/browser/config/charWidthReader.ts",
9597
"./vs/editor/browser/config/elementSizeObserver.ts",
98+
"./vs/editor/browser/controller/textAreaState.ts",
99+
"./vs/editor/common/commands/replaceCommand.ts",
96100
"./vs/editor/common/commands/surroundSelectionCommand.ts",
101+
"./vs/editor/common/commands/trimTrailingWhitespaceCommand.ts",
97102
"./vs/editor/common/config/editorOptions.ts",
98103
"./vs/editor/common/config/editorZoom.ts",
99104
"./vs/editor/common/config/fontInfo.ts",
@@ -109,6 +114,7 @@
109114
"./vs/editor/common/core/stringBuilder.ts",
110115
"./vs/editor/common/core/token.ts",
111116
"./vs/editor/common/core/uint.ts",
117+
"./vs/editor/common/diff/diffComputer.ts",
112118
"./vs/editor/common/editorAction.ts",
113119
"./vs/editor/common/editorCommon.ts",
114120
"./vs/editor/common/editorContextKeys.ts",
@@ -138,24 +144,30 @@
138144
"./vs/editor/common/modes/supports/characterPair.ts",
139145
"./vs/editor/common/modes/supports/electricCharacter.ts",
140146
"./vs/editor/common/modes/supports/indentRules.ts",
147+
"./vs/editor/common/modes/supports/inplaceReplaceSupport.ts",
141148
"./vs/editor/common/modes/supports/onEnter.ts",
142149
"./vs/editor/common/modes/supports/richEditBrackets.ts",
150+
"./vs/editor/common/modes/supports/tokenization.ts",
151+
"./vs/editor/common/modes/textToHtmlTokenizer.ts",
143152
"./vs/editor/common/modes/tokenizationRegistry.ts",
144153
"./vs/editor/common/services/editorWorkerService.ts",
145-
"./vs/editor/common/services/modeService.ts",
146154
"./vs/editor/common/services/modelService.ts",
155+
"./vs/editor/common/services/modeService.ts",
147156
"./vs/editor/common/services/resolverService.ts",
148157
"./vs/editor/common/standalone/standaloneBase.ts",
158+
"./vs/editor/common/view/minimapCharRenderer.ts",
149159
"./vs/editor/common/view/overviewZoneManager.ts",
160+
"./vs/editor/common/view/runtimeMinimapCharRenderer.ts",
161+
"./vs/editor/common/view/viewEvents.ts",
150162
"./vs/editor/common/viewLayout/whitespaceComputer.ts",
151163
"./vs/editor/common/viewModel/prefixSumComputer.ts",
152164
"./vs/editor/contrib/codeAction/codeActionTrigger.ts",
153165
"./vs/editor/contrib/colorPicker/colorPickerModel.ts",
154166
"./vs/editor/contrib/find/findState.ts",
155167
"./vs/editor/contrib/find/replaceAllCommand.ts",
156168
"./vs/editor/contrib/find/replacePattern.ts",
157-
"./vs/editor/contrib/inPlaceReplace/inPlaceReplaceCommand.ts",
158169
"./vs/editor/contrib/indentation/indentUtils.ts",
170+
"./vs/editor/contrib/inPlaceReplace/inPlaceReplaceCommand.ts",
159171
"./vs/editor/contrib/linesOperations/copyLinesCommand.ts",
160172
"./vs/editor/standalone/common/monarch/monarchCommon.ts",
161173
"./vs/editor/standalone/common/monarch/monarchCompile.ts",
@@ -202,8 +214,8 @@
202214
"./vs/platform/opener/common/opener.ts",
203215
"./vs/platform/output/node/outputAppender.ts",
204216
"./vs/platform/progress/common/progress.ts",
205-
"./vs/platform/quickOpen/common/quickOpen.ts",
206217
"./vs/platform/quickinput/common/quickInput.ts",
218+
"./vs/platform/quickOpen/common/quickOpen.ts",
207219
"./vs/platform/registry/common/platform.ts",
208220
"./vs/platform/search/common/search.ts",
209221
"./vs/platform/state/common/state.ts",

Diff for: src/vs/base/browser/dom.ts

+22-21
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export function clearNode(node: HTMLElement): void {
2020
}
2121
}
2222

23-
export function isInDOM(node: Node): boolean {
23+
export function isInDOM(node: Node | null): boolean {
2424
while (node) {
2525
if (node === document.body) {
2626
return true;
@@ -151,7 +151,7 @@ const _manualClassList = new class implements IDomClassList {
151151

152152
const _nativeClassList = new class implements IDomClassList {
153153
hasClass(node: HTMLElement, className: string): boolean {
154-
return className && node.classList && node.classList.contains(className);
154+
return Boolean(className) && node.classList && node.classList.contains(className);
155155
}
156156

157157
addClasses(node: HTMLElement, ...classNames: string[]): void {
@@ -198,7 +198,7 @@ class DomListener implements IDisposable {
198198
private readonly _type: string;
199199
private readonly _useCapture: boolean;
200200

201-
constructor(node: Element | Window | Document, type: string, handler: (e: any) => void, useCapture: boolean) {
201+
constructor(node: Element | Window | Document, type: string, handler: (e: any) => void, useCapture?: boolean) {
202202
this._node = node;
203203
this._type = type;
204204
this._handler = handler;
@@ -215,8 +215,8 @@ class DomListener implements IDisposable {
215215
this._node.removeEventListener(this._type, this._handler, this._useCapture);
216216

217217
// Prevent leakers from holding on to the dom or handler func
218-
this._node = null;
219-
this._handler = null;
218+
this._node = null!;
219+
this._handler = null!;
220220
}
221221
}
222222

@@ -257,7 +257,7 @@ export let addStandardDisposableListener: IAddStandardDisposableListenerSignatur
257257
export function addDisposableNonBubblingMouseOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable {
258258
return addDisposableListener(node, 'mouseout', (e: MouseEvent) => {
259259
// Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements
260-
let toElement = <Node>(e.relatedTarget || e.toElement);
260+
let toElement: Node | null = <Node>(e.relatedTarget || e.toElement);
261261
while (toElement && toElement !== node) {
262262
toElement = toElement.parentNode;
263263
}
@@ -311,7 +311,7 @@ class AnimationFrameQueueItem implements IDisposable {
311311
public priority: number;
312312
private _canceled: boolean;
313313

314-
constructor(runner: () => void, priority: number) {
314+
constructor(runner: () => void, priority: number = 0) {
315315
this._runner = runner;
316316
this.priority = priority;
317317
this._canceled = false;
@@ -366,7 +366,7 @@ class AnimationFrameQueueItem implements IDisposable {
366366
inAnimationFrameRunner = true;
367367
while (CURRENT_QUEUE.length > 0) {
368368
CURRENT_QUEUE.sort(AnimationFrameQueueItem.sort);
369-
let top = CURRENT_QUEUE.shift();
369+
let top = CURRENT_QUEUE.shift()!;
370370
top.execute();
371371
}
372372
inAnimationFrameRunner = false;
@@ -387,7 +387,7 @@ class AnimationFrameQueueItem implements IDisposable {
387387
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, priority?: number) => {
388388
if (inAnimationFrameRunner) {
389389
let item = new AnimationFrameQueueItem(runner, priority);
390-
CURRENT_QUEUE.push(item);
390+
CURRENT_QUEUE!.push(item);
391391
return item;
392392
} else {
393393
return scheduleAtNextAnimationFrame(runner, priority);
@@ -407,7 +407,7 @@ export function modify(callback: () => void): IDisposable {
407407
* Add a throttled listener. `handler` is fired at most every 16ms or with the next animation frame (if browser supports it).
408408
*/
409409
export interface IEventMerger<R, E> {
410-
(lastEvent: R, currentEvent: E): R;
410+
(lastEvent: R | null, currentEvent: E): R;
411411
}
412412

413413
export interface DOMEvent {
@@ -431,7 +431,7 @@ class TimeoutThrottledDomListener<R, E extends DOMEvent> extends Disposable {
431431

432432
let invokeHandler = () => {
433433
lastHandlerTime = (new Date()).getTime();
434-
handler(lastEvent);
434+
handler(<R>lastEvent);
435435
lastEvent = null;
436436
};
437437

@@ -455,7 +455,7 @@ export function addDisposableThrottledListener<R, E extends DOMEvent = DOMEvent>
455455
}
456456

457457
export function getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
458-
return document.defaultView.getComputedStyle(el, null);
458+
return document.defaultView!.getComputedStyle(el, null);
459459
}
460460

461461
// Adapted from WinJS
@@ -660,7 +660,7 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin
660660
// modern browsers
661661
return window.scrollX;
662662
} else {
663-
return document.body.scrollLeft + document.documentElement.scrollLeft;
663+
return document.body.scrollLeft + document.documentElement!.scrollLeft;
664664
}
665665
}
666666

@@ -669,7 +669,7 @@ export const StandardWindow: IStandardWindow = new class implements IStandardWin
669669
// modern browsers
670670
return window.scrollY;
671671
} else {
672-
return document.body.scrollTop + document.documentElement.scrollTop;
672+
return document.body.scrollTop + document.documentElement!.scrollTop;
673673
}
674674
}
675675
};
@@ -728,7 +728,7 @@ export function getLargestChildWidth(parent: HTMLElement, children: HTMLElement[
728728

729729
// ----------------------------------------------------------------------------------------
730730

731-
export function isAncestor(testChild: Node, testAncestor: Node): boolean {
731+
export function isAncestor(testChild: Node | null, testAncestor: Node): boolean {
732732
while (testChild) {
733733
if (testChild === testAncestor) {
734734
return true;
@@ -739,7 +739,7 @@ export function isAncestor(testChild: Node, testAncestor: Node): boolean {
739739
return false;
740740
}
741741

742-
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement {
742+
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {
743743
while (node) {
744744
if (hasClass(node, clazz)) {
745745
return node;
@@ -1002,17 +1002,18 @@ export function $<T extends HTMLElement>(description: string, attrs?: { [key: st
10021002
result.className = match[4].replace(/\./g, ' ').trim();
10031003
}
10041004

1005-
Object.keys(attrs || {}).forEach(name => {
1005+
attrs = attrs || {};
1006+
Object.keys(attrs).forEach(name => {
1007+
const value = attrs![name];
10061008
if (/^on\w+$/.test(name)) {
1007-
(<any>result)[name] = attrs[name];
1009+
(<any>result)[name] = value;
10081010
} else if (name === 'selected') {
1009-
const value = attrs[name];
10101011
if (value) {
10111012
result.setAttribute(name, 'true');
10121013
}
10131014

10141015
} else {
1015-
result.setAttribute(name, attrs[name]);
1016+
result.setAttribute(name, value);
10161017
}
10171018
});
10181019

@@ -1061,7 +1062,7 @@ export function hide(...elements: HTMLElement[]): void {
10611062
}
10621063
}
10631064

1064-
function findParentWithAttribute(node: Node, attribute: string): HTMLElement {
1065+
function findParentWithAttribute(node: Node | null, attribute: string): HTMLElement | null {
10651066
while (node) {
10661067
if (node instanceof HTMLElement && node.hasAttribute(attribute)) {
10671068
return node;

Diff for: src/vs/base/common/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,14 @@ export function areFunctions(...objects: any[]): boolean {
129129

130130
export type TypeConstraint = string | Function;
131131

132-
export function validateConstraints(args: any[], constraints: TypeConstraint[]): void {
132+
export function validateConstraints(args: any[], constraints: (TypeConstraint | undefined)[]): void {
133133
const len = Math.min(args.length, constraints.length);
134134
for (let i = 0; i < len; i++) {
135135
validateConstraint(args[i], constraints[i]);
136136
}
137137
}
138138

139-
export function validateConstraint(arg: any, constraint: TypeConstraint): void {
139+
export function validateConstraint(arg: any, constraint: TypeConstraint | undefined): void {
140140

141141
if (isString(constraint)) {
142142
if (typeof arg !== constraint) {

Diff for: src/vs/editor/browser/config/charWidthReader.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ class DomCharWidthReader {
3333
private readonly _bareFontInfo: BareFontInfo;
3434
private readonly _requests: CharWidthRequest[];
3535

36-
private _container: HTMLElement;
37-
private _testElements: HTMLSpanElement[];
36+
private _container: HTMLElement | null;
37+
private _testElements: HTMLSpanElement[] | null;
3838

3939
constructor(bareFontInfo: BareFontInfo, requests: CharWidthRequest[]) {
4040
this._bareFontInfo = bareFontInfo;
@@ -49,13 +49,13 @@ class DomCharWidthReader {
4949
this._createDomElements();
5050

5151
// Add the container to the DOM
52-
document.body.appendChild(this._container);
52+
document.body.appendChild(this._container!);
5353

5454
// Read character widths
5555
this._readFromDomElements();
5656

5757
// Remove the container from the DOM
58-
document.body.removeChild(this._container);
58+
document.body.removeChild(this._container!);
5959

6060
this._container = null;
6161
this._testElements = null;
@@ -107,11 +107,11 @@ class DomCharWidthReader {
107107
parent = italicDomNode;
108108
}
109109

110-
parent.appendChild(document.createElement('br'));
110+
parent!.appendChild(document.createElement('br'));
111111

112112
let testElement = document.createElement('span');
113113
DomCharWidthReader._render(testElement, request);
114-
parent.appendChild(testElement);
114+
parent!.appendChild(testElement);
115115

116116
testElements[i] = testElement;
117117
}
@@ -141,7 +141,7 @@ class DomCharWidthReader {
141141
private _readFromDomElements(): void {
142142
for (let i = 0, len = this._requests.length; i < len; i++) {
143143
const request = this._requests[i];
144-
const testElement = this._testElements[i];
144+
const testElement = this._testElements![i];
145145

146146
request.fulfill(testElement.offsetWidth / 256);
147147
}

Diff for: src/vs/editor/browser/controller/coreCommands.ts

+16-13
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
77
import { Position } from 'vs/editor/common/core/position';
88
import { Range } from 'vs/editor/common/core/range';
99
import * as editorCommon from 'vs/editor/common/editorCommon';
10-
import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext, EditOperationType } from 'vs/editor/common/controller/cursorCommon';
10+
import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext, EditOperationType, PartialCursorState } from 'vs/editor/common/controller/cursorCommon';
1111
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
1212
import { CursorMoveCommands, CursorMove as CursorMove_ } from 'vs/editor/common/controller/cursorMoveCommands';
1313
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
@@ -703,14 +703,14 @@ export namespace CoreNavigationCommands {
703703
public runCoreEditorCommand(cursors: ICursors, args: any): void {
704704
const context = cursors.context;
705705

706-
let newState: CursorState;
706+
let newState: PartialCursorState;
707707
if (args.wholeLine) {
708708
newState = CursorMoveCommands.line(context, cursors.getPrimaryCursor(), false, args.position, args.viewPosition);
709709
} else {
710710
newState = CursorMoveCommands.moveTo(context, cursors.getPrimaryCursor(), false, args.position, args.viewPosition);
711711
}
712712

713-
const states = cursors.getAll();
713+
const states: PartialCursorState[] = cursors.getAll();
714714

715715
// Check if we should remove a cursor (sort of like a toggle)
716716
if (states.length > 1) {
@@ -766,8 +766,9 @@ export namespace CoreNavigationCommands {
766766

767767
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
768768

769-
let newStates = cursors.getAll().slice(0);
770-
newStates[lastAddedCursorIndex] = CursorMoveCommands.moveTo(context, newStates[lastAddedCursorIndex], true, args.position, args.viewPosition);
769+
const states = cursors.getAll();
770+
let newStates: PartialCursorState[] = states.slice(0);
771+
newStates[lastAddedCursorIndex] = CursorMoveCommands.moveTo(context, states[lastAddedCursorIndex], true, args.position, args.viewPosition);
771772

772773
cursors.context.model.pushStackElement();
773774
cursors.setStates(
@@ -846,8 +847,8 @@ export namespace CoreNavigationCommands {
846847
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
847848
}
848849

849-
private _exec(context: CursorContext, cursors: CursorState[]): CursorState[] {
850-
let result: CursorState[] = [];
850+
private _exec(context: CursorContext, cursors: CursorState[]): PartialCursorState[] {
851+
let result: PartialCursorState[] = [];
851852
for (let i = 0, len = cursors.length; i < len; i++) {
852853
const cursor = cursors[i];
853854
const lineNumber = cursor.modelState.position.lineNumber;
@@ -925,8 +926,8 @@ export namespace CoreNavigationCommands {
925926
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
926927
}
927928

928-
private _exec(context: CursorContext, cursors: CursorState[]): CursorState[] {
929-
let result: CursorState[] = [];
929+
private _exec(context: CursorContext, cursors: CursorState[]): PartialCursorState[] {
930+
let result: PartialCursorState[] = [];
930931
for (let i = 0, len = cursors.length; i < len; i++) {
931932
const cursor = cursors[i];
932933
const lineNumber = cursor.modelState.position.lineNumber;
@@ -1245,8 +1246,9 @@ export namespace CoreNavigationCommands {
12451246

12461247
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
12471248

1248-
let newStates = cursors.getAll().slice(0);
1249-
let lastAddedState = newStates[lastAddedCursorIndex];
1249+
const states = cursors.getAll();
1250+
let newStates: PartialCursorState[] = states.slice(0);
1251+
let lastAddedState = states[lastAddedCursorIndex];
12501252
newStates[lastAddedCursorIndex] = CursorMoveCommands.word(context, lastAddedState, lastAddedState.modelState.hasSelection(), args.position);
12511253

12521254
context.model.pushStackElement();
@@ -1302,8 +1304,9 @@ export namespace CoreNavigationCommands {
13021304
public runCoreEditorCommand(cursors: ICursors, args: any): void {
13031305
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
13041306

1305-
let newStates = cursors.getAll().slice(0);
1306-
newStates[lastAddedCursorIndex] = CursorMoveCommands.line(cursors.context, newStates[lastAddedCursorIndex], this._inSelectionMode, args.position, args.viewPosition);
1307+
const states = cursors.getAll();
1308+
let newStates: PartialCursorState[] = states.slice(0);
1309+
newStates[lastAddedCursorIndex] = CursorMoveCommands.line(cursors.context, states[lastAddedCursorIndex], this._inSelectionMode, args.position, args.viewPosition);
13071310

13081311
cursors.context.model.pushStackElement();
13091312
cursors.setStates(

0 commit comments

Comments
 (0)