strict null checks (#60565)

This commit is contained in:
Alex Dima 2018-10-15 10:30:26 +02:00
parent bb0b08b720
commit 2e33dbc714
27 changed files with 262 additions and 212 deletions

View file

@ -62,6 +62,7 @@
"./vs/base/common/idGenerator.ts",
"./vs/base/common/iterator.ts",
"./vs/base/common/jsonSchema.ts",
"./vs/base/common/keybindingLabels.ts",
"./vs/base/common/keybindingParser.ts",
"./vs/base/common/keyCodes.ts",
"./vs/base/common/labels.ts",
@ -270,10 +271,15 @@
"./vs/editor/contrib/caretOperations/transpose.ts",
"./vs/editor/contrib/clipboard/clipboard.ts",
"./vs/editor/contrib/codeAction/codeActionTrigger.ts",
"./vs/editor/contrib/colorPicker/color.ts",
"./vs/editor/contrib/colorPicker/colorPickerModel.ts",
"./vs/editor/contrib/comment/blockCommentCommand.ts",
"./vs/editor/contrib/comment/comment.ts",
"./vs/editor/contrib/comment/lineCommentCommand.ts",
"./vs/editor/contrib/cursorUndo/cursorUndo.ts",
"./vs/editor/contrib/dnd/dragAndDropCommand.ts",
"./vs/editor/contrib/find/findDecorations.ts",
"./vs/editor/contrib/find/findModel.ts",
"./vs/editor/contrib/find/findState.ts",
"./vs/editor/contrib/find/replaceAllCommand.ts",
"./vs/editor/contrib/find/replacePattern.ts",
@ -288,12 +294,19 @@
"./vs/editor/contrib/linesOperations/deleteLinesCommand.ts",
"./vs/editor/contrib/linesOperations/sortLinesCommand.ts",
"./vs/editor/contrib/links/getLinks.ts",
"./vs/editor/contrib/links/links.ts",
"./vs/editor/contrib/quickOpen/quickOpen.ts",
"./vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode.ts",
"./vs/editor/contrib/wordHighlighter/wordHighlighter.ts",
"./vs/editor/contrib/wordOperations/wordOperations.ts",
"./vs/editor/contrib/wordPartOperations/wordPartOperations.ts",
"./vs/editor/editor.worker.ts",
"./vs/editor/standalone/browser/colorizer.ts",
"./vs/editor/standalone/browser/inspectTokens/inspectTokens.ts",
"./vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.ts",
"./vs/editor/standalone/browser/standaloneCodeServiceImpl.ts",
"./vs/editor/standalone/browser/standaloneThemeServiceImpl.ts",
"./vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.ts",
"./vs/editor/standalone/common/monarch/monarchCommon.ts",
"./vs/editor/standalone/common/monarch/monarchCompile.ts",
"./vs/editor/standalone/common/monarch/monarchTypes.ts",
@ -334,6 +347,7 @@
"./vs/platform/instantiation/common/serviceCollection.ts",
"./vs/platform/integrity/common/integrity.ts",
"./vs/platform/jsonschemas/common/jsonContributionRegistry.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",

View file

@ -71,23 +71,23 @@ export class KeybindingLabel implements IDisposable {
this.didEverRender = true;
}
private renderPart(parent: HTMLElement, part: ResolvedKeybindingPart, match: PartMatches) {
private renderPart(parent: HTMLElement, part: ResolvedKeybindingPart, match: PartMatches | null) {
const modifierLabels = UILabelProvider.modifierLabels[this.os];
if (part.ctrlKey) {
this.renderKey(parent, modifierLabels.ctrlKey, match && match.ctrlKey, modifierLabels.separator);
this.renderKey(parent, modifierLabels.ctrlKey, Boolean(match && match.ctrlKey), modifierLabels.separator);
}
if (part.shiftKey) {
this.renderKey(parent, modifierLabels.shiftKey, match && match.shiftKey, modifierLabels.separator);
this.renderKey(parent, modifierLabels.shiftKey, Boolean(match && match.shiftKey), modifierLabels.separator);
}
if (part.altKey) {
this.renderKey(parent, modifierLabels.altKey, match && match.altKey, modifierLabels.separator);
this.renderKey(parent, modifierLabels.altKey, Boolean(match && match.altKey), modifierLabels.separator);
}
if (part.metaKey) {
this.renderKey(parent, modifierLabels.metaKey, match && match.metaKey, modifierLabels.separator);
this.renderKey(parent, modifierLabels.metaKey, Boolean(match && match.metaKey), modifierLabels.separator);
}
const keyLabel = part.keyLabel;
if (keyLabel) {
this.renderKey(parent, keyLabel, match && match.keyCode, '');
this.renderKey(parent, keyLabel, Boolean(match && match.keyCode), '');
}
}
@ -99,7 +99,6 @@ export class KeybindingLabel implements IDisposable {
}
dispose() {
this.keybinding = null;
}
private static areSame(a: Matches, b: Matches): boolean {

View file

@ -26,13 +26,13 @@ export class ModifierLabelProvider {
public readonly modifierLabels: ModifierLabels[];
constructor(mac: ModifierLabels, windows: ModifierLabels, linux: ModifierLabels = windows) {
this.modifierLabels = [null];
this.modifierLabels = [null!]; // index 0 will never me accessed.
this.modifierLabels[OperatingSystem.Macintosh] = mac;
this.modifierLabels[OperatingSystem.Windows] = windows;
this.modifierLabels[OperatingSystem.Linux] = linux;
}
public toLabel(firstPartMod: Modifiers, firstPartKey: string, chordPartMod: Modifiers, chordPartKey: string, OS: OperatingSystem): string {
public toLabel(firstPartMod: Modifiers, firstPartKey: string, chordPartMod: Modifiers, chordPartKey: string, OS: OperatingSystem): string | null {
if (firstPartKey === null && chordPartKey === null) {
return null;
}

View file

@ -803,14 +803,6 @@ export interface IActiveCodeEditor extends ICodeEditor {
*/
getDomNode(): HTMLElement;
/**
* Get the hit test target at coordinates `clientX` and `clientY`.
* The coordinates are relative to the top-left of the viewport.
*
* @returns Hit test target or null if the coordinates fall outside the editor or the editor has no model.
*/
getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget;
/**
* Get the visible position for `position`.
* The result position takes scrolling into account and is relative to the top left corner of the editor.

View file

@ -201,17 +201,16 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
public readonly isSimpleWidget: boolean;
private readonly _telemetryData: object | null;
private readonly domElement: HTMLElement;
private readonly id: number;
private readonly _domElement: HTMLElement;
private readonly _id: number;
private readonly _configuration: editorCommon.IConfiguration;
protected _contributions: { [key: string]: editorCommon.IEditorContribution; };
protected _actions: { [key: string]: editorCommon.IEditorAction; };
protected readonly _contributions: { [key: string]: editorCommon.IEditorContribution; };
protected readonly _actions: { [key: string]: editorCommon.IEditorAction; };
// --- Members logically associated to a model
protected _modelData: ModelData | null;
protected readonly _instantiationService: IInstantiationService;
protected readonly _contextKeyService: IContextKeyService;
private readonly _notificationService: INotificationService;
@ -219,10 +218,10 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
private readonly _commandService: ICommandService;
private readonly _themeService: IThemeService;
private _focusTracker: CodeEditorWidgetFocusTracker;
private readonly _focusTracker: CodeEditorWidgetFocusTracker;
private contentWidgets: { [key: string]: IContentWidgetData; };
private overlayWidgets: { [key: string]: IOverlayWidgetData; };
private readonly _contentWidgets: { [key: string]: IContentWidgetData; };
private readonly _overlayWidgets: { [key: string]: IOverlayWidgetData; };
/**
* map from "parent" decoration type to live decoration ids.
@ -242,8 +241,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
@INotificationService notificationService: INotificationService
) {
super();
this.domElement = domElement;
this.id = (++EDITOR_ID);
this._domElement = domElement;
this._id = (++EDITOR_ID);
this._decorationTypeKeysToIds = {};
this._decorationTypeSubtypes = {};
this.isSimpleWidget = codeEditorWidgetOptions.isSimpleWidget || false;
@ -258,13 +257,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
this._onDidLayoutChange.fire(this._configuration.editor.layoutInfo);
}
if (this._configuration.editor.showUnused) {
this.domElement.classList.add(SHOW_UNUSED_ENABLED_CLASS);
this._domElement.classList.add(SHOW_UNUSED_ENABLED_CLASS);
} else {
this.domElement.classList.remove(SHOW_UNUSED_ENABLED_CLASS);
this._domElement.classList.remove(SHOW_UNUSED_ENABLED_CLASS);
}
}));
this._contextKeyService = this._register(contextKeyService.createScoped(this.domElement));
this._contextKeyService = this._register(contextKeyService.createScoped(this._domElement));
this._notificationService = notificationService;
this._codeEditorService = codeEditorService;
this._commandService = commandService;
@ -284,8 +283,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
this._editorWidgetFocus.setValue(this._focusTracker.hasFocus());
});
this.contentWidgets = {};
this.overlayWidgets = {};
this._contentWidgets = {};
this._overlayWidgets = {};
mark('editor/start/contrib');
let contributions: IEditorContributionCtor[];
@ -325,11 +324,11 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
}
protected _createConfiguration(options: editorOptions.IEditorOptions): editorCommon.IConfiguration {
return new Configuration(options, this.domElement);
return new Configuration(options, this._domElement);
}
public getId(): string {
return this.getEditorType() + ':' + this.id;
return this.getEditorType() + ':' + this._id;
}
public getEditorType(): string {
@ -339,9 +338,6 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
public dispose(): void {
this._codeEditorService.removeCodeEditor(this);
this.contentWidgets = {};
this.overlayWidgets = {};
this._focusTracker.dispose();
let keys = Object.keys(this._contributions);
@ -349,10 +345,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
let contributionId = keys[i];
this._contributions[contributionId].dispose();
}
this._contributions = {};
// editor actions don't need to be disposed
this._actions = {};
this._removeDecorationTypes();
this._postDetachModelCleanup(this._detachModel());
@ -1026,14 +1019,14 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
// callback will not be called
return null;
}
return this._modelData.model.changeDecorations(callback, this.id);
return this._modelData.model.changeDecorations(callback, this._id);
}
public getLineDecorations(lineNumber: number): IModelDecoration[] | null {
if (!this._modelData) {
return null;
}
return this._modelData.model.getLineDecorations(lineNumber, this.id, this._configuration.editor.readOnly);
return this._modelData.model.getLineDecorations(lineNumber, this._id, this._configuration.editor.readOnly);
}
public deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[] {
@ -1045,7 +1038,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
return oldDecorations;
}
return this._modelData.model.deltaDecorations(oldDecorations, newDecorations, this.id);
return this._modelData.model.deltaDecorations(oldDecorations, newDecorations, this._id);
}
public setDecorations(decorationTypeKey: string, decorationOptions: editorCommon.IDecorationOptions[]): void {
@ -1178,11 +1171,11 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
position: widget.getPosition()
};
if (this.contentWidgets.hasOwnProperty(widget.getId())) {
if (this._contentWidgets.hasOwnProperty(widget.getId())) {
console.warn('Overwriting a content widget with the same id.');
}
this.contentWidgets[widget.getId()] = widgetData;
this._contentWidgets[widget.getId()] = widgetData;
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.addContentWidget(widgetData);
@ -1191,8 +1184,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
public layoutContentWidget(widget: editorBrowser.IContentWidget): void {
let widgetId = widget.getId();
if (this.contentWidgets.hasOwnProperty(widgetId)) {
let widgetData = this.contentWidgets[widgetId];
if (this._contentWidgets.hasOwnProperty(widgetId)) {
let widgetData = this._contentWidgets[widgetId];
widgetData.position = widget.getPosition();
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.layoutContentWidget(widgetData);
@ -1202,9 +1195,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
public removeContentWidget(widget: editorBrowser.IContentWidget): void {
let widgetId = widget.getId();
if (this.contentWidgets.hasOwnProperty(widgetId)) {
let widgetData = this.contentWidgets[widgetId];
delete this.contentWidgets[widgetId];
if (this._contentWidgets.hasOwnProperty(widgetId)) {
let widgetData = this._contentWidgets[widgetId];
delete this._contentWidgets[widgetId];
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.removeContentWidget(widgetData);
}
@ -1217,11 +1210,11 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
position: widget.getPosition()
};
if (this.overlayWidgets.hasOwnProperty(widget.getId())) {
if (this._overlayWidgets.hasOwnProperty(widget.getId())) {
console.warn('Overwriting an overlay widget with the same id.');
}
this.overlayWidgets[widget.getId()] = widgetData;
this._overlayWidgets[widget.getId()] = widgetData;
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.addOverlayWidget(widgetData);
@ -1230,8 +1223,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
public layoutOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
let widgetId = widget.getId();
if (this.overlayWidgets.hasOwnProperty(widgetId)) {
let widgetData = this.overlayWidgets[widgetId];
if (this._overlayWidgets.hasOwnProperty(widgetId)) {
let widgetData = this._overlayWidgets[widgetId];
widgetData.position = widget.getPosition();
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.layoutOverlayWidget(widgetData);
@ -1241,9 +1234,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
public removeOverlayWidget(widget: editorBrowser.IOverlayWidget): void {
let widgetId = widget.getId();
if (this.overlayWidgets.hasOwnProperty(widgetId)) {
let widgetData = this.overlayWidgets[widgetId];
delete this.overlayWidgets[widgetId];
if (this._overlayWidgets.hasOwnProperty(widgetId)) {
let widgetData = this._overlayWidgets[widgetId];
delete this._overlayWidgets[widgetId];
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.removeOverlayWidget(widgetData);
}
@ -1311,17 +1304,17 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
const listenersToRemove: IDisposable[] = [];
this.domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
this._domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
this._configuration.setIsDominatedByLongLines(model.isDominatedByLongLines());
this._configuration.setMaxLineNumber(model.getLineCount());
model.onBeforeAttached();
const viewModel = new ViewModel(this.id, this._configuration, model, (callback) => dom.scheduleAtNextAnimationFrame(callback));
const viewModel = new ViewModel(this._id, this._configuration, model, (callback) => dom.scheduleAtNextAnimationFrame(callback));
listenersToRemove.push(model.onDidChangeDecorations((e) => this._onDidChangeModelDecorations.fire(e)));
listenersToRemove.push(model.onDidChangeLanguage((e) => {
this.domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
this._domElement.setAttribute('data-mode-id', model.getLanguageIdentifier().language);
this._onDidChangeModelLanguage.fire(e);
}));
listenersToRemove.push(model.onDidChangeLanguageConfiguration((e) => this._onDidChangeModelLanguageConfiguration.fire(e)));
@ -1365,18 +1358,18 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
const [view, hasRealView] = this._createView(viewModel, cursor);
if (hasRealView) {
this.domElement.appendChild(view.domNode.domNode);
this._domElement.appendChild(view.domNode.domNode);
let keys = Object.keys(this.contentWidgets);
let keys = Object.keys(this._contentWidgets);
for (let i = 0, len = keys.length; i < len; i++) {
let widgetId = keys[i];
view.addContentWidget(this.contentWidgets[widgetId]);
view.addContentWidget(this._contentWidgets[widgetId]);
}
keys = Object.keys(this.overlayWidgets);
keys = Object.keys(this._overlayWidgets);
for (let i = 0, len = keys.length; i < len; i++) {
let widgetId = keys[i];
view.addOverlayWidget(this.overlayWidgets[widgetId]);
view.addOverlayWidget(this._overlayWidgets[widgetId]);
}
view.render(false, true);
@ -1479,7 +1472,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
protected _postDetachModelCleanup(detachedModel: ITextModel | null): void {
if (detachedModel) {
detachedModel.removeAllDecorationsWithOwnerId(this.id);
detachedModel.removeAllDecorationsWithOwnerId(this._id);
}
}
@ -1493,9 +1486,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
this._modelData.dispose();
this._modelData = null;
this.domElement.removeAttribute('data-mode-id');
this._domElement.removeAttribute('data-mode-id');
if (removeDomNode) {
this.domElement.removeChild(removeDomNode);
this._domElement.removeChild(removeDomNode);
}
return model;

View file

@ -1231,8 +1231,13 @@ abstract class DiffEditorWidgetStyle extends Disposable implements IDiffEditorWi
public abstract layout(): number;
}
interface IMyViewZone extends editorBrowser.IViewZone {
interface IMyViewZone {
shouldNotShrink?: boolean;
afterLineNumber: number;
heightInLines: number;
minWidthInPx?: number;
domNode: HTMLElement | null;
marginDomNode?: HTMLElement | null;
}
class ForeignViewZonesIterator {
@ -1270,7 +1275,7 @@ abstract class ViewZonesComputer {
}
public getViewZones(): IEditorsZones {
let result: IEditorsZones = {
let result: { original: IMyViewZone[]; modified: IMyViewZone[]; } = {
original: [],
modified: []
};
@ -1286,7 +1291,7 @@ abstract class ViewZonesComputer {
return a.afterLineNumber - b.afterLineNumber;
};
let addAndCombineIfPossible = (destination: editorBrowser.IViewZone[], item: IMyViewZone) => {
let addAndCombineIfPossible = (destination: IMyViewZone[], item: IMyViewZone) => {
if (item.domNode === null && destination.length > 0) {
let lastItem = destination[destination.length - 1];
if (lastItem.afterLineNumber === item.afterLineNumber && lastItem.domNode === null) {

View file

@ -354,28 +354,33 @@ export class Range {
* A function that compares ranges, useful for sorting ranges
* It will first compare ranges on the startPosition and then on the endPosition
*/
public static compareRangesUsingStarts(a: IRange, b: IRange): number {
let aStartLineNumber = a.startLineNumber | 0;
let bStartLineNumber = b.startLineNumber | 0;
public static compareRangesUsingStarts(a: IRange | null | undefined, b: IRange | null | undefined): number {
if (a && b) {
const aStartLineNumber = a.startLineNumber | 0;
const bStartLineNumber = b.startLineNumber | 0;
if (aStartLineNumber === bStartLineNumber) {
let aStartColumn = a.startColumn | 0;
let bStartColumn = b.startColumn | 0;
if (aStartLineNumber === bStartLineNumber) {
const aStartColumn = a.startColumn | 0;
const bStartColumn = b.startColumn | 0;
if (aStartColumn === bStartColumn) {
let aEndLineNumber = a.endLineNumber | 0;
let bEndLineNumber = b.endLineNumber | 0;
if (aStartColumn === bStartColumn) {
const aEndLineNumber = a.endLineNumber | 0;
const bEndLineNumber = b.endLineNumber | 0;
if (aEndLineNumber === bEndLineNumber) {
let aEndColumn = a.endColumn | 0;
let bEndColumn = b.endColumn | 0;
return aEndColumn - bEndColumn;
if (aEndLineNumber === bEndLineNumber) {
const aEndColumn = a.endColumn | 0;
const bEndColumn = b.endColumn | 0;
return aEndColumn - bEndColumn;
}
return aEndLineNumber - bEndLineNumber;
}
return aEndLineNumber - bEndLineNumber;
return aStartColumn - bStartColumn;
}
return aStartColumn - bStartColumn;
return aStartLineNumber - bStartLineNumber;
}
return aStartLineNumber - bStartLineNumber;
const aExists = (a ? 1 : 0);
const bExists = (b ? 1 : 0);
return aExists - bExists;
}
/**

View file

@ -17,9 +17,9 @@ export class SearchParams {
public readonly searchString: string;
public readonly isRegex: boolean;
public readonly matchCase: boolean;
public readonly wordSeparators: string;
public readonly wordSeparators: string | null;
constructor(searchString: string, isRegex: boolean, matchCase: boolean, wordSeparators: string) {
constructor(searchString: string, isRegex: boolean, matchCase: boolean, wordSeparators: string | null) {
this.searchString = searchString;
this.isRegex = isRegex;
this.matchCase = matchCase;

View file

@ -200,7 +200,7 @@ export interface ITokenizationSupport {
getInitialState(): IState;
// add offsetDelta to each of the returned indices
tokenize?(line: string, state: IState, offsetDelta: number): TokenizationResult;
tokenize(line: string, state: IState, offsetDelta: number): TokenizationResult;
tokenize2(line: string, state: IState, offsetDelta: number): TokenizationResult2;
}

View file

@ -12,11 +12,11 @@ export interface CommentRule {
/**
* The line comment token, like `// this is a comment`
*/
lineComment?: string;
lineComment?: string | null;
/**
* The block comment character pair, like `/* block comment *&#47;`
*/
blockComment?: CharacterPair;
blockComment?: CharacterPair | null;
}
/**

View file

@ -4,18 +4,23 @@
*--------------------------------------------------------------------------------------------*/
import * as strings from 'vs/base/common/strings';
import { ITokenizationSupport, IState, LanguageId } from 'vs/editor/common/modes';
import { IState, LanguageId } from 'vs/editor/common/modes';
import { LineTokens, IViewLineTokens } from 'vs/editor/common/core/lineTokens';
import { CharCode } from 'vs/base/common/charCode';
import { NULL_STATE, nullTokenize2 } from 'vs/editor/common/modes/nullMode';
import { TokenizationResult2 } from 'vs/editor/common/core/token';
const fallback: ITokenizationSupport = {
export interface IReducedTokenizationSupport {
getInitialState(): IState;
tokenize2(line: string, state: IState, offsetDelta: number): TokenizationResult2;
}
const fallback: IReducedTokenizationSupport = {
getInitialState: () => NULL_STATE,
tokenize: undefined,
tokenize2: (buffer: string, state: IState, deltaOffset: number) => nullTokenize2(LanguageId.Null, buffer, state, deltaOffset)
};
export function tokenizeToString(text: string, tokenizationSupport: ITokenizationSupport = fallback): string {
export function tokenizeToString(text: string, tokenizationSupport: IReducedTokenizationSupport = fallback): string {
return _tokenizeToString(text, tokenizationSupport || fallback);
}
@ -88,7 +93,7 @@ export function tokenizeLineToHTML(text: string, viewLineTokens: IViewLineTokens
return result;
}
function _tokenizeToString(text: string, tokenizationSupport: ITokenizationSupport): string {
function _tokenizeToString(text: string, tokenizationSupport: IReducedTokenizationSupport): string {
let result = `<div class="monaco-tokenized-source">`;
let lines = text.split(/\r\n|\r|\n/);
let currentState = tokenizationSupport.getInitialState();

View file

@ -32,7 +32,7 @@ export function getColors(model: ITextModel, token: CancellationToken): Promise<
return Promise.all(promises).then(() => colors);
}
export function getColorPresentations(model: ITextModel, colorInfo: IColorInformation, provider: DocumentColorProvider, token: CancellationToken): Promise<IColorPresentation[]> {
export function getColorPresentations(model: ITextModel, colorInfo: IColorInformation, provider: DocumentColorProvider, token: CancellationToken): Promise<IColorPresentation[] | null | undefined> {
return Promise.resolve(provider.provideColorPresentations(model, colorInfo, token));
}

View file

@ -24,11 +24,11 @@ abstract class CommentLineAction extends EditorAction {
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
let model = editor.getModel();
if (!model) {
if (!editor.hasModel()) {
return;
}
let model = editor.getModel();
let commands: ICommand[] = [];
let selections = editor.getSelections();
let opts = model.getOptions();
@ -122,9 +122,12 @@ class BlockCommentAction extends EditorAction {
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
if (!editor.hasModel()) {
return;
}
let commands: ICommand[] = [];
let selections = editor.getSelections();
for (let i = 0; i < selections.length; i++) {
commands.push(new BlockCommentCommand(selections[i]));
}

View file

@ -26,11 +26,15 @@ export interface ILinePreflightData {
commentStrLength: number;
}
export interface IPreflightData {
supported: boolean;
export interface IPreflightDataSupported {
supported: true;
shouldRemoveComments: boolean;
lines: ILinePreflightData[];
}
export interface IPreflightDataUnsupported {
supported: false;
}
export type IPreflightData = IPreflightDataSupported | IPreflightDataUnsupported;
export interface ISimpleModel {
getLineContent(lineNumber: number): string;
@ -62,7 +66,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
* Do an initial pass over the lines and gather info about the line comment string.
* Returns null if any of the lines doesn't support a line comment string.
*/
public static _gatherPreflightCommentStrings(model: ITextModel, startLineNumber: number, endLineNumber: number): ILinePreflightData[] {
public static _gatherPreflightCommentStrings(model: ITextModel, startLineNumber: number, endLineNumber: number): ILinePreflightData[] | null {
model.tokenizeIfCheap(startLineNumber);
const languageId = model.getLanguageIdAtPosition(startLineNumber, 1);
@ -170,9 +174,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
const lines = LineCommentCommand._gatherPreflightCommentStrings(model, startLineNumber, endLineNumber);
if (lines === null) {
return {
supported: false,
shouldRemoveComments: false,
lines: null
supported: false
};
}
@ -182,7 +184,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
/**
* Given a successful analysis, execute either insert line comments, either remove line comments
*/
private _executeLineComments(model: ISimpleModel, builder: editorCommon.IEditOperationBuilder, data: IPreflightData, s: Selection): void {
private _executeLineComments(model: ISimpleModel, builder: editorCommon.IEditOperationBuilder, data: IPreflightDataSupported, s: Selection): void {
let ops: IIdentifiedSingleEditOperation[];
@ -200,7 +202,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
if (ops[i].range.isEmpty() && ops[i].range.getStartPosition().equals(cursorPosition)) {
const lineContent = model.getLineContent(cursorPosition.lineNumber);
if (lineContent.length + 1 === cursorPosition.column) {
this._deltaColumn = ops[i].text.length;
this._deltaColumn = (ops[i].text || '').length;
}
}
}
@ -208,7 +210,7 @@ export class LineCommentCommand implements editorCommon.ICommand {
this._selectionId = builder.trackSelection(s);
}
private _attemptRemoveBlockComment(model: ITextModel, s: Selection, startToken: string, endToken: string): IIdentifiedSingleEditOperation[] {
private _attemptRemoveBlockComment(model: ITextModel, s: Selection, startToken: string, endToken: string): IIdentifiedSingleEditOperation[] | null {
let startLineNumber = s.startLineNumber;
let endLineNumber = s.endLineNumber;

View file

@ -91,6 +91,9 @@ suite('Editor Contrib - Line Comment Command', () => {
' c',
'\t\td'
]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1);
if (!r.supported) {
throw new Error(`unexpected`);
}
assert.equal(r.shouldRemoveComments, false);
@ -119,6 +122,9 @@ suite('Editor Contrib - Line Comment Command', () => {
' !@# c',
'\t\t!@#d'
]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1);
if (!r.supported) {
throw new Error(`unexpected`);
}
assert.equal(r.shouldRemoveComments, true);

View file

@ -9,12 +9,12 @@ import { Range } from 'vs/editor/common/core/range';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { overviewRulerFindMatchForeground } from 'vs/platform/theme/common/colorRegistry';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
import { IModelDecorationsChangeAccessor, FindMatch, IModelDeltaDecoration, TrackedRangeStickiness, OverviewRulerLane } from 'vs/editor/common/model';
export class FindDecorations implements IDisposable {
private _editor: ICodeEditor;
private _editor: IActiveCodeEditor;
private _decorations: string[];
private _overviewRulerApproximateDecorations: string[];
private _findScopeDecorationId: string | null;
@ -22,7 +22,7 @@ export class FindDecorations implements IDisposable {
private _highlightedDecorationId: string | null;
private _startPosition: Position;
constructor(editor: ICodeEditor) {
constructor(editor: IActiveCodeEditor) {
this._editor = editor;
this._decorations = [];
this._overviewRulerApproximateDecorations = [];
@ -35,13 +35,11 @@ export class FindDecorations implements IDisposable {
public dispose(): void {
this._editor.deltaDecorations(this._allDecorations(), []);
this._editor = null;
this._decorations = [];
this._overviewRulerApproximateDecorations = [];
this._findScopeDecorationId = null;
this._rangeHighlightDecorationId = null;
this._highlightedDecorationId = null;
this._startPosition = null;
}
public reset(): void {
@ -56,7 +54,7 @@ export class FindDecorations implements IDisposable {
return this._decorations.length;
}
public getFindScope(): Range {
public getFindScope(): Range | null {
if (this._findScopeDecorationId) {
return this._editor.getModel().getDecorationRange(this._findScopeDecorationId);
}
@ -92,7 +90,7 @@ export class FindDecorations implements IDisposable {
return 1;
}
public setCurrentFindMatch(nextMatch: Range): number {
public setCurrentFindMatch(nextMatch: Range | null): number {
let newCurrentDecorationId: string | null = null;
let matchPosition = 0;
if (nextMatch) {
@ -121,7 +119,7 @@ export class FindDecorations implements IDisposable {
this._rangeHighlightDecorationId = null;
}
if (newCurrentDecorationId !== null) {
let rng = this._editor.getModel().getDecorationRange(newCurrentDecorationId);
let rng = this._editor.getModel().getDecorationRange(newCurrentDecorationId)!;
if (rng.startLineNumber !== rng.endLineNumber && rng.endColumn === 1) {
let lineBeforeEnd = rng.endLineNumber - 1;
let lineBeforeEndMaxColumn = this._editor.getModel().getLineMaxColumn(lineBeforeEnd);
@ -135,7 +133,7 @@ export class FindDecorations implements IDisposable {
return matchPosition;
}
public set(findMatches: FindMatch[], findScope: Range): void {
public set(findMatches: FindMatch[], findScope: Range | null): void {
this._editor.changeDecorations((accessor) => {
let findMatchesOptions: ModelDecorationOptions = FindDecorations._FIND_MATCH_DECORATION;
@ -207,7 +205,7 @@ export class FindDecorations implements IDisposable {
});
}
public matchBeforePosition(position: Position): Range {
public matchBeforePosition(position: Position): Range | null {
if (this._decorations.length === 0) {
return null;
}
@ -229,7 +227,7 @@ export class FindDecorations implements IDisposable {
return this._editor.getModel().getDecorationRange(this._decorations[this._decorations.length - 1]);
}
public matchAfterPosition(position: Position): Range {
public matchAfterPosition(position: Position): Range | null {
if (this._decorations.length === 0) {
return null;
}

View file

@ -20,7 +20,7 @@ import { SearchParams } from 'vs/editor/common/model/textModelSearch';
import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CursorChangeReason, ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
import { ITextModel, FindMatch, EndOfLinePreference } from 'vs/editor/common/model';
export const CONTEXT_FIND_WIDGET_VISIBLE = new RawContextKey<boolean>('findWidgetVisible', false);
@ -69,7 +69,7 @@ const RESEARCH_DELAY = 240;
export class FindModelBoundToEditorModel {
private _editor: ICodeEditor;
private _editor: IActiveCodeEditor;
private _state: FindReplaceState;
private _toDispose: IDisposable[];
private _decorations: FindDecorations;
@ -79,7 +79,7 @@ export class FindModelBoundToEditorModel {
private _updateDecorationsScheduler: RunOnceScheduler;
private _isDisposed: boolean;
constructor(editor: ICodeEditor, state: FindReplaceState) {
constructor(editor: IActiveCodeEditor, state: FindReplaceState) {
this._editor = editor;
this._state = state;
this._toDispose = [];
@ -158,18 +158,16 @@ export class FindModelBoundToEditorModel {
}
}
private static _getSearchRange(model: ITextModel, findScope: Range): Range {
let searchRange = model.getFullModelRange();
private static _getSearchRange(model: ITextModel, findScope: Range | null): Range {
// If we have set now or before a find scope, use it for computing the search range
if (findScope) {
searchRange = searchRange.intersectRanges(findScope);
return findScope;
}
return searchRange;
return model.getFullModelRange();
}
private research(moveCursor: boolean, newFindScope?: Range): void {
private research(moveCursor: boolean, newFindScope?: Range | null): void {
let findScope: Range | null = null;
if (typeof newFindScope !== 'undefined') {
findScope = newFindScope;
@ -299,7 +297,7 @@ export class FindModelBoundToEditorModel {
if (!prevMatch) {
// there is precisely one match and selection is on top of it
return null;
return;
}
if (!isRecursed && !searchRange.containsRange(prevMatch.range)) {
@ -358,7 +356,7 @@ export class FindModelBoundToEditorModel {
}
}
private _getNextMatch(after: Position, captureMatches: boolean, forceMove: boolean, isRecursed: boolean = false): FindMatch {
private _getNextMatch(after: Position, captureMatches: boolean, forceMove: boolean, isRecursed: boolean = false): FindMatch | null {
if (this._cannotFind()) {
return null;
}
@ -438,7 +436,7 @@ export class FindModelBoundToEditorModel {
}
}
private _findMatches(findScope: Range, captureMatches: boolean, limitResultCount: number): FindMatch[] {
private _findMatches(findScope: Range | null, captureMatches: boolean, limitResultCount: number): FindMatch[] {
let searchRange = FindModelBoundToEditorModel._getSearchRange(this._editor.getModel(), findScope);
return this._editor.getModel().findMatches(this._state.searchString, searchRange, this._state.isRegex, this._state.matchCase, this._state.wholeWord ? this._editor.getConfiguration().wordSeparators : null, captureMatches, limitResultCount);
}
@ -497,7 +495,7 @@ export class FindModelBoundToEditorModel {
this._executeEditorCommand('replaceAll', command);
}
private _regularReplaceAll(findScope: Range): void {
private _regularReplaceAll(findScope: Range | null): void {
const replacePattern = this._getReplacePattern();
// Get all the ranges (even more than the highlighted ones)
let matches = this._findMatches(findScope, replacePattern.hasReplacementPatterns, Constants.MAX_SAFE_SMALL_INTEGER);

View file

@ -110,7 +110,7 @@ export class FindReplaceState implements IDisposable {
public dispose(): void {
}
public changeMatchInfo(matchesPosition: number, matchesCount: number, currentMatch: Range): void {
public changeMatchInfo(matchesPosition: number, matchesCount: number, currentMatch: Range | undefined): void {
let changeEvent: FindReplaceStateChangedEvent = {
moveCursor: false,
updateHistory: false,

View file

@ -48,7 +48,7 @@ export class ReplacePattern {
}
}
public buildReplaceString(matches: string[]): string {
public buildReplaceString(matches: string[] | null): string {
if (this._state.kind === ReplacePatternKind.StaticValue) {
return this._state.staticValue;
}
@ -69,7 +69,10 @@ export class ReplacePattern {
return result;
}
private static _substitute(matchIndex: number, matches: string[]): string {
private static _substitute(matchIndex: number, matches: string[] | null): string {
if (matches === null) {
return '';
}
if (matchIndex === 0) {
return matches[0];
}

View file

@ -111,7 +111,7 @@ class LinkOccurrence {
}
private static _getOptions(link: Link, useMetaKey: boolean, isActive: boolean): ModelDecorationOptions {
if (/^command:/i.test(link.url)) {
if (link.url && /^command:/i.test(link.url)) {
if (useMetaKey) {
return (isActive ? decoration.metaCommandActive : decoration.metaCommand);
} else {
@ -157,8 +157,8 @@ class LinkDetector implements editorCommon.IEditorContribution {
private enabled: boolean;
private listenersToRemove: IDisposable[];
private timeout: async.TimeoutTimer;
private computePromise: async.CancelablePromise<Link[]>;
private activeLinkDecorationId: string;
private computePromise: async.CancelablePromise<Link[]> | null;
private activeLinkDecorationId: string | null;
private openerService: IOpenerService;
private notificationService: INotificationService;
private currentOccurrences: { [decorationId: string]: LinkOccurrence; };
@ -236,15 +236,17 @@ class LinkDetector implements editorCommon.IEditorContribution {
}
private async beginCompute(): Promise<void> {
if (!this.editor.getModel() || !this.enabled) {
if (!this.editor.hasModel() || !this.enabled) {
return;
}
if (!LinkProviderRegistry.has(this.editor.getModel())) {
const model = this.editor.getModel();
if (!LinkProviderRegistry.has(model)) {
return;
}
this.computePromise = async.createCancelablePromise(token => getLinks(this.editor.getModel(), token));
this.computePromise = async.createCancelablePromise(token => getLinks(model, token));
try {
const links = await this.computePromise;
this.updateDecorations(links);
@ -283,11 +285,11 @@ class LinkDetector implements editorCommon.IEditorContribution {
}
}
private _onEditorMouseMove(mouseEvent: ClickLinkMouseEvent, withKey?: ClickLinkKeyboardEvent): void {
private _onEditorMouseMove(mouseEvent: ClickLinkMouseEvent, withKey: ClickLinkKeyboardEvent | null): void {
const useMetaKey = (this.editor.getConfiguration().multiCursorModifier === 'altKey');
if (this.isEnabled(mouseEvent, withKey)) {
this.cleanUpActiveLinkDecoration(); // always remove previous link decoration as their can only be one
const occurrence = this.getLinkOccurrence(mouseEvent.target.position);
const occurrence = this.getLinkOccurrence(mouseEvent.target!.position);
if (occurrence) {
this.editor.changeDecorations((changeAccessor) => {
occurrence.activate(changeAccessor, useMetaKey);
@ -317,7 +319,7 @@ class LinkDetector implements editorCommon.IEditorContribution {
if (!this.isEnabled(mouseEvent)) {
return;
}
const occurrence = this.getLinkOccurrence(mouseEvent.target.position);
const occurrence = this.getLinkOccurrence(mouseEvent.target!.position);
if (!occurrence) {
return;
}
@ -348,7 +350,10 @@ class LinkDetector implements editorCommon.IEditorContribution {
});
}
public getLinkOccurrence(position: Position): LinkOccurrence {
public getLinkOccurrence(position: Position | null): LinkOccurrence | null {
if (!this.editor.hasModel() || !position) {
return null;
}
const decorations = this.editor.getModel().getDecorationsInRange({
startLineNumber: position.lineNumber,
startColumn: position.column,
@ -367,9 +372,9 @@ class LinkDetector implements editorCommon.IEditorContribution {
return null;
}
private isEnabled(mouseEvent: ClickLinkMouseEvent, withKey?: ClickLinkKeyboardEvent): boolean {
return (
mouseEvent.target.type === MouseTargetType.CONTENT_TEXT
private isEnabled(mouseEvent: ClickLinkMouseEvent, withKey?: ClickLinkKeyboardEvent | null): boolean {
return Boolean(
(mouseEvent.target && mouseEvent.target.type === MouseTargetType.CONTENT_TEXT)
&& (mouseEvent.hasTriggerModifier || (withKey && withKey.keyCodeIsTriggerKey))
);
}
@ -405,6 +410,9 @@ class OpenLinkAction extends EditorAction {
if (!linkDetector) {
return;
}
if (!editor.hasModel()) {
return;
}
let selections = editor.getSelections();

View file

@ -9,9 +9,10 @@ import { first, createCancelablePromise, CancelablePromise, timeout } from 'vs/b
import { onUnexpectedExternalError, onUnexpectedError } from 'vs/base/common/errors';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as arrays from 'vs/base/common/arrays';
import { registerEditorContribution, EditorAction, IActionOptions, registerEditorAction, registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { DocumentHighlight, DocumentHighlightKind, DocumentHighlightProviderRegistry } from 'vs/editor/common/modes';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import { registerColor, editorSelectionHighlight, overviewRulerSelectionHighlightForeground, activeContrastBorder, editorSelectionHighlightBorder } from 'vs/platform/theme/common/colorRegistry';
@ -22,8 +23,7 @@ import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/cont
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { firstIndex, isFalsyOrEmpty } from 'vs/base/common/arrays';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
import { ITextModel, TrackedRangeStickiness, OverviewRulerLane, IModelDeltaDecoration } from 'vs/editor/common/model';
import { CancellationToken } from 'vs/base/common/cancellation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
@ -38,17 +38,17 @@ export const overviewRulerWordHighlightStrongForeground = registerColor('editorO
export const ctxHasWordHighlights = new RawContextKey<boolean>('hasWordHighlights', false);
export function getOccurrencesAtPosition(model: ITextModel, position: Position, token: CancellationToken): Promise<DocumentHighlight[]> {
export function getOccurrencesAtPosition(model: ITextModel, position: Position, token: CancellationToken): Promise<DocumentHighlight[] | null | undefined> {
const orderedByScore = DocumentHighlightProviderRegistry.ordered(model);
// in order of score ask the occurrences provider
// until someone response with a good result
// (good = none empty array)
return first(orderedByScore.map(provider => () => {
return first<DocumentHighlight[] | null | undefined>(orderedByScore.map(provider => () => {
return Promise.resolve(provider.provideDocumentHighlights(model, position, token))
.then(undefined, onUnexpectedExternalError);
}), result => !isFalsyOrEmpty(result));
}), result => !arrays.isFalsyOrEmpty(result));
}
interface IOccurenceAtPositionRequest {
@ -59,7 +59,7 @@ interface IOccurenceAtPositionRequest {
abstract class OccurenceAtPositionRequest implements IOccurenceAtPositionRequest {
private readonly _wordRange: Range;
private readonly _wordRange: Range | null;
public readonly result: CancelablePromise<DocumentHighlight[]>;
constructor(model: ITextModel, selection: Selection, wordSeparators: string) {
@ -69,7 +69,7 @@ abstract class OccurenceAtPositionRequest implements IOccurenceAtPositionRequest
protected abstract _compute(model: ITextModel, selection: Selection, wordSeparators: string, token: CancellationToken): Thenable<DocumentHighlight[]>;
private _getCurrentWordRange(model: ITextModel, selection: Selection): Range {
private _getCurrentWordRange(model: ITextModel, selection: Selection): Range | null {
const word = model.getWordAtPosition(selection.getPosition());
if (word) {
return new Range(selection.startLineNumber, word.startColumn, selection.startLineNumber, word.endColumn);
@ -84,7 +84,7 @@ abstract class OccurenceAtPositionRequest implements IOccurenceAtPositionRequest
const endColumn = selection.endColumn;
const currentWordRange = this._getCurrentWordRange(model, selection);
let requestIsValid = (this._wordRange && this._wordRange.equalsRange(currentWordRange));
let requestIsValid = Boolean(this._wordRange && this._wordRange.equalsRange(currentWordRange));
// Even if we are on a different word, if that word is in the decorations ranges, the request is still valid
// (Same symbol)
@ -161,14 +161,14 @@ registerDefaultLanguageCommand('_executeDocumentHighlights', (model, position) =
class WordHighlighter {
private editor: ICodeEditor;
private editor: IActiveCodeEditor;
private occurrencesHighlight: boolean;
private model: ITextModel;
private _decorationIds: string[];
private toUnhook: IDisposable[];
private workerRequestTokenId: number = 0;
private workerRequest: IOccurenceAtPositionRequest;
private workerRequest: IOccurenceAtPositionRequest | null;
private workerRequestCompleted: boolean = false;
private workerRequestValue: DocumentHighlight[] = [];
@ -178,7 +178,7 @@ class WordHighlighter {
private _hasWordHighlights: IContextKey<boolean>;
private _ignorePositionChangeEvent: boolean;
constructor(editor: ICodeEditor, contextKeyService: IContextKeyService) {
constructor(editor: IActiveCodeEditor, contextKeyService: IContextKeyService) {
this.editor = editor;
this._hasWordHighlights = ctxHasWordHighlights.bindTo(contextKeyService);
this._ignorePositionChangeEvent = false;
@ -200,10 +200,6 @@ class WordHighlighter {
this._onPositionChanged(e);
}));
this.toUnhook.push(editor.onDidChangeModel((e) => {
this._stopAll();
this.model = this.editor.getModel();
}));
this.toUnhook.push(editor.onDidChangeModelContent((e) => {
this._stopAll();
}));
@ -236,14 +232,16 @@ class WordHighlighter {
}
private _getSortedHighlights(): Range[] {
return this._decorationIds
.map((id) => this.model.getDecorationRange(id))
.sort(Range.compareRangesUsingStarts);
return arrays.coalesce(
this._decorationIds
.map((id) => this.model.getDecorationRange(id))
.sort(Range.compareRangesUsingStarts)
);
}
public moveNext() {
let highlights = this._getSortedHighlights();
let index = firstIndex(highlights, (range) => range.containsPosition(this.editor.getPosition()));
let index = arrays.firstIndex(highlights, (range) => range.containsPosition(this.editor.getPosition()));
let newIndex = ((index + 1) % highlights.length);
let dest = highlights[newIndex];
try {
@ -257,7 +255,7 @@ class WordHighlighter {
public moveBack() {
let highlights = this._getSortedHighlights();
let index = firstIndex(highlights, (range) => range.containsPosition(this.editor.getPosition()));
let index = arrays.firstIndex(highlights, (range) => range.containsPosition(this.editor.getPosition()));
let newIndex = ((index - 1 + highlights.length) % highlights.length);
let dest = highlights[newIndex];
try {
@ -461,7 +459,7 @@ class WordHighlighter {
}
}
class WordHighlighterContribution implements editorCommon.IEditorContribution {
class WordHighlighterContribution extends Disposable implements editorCommon.IEditorContribution {
private static readonly ID = 'editor.contrib.wordHighlighter';
@ -469,10 +467,23 @@ class WordHighlighterContribution implements editorCommon.IEditorContribution {
return editor.getContribution<WordHighlighterContribution>(WordHighlighterContribution.ID);
}
private wordHighligher: WordHighlighter;
private wordHighligher: WordHighlighter | null;
constructor(editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService) {
this.wordHighligher = new WordHighlighter(editor, contextKeyService);
super();
const createWordHighlighterIfPossible = () => {
if (editor.hasModel()) {
this.wordHighligher = new WordHighlighter(editor, contextKeyService);
}
};
this._register(editor.onDidChangeModel((e) => {
if (this.wordHighligher) {
this.wordHighligher.dispose();
this.wordHighligher = null;
}
createWordHighlighterIfPossible();
}));
createWordHighlighterIfPossible();
}
public getId(): string {
@ -480,28 +491,36 @@ class WordHighlighterContribution implements editorCommon.IEditorContribution {
}
public saveViewState(): boolean {
if (this.wordHighligher.hasDecorations()) {
if (this.wordHighligher && this.wordHighligher.hasDecorations()) {
return true;
}
return false;
}
public moveNext() {
this.wordHighligher.moveNext();
if (this.wordHighligher) {
this.wordHighligher.moveNext();
}
}
public moveBack() {
this.wordHighligher.moveBack();
if (this.wordHighligher) {
this.wordHighligher.moveBack();
}
}
public restoreViewState(state: boolean | undefined): void {
if (state) {
if (this.wordHighligher && state) {
this.wordHighligher.restore();
}
}
public dispose(): void {
this.wordHighligher.dispose();
if (this.wordHighligher) {
this.wordHighligher.dispose();
this.wordHighligher = null;
}
super.dispose();
}
}

View file

@ -31,29 +31,32 @@ export class Colorizer {
let mimeType = options.mimeType || domNode.getAttribute('lang') || domNode.getAttribute('data-lang');
if (!mimeType) {
console.error('Mode not detected');
return undefined;
return Promise.resolve();
}
themeService.setTheme(theme);
let text = domNode.firstChild.nodeValue;
let text = domNode.firstChild ? domNode.firstChild.nodeValue : '';
domNode.className += ' ' + theme;
let render = (str: string) => {
domNode.innerHTML = str;
};
return this.colorize(modeService, text, mimeType, options).then(render, (err) => console.error(err));
return this.colorize(modeService, text || '', mimeType, options).then(render, (err) => console.error(err));
}
public static colorize(modeService: IModeService, text: string, mimeType: string, options: IColorizerOptions): Promise<string> {
public static colorize(modeService: IModeService, text: string, mimeType: string, options: IColorizerOptions | null | undefined): Promise<string> {
let tabSize = 4;
if (options && typeof options.tabSize === 'number') {
tabSize = options.tabSize;
}
if (strings.startsWithUTF8BOM(text)) {
text = text.substr(1);
}
let lines = text.split(/\r\n|\r|\n/);
let language = modeService.getModeId(mimeType);
options = options || {};
if (typeof options.tabSize === 'undefined') {
options.tabSize = 4;
if (!language) {
return Promise.resolve(_fakeColorize(lines, tabSize));
}
// Send out the event to create the mode
@ -61,7 +64,7 @@ export class Colorizer {
let tokenizationSupport = TokenizationRegistry.get(language);
if (tokenizationSupport) {
return Promise.resolve(_colorize(lines, options.tabSize, tokenizationSupport));
return Promise.resolve(_colorize(lines, tabSize, tokenizationSupport));
}
return new Promise<string>((resolve, reject) => {
@ -77,18 +80,18 @@ export class Colorizer {
timeout.dispose();
timeout = null;
}
const tokenizationSupport = TokenizationRegistry.get(language);
const tokenizationSupport = TokenizationRegistry.get(language!);
if (tokenizationSupport) {
return resolve(_colorize(lines, options.tabSize, tokenizationSupport));
return resolve(_colorize(lines, tabSize, tokenizationSupport));
}
return resolve(_fakeColorize(lines, options.tabSize));
return resolve(_fakeColorize(lines, tabSize));
};
// wait 500ms for mode to load, then give up
timeout = new TimeoutTimer();
timeout.cancelAndSet(execute, 500);
listener = TokenizationRegistry.onDidChange((e) => {
if (e.changedLanguages.indexOf(language) >= 0) {
if (e.changedLanguages.indexOf(language!) >= 0) {
execute();
}
});

View file

@ -11,7 +11,7 @@ import { Position } from 'vs/editor/common/core/position';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import { registerEditorAction, registerEditorContribution, EditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { ICodeEditor, ContentWidgetPositionPreference, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
import { ICodeEditor, ContentWidgetPositionPreference, IContentWidget, IContentWidgetPosition, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
import { IModeService } from 'vs/editor/common/services/modeService';
import { TokenizationRegistry, LanguageIdentifier, FontStyle, StandardTokenType, ITokenizationSupport, IState, TokenMetadata } from 'vs/editor/common/modes';
import { CharCode } from 'vs/base/common/charCode';
@ -32,7 +32,6 @@ class InspectTokensController extends Disposable implements IEditorContribution
}
private _editor: ICodeEditor;
private _standaloneThemeService: IStandaloneThemeService;
private _modeService: IModeService;
private _widget: InspectTokensWidget | null;
@ -43,7 +42,6 @@ class InspectTokensController extends Disposable implements IEditorContribution
) {
super();
this._editor = editor;
this._standaloneThemeService = standaloneColorService;
this._modeService = modeService;
this._widget = null;
@ -68,7 +66,7 @@ class InspectTokensController extends Disposable implements IEditorContribution
if (!this._editor.hasModel()) {
return;
}
this._widget = new InspectTokensWidget(this._editor, this._standaloneThemeService, this._modeService);
this._widget = new InspectTokensWidget(this._editor, this._modeService);
}
public stop(): void {
@ -164,15 +162,14 @@ class InspectTokensWidget extends Disposable implements IContentWidget {
// Editor.IContentWidget.allowEditorOverflow
public allowEditorOverflow = true;
private _editor: ICodeEditor;
private _editor: IActiveCodeEditor;
private _modeService: IModeService;
private _tokenizationSupport: ITokenizationSupport;
private _model: ITextModel;
private _domNode: HTMLElement;
constructor(
editor: ICodeEditor,
standaloneThemeService: IStandaloneThemeService,
editor: IActiveCodeEditor,
modeService: IModeService
) {
super();
@ -249,14 +246,14 @@ class InspectTokensWidget extends Disposable implements IContentWidget {
}
private _decodeMetadata(metadata: number): IDecodedMetadata {
let colorMap = TokenizationRegistry.getColorMap();
let colorMap = TokenizationRegistry.getColorMap()!;
let languageId = TokenMetadata.getLanguageId(metadata);
let tokenType = TokenMetadata.getTokenType(metadata);
let fontStyle = TokenMetadata.getFontStyle(metadata);
let foreground = TokenMetadata.getForeground(metadata);
let background = TokenMetadata.getBackground(metadata);
return {
languageIdentifier: this._modeService.getLanguageIdentifier(languageId),
languageIdentifier: this._modeService.getLanguageIdentifier(languageId)!,
tokenType: tokenType,
fontStyle: fontStyle,
foreground: colorMap[foreground],

View file

@ -27,9 +27,9 @@ class StandaloneTheme implements IStandaloneTheme {
public readonly themeName: string;
private themeData: IStandaloneThemeData;
private colors: { [colorId: string]: Color };
private defaultColors: { [colorId: string]: Color };
private _tokenTheme: TokenTheme;
private colors: { [colorId: string]: Color } | null;
private defaultColors: { [colorId: string]: Color | null; };
private _tokenTheme: TokenTheme | null;
constructor(name: string, standaloneThemeData: IStandaloneThemeData) {
this.themeData = standaloneThemeData;
@ -77,7 +77,7 @@ class StandaloneTheme implements IStandaloneTheme {
return this.colors;
}
public getColor(colorId: ColorIdentifier, useDefault?: boolean): Color {
public getColor(colorId: ColorIdentifier, useDefault?: boolean): Color | null {
const color = this.getColors()[colorId];
if (color) {
return color;
@ -88,7 +88,7 @@ class StandaloneTheme implements IStandaloneTheme {
return null;
}
private getDefault(colorId: ColorIdentifier): Color {
private getDefault(colorId: ColorIdentifier): Color | null {
let color = this.defaultColors[colorId];
if (color) {
return color;
@ -113,7 +113,7 @@ class StandaloneTheme implements IStandaloneTheme {
public get tokenTheme(): TokenTheme {
if (!this._tokenTheme) {
let rules: ITokenThemeRule[] = [];
let encodedTokensColors = [];
let encodedTokensColors: string[] = [];
if (this.themeData.inherit) {
let baseData = getBuiltinRules(this.themeData.base);
rules = baseData.rules;

View file

@ -10,7 +10,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
class ToggleHighContrast extends EditorAction {
private _originalThemeName: string;
private _originalThemeName: string | null;
constructor() {
super({

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

@ -675,7 +675,7 @@ declare namespace monaco {
* A function that compares ranges, useful for sorting ranges
* It will first compare ranges on the startPosition and then on the endPosition
*/
static compareRangesUsingStarts(a: IRange, b: IRange): number;
static compareRangesUsingStarts(a: IRange | null | undefined, b: IRange | null | undefined): number;
/**
* A function that compares ranges, useful for sorting ranges
* It will first compare ranges on the endPosition and then on the startPosition
@ -4403,11 +4403,11 @@ declare namespace monaco.languages {
/**
* The line comment token, like `// this is a comment`
*/
lineComment?: string;
lineComment?: string | null;
/**
* The block comment character pair, like `/* block comment *&#47;`
*/
blockComment?: CharacterPair;
blockComment?: CharacterPair | null;
}
/**

View file

@ -52,7 +52,7 @@ export interface ITheme {
* @param color the id of the color
* @param useDefault specifies if the default color should be used. If not set, the default is used.
*/
getColor(color: ColorIdentifier, useDefault?: boolean): Color;
getColor(color: ColorIdentifier, useDefault?: boolean): Color | null;
/**
* Returns wheter the theme defines a value for the color. If not, that means the