strict null checks (#60565)

This commit is contained in:
Alex Dima 2018-10-15 15:19:37 +02:00
parent 409e61c5ca
commit 5d645696cc
37 changed files with 323 additions and 286 deletions

View file

@ -75,6 +75,7 @@
"./vs/base/common/normalization.ts",
"./vs/base/common/numbers.ts",
"./vs/base/common/objects.ts",
"./vs/base/common/paging.ts",
"./vs/base/common/parsers.ts",
"./vs/base/common/paths.ts",
"./vs/base/common/platform.ts",
@ -332,12 +333,14 @@
"./vs/platform/commands/common/commands.ts",
"./vs/platform/configuration/common/configuration.ts",
"./vs/platform/configuration/common/configurationRegistry.ts",
"./vs/platform/contextkey/browser/contextKeyService.ts",
"./vs/platform/contextkey/common/contextkey.ts",
"./vs/platform/download/common/download.ts",
"./vs/platform/editor/common/editor.ts",
"./vs/platform/environment/common/environment.ts",
"./vs/platform/extensions/common/extensionHost.ts",
"./vs/platform/extensions/common/extensions.ts",
"./vs/platform/extensions/node/extensionValidator.ts",
"./vs/platform/files/common/files.ts",
"./vs/platform/files/node/files.ts",
"./vs/platform/instantiation/common/descriptors.ts",
@ -346,11 +349,14 @@
"./vs/platform/instantiation/common/instantiation.ts",
"./vs/platform/instantiation/common/serviceCollection.ts",
"./vs/platform/integrity/common/integrity.ts",
"./vs/platform/integrity/node/integrityServiceImpl.ts",
"./vs/platform/jsonschemas/common/jsonContributionRegistry.ts",
"./vs/platform/keybinding/common/abstractKeybindingService.ts",
"./vs/platform/keybinding/common/keybinding.ts",
"./vs/platform/keybinding/common/keybindingResolver.ts",
"./vs/platform/keybinding/common/keybindingsRegistry.ts",
"./vs/platform/keybinding/common/resolvedKeybindingItem.ts",
"./vs/platform/keybinding/common/usLayoutResolvedKeybinding.ts",
"./vs/platform/lifecycle/common/lifecycle.ts",
"./vs/platform/localizations/common/localizations.ts",
"./vs/platform/log/common/bufferLog.ts",
@ -400,6 +406,9 @@
"./vs/workbench/common/viewlet.ts",
"./vs/workbench/parts/codeEditor/browser/menuPreventer.ts",
"./vs/workbench/parts/codeEditor/browser/simpleEditorOptions.ts",
"./vs/workbench/parts/codeEditor/electron-browser/largeFileOptimizations.ts",
"./vs/workbench/parts/codeEditor/electron-browser/selectionClipboard.ts",
"./vs/workbench/parts/codeEditor/electron-browser/toggleWordWrap.ts",
"./vs/workbench/parts/comments/electron-browser/commentGlyphWidget.ts",
"./vs/workbench/parts/execution/common/execution.ts",
"./vs/workbench/parts/extensions/common/extensionQuery.ts",
@ -426,6 +435,8 @@
"./vs/workbench/services/configuration/common/jsonEditing.ts",
"./vs/workbench/services/configurationResolver/common/configurationResolver.ts",
"./vs/workbench/services/decorations/browser/decorations.ts",
"./vs/workbench/services/extensions/common/extensions.ts",
"./vs/workbench/services/extensions/common/extensionsRegistry.ts",
"./vs/workbench/services/extensions/node/lazyPromise.ts",
"./vs/workbench/services/extensions/node/proxyIdentifier.ts",
"./vs/workbench/services/files/node/watcher/common.ts",
@ -433,11 +444,17 @@
"./vs/workbench/services/files/node/watcher/unix/watcher.ts",
"./vs/workbench/services/hash/common/hashService.ts",
"./vs/workbench/services/hash/node/hashService.ts",
"./vs/workbench/services/keybinding/common/keybindingIO.ts",
"./vs/workbench/services/keybinding/common/keyboardMapper.ts",
"./vs/workbench/services/keybinding/common/macLinuxFallbackKeyboardMapper.ts",
"./vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts",
"./vs/workbench/services/keybinding/common/windowsKeyboardMapper.ts",
"./vs/workbench/services/panel/common/panelService.ts",
"./vs/workbench/services/scm/common/scm.ts",
"./vs/workbench/services/scm/common/scmService.ts",
"./vs/workbench/services/search/node/search.ts",
"./vs/workbench/services/textMate/electron-browser/textMateService.ts",
"./vs/workbench/services/textMate/electron-browser/TMHelper.ts",
"./vs/workbench/services/themes/common/colorThemeSchema.ts",
"./vs/workbench/services/themes/common/fileIconThemeSchema.ts",
"./vs/workbench/services/themes/common/workbenchThemeService.ts",

View file

@ -529,10 +529,10 @@ export class ResolvedKeybindingPart {
readonly altKey: boolean;
readonly metaKey: boolean;
readonly keyLabel: string;
readonly keyAriaLabel: string;
readonly keyLabel: string | null;
readonly keyAriaLabel: string | null;
constructor(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, metaKey: boolean, kbLabel: string, kbAriaLabel: string) {
constructor(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, metaKey: boolean, kbLabel: string | null, kbAriaLabel: string | null) {
this.ctrlKey = ctrlKey;
this.shiftKey = shiftKey;
this.altKey = altKey;
@ -549,20 +549,20 @@ export abstract class ResolvedKeybinding {
/**
* This prints the binding in a format suitable for displaying in the UI.
*/
public abstract getLabel(): string;
public abstract getLabel(): string | null;
/**
* This prints the binding in a format suitable for ARIA.
*/
public abstract getAriaLabel(): string;
public abstract getAriaLabel(): string | null;
/**
* This prints the binding in a format suitable for electron's accelerators.
* See https://github.com/electron/electron/blob/master/docs/api/accelerator.md
*/
public abstract getElectronAccelerator(): string;
public abstract getElectronAccelerator(): string | null;
/**
* This prints the binding in a format suitable for user settings.
*/
public abstract getUserSettingsLabel(): string;
public abstract getUserSettingsLabel(): string | null;
/**
* Is the user settings label reflecting the label?
*/
@ -576,10 +576,10 @@ export abstract class ResolvedKeybinding {
/**
* Returns the firstPart, chordPart that should be used for dispatching.
*/
public abstract getDispatchParts(): [string, string];
public abstract getDispatchParts(): [string | null, string | null];
/**
* Returns the firstPart, chordPart of the keybinding.
* For simple keybindings, the second element will be null.
*/
public abstract getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart];
public abstract getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart | null];
}

View file

@ -32,8 +32,8 @@ export class ModifierLabelProvider {
this.modifierLabels[OperatingSystem.Linux] = linux;
}
public toLabel(firstPartMod: Modifiers, firstPartKey: string, chordPartMod: Modifiers, chordPartKey: string, OS: OperatingSystem): string | null {
if (firstPartKey === null && chordPartKey === null) {
public toLabel(firstPartMod: Modifiers | null, firstPartKey: string | null, chordPartMod: Modifiers | null, chordPartKey: string | null, OS: OperatingSystem): string | null {
if (firstPartMod === null || firstPartKey === null) {
return null;
}
return _asString(firstPartMod, firstPartKey, chordPartMod, chordPartKey, this.modifierLabels[OS]);
@ -172,10 +172,10 @@ function _simpleAsString(modifiers: Modifiers, key: string, labels: ModifierLabe
return result.join(labels.separator);
}
function _asString(firstPartMod: Modifiers, firstPartKey: string, chordPartMod: Modifiers, chordPartKey: string, labels: ModifierLabels): string {
function _asString(firstPartMod: Modifiers, firstPartKey: string, chordPartMod: Modifiers | null, chordPartKey: string | null, labels: ModifierLabels): string {
let result = _simpleAsString(firstPartMod, firstPartKey, labels);
if (chordPartKey !== null) {
if (chordPartMod !== null && chordPartKey !== null) {
result += ' ';
result += _simpleAsString(chordPartMod, chordPartKey, labels);
}

View file

@ -21,8 +21,8 @@ export interface IPager<T> {
interface IPage<T> {
isResolved: boolean;
promise: Thenable<void>;
cts: CancellationTokenSource;
promise: Thenable<void> | null;
cts: CancellationTokenSource | null;
promiseIndexes: Set<number>;
elements: T[];
}
@ -52,7 +52,9 @@ export function singlePagePager<T>(elements: T[]): IPager<T> {
firstPage: elements,
total: elements.length,
pageSize: elements.length,
getPage: null
getPage: (pageIndex: number, cancellationToken: CancellationToken): Thenable<T[]> => {
return Promise.resolve(elements);
}
};
}

View file

@ -183,7 +183,7 @@ export interface IOverlayWidgetPosition {
/**
* The position preference for the overlay widget.
*/
preference: OverlayWidgetPositionPreference;
preference: OverlayWidgetPositionPreference | null;
}
/**
* An overlay widgets renders on top of the text.

View file

@ -14,7 +14,7 @@ export const IModelService = createDecorator<IModelService>('modelService');
export interface IModelService {
_serviceBrand: any;
createModel(value: string | ITextBufferFactory, modeOrPromise: Promise<IMode> | IMode, resource: URI, isForSimpleWidget?: boolean): ITextModel;
createModel(value: string | ITextBufferFactory, modeOrPromise: Promise<IMode> | IMode, resource: URI | undefined, isForSimpleWidget?: boolean): ITextModel;
updateModel(model: ITextModel, value: string | ITextBufferFactory): void;

View file

@ -77,7 +77,7 @@ const nlsSingleSelection = nls.localize("singleSelection", "Line {0}, Column {1}
const nlsMultiSelectionRange = nls.localize("multiSelectionRange", "{0} selections ({1} characters selected)");
const nlsMultiSelection = nls.localize("multiSelection", "{0} selections");
function getSelectionLabel(selections: Selection[], charactersSelected: number): string {
function getSelectionLabel(selections: Selection[] | null, charactersSelected: number): string | null {
if (!selections || selections.length === 0) {
return nlsNoSelection;
}
@ -257,13 +257,13 @@ class AccessibilityHelpWidget extends Widget implements IOverlayWidget {
}
}
const turnOnMessage = (
platform.isMacintosh
? nls.localize("changeConfigToOnMac", "To configure the editor to be optimized for usage with a Screen Reader press Command+E now.")
: nls.localize("changeConfigToOnWinLinux", "To configure the editor to be optimized for usage with a Screen Reader press Control+E now.")
);
switch (opts.accessibilitySupport) {
case platform.AccessibilitySupport.Unknown:
const turnOnMessage = (
platform.isMacintosh
? nls.localize("changeConfigToOnMac", "To configure the editor to be optimized for usage with a Screen Reader press Command+E now.")
: nls.localize("changeConfigToOnWinLinux", "To configure the editor to be optimized for usage with a Screen Reader press Control+E now.")
);
text += '\n\n - ' + turnOnMessage;
break;
case platform.AccessibilitySupport.Enabled:

View file

@ -121,9 +121,9 @@ export class SimpleEditorModelResolverService implements ITextModelService {
};
}
private findModel(editor: ICodeEditor, resource: URI): ITextModel {
private findModel(editor: ICodeEditor, resource: URI): ITextModel | null {
let model = editor.getModel();
if (model.uri.toString() !== resource.toString()) {
if (model && model.uri.toString() !== resource.toString()) {
return null;
}
@ -256,7 +256,7 @@ export class StandaloneCommandService implements ICommandService {
}
export class StandaloneKeybindingService extends AbstractKeybindingService {
private _cachedResolver: KeybindingResolver;
private _cachedResolver: KeybindingResolver | null;
private _dynamicKeybindings: IKeybindingItem[];
constructor(
@ -280,7 +280,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
}));
}
public addDynamicKeybinding(commandId: string, keybinding: number, handler: ICommandHandler, when: ContextKeyExpr): IDisposable {
public addDynamicKeybinding(commandId: string, keybinding: number, handler: ICommandHandler, when: ContextKeyExpr | null): IDisposable {
let toDispose: IDisposable[] = [];
this._dynamicKeybindings.push({
@ -411,7 +411,7 @@ export class SimpleConfigurationService implements IConfigurationService {
public updateValue(key: string, value: any, arg3?: any, arg4?: any): Promise<void> {
this.configuration().updateValue(key, value);
return Promise.resolve(null);
return Promise.resolve();
}
public inspect<C>(key: string, options: IConfigurationOverrides = {}): {

View file

@ -122,13 +122,13 @@ export interface IDiffEditorConstructionOptions extends IDiffEditorOptions {
}
export interface IStandaloneCodeEditor extends ICodeEditor {
addCommand(keybinding: number, handler: ICommandHandler, context: string): string;
addCommand(keybinding: number, handler: ICommandHandler, context: string): string | null;
createContextKey<T>(key: string, defaultValue: T): IContextKey<T>;
addAction(descriptor: IActionDescriptor): IDisposable;
}
export interface IStandaloneDiffEditor extends IDiffEditor {
addCommand(keybinding: number, handler: ICommandHandler, context: string): string;
addCommand(keybinding: number, handler: ICommandHandler, context: string): string | null;
createContextKey<T>(key: string, defaultValue: T): IContextKey<T>;
addAction(descriptor: IActionDescriptor): IDisposable;
@ -182,7 +182,7 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon
createAriaDomNode();
}
public addCommand(keybinding: number, handler: ICommandHandler, context: string): string {
public addCommand(keybinding: number, handler: ICommandHandler, context: string): string | null {
if (!this._standaloneKeybindingService) {
console.warn('Cannot add command because the editor is configured with an unrecognized KeybindingService');
return null;
@ -284,7 +284,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
constructor(
domElement: HTMLElement,
options: IEditorConstructionOptions,
options: IEditorConstructionOptions | undefined,
toDispose: IDisposable,
@IInstantiationService instantiationService: IInstantiationService,
@ICodeEditorService codeEditorService: ICodeEditorService,
@ -301,7 +301,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
if (typeof options.theme === 'string') {
themeService.setTheme(options.theme);
}
let model: ITextModel = options.model;
let _model: ITextModel | null | undefined = options.model;
delete options.model;
super(domElement, options, instantiationService, codeEditorService, commandService, contextKeyService, keybindingService, themeService, notificationService);
@ -309,10 +309,12 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
this._configurationService = configurationService;
this._register(toDispose);
if (typeof model === 'undefined') {
let model: ITextModel | null;
if (typeof _model === 'undefined') {
model = (<any>self).monaco.editor.createModel(options.value || '', options.language || 'text/plain');
this._ownsModel = true;
} else {
model = _model;
this._ownsModel = false;
}
@ -335,7 +337,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
super.updateOptions(newOptions);
}
_attachModel(model: ITextModel): void {
_attachModel(model: ITextModel | null): void {
super._attachModel(model);
if (this._modelData) {
this._contextViewService.setContainer(this._modelData.view.domNode.domNode);
@ -407,7 +409,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
return <StandaloneCodeEditor>super.getModifiedEditor();
}
public addCommand(keybinding: number, handler: ICommandHandler, context: string): string {
public addCommand(keybinding: number, handler: ICommandHandler, context: string): string | null {
return this.getModifiedEditor().addCommand(keybinding, handler, context);
}

View file

@ -65,7 +65,7 @@ function withAllStandaloneServices<T extends editorCommon.IEditor>(domElement: H
* The editor will read the size of `domElement`.
*/
export function create(domElement: HTMLElement, options?: IEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneCodeEditor {
return withAllStandaloneServices(domElement, override, (services) => {
return withAllStandaloneServices(domElement, override || {}, (services) => {
return new StandaloneEditor(
domElement,
options,
@ -188,7 +188,7 @@ export function getModelMarkers(filter: { owner?: string, resource?: URI, take?:
/**
* Get the model that has `uri` if it exists.
*/
export function getModel(uri: URI): ITextModel {
export function getModel(uri: URI): ITextModel | null {
return StaticServices.modelService.get().getModel(uri);
}

View file

@ -39,7 +39,7 @@ export function getLanguages(): ILanguageExtensionPoint[] {
export function getEncodedLanguageId(languageId: string): number {
let lid = StaticServices.modeService.get().getLanguageIdentifier(languageId);
return lid && lid.id;
return lid ? lid.id : 0;
}
/**
@ -347,7 +347,7 @@ export function registerHoverProvider(languageId: string, provider: modes.HoverP
provideHover: (model: model.ITextModel, position: Position, token: CancellationToken): Thenable<modes.Hover> => {
let word = model.getWordAtPosition(position);
return Promise.resolve<modes.Hover>(provider.provideHover(model, position, token)).then((value) => {
return Promise.resolve<modes.Hover | null | undefined>(provider.provideHover(model, position, token)).then((value) => {
if (!value) {
return undefined;
}

View file

@ -130,11 +130,8 @@ export function log(lexer: ILexerMin, msg: string) {
// Throwing errors
/**
* Throws error. May actually just log the error and continue.
*/
export function throwError(lexer: ILexerMin, msg: string) {
throw new Error(`${lexer.languageId}: ${msg}`);
export function createError(lexer: ILexerMin, msg: string): Error {
return new Error(`${lexer.languageId}: ${msg}`);
}
// Helper functions for rule finding and substitution

View file

@ -70,9 +70,9 @@ function compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp {
sub = lexer[attr].source;
} else {
if (lexer[attr] === undefined) {
monarchCommon.throwError(lexer, 'language definition does not contain attribute \'' + attr + '\', used at: ' + str);
throw monarchCommon.createError(lexer, 'language definition does not contain attribute \'' + attr + '\', used at: ' + str);
} else {
monarchCommon.throwError(lexer, 'attribute reference \'' + attr + '\' must be a string, used at: ' + str);
throw monarchCommon.createError(lexer, 'attribute reference \'' + attr + '\' must be a string, used at: ' + str);
}
}
return (monarchCommon.empty(sub) ? '' : '(?:' + sub + ')');
@ -148,10 +148,10 @@ function createGuard(lexer: monarchCommon.ILexerMin, ruleName: string, tkey: str
else if (op === '@' || op === '!@') {
let words = lexer[pat];
if (!words) {
monarchCommon.throwError(lexer, 'the @ match target \'' + pat + '\' is not defined, in rule: ' + ruleName);
throw monarchCommon.createError(lexer, 'the @ match target \'' + pat + '\' is not defined, in rule: ' + ruleName);
}
if (!(isArrayOf(function (elem) { return (typeof (elem) === 'string'); }, words))) {
monarchCommon.throwError(lexer, 'the @ match target \'' + pat + '\' must be an array of strings, in rule: ' + ruleName);
throw monarchCommon.createError(lexer, 'the @ match target \'' + pat + '\' must be an array of strings, in rule: ' + ruleName);
}
let inWords = objects.createKeywordMatcher(words, lexer.ignoreCase);
tester = function (s) { return (op === '@' ? inWords(s) : !inWords(s)); };
@ -218,7 +218,7 @@ function compileAction(lexer: monarchCommon.ILexerMin, ruleName: string, action:
}
else if (action.token || action.token === '') {
if (typeof (action.token) !== 'string') {
monarchCommon.throwError(lexer, 'a \'token\' attribute must be of type string, in rule: ' + ruleName);
throw monarchCommon.createError(lexer, 'a \'token\' attribute must be of type string, in rule: ' + ruleName);
return { token: '' };
}
else {
@ -233,12 +233,12 @@ function compileAction(lexer: monarchCommon.ILexerMin, ruleName: string, action:
} else if (action.bracket === '@close') {
newAction.bracket = monarchCommon.MonarchBracket.Close;
} else {
monarchCommon.throwError(lexer, 'a \'bracket\' attribute must be either \'@open\' or \'@close\', in rule: ' + ruleName);
throw monarchCommon.createError(lexer, 'a \'bracket\' attribute must be either \'@open\' or \'@close\', in rule: ' + ruleName);
}
}
if (action.next) {
if (typeof (action.next) !== 'string') {
monarchCommon.throwError(lexer, 'the next state must be a string value in rule: ' + ruleName);
throw monarchCommon.createError(lexer, 'the next state must be a string value in rule: ' + ruleName);
}
else {
let next: string = action.next;
@ -248,7 +248,7 @@ function compileAction(lexer: monarchCommon.ILexerMin, ruleName: string, action:
}
if (next.indexOf('$') < 0) { // no dollar substitution, we can check if the state exists
if (!monarchCommon.stateExists(lexer, monarchCommon.substituteMatches(lexer, next, '', [], ''))) {
monarchCommon.throwError(lexer, 'the next state \'' + action.next + '\' is not defined in rule: ' + ruleName);
throw monarchCommon.createError(lexer, 'the next state \'' + action.next + '\' is not defined in rule: ' + ruleName);
}
}
}
@ -320,7 +320,7 @@ function compileAction(lexer: monarchCommon.ILexerMin, ruleName: string, action:
};
}
else {
monarchCommon.throwError(lexer, 'an action must be a string, an object with a \'token\' or \'cases\' attribute, or an array of actions; in rule: ' + ruleName);
throw monarchCommon.createError(lexer, 'an action must be a string, an object with a \'token\' or \'cases\' attribute, or an array of actions; in rule: ' + ruleName);
return '';
}
}
@ -347,7 +347,7 @@ class Rule implements monarchCommon.IRule {
sregex = (<RegExp>re).source;
}
else {
return monarchCommon.throwError(lexer, 'rules must start with a match string or regular expression: ' + this.name);
throw monarchCommon.createError(lexer, 'rules must start with a match string or regular expression: ' + this.name);
}
this.matchOnlyAtLineStart = (sregex.length > 0 && sregex[0] === '^');
@ -407,13 +407,13 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm
let include = rule.include;
if (include) {
if (typeof (include) !== 'string') {
monarchCommon.throwError(lexer, 'an \'include\' attribute must be a string at: ' + state);
throw monarchCommon.createError(lexer, 'an \'include\' attribute must be a string at: ' + state);
}
if (include[0] === '@') {
include = include.substr(1); // peel off starting @
}
if (!json.tokenizer[include]) {
monarchCommon.throwError(lexer, 'include target \'' + include + '\' is not defined at: ' + state);
throw monarchCommon.createError(lexer, 'include target \'' + include + '\' is not defined at: ' + state);
}
addRules(state + '.' + include, newrules, json.tokenizer[include]);
}
@ -434,7 +434,7 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm
newrule.setAction(lexerMin, rule1);
}
else {
monarchCommon.throwError(lexer, 'a next state as the last element of a rule can only be given if the action is either an object or a string, at: ' + state);
throw monarchCommon.createError(lexer, 'a next state as the last element of a rule can only be given if the action is either an object or a string, at: ' + state);
}
}
else {
@ -443,7 +443,7 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm
}
else {
if (!rule.regex) {
monarchCommon.throwError(lexer, 'a rule must either be an array, or an object with a \'regex\' or \'include\' field at: ' + state);
throw monarchCommon.createError(lexer, 'a rule must either be an array, or an object with a \'regex\' or \'include\' field at: ' + state);
}
if (rule.name) {
if (typeof rule.name === 'string') {
@ -465,7 +465,7 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm
// compile the tokenizer rules
if (!json.tokenizer || typeof (json.tokenizer) !== 'object') {
monarchCommon.throwError(lexer, 'a language definition must define the \'tokenizer\' attribute as an object');
throw monarchCommon.createError(lexer, 'a language definition must define the \'tokenizer\' attribute as an object');
}
lexer.tokenizer = <any>[];
@ -485,7 +485,7 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm
// Set simple brackets
if (json.brackets) {
if (!(Array.isArray(<any>json.brackets))) {
monarchCommon.throwError(lexer, 'the \'brackets\' attribute must be defined as an array');
throw monarchCommon.createError(lexer, 'the \'brackets\' attribute must be defined as an array');
}
}
else {
@ -503,7 +503,7 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm
desc = { token: desc[2], open: desc[0], close: desc[1] };
}
if (desc.open === desc.close) {
monarchCommon.throwError(lexer, 'open and close brackets in a \'brackets\' attribute must be different: ' + desc.open +
throw monarchCommon.createError(lexer, 'open and close brackets in a \'brackets\' attribute must be different: ' + desc.open +
'\n hint: use the \'bracket\' attribute if matching on equal brackets is required.');
}
if (typeof desc.open === 'string' && typeof desc.token === 'string' && typeof desc.close === 'string') {
@ -514,7 +514,7 @@ export function compile(languageId: string, json: IMonarchLanguage): monarchComm
});
}
else {
monarchCommon.throwError(lexer, 'every element in the \'brackets\' array must be a \'{open,close,token}\' object or array');
throw monarchCommon.createError(lexer, 'every element in the \'brackets\' array must be a \'{open,close,token}\' object or array');
}
}
}

View file

@ -25,7 +25,7 @@ const CACHE_STACK_DEPTH = 5;
class MonarchStackElementFactory {
private static readonly _INSTANCE = new MonarchStackElementFactory(CACHE_STACK_DEPTH);
public static create(parent: MonarchStackElement, state: string): MonarchStackElement {
public static create(parent: MonarchStackElement | null, state: string): MonarchStackElement {
return this._INSTANCE.create(parent, state);
}
@ -37,7 +37,7 @@ class MonarchStackElementFactory {
this._entries = Object.create(null);
}
public create(parent: MonarchStackElement, state: string): MonarchStackElement {
public create(parent: MonarchStackElement | null, state: string): MonarchStackElement {
if (parent !== null && parent.depth >= this._maxCacheDepth) {
// no caching above a certain depth
return new MonarchStackElement(parent, state);
@ -60,17 +60,17 @@ class MonarchStackElementFactory {
class MonarchStackElement {
public readonly parent: MonarchStackElement;
public readonly parent: MonarchStackElement | null;
public readonly state: string;
public readonly depth: number;
constructor(parent: MonarchStackElement, state: string) {
constructor(parent: MonarchStackElement | null, state: string) {
this.parent = parent;
this.state = state;
this.depth = (this.parent ? this.parent.depth : 0) + 1;
}
public static getStackElementId(element: MonarchStackElement): string {
public static getStackElementId(element: MonarchStackElement | null): string {
let result = '';
while (element !== null) {
if (result.length > 0) {
@ -82,7 +82,7 @@ class MonarchStackElement {
return result;
}
private static _equals(a: MonarchStackElement, b: MonarchStackElement): boolean {
private static _equals(a: MonarchStackElement | null, b: MonarchStackElement | null): boolean {
while (a !== null && b !== null) {
if (a === b) {
return true;
@ -107,7 +107,7 @@ class MonarchStackElement {
return MonarchStackElementFactory.create(this, state);
}
public pop(): MonarchStackElement {
public pop(): MonarchStackElement | null {
return this.parent;
}
@ -156,7 +156,7 @@ class EmbeddedModeData {
class MonarchLineStateFactory {
private static readonly _INSTANCE = new MonarchLineStateFactory(CACHE_STACK_DEPTH);
public static create(stack: MonarchStackElement, embeddedModeData: EmbeddedModeData): MonarchLineState {
public static create(stack: MonarchStackElement, embeddedModeData: EmbeddedModeData | null): MonarchLineState {
return this._INSTANCE.create(stack, embeddedModeData);
}
@ -168,7 +168,7 @@ class MonarchLineStateFactory {
this._entries = Object.create(null);
}
public create(stack: MonarchStackElement, embeddedModeData: EmbeddedModeData): MonarchLineState {
public create(stack: MonarchStackElement, embeddedModeData: EmbeddedModeData | null): MonarchLineState {
if (embeddedModeData !== null) {
// no caching when embedding
return new MonarchLineState(stack, embeddedModeData);
@ -192,11 +192,11 @@ class MonarchLineStateFactory {
class MonarchLineState implements modes.IState {
public readonly stack: MonarchStackElement;
public readonly embeddedModeData: EmbeddedModeData;
public readonly embeddedModeData: EmbeddedModeData | null;
constructor(
stack: MonarchStackElement,
embeddedModeData: EmbeddedModeData
embeddedModeData: EmbeddedModeData | null
) {
this.stack = stack;
this.embeddedModeData = embeddedModeData;
@ -239,9 +239,9 @@ interface IMonarchTokensCollector {
class MonarchClassicTokensCollector implements IMonarchTokensCollector {
private _tokens: Token[];
private _language: string;
private _lastTokenType: string;
private _lastTokenLanguage: string;
private _language: string | null;
private _lastTokenType: string | null;
private _lastTokenLanguage: string | null;
constructor() {
this._tokens = [];
@ -291,7 +291,7 @@ class MonarchModernTokensCollector implements IMonarchTokensCollector {
private _modeService: IModeService;
private _theme: TokenTheme;
private _prependTokens: Uint32Array;
private _prependTokens: Uint32Array | null;
private _tokens: number[];
private _currentLanguageId: modes.LanguageId;
private _lastTokenMetadata: number;
@ -319,7 +319,7 @@ class MonarchModernTokensCollector implements IMonarchTokensCollector {
this._tokens.push(metadata);
}
private static _merge(a: Uint32Array, b: number[], c: Uint32Array): Uint32Array {
private static _merge(a: Uint32Array | null, b: number[], c: Uint32Array | null): Uint32Array {
let aLen = (a !== null ? a.length : 0);
let bLen = b.length;
let cLen = (c !== null ? c.length : 0);
@ -328,10 +328,10 @@ class MonarchModernTokensCollector implements IMonarchTokensCollector {
return new Uint32Array(0);
}
if (aLen === 0 && bLen === 0) {
return c;
return c!;
}
if (bLen === 0 && cLen === 0) {
return a;
return a!;
}
let result = new Uint32Array(aLen + bLen + cLen);
@ -442,11 +442,11 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
}
private _findLeavingNestedModeOffset(line: string, state: MonarchLineState): number {
let rules = this._lexer.tokenizer[state.stack.state];
let rules: monarchCommon.IRule[] | null = this._lexer.tokenizer[state.stack.state];
if (!rules) {
rules = monarchCommon.findRules(this._lexer, state.stack.state); // do parent matching
if (!rules) {
monarchCommon.throwError(this._lexer, 'tokenizer state is not defined: ' + state.stack.state);
throw monarchCommon.createError(this._lexer, 'tokenizer state is not defined: ' + state.stack.state);
}
}
@ -480,7 +480,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
}
if (!hasEmbeddedPopRule) {
monarchCommon.throwError(this._lexer, 'no rule containing nextEmbedded: "@pop" in tokenizer embedded state: ' + state.stack.state);
throw monarchCommon.createError(this._lexer, 'no rule containing nextEmbedded: "@pop" in tokenizer embedded state: ' + state.stack.state);
}
return popOffset;
@ -492,14 +492,14 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
if (popOffset === -1) {
// tokenization will not leave nested mode
let nestedEndState = tokensCollector.nestedModeTokenize(line, lineState.embeddedModeData, offsetDelta);
return MonarchLineStateFactory.create(lineState.stack, new EmbeddedModeData(lineState.embeddedModeData.modeId, nestedEndState));
let nestedEndState = tokensCollector.nestedModeTokenize(line, lineState.embeddedModeData!, offsetDelta);
return MonarchLineStateFactory.create(lineState.stack, new EmbeddedModeData(lineState.embeddedModeData!.modeId, nestedEndState));
}
let nestedModeLine = line.substring(0, popOffset);
if (nestedModeLine.length > 0) {
// tokenize with the nested mode
tokensCollector.nestedModeTokenize(nestedModeLine, lineState.embeddedModeData, offsetDelta);
tokensCollector.nestedModeTokenize(nestedModeLine, lineState.embeddedModeData!, offsetDelta);
}
let restOfTheLine = line.substring(popOffset);
@ -517,37 +517,37 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
// regular expression group matching
// these never need cloning or equality since they are only used within a line match
let groupActions: monarchCommon.FuzzyAction[] = null;
let groupMatches: string[] | null = null;
let groupMatched: string[] | null = null;
let groupRule: monarchCommon.IRule = null;
interface GroupMatching {
matches: string[];
rule: monarchCommon.IRule;
groups: { action: monarchCommon.FuzzyAction; matched: string; }[];
}
let groupMatching: GroupMatching | null = null;
while (pos < lineLength) {
const pos0 = pos;
const stackLen0 = stack.depth;
const groupLen0 = groupActions ? groupActions.length : 0;
const groupLen0 = groupMatching ? groupMatching.groups.length : 0;
const state = stack.state;
let matches: string[] | null = null;
let matched: string | null = null;
let action: monarchCommon.FuzzyAction | monarchCommon.FuzzyAction[] = null;
let rule: monarchCommon.IRule = null;
let action: monarchCommon.FuzzyAction | monarchCommon.FuzzyAction[] | null = null;
let rule: monarchCommon.IRule | null = null;
let enteringEmbeddedMode: string | null = null;
// check if we need to process group matches first
if (groupActions) {
matches = groupMatches;
matched = groupMatched.shift();
action = groupActions.shift();
rule = groupRule;
if (groupMatching) {
matches = groupMatching.matches;
const groupEntry = groupMatching.groups.shift()!;
matched = groupEntry.matched;
action = groupEntry.action;
rule = groupMatching.rule;
// cleanup if necessary
if (groupActions.length === 0) {
groupActions = null;
groupMatches = null;
groupMatched = null;
groupRule = null;
if (groupMatching.groups.length === 0) {
groupMatching = null;
}
} else {
// otherwise we match on the token stream
@ -558,11 +558,11 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
}
// get the rules for this state
let rules = this._lexer.tokenizer[state];
let rules: monarchCommon.IRule[] | null = this._lexer.tokenizer[state];
if (!rules) {
rules = monarchCommon.findRules(this._lexer, state); // do parent matching
if (!rules) {
monarchCommon.throwError(this._lexer, 'tokenizer state is not defined: ' + state);
throw monarchCommon.createError(this._lexer, 'tokenizer state is not defined: ' + state);
}
}
@ -607,7 +607,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
action = action.test(matched, matches, state, pos === lineLength);
}
let result: monarchCommon.FuzzyAction | monarchCommon.FuzzyAction[] = null;
let result: monarchCommon.FuzzyAction | monarchCommon.FuzzyAction[] | null = null;
// set the result: either a string or an array of actions
if (typeof action === 'string' || Array.isArray(action)) {
result = action;
@ -626,11 +626,11 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
if (action.nextEmbedded) {
if (action.nextEmbedded === '@pop') {
if (!embeddedModeData) {
monarchCommon.throwError(this._lexer, 'cannot pop embedded mode if not inside one');
throw monarchCommon.createError(this._lexer, 'cannot pop embedded mode if not inside one');
}
embeddedModeData = null;
} else if (embeddedModeData) {
monarchCommon.throwError(this._lexer, 'cannot enter embedded mode from within an embedded mode');
throw monarchCommon.createError(this._lexer, 'cannot enter embedded mode from within an embedded mode');
} else {
enteringEmbeddedMode = monarchCommon.substituteMatches(this._lexer, action.nextEmbedded, matched, matches, state);
}
@ -647,23 +647,23 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
nextState = nextState.substr(1); // peel off starting '@'
}
if (!monarchCommon.findRules(this._lexer, nextState)) {
monarchCommon.throwError(this._lexer, 'trying to switch to a state \'' + nextState + '\' that is undefined in rule: ' + rule.name);
throw monarchCommon.createError(this._lexer, 'trying to switch to a state \'' + nextState + '\' that is undefined in rule: ' + rule.name);
} else {
stack = stack.switchTo(nextState);
}
} else if (action.transform && typeof action.transform === 'function') {
monarchCommon.throwError(this._lexer, 'action.transform not supported');
throw monarchCommon.createError(this._lexer, 'action.transform not supported');
} else if (action.next) {
if (action.next === '@push') {
if (stack.depth >= this._lexer.maxStack) {
monarchCommon.throwError(this._lexer, 'maximum tokenizer stack size reached: [' +
throw monarchCommon.createError(this._lexer, 'maximum tokenizer stack size reached: [' +
stack.state + ',' + stack.parent.state + ',...]');
} else {
stack = stack.push(state);
}
} else if (action.next === '@pop') {
if (stack.depth <= 1) {
monarchCommon.throwError(this._lexer, 'trying to pop an empty stack in rule: ' + rule.name);
throw monarchCommon.createError(this._lexer, 'trying to pop an empty stack in rule: ' + rule.name);
} else {
stack = stack.pop();
}
@ -676,7 +676,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
}
if (!monarchCommon.findRules(this._lexer, nextState)) {
monarchCommon.throwError(this._lexer, 'trying to set a next state \'' + nextState + '\' that is undefined in rule: ' + rule.name);
throw monarchCommon.createError(this._lexer, 'trying to set a next state \'' + nextState + '\' that is undefined in rule: ' + rule.name);
} else {
stack = stack.push(nextState);
}
@ -690,28 +690,37 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
// check result
if (result === null) {
monarchCommon.throwError(this._lexer, 'lexer rule has no well-defined action in rule: ' + rule.name);
throw monarchCommon.createError(this._lexer, 'lexer rule has no well-defined action in rule: ' + rule.name);
}
// is the result a group match?
if (Array.isArray(result)) {
if (groupActions && groupActions.length > 0) {
monarchCommon.throwError(this._lexer, 'groups cannot be nested: ' + rule.name);
if (groupMatching && groupMatching.groups.length > 0) {
throw monarchCommon.createError(this._lexer, 'groups cannot be nested: ' + rule.name);
}
if (matches.length !== result.length + 1) {
monarchCommon.throwError(this._lexer, 'matched number of groups does not match the number of actions in rule: ' + rule.name);
throw monarchCommon.createError(this._lexer, 'matched number of groups does not match the number of actions in rule: ' + rule.name);
}
let totalLen = 0;
for (let i = 1; i < matches.length; i++) {
totalLen += matches[i].length;
}
if (totalLen !== matched.length) {
monarchCommon.throwError(this._lexer, 'with groups, all characters should be matched in consecutive groups in rule: ' + rule.name);
throw monarchCommon.createError(this._lexer, 'with groups, all characters should be matched in consecutive groups in rule: ' + rule.name);
}
groupMatches = matches;
groupMatched = matches.slice(1);
groupActions = result.slice(0);
groupRule = rule;
groupMatching = {
rule: rule,
matches: matches,
groups: []
};
for (let i = 0; i < result.length; i++) {
groupMatching.groups[i] = {
action: result[i],
matched: matches[i + 1]
};
}
pos -= matched.length;
// call recursively to initiate first result match
continue;
@ -728,10 +737,10 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
// check progress
if (matched.length === 0) {
if (stackLen0 !== stack.depth || state !== stack.state || (!groupActions ? 0 : groupActions.length) !== groupLen0) {
if (stackLen0 !== stack.depth || state !== stack.state || (!groupMatching ? 0 : groupMatching.groups.length) !== groupLen0) {
continue;
} else {
monarchCommon.throwError(this._lexer, 'no progress in tokenizer in rule: ' + rule.name);
throw monarchCommon.createError(this._lexer, 'no progress in tokenizer in rule: ' + rule.name);
pos = lineLength; // must make progress or editor loops
}
}
@ -743,7 +752,7 @@ class MonarchTokenizer implements modes.ITokenizationSupport {
let rest = result.substr('@brackets'.length);
let bracket = findBracket(this._lexer, matched);
if (!bracket) {
monarchCommon.throwError(this._lexer, '@brackets token returned but no bracket defined as: ' + matched);
throw monarchCommon.createError(this._lexer, '@brackets token returned but no bracket defined as: ' + matched);
bracket = { token: '', bracketType: monarchCommon.MonarchBracket.None };
}
tokenType = monarchCommon.sanitize(bracket.token + rest);

8
src/vs/monaco.d.ts vendored
View file

@ -879,7 +879,7 @@ declare namespace monaco.editor {
/**
* Get the model that has `uri` if it exists.
*/
export function getModel(uri: Uri): ITextModel;
export function getModel(uri: Uri): ITextModel | null;
/**
* Get all the created models.
@ -1092,13 +1092,13 @@ declare namespace monaco.editor {
}
export interface IStandaloneCodeEditor extends ICodeEditor {
addCommand(keybinding: number, handler: ICommandHandler, context: string): string;
addCommand(keybinding: number, handler: ICommandHandler, context: string): string | null;
createContextKey<T>(key: string, defaultValue: T): IContextKey<T>;
addAction(descriptor: IActionDescriptor): IDisposable;
}
export interface IStandaloneDiffEditor extends IDiffEditor {
addCommand(keybinding: number, handler: ICommandHandler, context: string): string;
addCommand(keybinding: number, handler: ICommandHandler, context: string): string | null;
createContextKey<T>(key: string, defaultValue: T): IContextKey<T>;
addAction(descriptor: IActionDescriptor): IDisposable;
getOriginalEditor(): IStandaloneCodeEditor;
@ -3623,7 +3623,7 @@ declare namespace monaco.editor {
/**
* The position preference for the overlay widget.
*/
preference: OverlayWidgetPositionPreference;
preference: OverlayWidgetPositionPreference | null;
}
/**

View file

@ -15,11 +15,11 @@ const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';
export class Context implements IContext {
protected _parent: Context;
protected _parent: Context | null;
protected _value: { [key: string]: any; };
protected _id: number;
constructor(id: number, parent: Context) {
constructor(id: number, parent: Context | null) {
this._id = id;
this._parent = parent;
this._value = Object.create(null);
@ -311,7 +311,7 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon
class ScopedContextKeyService extends AbstractContextKeyService {
private _parent: AbstractContextKeyService;
private _domNode: IContextKeyServiceTarget;
private _domNode: IContextKeyServiceTarget | undefined;
constructor(parent: AbstractContextKeyService, emitter: Emitter<string | string[]>, domNode?: IContextKeyServiceTarget) {
super(parent.createChildContext());
@ -349,10 +349,14 @@ class ScopedContextKeyService extends AbstractContextKeyService {
}
}
function findContextAttr(domNode: IContextKeyServiceTarget): number {
function findContextAttr(domNode: IContextKeyServiceTarget | null): number {
while (domNode) {
if (domNode.hasAttribute(KEYBINDING_CONTEXT_ATTR)) {
return parseInt(domNode.getAttribute(KEYBINDING_CONTEXT_ATTR), 10);
const attr = domNode.getAttribute(KEYBINDING_CONTEXT_ATTR);
if (attr) {
return parseInt(attr, 10);
}
return NaN;
}
domNode = domNode.parentElement;
}

View file

@ -42,7 +42,7 @@ export abstract class ContextKeyExpr {
return new ContextKeyAndExpr(expr);
}
public static deserialize(serialized: string): ContextKeyExpr | null {
public static deserialize(serialized: string | null | undefined): ContextKeyExpr | null {
if (!serialized) {
return null;
}

View file

@ -15,7 +15,7 @@ export interface IParsedVersion {
minorMustEqual: boolean;
patchBase: number;
patchMustEqual: boolean;
preRelease: string;
preRelease: string | null;
}
export interface INormalizedVersion {
@ -35,7 +35,7 @@ export function isValidVersionStr(version: string): boolean {
return (version === '*' || VERSION_REGEXP.test(version));
}
export function parseVersion(version: string): IParsedVersion {
export function parseVersion(version: string): IParsedVersion | null {
if (!isValidVersionStr(version)) {
return null;
}
@ -57,6 +57,9 @@ export function parseVersion(version: string): IParsedVersion {
}
let m = version.match(VERSION_REGEXP);
if (!m) {
return null;
}
return {
hasCaret: m[1] === '^',
hasGreaterEquals: m[1] === '>=',
@ -70,7 +73,7 @@ export function parseVersion(version: string): IParsedVersion {
};
}
export function normalizeVersion(version: IParsedVersion): INormalizedVersion {
export function normalizeVersion(version: IParsedVersion | null): INormalizedVersion | null {
if (!version) {
return null;
}
@ -103,14 +106,14 @@ export function normalizeVersion(version: IParsedVersion): INormalizedVersion {
}
export function isValidVersion(_version: string | INormalizedVersion, _desiredVersion: string | INormalizedVersion): boolean {
let version: INormalizedVersion;
let version: INormalizedVersion | null;
if (typeof _version === 'string') {
version = normalizeVersion(parseVersion(_version));
} else {
version = _version;
}
let desiredVersion: INormalizedVersion;
let desiredVersion: INormalizedVersion | null;
if (typeof _desiredVersion === 'string') {
desiredVersion = normalizeVersion(parseVersion(_desiredVersion));
} else {

View file

@ -16,21 +16,21 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
interface IStorageData {
dontShowPrompt: boolean;
commit: string;
commit: string | undefined;
}
class IntegrityStorage {
private static readonly KEY = 'integrityService';
private storageService: IStorageService;
private value: IStorageData;
private value: IStorageData | null;
constructor(storageService: IStorageService) {
this.storageService = storageService;
this.value = this._read();
}
private _read(): IStorageData {
private _read(): IStorageData | null {
let jsonValue = this.storageService.get(IntegrityStorage.KEY, StorageScope.GLOBAL);
if (!jsonValue) {
return null;
@ -42,11 +42,11 @@ class IntegrityStorage {
}
}
get(): IStorageData {
get(): IStorageData | null {
return this.value;
}
set(data: IStorageData): void {
set(data: IStorageData | null): void {
this.value = data;
this.storageService.store(IntegrityStorage.KEY, JSON.stringify(this.value), StorageScope.GLOBAL);
}

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as arrays from 'vs/base/common/arrays';
import { ResolvedKeybinding, Keybinding, KeyCode } from 'vs/base/common/keyCodes';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { ICommandService } from 'vs/platform/commands/common/commands';
@ -19,19 +20,19 @@ import { IntervalTimer } from 'vs/base/common/async';
interface CurrentChord {
keypress: string;
label: string;
label: string | null;
}
export abstract class AbstractKeybindingService extends Disposable implements IKeybindingService {
public _serviceBrand: any;
private _currentChord: CurrentChord;
private _currentChord: CurrentChord | null;
private _currentChordChecker: IntervalTimer;
private _currentChordStatusMessage: IDisposable;
private _currentChordStatusMessage: IDisposable | null;
protected _onDidUpdateKeybindings: Emitter<IKeybindingEvent>;
private _contextKeyService: IContextKeyService;
private _statusService: IStatusbarService;
private _statusService: IStatusbarService | undefined;
private _notificationService: INotificationService;
protected _commandService: ICommandService;
protected _telemetryService: ITelemetryService;
@ -87,10 +88,12 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
}
public lookupKeybindings(commandId: string): ResolvedKeybinding[] {
return this._getResolver().lookupKeybindings(commandId).map(item => item.resolvedKeybinding);
return arrays.coalesce(
this._getResolver().lookupKeybindings(commandId).map(item => item.resolvedKeybinding)
);
}
public lookupKeybinding(commandId: string): ResolvedKeybinding {
public lookupKeybinding(commandId: string): ResolvedKeybinding | null {
let result = this._getResolver().lookupPrimaryKeybinding(commandId);
if (!result) {
return null;
@ -98,7 +101,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
return result.resolvedKeybinding;
}
public softDispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult {
public softDispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult | null {
const keybinding = this.resolveKeyboardEvent(e);
if (keybinding.isChord()) {
console.warn('Unexpected keyboard event mapped to a chord');
@ -115,7 +118,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
return this._getResolver().resolve(contextValue, currentChord, firstPart);
}
private _enterChordMode(firstPart: string, keypressLabel: string): void {
private _enterChordMode(firstPart: string, keypressLabel: string | null): void {
this._currentChord = {
keypress: firstPart,
label: keypressLabel
@ -155,7 +158,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
const keybinding = this.resolveKeyboardEvent(e);
if (keybinding.isChord()) {
console.warn('Unexpected keyboard event mapped to a chord');
return null;
return false;
}
const [firstPart,] = keybinding.getDispatchParts();
if (firstPart === null) {

View file

@ -55,7 +55,7 @@ export interface IKeybindingService {
/**
* Resolve and dispatch `keyboardEvent`, but do not invoke the command or change inner state.
*/
softDispatch(keyboardEvent: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult;
softDispatch(keyboardEvent: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult | null;
/**
* Look up keybindings for a command.
@ -67,7 +67,7 @@ export interface IKeybindingService {
* Look up the preferred (last defined) keybinding for a command.
* @returns The preferred keybinding or null if the command is not bound.
*/
lookupKeybinding(commandId: string): ResolvedKeybinding;
lookupKeybinding(commandId: string): ResolvedKeybinding | null;
getDefaultKeybindingsContent(): string;

View file

@ -29,7 +29,9 @@ export class KeybindingResolver {
this._defaultBoundCommands = new Map<string, boolean>();
for (let i = 0, len = defaultKeybindings.length; i < len; i++) {
const command = defaultKeybindings[i].command;
this._defaultBoundCommands.set(command, true);
if (command) {
this._defaultBoundCommands.set(command, true);
}
}
this._map = new Map<string, ResolvedKeybindingItem[]>();
@ -47,7 +49,7 @@ export class KeybindingResolver {
}
}
private static _isTargetedForRemoval(defaultKb: ResolvedKeybindingItem, keypressFirstPart: string | null, keypressChordPart: string | null, command: string, when: ContextKeyExpr): boolean {
private static _isTargetedForRemoval(defaultKb: ResolvedKeybindingItem, keypressFirstPart: string | null, keypressChordPart: string | null, command: string, when: ContextKeyExpr | null): boolean {
if (defaultKb.command !== command) {
return false;
}
@ -147,6 +149,9 @@ export class KeybindingResolver {
}
private _removeFromLookupMap(item: ResolvedKeybindingItem): void {
if (!item.command) {
return;
}
let arr = this._lookupMap.get(item.command);
if (typeof arr === 'undefined') {
return;
@ -163,7 +168,7 @@ export class KeybindingResolver {
* Returns true if it is provable `a` implies `b`.
* **Precondition**: Assumes `a` and `b` are normalized!
*/
public static whenIsEntirelyIncluded(a: ContextKeyExpr, b: ContextKeyExpr): boolean {
public static whenIsEntirelyIncluded(a: ContextKeyExpr | null, b: ContextKeyExpr | null): boolean {
if (!b) {
return true;
}
@ -229,7 +234,7 @@ export class KeybindingResolver {
return items[items.length - 1];
}
public resolve(context: IContext, currentChord: string, keypress: string): IResolveResult | null {
public resolve(context: IContext, currentChord: string | null, keypress: string): IResolveResult | null {
let lookupMap: ResolvedKeybindingItem[] | null = null;
if (currentChord !== null) {
@ -294,7 +299,7 @@ export class KeybindingResolver {
return null;
}
public static contextMatchesRules(context: IContext, rules: ContextKeyExpr): boolean {
public static contextMatchesRules(context: IContext, rules: ContextKeyExpr | null): boolean {
if (!rules) {
return true;
}

View file

@ -42,13 +42,13 @@ export interface IKeybindingRule extends IKeybindings {
}
export interface IKeybindingRule2 {
primary: Keybinding;
win?: { primary: Keybinding; };
linux?: { primary: Keybinding; };
mac?: { primary: Keybinding; };
primary: Keybinding | null;
win?: { primary: Keybinding | null; } | null;
linux?: { primary: Keybinding | null; } | null;
mac?: { primary: Keybinding | null; } | null;
id: string;
weight: number;
when: ContextKeyExpr;
when: ContextKeyExpr | null;
}
export const enum KeybindingRuleSource {
@ -110,7 +110,7 @@ class KeybindingsRegistryImpl implements IKeybindingsRegistry {
/**
* Take current platform into account and reduce to primary & secondary.
*/
private static bindToCurrentPlatform2(kb: IKeybindingRule2): { primary?: Keybinding; } {
private static bindToCurrentPlatform2(kb: IKeybindingRule2): { primary?: Keybinding | null; } {
if (OS === OperatingSystem.Windows) {
if (kb && kb.win) {
return kb.win;

View file

@ -10,16 +10,16 @@ import { CharCode } from 'vs/base/common/charCode';
export class ResolvedKeybindingItem {
_resolvedKeybindingItemBrand: void;
public readonly resolvedKeybinding: ResolvedKeybinding;
public readonly resolvedKeybinding: ResolvedKeybinding | null;
public readonly keypressFirstPart: string | null;
public readonly keypressChordPart: string | null;
public readonly bubble: boolean;
public readonly command: string;
public readonly command: string | null;
public readonly commandArgs: any;
public readonly when: ContextKeyExpr;
public readonly when: ContextKeyExpr | null;
public readonly isDefault: boolean;
constructor(resolvedKeybinding: ResolvedKeybinding, command: string, commandArgs: any, when: ContextKeyExpr, isDefault: boolean) {
constructor(resolvedKeybinding: ResolvedKeybinding | null, command: string | null, commandArgs: any, when: ContextKeyExpr | null, isDefault: boolean) {
this.resolvedKeybinding = resolvedKeybinding;
if (resolvedKeybinding) {
let [keypressFirstPart, keypressChordPart] = resolvedKeybinding.getDispatchParts();
@ -30,7 +30,7 @@ export class ResolvedKeybindingItem {
this.keypressChordPart = null;
}
this.bubble = (command ? command.charCodeAt(0) === CharCode.Caret : false);
this.command = this.bubble ? command.substr(1) : command;
this.command = this.bubble ? command!.substr(1) : command;
this.commandArgs = commandArgs;
this.when = when;
this.isDefault = isDefault;

View file

@ -14,12 +14,12 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
private readonly _os: OperatingSystem;
private readonly _firstPart: SimpleKeybinding;
private readonly _chordPart: SimpleKeybinding;
private readonly _chordPart: SimpleKeybinding | null;
constructor(actual: Keybinding, OS: OperatingSystem) {
super();
this._os = OS;
if (actual === null) {
if (!actual) {
throw new Error(`Invalid USLayoutResolvedKeybinding`);
} else if (actual.type === KeybindingType.Chord) {
this._firstPart = actual.firstPart;
@ -46,7 +46,7 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
return KeyCodeUtils.toString(keyCode);
}
private _getUILabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getUILabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -56,13 +56,13 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
return this._keyCodeToUILabel(keybinding.keyCode);
}
public getLabel(): string {
public getLabel(): string | null {
let firstPart = this._getUILabelForKeybinding(this._firstPart);
let chordPart = this._getUILabelForKeybinding(this._chordPart);
return UILabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, this._os);
}
private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -72,13 +72,13 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
return KeyCodeUtils.toString(keybinding.keyCode);
}
public getAriaLabel(): string {
public getAriaLabel(): string | null {
let firstPart = this._getAriaLabelForKeybinding(this._firstPart);
let chordPart = this._getAriaLabelForKeybinding(this._chordPart);
return AriaLabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, this._os);
}
private _keyCodeToElectronAccelerator(keyCode: KeyCode): string {
private _keyCodeToElectronAccelerator(keyCode: KeyCode): string | null {
if (keyCode >= KeyCode.NUMPAD_0 && keyCode <= KeyCode.NUMPAD_DIVIDE) {
// Electron cannot handle numpad keys
return null;
@ -98,7 +98,7 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
return KeyCodeUtils.toString(keyCode);
}
private _getElectronAcceleratorLabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getElectronAcceleratorLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -108,7 +108,7 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
return this._keyCodeToElectronAccelerator(keybinding.keyCode);
}
public getElectronAccelerator(): string {
public getElectronAccelerator(): string | null {
if (this._chordPart !== null) {
// Electron cannot handle chords
return null;
@ -118,7 +118,7 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
return ElectronAcceleratorLabelProvider.toLabel(this._firstPart, firstPart, null, null, this._os);
}
private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -128,7 +128,7 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
return KeyCodeUtils.toUserSettingsUS(keybinding.keyCode);
}
public getUserSettingsLabel(): string {
public getUserSettingsLabel(): string | null {
let firstPart = this._getUserSettingsLabelForKeybinding(this._firstPart);
let chordPart = this._getUserSettingsLabelForKeybinding(this._chordPart);
let result = UserSettingsLabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, this._os);
@ -143,18 +143,14 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
return (this._chordPart ? true : false);
}
public getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart] {
public getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart | null] {
return [
this._toResolvedKeybindingPart(this._firstPart),
this._toResolvedKeybindingPart(this._chordPart)
this._chordPart ? this._toResolvedKeybindingPart(this._chordPart) : null
];
}
private _toResolvedKeybindingPart(keybinding: SimpleKeybinding): ResolvedKeybindingPart {
if (!keybinding) {
return null;
}
return new ResolvedKeybindingPart(
keybinding.ctrlKey,
keybinding.shiftKey,
@ -165,13 +161,13 @@ export class USLayoutResolvedKeybinding extends ResolvedKeybinding {
);
}
public getDispatchParts(): [string, string] {
public getDispatchParts(): [string | null, string | null] {
let firstPart = this._firstPart ? USLayoutResolvedKeybinding.getDispatchStr(this._firstPart) : null;
let chordPart = this._chordPart ? USLayoutResolvedKeybinding.getDispatchStr(this._chordPart) : null;
return [firstPart, chordPart];
}
public static getDispatchStr(keybinding: SimpleKeybinding): string {
public static getDispatchStr(keybinding: SimpleKeybinding): string | null {
if (keybinding.isModifierKey()) {
return null;
}

View file

@ -30,7 +30,7 @@ export class LargeFileOptimizationsWarner extends Disposable implements IEditorC
) {
super();
this._isDisabled = this._storageService.getBoolean('editor.neverPromptForLargeFiles', StorageScope.GLOBAL, false);
this._isDisabled = Boolean(this._storageService.getBoolean('editor.neverPromptForLargeFiles', StorageScope.GLOBAL, false));
this._register(this._editor.onDidChangeModel((e) => {
const model = this._editor.getModel();

View file

@ -36,18 +36,18 @@ export class SelectionClipboard extends Disposable implements IEditorContributio
if (!isEnabled) {
return;
}
if (!editor.getModel()) {
if (!editor.hasModel()) {
return;
}
if (e.event.middleButton) {
e.event.preventDefault();
editor.focus();
if (e.target.position) {
if (e.target && e.target.position) {
editor.setPosition(e.target.position);
}
if (e.target.type === MouseTargetType.SCROLLBAR) {
if (e.target && e.target.type === MouseTargetType.SCROLLBAR) {
return;
}
@ -63,11 +63,10 @@ export class SelectionClipboard extends Disposable implements IEditorContributio
}));
let setSelectionToClipboard = this._register(new RunOnceScheduler(() => {
let model = editor.getModel();
if (!model) {
if (!editor.hasModel()) {
return;
}
let model = editor.getModel();
let selections = editor.getSelections();
selections = selections.slice(0);
selections.sort(Range.compareRangesUsingStarts);

View file

@ -33,15 +33,15 @@ interface IWordWrapTransientState {
}
interface IWordWrapState {
readonly configuredWordWrap: 'on' | 'off' | 'wordWrapColumn' | 'bounded';
readonly configuredWordWrap: 'on' | 'off' | 'wordWrapColumn' | 'bounded' | undefined;
readonly configuredWordWrapMinified: boolean;
readonly transientState: IWordWrapTransientState;
readonly transientState: IWordWrapTransientState | null;
}
/**
* Store (in memory) the word wrap state for a particular model.
*/
function writeTransientState(model: ITextModel, state: IWordWrapTransientState, codeEditorService: ICodeEditorService): void {
function writeTransientState(model: ITextModel, state: IWordWrapTransientState | null, codeEditorService: ICodeEditorService): void {
codeEditorService.setTransientModelProperty(model, transientWordWrapState, state);
}
@ -131,6 +131,9 @@ class ToggleWordWrapAction extends EditorAction {
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
if (!editor.hasModel()) {
return;
}
const editorConfiguration = editor.getConfiguration();
if (editorConfiguration.wrappingInfo.inDiffEditor) {
// Cannot change wrapping settings inside the diff editor

View file

@ -71,8 +71,8 @@ export interface IExtensionPoint<T> {
export class ExtensionPoint<T> implements IExtensionPoint<T> {
public readonly name: string;
private _handler: IExtensionPointHandler<T>;
private _users: IExtensionPointUser<T>[];
private _handler: IExtensionPointHandler<T> | null;
private _users: IExtensionPointUser<T>[] | null;
private _done: boolean;
constructor(name: string) {

View file

@ -12,16 +12,19 @@ import { ScanCodeBinding } from 'vs/base/common/scanCode';
import { KeybindingParser } from 'vs/base/common/keybindingParser';
export interface IUserKeybindingItem {
firstPart: SimpleKeybinding | ScanCodeBinding;
chordPart: SimpleKeybinding | ScanCodeBinding;
command: string;
firstPart: SimpleKeybinding | ScanCodeBinding | null;
chordPart: SimpleKeybinding | ScanCodeBinding | null;
command: string | null;
commandArgs?: any;
when: ContextKeyExpr;
when: ContextKeyExpr | null;
}
export class KeybindingIO {
public static writeKeybindingItem(out: OutputBuilder, item: ResolvedKeybindingItem, OS: OperatingSystem): void {
if (!item.resolvedKeybinding) {
return;
}
let quotedSerializedKeybinding = JSON.stringify(item.resolvedKeybinding.getUserSettingsLabel());
out.write(`{ "key": ${rightPaddedString(quotedSerializedKeybinding + ',', 25)} "command": `);

View file

@ -11,7 +11,7 @@ export interface IKeyboardMapper {
dumpDebugInfo(): string;
resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[];
resolveKeyboardEvent(keyboardEvent: IKeyboardEvent): ResolvedKeybinding;
resolveUserBinding(firstPart: SimpleKeybinding | ScanCodeBinding, chordPart: SimpleKeybinding | ScanCodeBinding): ResolvedKeybinding[];
resolveUserBinding(firstPart: SimpleKeybinding | ScanCodeBinding | null, chordPart: SimpleKeybinding | ScanCodeBinding | null): ResolvedKeybinding[];
}
export class CachedKeyboardMapper implements IKeyboardMapper {

View file

@ -103,7 +103,7 @@ export class MacLinuxFallbackKeyboardMapper implements IKeyboardMapper {
return KeyCode.Unknown;
}
private _resolveSimpleUserBinding(binding: SimpleKeybinding | ScanCodeBinding): SimpleKeybinding {
private _resolveSimpleUserBinding(binding: SimpleKeybinding | ScanCodeBinding | null): SimpleKeybinding | null {
if (!binding) {
return null;
}
@ -117,7 +117,7 @@ export class MacLinuxFallbackKeyboardMapper implements IKeyboardMapper {
return new SimpleKeybinding(binding.ctrlKey, binding.shiftKey, binding.altKey, binding.metaKey, keyCode);
}
public resolveUserBinding(firstPart: SimpleKeybinding | ScanCodeBinding, chordPart: SimpleKeybinding | ScanCodeBinding): ResolvedKeybinding[] {
public resolveUserBinding(firstPart: SimpleKeybinding | ScanCodeBinding | null, chordPart: SimpleKeybinding | ScanCodeBinding | null): ResolvedKeybinding[] {
const _firstPart = this._resolveSimpleUserBinding(firstPart);
const _chordPart = this._resolveSimpleUserBinding(chordPart);
if (_firstPart && _chordPart) {

View file

@ -37,7 +37,7 @@ export interface IMacLinuxKeyboardMapping {
[scanCode: string]: IMacLinuxKeyMapping;
}
export function macLinuxKeyboardMappingEquals(a: IMacLinuxKeyboardMapping, b: IMacLinuxKeyboardMapping): boolean {
export function macLinuxKeyboardMappingEquals(a: IMacLinuxKeyboardMapping | null, b: IMacLinuxKeyboardMapping | null): boolean {
if (!a && !b) {
return true;
}
@ -61,16 +61,16 @@ export function macLinuxKeyboardMappingEquals(a: IMacLinuxKeyboardMapping, b: IM
* - '/' => { keyCode: KeyCode.US_SLASH, shiftKey: false }
* - '?' => { keyCode: KeyCode.US_SLASH, shiftKey: true }
*/
const CHAR_CODE_TO_KEY_CODE: { keyCode: KeyCode; shiftKey: boolean }[] = [];
const CHAR_CODE_TO_KEY_CODE: ({ keyCode: KeyCode; shiftKey: boolean } | null)[] = [];
export class NativeResolvedKeybinding extends ResolvedKeybinding {
private readonly _mapper: MacLinuxKeyboardMapper;
private readonly _OS: OperatingSystem;
private readonly _firstPart: ScanCodeBinding;
private readonly _chordPart: ScanCodeBinding;
private readonly _chordPart: ScanCodeBinding | null;
constructor(mapper: MacLinuxKeyboardMapper, OS: OperatingSystem, firstPart: ScanCodeBinding, chordPart: ScanCodeBinding) {
constructor(mapper: MacLinuxKeyboardMapper, OS: OperatingSystem, firstPart: ScanCodeBinding, chordPart: ScanCodeBinding | null) {
super();
if (!firstPart) {
throw new Error(`Invalid USLayoutResolvedKeybinding`);
@ -81,19 +81,19 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding {
this._chordPart = chordPart;
}
public getLabel(): string {
public getLabel(): string | null {
let firstPart = this._mapper.getUILabelForScanCodeBinding(this._firstPart);
let chordPart = this._mapper.getUILabelForScanCodeBinding(this._chordPart);
return UILabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, this._OS);
}
public getAriaLabel(): string {
public getAriaLabel(): string | null {
let firstPart = this._mapper.getAriaLabelForScanCodeBinding(this._firstPart);
let chordPart = this._mapper.getAriaLabelForScanCodeBinding(this._chordPart);
return AriaLabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, this._OS);
}
public getElectronAccelerator(): string {
public getElectronAccelerator(): string | null {
if (this._chordPart !== null) {
// Electron cannot handle chords
return null;
@ -103,13 +103,13 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding {
return ElectronAcceleratorLabelProvider.toLabel(this._firstPart, firstPart, null, null, this._OS);
}
public getUserSettingsLabel(): string {
public getUserSettingsLabel(): string | null {
let firstPart = this._mapper.getUserSettingsLabelForScanCodeBinding(this._firstPart);
let chordPart = this._mapper.getUserSettingsLabelForScanCodeBinding(this._chordPart);
return UserSettingsLabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, this._OS);
}
private _isWYSIWYG(binding: ScanCodeBinding): boolean {
private _isWYSIWYG(binding: ScanCodeBinding | null): boolean {
if (!binding) {
return true;
}
@ -136,18 +136,14 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding {
return (this._chordPart ? true : false);
}
public getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart] {
public getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart | null] {
return [
this._toResolvedKeybindingPart(this._firstPart),
this._toResolvedKeybindingPart(this._chordPart)
this._chordPart ? this._toResolvedKeybindingPart(this._chordPart) : null
];
}
private _toResolvedKeybindingPart(binding: ScanCodeBinding): ResolvedKeybindingPart {
if (!binding) {
return null;
}
return new ResolvedKeybindingPart(
binding.ctrlKey,
binding.shiftKey,
@ -158,7 +154,7 @@ export class NativeResolvedKeybinding extends ResolvedKeybinding {
);
}
public getDispatchParts(): [string, string] {
public getDispatchParts(): [string | null, string | null] {
let firstPart = this._firstPart ? this._mapper.getDispatchStrForScanCodeBinding(this._firstPart) : null;
let chordPart = this._chordPart ? this._mapper.getDispatchStrForScanCodeBinding(this._chordPart) : null;
return [firstPart, chordPart];
@ -449,11 +445,11 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
/**
* UI label for a ScanCode.
*/
private readonly _scanCodeToLabel: string[] = [];
private readonly _scanCodeToLabel: (string | null)[] = [];
/**
* Dispatching string for a ScanCode.
*/
private readonly _scanCodeToDispatch: string[] = [];
private readonly _scanCodeToDispatch: (string | null)[] = [];
constructor(isUSStandard: boolean, rawMappings: IMacLinuxKeyboardMapping, OS: OperatingSystem) {
this._isUSStandard = isUSStandard;
@ -838,7 +834,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return result.join('\n');
}
private _leftPad(str: string, cnt: number): string {
private _leftPad(str: string | null, cnt: number): string {
if (str === null) {
str = 'null';
}
@ -866,7 +862,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return result;
}
public getUILabelForScanCodeBinding(binding: ScanCodeBinding): string {
public getUILabelForScanCodeBinding(binding: ScanCodeBinding | null): string | null {
if (!binding) {
return null;
}
@ -888,7 +884,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return this._scanCodeToLabel[binding.scanCode];
}
public getAriaLabelForScanCodeBinding(binding: ScanCodeBinding): string {
public getAriaLabelForScanCodeBinding(binding: ScanCodeBinding | null): string | null {
if (!binding) {
return null;
}
@ -898,7 +894,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return this._scanCodeToLabel[binding.scanCode];
}
public getDispatchStrForScanCodeBinding(keypress: ScanCodeBinding): string {
public getDispatchStrForScanCodeBinding(keypress: ScanCodeBinding): string | null {
const codeDispatch = this._scanCodeToDispatch[keypress.scanCode];
if (!codeDispatch) {
return null;
@ -922,7 +918,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return result;
}
public getUserSettingsLabelForScanCodeBinding(binding: ScanCodeBinding): string {
public getUserSettingsLabelForScanCodeBinding(binding: ScanCodeBinding | null): string | null {
if (!binding) {
return null;
}
@ -951,7 +947,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return this._scanCodeToDispatch[binding.scanCode];
}
private _getElectronLabelForKeyCode(keyCode: KeyCode): string {
private _getElectronLabelForKeyCode(keyCode: KeyCode): string | null {
if (keyCode >= KeyCode.NUMPAD_0 && keyCode <= KeyCode.NUMPAD_DIVIDE) {
// Electron cannot handle numpad keys
return null;
@ -972,7 +968,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return KeyCodeUtils.toString(keyCode);
}
public getElectronAcceleratorLabelForScanCodeBinding(binding: ScanCodeBinding): string {
public getElectronAcceleratorLabelForScanCodeBinding(binding: ScanCodeBinding | null): string | null {
if (!binding) {
return null;
}
@ -1101,7 +1097,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return new NativeResolvedKeybinding(this, this._OS, keypress, null);
}
private _resolveSimpleUserBinding(binding: SimpleKeybinding | ScanCodeBinding): ScanCodeBinding[] {
private _resolveSimpleUserBinding(binding: SimpleKeybinding | ScanCodeBinding | null): ScanCodeBinding[] {
if (!binding) {
return [];
}
@ -1111,7 +1107,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return this.simpleKeybindingToScanCodeBinding(binding);
}
public resolveUserBinding(_firstPart: SimpleKeybinding | ScanCodeBinding, _chordPart: SimpleKeybinding | ScanCodeBinding): ResolvedKeybinding[] {
public resolveUserBinding(_firstPart: SimpleKeybinding | ScanCodeBinding | null, _chordPart: SimpleKeybinding | ScanCodeBinding | null): ResolvedKeybinding[] {
const firstParts = this._resolveSimpleUserBinding(_firstPart);
const chordParts = this._resolveSimpleUserBinding(_chordPart);
@ -1131,7 +1127,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
return result;
}
private static _charCodeToKb(charCode: number): { keyCode: KeyCode; shiftKey: boolean } {
private static _charCodeToKb(charCode: number): { keyCode: KeyCode; shiftKey: boolean } | null {
if (charCode < CHAR_CODE_TO_KEY_CODE.length) {
return CHAR_CODE_TO_KEY_CODE[charCode];
}

View file

@ -39,7 +39,7 @@ export interface IWindowsKeyboardMapping {
[scanCode: string]: IWindowsKeyMapping;
}
export function windowsKeyboardMappingEquals(a: IWindowsKeyboardMapping, b: IWindowsKeyboardMapping): boolean {
export function windowsKeyboardMappingEquals(a: IWindowsKeyboardMapping | null, b: IWindowsKeyboardMapping | null): boolean {
if (!a && !b) {
return true;
}
@ -80,9 +80,9 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
private readonly _mapper: WindowsKeyboardMapper;
private readonly _firstPart: SimpleKeybinding;
private readonly _chordPart: SimpleKeybinding;
private readonly _chordPart: SimpleKeybinding | null;
constructor(mapper: WindowsKeyboardMapper, firstPart: SimpleKeybinding, chordPart: SimpleKeybinding) {
constructor(mapper: WindowsKeyboardMapper, firstPart: SimpleKeybinding, chordPart: SimpleKeybinding | null) {
super();
if (!firstPart) {
throw new Error(`Invalid WindowsNativeResolvedKeybinding firstPart`);
@ -92,7 +92,7 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
this._chordPart = chordPart;
}
private _getUILabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getUILabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -102,13 +102,13 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return this._mapper.getUILabelForKeyCode(keybinding.keyCode);
}
public getLabel(): string {
public getLabel(): string | null {
let firstPart = this._getUILabelForKeybinding(this._firstPart);
let chordPart = this._getUILabelForKeybinding(this._chordPart);
return UILabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, OperatingSystem.Windows);
}
private _getUSLabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getUSLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -118,13 +118,13 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return KeyCodeUtils.toString(keybinding.keyCode);
}
public getUSLabel(): string {
public getUSLabel(): string | null {
let firstPart = this._getUSLabelForKeybinding(this._firstPart);
let chordPart = this._getUSLabelForKeybinding(this._chordPart);
return UILabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, OperatingSystem.Windows);
}
private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getAriaLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -134,13 +134,13 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return this._mapper.getAriaLabelForKeyCode(keybinding.keyCode);
}
public getAriaLabel(): string {
public getAriaLabel(): string | null {
let firstPart = this._getAriaLabelForKeybinding(this._firstPart);
let chordPart = this._getAriaLabelForKeybinding(this._chordPart);
return AriaLabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, OperatingSystem.Windows);
}
private _keyCodeToElectronAccelerator(keyCode: KeyCode): string {
private _keyCodeToElectronAccelerator(keyCode: KeyCode): string | null {
if (keyCode >= KeyCode.NUMPAD_0 && keyCode <= KeyCode.NUMPAD_DIVIDE) {
// Electron cannot handle numpad keys
return null;
@ -161,7 +161,7 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return KeyCodeUtils.toString(keyCode);
}
private _getElectronAcceleratorLabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getElectronAcceleratorLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -171,7 +171,7 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return this._keyCodeToElectronAccelerator(keybinding.keyCode);
}
public getElectronAccelerator(): string {
public getElectronAccelerator(): string | null {
if (this._chordPart !== null) {
// Electron cannot handle chords
return null;
@ -181,7 +181,7 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return ElectronAcceleratorLabelProvider.toLabel(this._firstPart, firstPart, null, null, OperatingSystem.Windows);
}
private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding): string {
private _getUserSettingsLabelForKeybinding(keybinding: SimpleKeybinding | null): string | null {
if (!keybinding) {
return null;
}
@ -191,7 +191,7 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return this._mapper.getUserSettingsLabelForKeyCode(keybinding.keyCode);
}
public getUserSettingsLabel(): string {
public getUserSettingsLabel(): string | null {
let firstPart = this._getUserSettingsLabelForKeybinding(this._firstPart);
let chordPart = this._getUserSettingsLabelForKeybinding(this._chordPart);
let result = UserSettingsLabelProvider.toLabel(this._firstPart, firstPart, this._chordPart, chordPart, OperatingSystem.Windows);
@ -226,18 +226,14 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return (this._chordPart ? true : false);
}
public getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart] {
public getParts(): [ResolvedKeybindingPart, ResolvedKeybindingPart | null] {
return [
this._toResolvedKeybindingPart(this._firstPart),
this._toResolvedKeybindingPart(this._chordPart)
this._chordPart ? this._toResolvedKeybindingPart(this._chordPart) : null
];
}
private _toResolvedKeybindingPart(keybinding: SimpleKeybinding): ResolvedKeybindingPart {
if (!keybinding) {
return null;
}
return new ResolvedKeybindingPart(
keybinding.ctrlKey,
keybinding.shiftKey,
@ -248,13 +244,13 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
);
}
public getDispatchParts(): [string, string] {
public getDispatchParts(): [string | null, string | null] {
let firstPart = this._firstPart ? this._getDispatchStr(this._firstPart) : null;
let chordPart = this._chordPart ? this._getDispatchStr(this._chordPart) : null;
return [firstPart, chordPart];
}
private _getDispatchStr(keybinding: SimpleKeybinding): string {
private _getDispatchStr(keybinding: SimpleKeybinding): string | null {
if (keybinding.isModifierKey()) {
return null;
}
@ -277,7 +273,7 @@ export class WindowsNativeResolvedKeybinding extends ResolvedKeybinding {
return result;
}
private static getProducedCharCode(kb: ScanCodeBinding, mapping: IScanCodeMapping): string {
private static getProducedCharCode(kb: ScanCodeBinding, mapping: IScanCodeMapping): string | null {
if (!mapping) {
return null;
}
@ -307,7 +303,7 @@ export class WindowsKeyboardMapper implements IKeyboardMapper {
public readonly isUSStandard: boolean;
private readonly _codeInfo: IScanCodeMapping[];
private readonly _scanCodeToKeyCode: KeyCode[];
private readonly _keyCodeToLabel: string[] = [];
private readonly _keyCodeToLabel: (string | null)[] = [];
private readonly _keyCodeExists: boolean[];
constructor(isUSStandard: boolean, rawMappings: IWindowsKeyboardMapping) {
@ -492,7 +488,7 @@ export class WindowsKeyboardMapper implements IKeyboardMapper {
return result.join('\n');
}
private _leftPad(str: string, cnt: number): string {
private _leftPad(str: string | null, cnt: number): string {
if (str === null) {
str = 'null';
}
@ -542,7 +538,7 @@ export class WindowsKeyboardMapper implements IKeyboardMapper {
return new WindowsNativeResolvedKeybinding(this, keybinding, null);
}
private _resolveSimpleUserBinding(binding: SimpleKeybinding | ScanCodeBinding): SimpleKeybinding {
private _resolveSimpleUserBinding(binding: SimpleKeybinding | ScanCodeBinding | null): SimpleKeybinding | null {
if (!binding) {
return null;
}
@ -559,7 +555,7 @@ export class WindowsKeyboardMapper implements IKeyboardMapper {
return new SimpleKeybinding(binding.ctrlKey, binding.shiftKey, binding.altKey, binding.metaKey, keyCode);
}
public resolveUserBinding(firstPart: SimpleKeybinding | ScanCodeBinding, chordPart: SimpleKeybinding | ScanCodeBinding): ResolvedKeybinding[] {
public resolveUserBinding(firstPart: SimpleKeybinding | ScanCodeBinding | null, chordPart: SimpleKeybinding | ScanCodeBinding | null): ResolvedKeybinding[] {
const _firstPart = this._resolveSimpleUserBinding(firstPart);
const _chordPart = this._resolveSimpleUserBinding(chordPart);
if (_firstPart && _chordPart) {

View file

@ -41,9 +41,9 @@ import { KeybindingParser } from 'vs/base/common/keybindingParser';
export class KeyboardMapperFactory {
public static readonly INSTANCE = new KeyboardMapperFactory();
private _layoutInfo: nativeKeymap.IKeyboardLayoutInfo;
private _rawMapping: nativeKeymap.IKeyboardMapping;
private _keyboardMapper: IKeyboardMapper;
private _layoutInfo: nativeKeymap.IKeyboardLayoutInfo | null;
private _rawMapping: nativeKeymap.IKeyboardMapping | null;
private _keyboardMapper: IKeyboardMapper | null;
private _initialized: boolean;
private readonly _onDidChangeKeyboardMapper: Emitter<void> = new Emitter<void>();
@ -70,10 +70,10 @@ export class KeyboardMapperFactory {
// Forcefully set to use keyCode
return new MacLinuxFallbackKeyboardMapper(OS);
}
return this._keyboardMapper;
return this._keyboardMapper!;
}
public getCurrentKeyboardLayout(): nativeKeymap.IKeyboardLayoutInfo {
public getCurrentKeyboardLayout(): nativeKeymap.IKeyboardLayoutInfo | null {
if (!this._initialized) {
this._setKeyboardData(nativeKeymap.getCurrentKeyboardLayout(), nativeKeymap.getKeyMap());
}
@ -99,7 +99,7 @@ export class KeyboardMapperFactory {
return false;
}
public getRawKeyboardMapping(): nativeKeymap.IKeyboardMapping {
public getRawKeyboardMapping(): nativeKeymap.IKeyboardMapping | null {
if (!this._initialized) {
this._setKeyboardData(nativeKeymap.getCurrentKeyboardLayout(), nativeKeymap.getKeyMap());
}
@ -144,7 +144,7 @@ export class KeyboardMapperFactory {
return new MacLinuxKeyboardMapper(isUSStandard, <IMacLinuxKeyboardMapping>rawMapping, OS);
}
private static _equals(a: nativeKeymap.IKeyboardMapping, b: nativeKeymap.IKeyboardMapping): boolean {
private static _equals(a: nativeKeymap.IKeyboardMapping | null, b: nativeKeymap.IKeyboardMapping | null): boolean {
if (OS === OperatingSystem.Windows) {
return windowsKeyboardMappingEquals(<IWindowsKeyboardMapping>a, <IWindowsKeyboardMapping>b);
}
@ -254,7 +254,7 @@ function getDispatchConfig(configurationService: IConfigurationService): Dispatc
export class WorkbenchKeybindingService extends AbstractKeybindingService {
private _keyboardMapper: IKeyboardMapper;
private _cachedResolver: KeybindingResolver;
private _cachedResolver: KeybindingResolver | null;
private _firstTimeComputingResolver: boolean;
private userKeybindings: ConfigWatcher<IUserFriendlyKeybinding[]>;
@ -479,7 +479,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
return commandAdded;
}
private _asCommandRule(isBuiltin: boolean, idx: number, binding: ContributedKeyBinding): IKeybindingRule2 {
private _asCommandRule(isBuiltin: boolean, idx: number, binding: ContributedKeyBinding): IKeybindingRule2 | undefined {
let { command, when, key, mac, linux, win } = binding;
@ -490,14 +490,14 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService {
weight = KeybindingWeight.ExternalExtension + idx;
}
let desc = {
let desc: IKeybindingRule2 = {
id: command,
when: ContextKeyExpr.deserialize(when),
weight: weight,
primary: KeybindingParser.parseKeybinding(key, OS),
mac: mac && { primary: KeybindingParser.parseKeybinding(mac, OS) },
linux: linux && { primary: KeybindingParser.parseKeybinding(linux, OS) },
win: win && { primary: KeybindingParser.parseKeybinding(win, OS) }
mac: mac ? { primary: KeybindingParser.parseKeybinding(mac, OS) } : null,
linux: linux ? { primary: KeybindingParser.parseKeybinding(linux, OS) } : null,
win: win ? { primary: KeybindingParser.parseKeybinding(win, OS) } : null
};
if (!desc.primary && !desc.mac && !desc.linux && !desc.win) {

View file

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as path from 'path';
import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper';
import { Keybinding, ResolvedKeybinding, SimpleKeybinding } from 'vs/base/common/keyCodes';
import { TPromise } from 'vs/base/common/winjs.base';
@ -62,13 +63,14 @@ export function readRawMapping<T>(file: string): TPromise<T> {
}
export function assertMapping(writeFileIfDifferent: boolean, mapper: IKeyboardMapper, file: string): TPromise<void> {
const filePath = getPathFromAmdModule(require, `vs/workbench/services/keybinding/test/${file}`);
const filePath = path.normalize(getPathFromAmdModule(require, `vs/workbench/services/keybinding/test/${file}`));
return readFile(filePath).then((buff) => {
let expected = buff.toString();
const actual = mapper.dumpDebugInfo();
if (actual !== expected && writeFileIfDifferent) {
writeFile(filePath, actual);
const destPath = filePath.replace(/vscode\/out\/vs/, 'vscode/src/vs');
writeFile(destPath, actual);
}
assert.deepEqual(actual.split(/\r\n|\n/), expected.split(/\r\n|\n/));

View file

@ -5,7 +5,7 @@
import { IColorTheme, ITokenColorizationSetting } from 'vs/workbench/services/themes/common/workbenchThemeService';
export function findMatchingThemeRule(theme: IColorTheme, scopes: string[], onlyColorRules: boolean = true): ThemeRule {
export function findMatchingThemeRule(theme: IColorTheme, scopes: string[], onlyColorRules: boolean = true): ThemeRule | null {
for (let i = scopes.length - 1; i >= 0; i--) {
let parentScopes = scopes.slice(0, i);
let scope = scopes[i];
@ -17,7 +17,7 @@ export function findMatchingThemeRule(theme: IColorTheme, scopes: string[], only
return null;
}
function findMatchingThemeRule2(theme: IColorTheme, scope: string, parentScopes: string[], onlyColorRules: boolean): ThemeRule {
function findMatchingThemeRule2(theme: IColorTheme, scope: string, parentScopes: string[], onlyColorRules: boolean): ThemeRule | null {
let result: ThemeRule | null = null;
// Loop backwards, to ensure the last most specific rule wins
@ -69,7 +69,7 @@ export class ThemeRule {
return ThemeRule._matches(this.scope, this.parentScopes, scope, parentScopes);
}
private static _cmp(a: ThemeRule, b: ThemeRule): number {
private static _cmp(a: ThemeRule | null, b: ThemeRule | null): number {
if (a === null && b === null) {
return 0;
}
@ -101,7 +101,7 @@ export class ThemeRule {
return 0;
}
public isMoreSpecific(other: ThemeRule): boolean {
public isMoreSpecific(other: ThemeRule | null): boolean {
return (ThemeRule._cmp(this, other) > 0);
}