Skip to content

Commit 6738976

Browse files
committed
More strict null checks (microsoft#60565)
1 parent 2fc4843 commit 6738976

12 files changed

Lines changed: 92 additions & 59 deletions

File tree

src/tsconfig.strictNullChecks.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@
358358
"./vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.ts",
359359
"./vs/editor/standalone/common/monarch/monarchCommon.ts",
360360
"./vs/editor/standalone/common/monarch/monarchCompile.ts",
361+
"./vs/editor/standalone/common/monarch/monarchLexer.ts",
361362
"./vs/editor/standalone/common/monarch/monarchTypes.ts",
362363
"./vs/editor/standalone/common/standaloneThemeService.ts",
363364
"./vs/editor/standalone/common/themes.ts",
@@ -565,8 +566,10 @@
565566
"./vs/workbench/parts/codeEditor/browser/menuPreventer.ts",
566567
"./vs/workbench/parts/codeEditor/browser/simpleEditorOptions.ts",
567568
"./vs/workbench/parts/codeEditor/electron-browser/accessibility.ts",
569+
"./vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts",
568570
"./vs/workbench/parts/codeEditor/electron-browser/largeFileOptimizations.ts",
569571
"./vs/workbench/parts/codeEditor/electron-browser/selectionClipboard.ts",
572+
"./vs/workbench/parts/codeEditor/electron-browser/textMate/inspectTMScopes.ts",
570573
"./vs/workbench/parts/codeEditor/electron-browser/toggleMinimap.ts",
571574
"./vs/workbench/parts/codeEditor/electron-browser/toggleMultiCursorModifier.ts",
572575
"./vs/workbench/parts/codeEditor/electron-browser/toggleRenderControlCharacter.ts",
@@ -661,6 +664,7 @@
661664
"./vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts",
662665
"./vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts",
663666
"./vs/workbench/services/extensions/node/extensionManagementServerService.ts",
667+
"./vs/workbench/services/extensions/node/extensionPoints.ts",
664668
"./vs/workbench/services/extensions/node/lazyPromise.ts",
665669
"./vs/workbench/services/extensions/node/proxyIdentifier.ts",
666670
"./vs/workbench/services/extensions/node/rpcProtocol.ts",
@@ -713,6 +717,7 @@
713717
"./vs/workbench/services/search/test/node/textSearchManager.test.ts",
714718
"./vs/workbench/services/textMate/electron-browser/TMGrammars.ts",
715719
"./vs/workbench/services/textMate/electron-browser/TMHelper.ts",
720+
"./vs/workbench/services/textMate/electron-browser/TMSyntax.ts",
716721
"./vs/workbench/services/textMate/electron-browser/textMateService.ts",
717722
"./vs/workbench/services/textfile/electron-browser/textResourcePropertiesService.ts",
718723
"./vs/workbench/services/themes/common/colorExtensionPoint.ts",

src/typings/vscode-textmate.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ declare module "vscode-textmate" {
3030
*/
3131
export interface RegistryOptions {
3232
theme?: IRawTheme;
33-
loadGrammar(scopeName: string): Thenable<IRawGrammar>;
33+
loadGrammar(scopeName: string): Thenable<IRawGrammar | null> | null;
3434
getInjections?(scopeName: string): string[];
3535
getOnigLib?(): Thenable<IOnigLib>;
3636
}
@@ -102,7 +102,7 @@ declare module "vscode-textmate" {
102102
/**
103103
* Tokenize `lineText` using previous line state `prevState`.
104104
*/
105-
tokenizeLine(lineText: string, prevState: StackElement): ITokenizeLineResult;
105+
tokenizeLine(lineText: string, prevState: StackElement | null): ITokenizeLineResult;
106106
/**
107107
* Tokenize `lineText` using previous line state `prevState`.
108108
* The result contains the tokens in binary format, resolved with the following information:
@@ -113,7 +113,7 @@ declare module "vscode-textmate" {
113113
* - background color
114114
* e.g. for getting the languageId: `(metadata & MetadataConsts.LANGUAGEID_MASK) >>> MetadataConsts.LANGUAGEID_OFFSET`
115115
*/
116-
tokenizeLine2(lineText: string, prevState: StackElement): ITokenizeLineResult2;
116+
tokenizeLine2(lineText: string, prevState: StackElement | null): ITokenizeLineResult2;
117117
}
118118
export interface ITokenizeLineResult {
119119
readonly tokens: IToken[];

src/vs/base/common/htmlContent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export class MarkdownString implements IMarkdownString {
4343
}
4444
}
4545

46-
export function isEmptyMarkdownString(oneOrMany: IMarkdownString | IMarkdownString[]): boolean {
46+
export function isEmptyMarkdownString(oneOrMany: IMarkdownString | IMarkdownString[] | null | undefined): boolean {
4747
if (isMarkdownString(oneOrMany)) {
4848
return !oneOrMany.value;
4949
} else if (Array.isArray(oneOrMany)) {

src/vs/editor/common/modes/languageConfiguration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,11 @@ export interface IndentationRule {
9696
/**
9797
* If a line matches this pattern, then **only the next line** after it should be indented once.
9898
*/
99-
indentNextLinePattern?: RegExp;
99+
indentNextLinePattern?: RegExp | null;
100100
/**
101101
* If a line matches this pattern, then its indentation should not be changed and it should not be evaluated against the other rules.
102102
*/
103-
unIndentedLinePattern?: RegExp;
103+
unIndentedLinePattern?: RegExp | null;
104104

105105
}
106106

src/vs/editor/common/modes/tokenizationRegistry.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { Color } from 'vs/base/common/color';
77
import { Emitter, Event } from 'vs/base/common/event';
8-
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
8+
import { IDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle';
99
import { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent } from 'vs/editor/common/modes';
1010

1111
export class TokenizationRegistryImpl implements ITokenizationRegistry {
@@ -43,10 +43,14 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry {
4343
});
4444
}
4545

46-
public registerPromise(language: string, supportPromise: Thenable<ITokenizationSupport>): Thenable<IDisposable> {
46+
public registerPromise(language: string, supportPromise: Thenable<ITokenizationSupport | null>): Thenable<IDisposable> {
4747
const promise = this._promises[language] = supportPromise.then(support => {
4848
delete this._promises[language];
49-
return this.register(language, support);
49+
if (support) {
50+
return this.register(language, support);
51+
} else {
52+
return Disposable.None;
53+
}
5054
});
5155
return promise;
5256
}

src/vs/editor/contrib/hover/hoverOperation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ export class HoverOperation<Result> {
5858
private _asyncComputationPromiseDone: boolean;
5959

6060
private _completeCallback: (r: Result) => void;
61-
private _errorCallback?: (err: any) => void;
61+
private _errorCallback: ((err: any) => void) | null | undefined;
6262
private _progressCallback: (progress: any) => void;
6363

64-
constructor(computer: IHoverComputer<Result>, success: (r: Result) => void, error: undefined | ((err: any) => void), progress: (progress: any) => void, hoverTime: number) {
64+
constructor(computer: IHoverComputer<Result>, success: (r: Result) => void, error: ((err: any) => void) | null | undefined, progress: (progress: any) => void, hoverTime: number) {
6565
this._computer = computer;
6666
this._state = ComputeHoverOperationState.IDLE;
6767
this._hoverTime = hoverTime;

src/vs/editor/contrib/hover/modesContentHover.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ModesContentComputer implements IHoverComputer<HoverPart[]> {
4040

4141
private _editor: ICodeEditor;
4242
private _result: HoverPart[];
43-
private _range: Range;
43+
private _range: Range | null;
4444

4545
constructor(editor: ICodeEditor) {
4646
this._editor = editor;
@@ -57,10 +57,14 @@ class ModesContentComputer implements IHoverComputer<HoverPart[]> {
5757
}
5858

5959
computeAsync(token: CancellationToken): Promise<HoverPart[]> {
60+
if (!this._editor.hasModel() || !this._range) {
61+
return Promise.resolve([]);
62+
}
63+
6064
const model = this._editor.getModel();
6165

6266
if (!HoverProviderRegistry.has(model)) {
63-
return Promise.resolve(null);
67+
return Promise.resolve([]);
6468
}
6569

6670
return getHover(model, new Position(
@@ -70,6 +74,10 @@ class ModesContentComputer implements IHoverComputer<HoverPart[]> {
7074
}
7175

7276
computeSync(): HoverPart[] {
77+
if (!this._editor.hasModel() || !this._range) {
78+
return [];
79+
}
80+
7381
const lineNumber = this._range.startLineNumber;
7482

7583
if (lineNumber > this._editor.getModel().getLineCount()) {
@@ -157,14 +165,14 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
157165
static readonly ID = 'editor.contrib.modesContentHoverWidget';
158166

159167
private _messages: HoverPart[];
160-
private _lastRange: Range;
168+
private _lastRange: Range | null;
161169
private _computer: ModesContentComputer;
162170
private _hoverOperation: HoverOperation<HoverPart[]>;
163171
private _highlightDecorations: string[];
164172
private _isChangingDecorations: boolean;
165173
private _markdownRenderer: MarkdownRenderer;
166174
private _shouldFocus: boolean;
167-
private _colorPicker: ColorPickerWidget;
175+
private _colorPicker: ColorPickerWidget | null;
168176

169177
private renderDisposable: IDisposable = Disposable.None;
170178

@@ -175,6 +183,8 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
175183
) {
176184
super(ModesContentHoverWidget.ID, editor);
177185

186+
this._messages = [];
187+
this._lastRange = null;
178188
this._computer = new ModesContentComputer(this._editor);
179189
this._highlightDecorations = [];
180190
this._isChangingDecorations = false;

src/vs/editor/standalone/common/monarch/monarchLexer.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ class MonarchClassicTokensCollector implements IMonarchTokensCollector {
260260
}
261261
this._lastTokenType = type;
262262
this._lastTokenLanguage = this._language;
263-
this._tokens.push(new Token(startOffset, type, this._language));
263+
this._tokens.push(new Token(startOffset, type, this._language!));
264264
}
265265

266266
public nestedModeTokenize(embeddedModeLine: string, embeddedModeData: EmbeddedModeData, offsetDelta: number): modes.IState {
@@ -306,7 +306,7 @@ class MonarchModernTokensCollector implements IMonarchTokensCollector {
306306
}
307307

308308
public enterMode(startOffset: number, modeId: string): void {
309-
this._currentLanguageId = this._modeService.getLanguageIdentifier(modeId).id;
309+
this._currentLanguageId = this._modeService.getLanguageIdentifier(modeId)!.id;
310310
}
311311

312312
public emit(startOffset: number, type: string): void {
@@ -417,7 +417,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
417417
}
418418

419419
public getInitialState(): modes.IState {
420-
let rootState = MonarchStackElementFactory.create(null, this._lexer.start);
420+
let rootState = MonarchStackElementFactory.create(null, this._lexer.start!);
421421
return MonarchLineStateFactory.create(rootState, null);
422422
}
423423

@@ -506,6 +506,13 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
506506
return this._myTokenize(restOfTheLine, lineState, offsetDelta + popOffset, tokensCollector);
507507
}
508508

509+
private _safeRuleName(rule: monarchCommon.IRule | null): string {
510+
if (rule) {
511+
return rule.name;
512+
}
513+
return '(unknown)';
514+
}
515+
509516
private _myTokenize(line: string, lineState: MonarchLineState, offsetDelta: number, tokensCollector: IMonarchTokensCollector): MonarchLineState {
510517
tokensCollector.enterMode(offsetDelta, this._modeId);
511518

@@ -519,7 +526,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
519526
// these never need cloning or equality since they are only used within a line match
520527
interface GroupMatching {
521528
matches: string[];
522-
rule: monarchCommon.IRule;
529+
rule: monarchCommon.IRule | null;
523530
groups: { action: monarchCommon.FuzzyAction; matched: string; }[];
524531
}
525532
let groupMatching: GroupMatching | null = null;
@@ -599,6 +606,11 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
599606
action = this._lexer.defaultToken;
600607
}
601608

609+
if (!matched) {
610+
// should never happen, needed for strict null checking
611+
break;
612+
}
613+
602614
// advance stream
603615
pos += matched.length;
604616

@@ -647,7 +659,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
647659
nextState = nextState.substr(1); // peel off starting '@'
648660
}
649661
if (!monarchCommon.findRules(this._lexer, nextState)) {
650-
throw monarchCommon.createError(this._lexer, 'trying to switch to a state \'' + nextState + '\' that is undefined in rule: ' + rule.name);
662+
throw monarchCommon.createError(this._lexer, 'trying to switch to a state \'' + nextState + '\' that is undefined in rule: ' + this._safeRuleName(rule));
651663
} else {
652664
stack = stack.switchTo(nextState);
653665
}
@@ -657,15 +669,15 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
657669
if (action.next === '@push') {
658670
if (stack.depth >= this._lexer.maxStack) {
659671
throw monarchCommon.createError(this._lexer, 'maximum tokenizer stack size reached: [' +
660-
stack.state + ',' + stack.parent.state + ',...]');
672+
stack.state + ',' + stack.parent!.state + ',...]');
661673
} else {
662674
stack = stack.push(state);
663675
}
664676
} else if (action.next === '@pop') {
665677
if (stack.depth <= 1) {
666-
throw monarchCommon.createError(this._lexer, 'trying to pop an empty stack in rule: ' + rule.name);
678+
throw monarchCommon.createError(this._lexer, 'trying to pop an empty stack in rule: ' + this._safeRuleName(rule));
667679
} else {
668-
stack = stack.pop();
680+
stack = stack.pop()!;
669681
}
670682
} else if (action.next === '@popall') {
671683
stack = stack.popall();
@@ -676,7 +688,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
676688
}
677689

678690
if (!monarchCommon.findRules(this._lexer, nextState)) {
679-
throw monarchCommon.createError(this._lexer, 'trying to set a next state \'' + nextState + '\' that is undefined in rule: ' + rule.name);
691+
throw monarchCommon.createError(this._lexer, 'trying to set a next state \'' + nextState + '\' that is undefined in rule: ' + this._safeRuleName(rule));
680692
} else {
681693
stack = stack.push(nextState);
682694
}
@@ -690,23 +702,23 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
690702

691703
// check result
692704
if (result === null) {
693-
throw monarchCommon.createError(this._lexer, 'lexer rule has no well-defined action in rule: ' + rule.name);
705+
throw monarchCommon.createError(this._lexer, 'lexer rule has no well-defined action in rule: ' + this._safeRuleName(rule));
694706
}
695707

696708
// is the result a group match?
697709
if (Array.isArray(result)) {
698710
if (groupMatching && groupMatching.groups.length > 0) {
699-
throw monarchCommon.createError(this._lexer, 'groups cannot be nested: ' + rule.name);
711+
throw monarchCommon.createError(this._lexer, 'groups cannot be nested: ' + this._safeRuleName(rule));
700712
}
701713
if (matches.length !== result.length + 1) {
702-
throw monarchCommon.createError(this._lexer, 'matched number of groups does not match the number of actions in rule: ' + rule.name);
714+
throw monarchCommon.createError(this._lexer, 'matched number of groups does not match the number of actions in rule: ' + this._safeRuleName(rule));
703715
}
704716
let totalLen = 0;
705717
for (let i = 1; i < matches.length; i++) {
706718
totalLen += matches[i].length;
707719
}
708720
if (totalLen !== matched.length) {
709-
throw monarchCommon.createError(this._lexer, 'with groups, all characters should be matched in consecutive groups in rule: ' + rule.name);
721+
throw monarchCommon.createError(this._lexer, 'with groups, all characters should be matched in consecutive groups in rule: ' + this._safeRuleName(rule));
710722
}
711723

712724
groupMatching = {
@@ -740,7 +752,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
740752
if (stackLen0 !== stack.depth || state !== stack.state || (!groupMatching ? 0 : groupMatching.groups.length) !== groupLen0) {
741753
continue;
742754
} else {
743-
throw monarchCommon.createError(this._lexer, 'no progress in tokenizer in rule: ' + rule.name);
755+
throw monarchCommon.createError(this._lexer, 'no progress in tokenizer in rule: ' + this._safeRuleName(rule));
744756
pos = lineLength; // must make progress or editor loops
745757
}
746758
}

src/vs/workbench/parts/codeEditor/electron-browser/languageConfiguration/languageConfigurationExtensionPoint.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ interface ILanguageConfiguration {
4141
autoCloseBefore?: string;
4242
}
4343

44-
function isStringArr(something: string[]): boolean {
44+
function isStringArr(something: string[] | null): something is string[] {
4545
if (!Array.isArray(something)) {
4646
return false;
4747
}
@@ -54,7 +54,7 @@ function isStringArr(something: string[]): boolean {
5454

5555
}
5656

57-
function isCharacterPair(something: CharacterPair): boolean {
57+
function isCharacterPair(something: CharacterPair | null): boolean {
5858
return (
5959
isStringArr(something)
6060
&& something.length === 2
@@ -82,7 +82,7 @@ export class LanguageConfigurationFileHandler {
8282
});
8383
});
8484
textMateService.onDidEncounterLanguage((languageId) => {
85-
this._loadConfigurationsForMode(this._modeService.getLanguageIdentifier(languageId));
85+
this._loadConfigurationsForMode(this._modeService.getLanguageIdentifier(languageId)!);
8686
});
8787
}
8888

@@ -109,7 +109,7 @@ export class LanguageConfigurationFileHandler {
109109
});
110110
}
111111

112-
private _extractValidCommentRule(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): CommentRule {
112+
private _extractValidCommentRule(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): CommentRule | null {
113113
const source = configuration.comments;
114114
if (typeof source === 'undefined') {
115115
return null;
@@ -139,7 +139,7 @@ export class LanguageConfigurationFileHandler {
139139
return result;
140140
}
141141

142-
private _extractValidBrackets(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): CharacterPair[] {
142+
private _extractValidBrackets(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): CharacterPair[] | null {
143143
const source = configuration.brackets;
144144
if (typeof source === 'undefined') {
145145
return null;
@@ -163,7 +163,7 @@ export class LanguageConfigurationFileHandler {
163163
return result;
164164
}
165165

166-
private _extractValidAutoClosingPairs(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): IAutoClosingPairConditional[] {
166+
private _extractValidAutoClosingPairs(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): IAutoClosingPairConditional[] | null {
167167
const source = configuration.autoClosingPairs;
168168
if (typeof source === 'undefined') {
169169
return null;
@@ -209,7 +209,7 @@ export class LanguageConfigurationFileHandler {
209209
return result;
210210
}
211211

212-
private _extractValidSurroundingPairs(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): IAutoClosingPair[] {
212+
private _extractValidSurroundingPairs(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): IAutoClosingPair[] | null {
213213
const source = configuration.surroundingPairs;
214214
if (typeof source === 'undefined') {
215215
return null;
@@ -327,7 +327,7 @@ export class LanguageConfigurationFileHandler {
327327
return null;
328328
}
329329

330-
private _mapIndentationRules(indentationRules: IIndentationRules): IndentationRule {
330+
private _mapIndentationRules(indentationRules: IIndentationRules): IndentationRule | null {
331331
try {
332332
let increaseIndentPattern = this._parseRegex(indentationRules.increaseIndentPattern);
333333
let decreaseIndentPattern = this._parseRegex(indentationRules.decreaseIndentPattern);

0 commit comments

Comments
 (0)