Merge from vscode 011858832762aaff245b2336fb1c38166e7a10fb (#4663)

This commit is contained in:
Anthony Dresser
2019-03-22 13:07:54 -07:00
committed by GitHub
parent f5c9174c2f
commit 4a87a24235
296 changed files with 2531 additions and 2472 deletions

View File

@@ -20,6 +20,7 @@ import { IConstructorSignature1, ServicesAccessor } from 'vs/platform/instantiat
import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { withNullAsUndefined } from 'vs/base/common/types';
export type ServicesAccessor = ServicesAccessor;
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, IEditorContribution>;
@@ -88,7 +89,7 @@ export abstract class Command {
id: this.id,
handler: (accessor, args) => this.runCommand(accessor, args),
weight: this._kbOpts.weight,
when: kbWhen || null,
when: kbWhen,
primary: this._kbOpts.primary,
secondary: this._kbOpts.secondary,
win: this._kbOpts.win,
@@ -156,7 +157,7 @@ export abstract class EditorCommand extends Command {
return editor.invokeWithinContext((editorAccessor) => {
const kbService = editorAccessor.get(IContextKeyService);
if (!kbService.contextMatchesRules(this.precondition)) {
if (!kbService.contextMatchesRules(withNullAsUndefined(this.precondition))) {
// precondition does not hold
return;
}

View File

@@ -272,7 +272,7 @@ class Widget {
public setPosition(position: IPosition | null | undefined, range: IRange | null | undefined, preference: ContentWidgetPositionPreference[] | null | undefined): void {
this._setPosition(position, range);
this._preference = preference || null;
this._preference = withUndefinedAsNull(preference);
this._cachedDomNodeClientWidth = -1;
this._cachedDomNodeClientHeight = -1;
}

View File

@@ -49,6 +49,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { withNullAsUndefined } from 'vs/base/common/types';
let EDITOR_ID = 0;
@@ -308,7 +309,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
action.id,
action.label,
action.alias,
action.precondition,
withNullAsUndefined(action.precondition),
(): Promise<void> => {
return this._instantiationService.invokeFunction((accessor) => {
return Promise.resolve(action.runEditorCommand(accessor, this, null));
@@ -1644,6 +1645,8 @@ export class EditorModeContext extends Disposable {
private readonly _hasRenameProvider: IContextKey<boolean>;
private readonly _hasDocumentFormattingProvider: IContextKey<boolean>;
private readonly _hasDocumentSelectionFormattingProvider: IContextKey<boolean>;
private readonly _hasMultipleDocumentFormattingProvider: IContextKey<boolean>;
private readonly _hasMultipleDocumentSelectionFormattingProvider: IContextKey<boolean>;
private readonly _hasSignatureHelpProvider: IContextKey<boolean>;
private readonly _isInWalkThrough: IContextKey<boolean>;
@@ -1667,9 +1670,11 @@ export class EditorModeContext extends Disposable {
this._hasDocumentSymbolProvider = EditorContextKeys.hasDocumentSymbolProvider.bindTo(contextKeyService);
this._hasReferenceProvider = EditorContextKeys.hasReferenceProvider.bindTo(contextKeyService);
this._hasRenameProvider = EditorContextKeys.hasRenameProvider.bindTo(contextKeyService);
this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(contextKeyService);
this._hasDocumentFormattingProvider = EditorContextKeys.hasDocumentFormattingProvider.bindTo(contextKeyService);
this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(contextKeyService);
this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(contextKeyService);
this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(contextKeyService);
this._hasMultipleDocumentSelectionFormattingProvider = EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(contextKeyService);
this._isInWalkThrough = EditorContextKeys.isInEmbeddedEditor.bindTo(contextKeyService);
const update = () => this._update();
@@ -1744,6 +1749,8 @@ export class EditorModeContext extends Disposable {
this._hasSignatureHelpProvider.set(modes.SignatureHelpProviderRegistry.has(model));
this._hasDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.has(model) || modes.DocumentRangeFormattingEditProviderRegistry.has(model));
this._hasDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.has(model));
this._hasMultipleDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.all(model).length > 1 || modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
this._hasMultipleDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1);
this._isInWalkThrough.set(model.uri.scheme === Schemas.walkThroughSnippet);
}
}

View File

@@ -12,7 +12,7 @@ export class InternalEditorAction implements IEditorAction {
public readonly label: string;
public readonly alias: string;
private readonly _precondition: ContextKeyExpr | null;
private readonly _precondition: ContextKeyExpr | undefined;
private readonly _run: () => Promise<void>;
private readonly _contextKeyService: IContextKeyService;
@@ -20,7 +20,7 @@ export class InternalEditorAction implements IEditorAction {
id: string,
label: string,
alias: string,
precondition: ContextKeyExpr | null,
precondition: ContextKeyExpr | undefined,
run: () => Promise<void>,
contextKeyService: IContextKeyService
) {

View File

@@ -46,7 +46,12 @@ export namespace EditorContextKeys {
export const hasDocumentSymbolProvider = new RawContextKey<boolean>('editorHasDocumentSymbolProvider', false);
export const hasReferenceProvider = new RawContextKey<boolean>('editorHasReferenceProvider', false);
export const hasRenameProvider = new RawContextKey<boolean>('editorHasRenameProvider', false);
export const hasSignatureHelpProvider = new RawContextKey<boolean>('editorHasSignatureHelpProvider', false);
// -- mode context keys: formatting
export const hasDocumentFormattingProvider = new RawContextKey<boolean>('editorHasDocumentFormattingProvider', false);
export const hasDocumentSelectionFormattingProvider = new RawContextKey<boolean>('editorHasDocumentSelectionFormattingProvider', false);
export const hasSignatureHelpProvider = new RawContextKey<boolean>('editorHasSignatureHelpProvider', false);
export const hasMultipleDocumentFormattingProvider = new RawContextKey<boolean>('editorHasMultipleDocumentFormattingProvider', false);
export const hasMultipleDocumentSelectionFormattingProvider = new RawContextKey<boolean>('editorHasMultipleDocumentSelectionFormattingProvider', false);
}

View File

@@ -32,6 +32,7 @@ import { ignoreBracketsInToken } from 'vs/editor/common/modes/supports';
import { BracketsUtils, RichEditBracket, RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets';
import { IStringStream, ITextSnapshot } from 'vs/platform/files/common/files';
import { ITheme, ThemeColor } from 'vs/platform/theme/common/themeService';
import { withUndefinedAsNull } from 'vs/base/common/types';
const CHEAP_TOKENIZATION_LENGTH_LIMIT = 2048;
@@ -2877,8 +2878,8 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions {
this.stickiness = options.stickiness || model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges;
this.zIndex = options.zIndex || 0;
this.className = options.className ? cleanClassName(options.className) : null;
this.hoverMessage = options.hoverMessage || null;
this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || null;
this.hoverMessage = withUndefinedAsNull(options.hoverMessage);
this.glyphMarginHoverMessage = withUndefinedAsNull(options.glyphMarginHoverMessage);
this.isWholeLine = options.isWholeLine || false;
this.showIfCollapsed = options.showIfCollapsed || false;
this.collapseOnReplaceEdit = options.collapseOnReplaceEdit || false;

View File

@@ -929,6 +929,8 @@ export interface DocumentFormattingEditProvider {
*/
readonly extensionId?: ExtensionIdentifier;
readonly displayName?: string;
/**
* Provide formatting edits for a whole document.
*/
@@ -939,13 +941,13 @@ export interface DocumentFormattingEditProvider {
* the formatting-feature.
*/
export interface DocumentRangeFormattingEditProvider {
/**
* @internal
*/
readonly extensionId?: ExtensionIdentifier;
readonly displayName?: string;
/**
* Provide formatting edits for a range in a document.
*
@@ -1396,6 +1398,24 @@ export interface WorkspaceCommentProvider {
onDidChangeCommentThreads(): Event<CommentThreadChangedEvent>;
}
/**
* @internal
*/
export interface IWebviewOptions {
readonly enableScripts?: boolean;
readonly enableCommandUris?: boolean;
readonly localResourceRoots?: ReadonlyArray<URI>;
readonly portMapping?: ReadonlyArray<{ port: number, resolvedPort: number }>;
}
/**
* @internal
*/
export interface IWebviewPanelOptions {
readonly enableFindWidget?: boolean;
readonly retainContextWhenHidden?: boolean;
}
export interface ICodeLensSymbol {
range: IRange;
id?: string;

View File

@@ -26,7 +26,7 @@ export interface IEditorWorkerService {
canComputeDirtyDiff(original: URI, modified: URI): boolean;
computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise<IChange[] | null>;
computeMoreMinimalEdits(resource: URI, edits: TextEdit[] | null | undefined): Promise<TextEdit[] | null | undefined>;
computeMoreMinimalEdits(resource: URI, edits: TextEdit[] | null | undefined): Promise<TextEdit[] | undefined>;
canComputeWordRanges(resource: URI): boolean;
computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null>;

View File

@@ -20,6 +20,7 @@ import { IDiffComputationResult, IEditorWorkerService } from 'vs/editor/common/s
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { regExpFlags } from 'vs/base/common/strings';
import { isNonEmptyArray } from 'vs/base/common/arrays';
/**
* Stop syncing a model to the worker if it was not needed for 1 min.
@@ -88,14 +89,15 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker
return this._workerManager.withWorker().then(client => client.computeDirtyDiff(original, modified, ignoreTrimWhitespace));
}
public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[] | null | undefined): Promise<modes.TextEdit[] | null | undefined> {
if (!Array.isArray(edits) || edits.length === 0) {
return Promise.resolve(edits);
} else {
public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[] | null | undefined): Promise<modes.TextEdit[] | undefined> {
if (isNonEmptyArray(edits)) {
if (!canSyncModel(this._modelService, resource)) {
return Promise.resolve(edits); // File too large
}
return this._workerManager.withWorker().then(client => client.computeMoreMinimalEdits(resource, edits));
} else {
return Promise.resolve(undefined);
}
}

View File

@@ -15,6 +15,7 @@ import { NULL_LANGUAGE_IDENTIFIER, NULL_MODE_ID } from 'vs/editor/common/modes/n
import { ILanguageExtensionPoint } from 'vs/editor/common/services/modeService';
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { withUndefinedAsNull } from 'vs/base/common/types';
const hasOwnProperty = Object.prototype.hasOwnProperty;
@@ -267,7 +268,7 @@ export class LanguagesRegistry extends Disposable {
return null;
}
const language = this._languages[modeId];
return (language.mimetypes[0] || null);
return withUndefinedAsNull(language.mimetypes[0]);
}
public extractModeIds(commaSeparatedMimetypesOrCommaSeparatedIds: string | undefined): string[] {

View File

@@ -16,6 +16,7 @@ import { keys } from 'vs/base/common/map';
import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService';
import { Schemas } from 'vs/base/common/network';
import { Emitter, Event } from 'vs/base/common/event';
import { withUndefinedAsNull } from 'vs/base/common/types';
function MODEL_ID(resource: URI): string {
return resource.toString();
@@ -80,7 +81,7 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
getMarker(model: ITextModel, decoration: IModelDecoration): IMarker | null {
const markerDecorations = this._markerDecorations.get(MODEL_ID(model.uri));
return markerDecorations ? markerDecorations.getMarker(decoration) || null : null;
return markerDecorations ? withUndefinedAsNull(markerDecorations.getMarker(decoration)) : null;
}
getLiveMarkers(model: ITextModel): [Range, IMarker][] {

View File

@@ -163,7 +163,7 @@ export class LightBulbWidget extends Disposable implements IContentWidget {
const lineContent = model.getLineContent(lineNumber);
const indent = TextModel.computeIndentLevel(lineContent, tabSize);
const lineHasSpace = config.fontInfo.spaceWidth * indent > 22;
const isFolded = (lineNumber) => {
const isFolded = (lineNumber: number) => {
return lineNumber > 2 && this._editor.getTopForLineNumber(lineNumber) === this._editor.getTopForLineNumber(lineNumber - 1);
};

View File

@@ -25,7 +25,7 @@ class CodeLensViewZone implements editorBrowser.IViewZone {
afterLineNumber: number;
private _lastHeight: number;
private _lastHeight?: number;
private readonly _onHeight: Function;
constructor(afterLineNumber: number, onHeight: Function) {

View File

@@ -67,7 +67,7 @@ suite('FindController', () => {
getBoolean: (key: string) => !!queryState[key],
getNumber: (key: string) => undefined,
store: (key: string, value: any) => { queryState[key] = value; return Promise.resolve(); },
remove: (key) => undefined
remove: () => undefined
} as any);
if (platform.isMacintosh) {
@@ -442,7 +442,7 @@ suite('FindController query options persistence', () => {
getBoolean: (key: string) => !!queryState[key],
getNumber: (key: string) => undefined,
store: (key: string, value: any) => { queryState[key] = value; return Promise.resolve(); },
remove: (key) => undefined
remove: () => undefined
} as any);
test('matchCase', () => {

View File

@@ -66,7 +66,7 @@ export class FoldingModel {
public update(newRegions: FoldingRegions, blockedLineNumers: number[] = []): void {
let newEditorDecorations: IModelDeltaDecoration[] = [];
let isBlocked = (startLineNumber, endLineNumber) => {
let isBlocked = (startLineNumber: number, endLineNumber: number) => {
for (let blockedLineNumber of blockedLineNumers) {
if (startLineNumber < blockedLineNumber && blockedLineNumber <= endLineNumber) { // first line is visible
return true;

View File

@@ -3,138 +3,258 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { alert } from 'vs/base/browser/ui/aria/aria';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/errors';
import { URI } from 'vs/base/common/uri';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { DocumentFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry, FormattingOptions, TextEdit } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import { first } from 'vs/base/common/async';
import { CodeEditorStateFlag, EditorState } from 'vs/editor/browser/core/editorState';
import { IActiveCodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { registerLanguageCommand, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ISingleEditOperation, ITextModel } from 'vs/editor/common/model';
import { DocumentFormattingEditProvider, DocumentFormattingEditProviderRegistry, DocumentRangeFormattingEditProvider, DocumentRangeFormattingEditProviderRegistry, FormattingOptions, OnTypeFormattingEditProviderRegistry, TextEdit } from 'vs/editor/common/modes';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IModelService } from 'vs/editor/common/services/modelService';
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
import * as nls from 'vs/nls';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IDisposable } from 'vs/base/common/lifecycle';
export const enum FormatMode {
Auto = 1,
Manual = 2,
}
export function alertFormattingEdits(edits: ISingleEditOperation[]): void {
export const enum FormatKind {
Document = 8,
Range = 16,
OnType = 32,
}
edits = edits.filter(edit => edit.range);
if (!edits.length) {
return;
}
export interface IFormatterConflictCallback {
(extensionIds: (ExtensionIdentifier | undefined)[], model: ITextModel, mode: number): void;
}
let _conflictResolver: IFormatterConflictCallback | undefined;
export function setFormatterConflictCallback(callback: IFormatterConflictCallback): IDisposable {
let oldCallback = _conflictResolver;
_conflictResolver = callback;
return {
dispose() {
if (oldCallback) {
_conflictResolver = oldCallback;
oldCallback = undefined;
}
let { range } = edits[0];
for (let i = 1; i < edits.length; i++) {
range = Range.plusRange(range, edits[i].range);
}
const { startLineNumber, endLineNumber } = range;
if (startLineNumber === endLineNumber) {
if (edits.length === 1) {
alert(nls.localize('hint11', "Made 1 formatting edit on line {0}", startLineNumber));
} else {
alert(nls.localize('hintn1', "Made {0} formatting edits on line {1}", edits.length, startLineNumber));
}
} else {
if (edits.length === 1) {
alert(nls.localize('hint1n', "Made 1 formatting edit between lines {0} and {1}", startLineNumber, endLineNumber));
} else {
alert(nls.localize('hintnn', "Made {0} formatting edits between lines {1} and {2}", edits.length, startLineNumber, endLineNumber));
}
};
}
function invokeFormatterCallback<T extends { extensionId?: ExtensionIdentifier }>(formatter: T[], model: ITextModel, mode: number): void {
if (_conflictResolver) {
const ids = formatter.map(formatter => formatter.extensionId);
_conflictResolver(ids, model, mode);
}
}
export async function getDocumentRangeFormattingEdits(
telemetryService: ITelemetryService,
export function getRealAndSyntheticDocumentFormattersOrdered(model: ITextModel): DocumentFormattingEditProvider[] {
const result: DocumentFormattingEditProvider[] = [];
const seen = new Set<string>();
// (1) add all document formatter
const docFormatter = DocumentFormattingEditProviderRegistry.ordered(model);
for (const formatter of docFormatter) {
result.push(formatter);
if (formatter.extensionId) {
seen.add(ExtensionIdentifier.toKey(formatter.extensionId));
}
}
// (2) add all range formatter as document formatter (unless the same extension already did that)
const rangeFormatter = DocumentRangeFormattingEditProviderRegistry.ordered(model);
for (const formatter of rangeFormatter) {
if (formatter.extensionId) {
if (seen.has(ExtensionIdentifier.toKey(formatter.extensionId))) {
continue;
}
seen.add(ExtensionIdentifier.toKey(formatter.extensionId));
}
result.push({
displayName: formatter.displayName,
extensionId: formatter.extensionId,
provideDocumentFormattingEdits(model, options, token) {
return formatter.provideDocumentRangeFormattingEdits(model, model.getFullModelRange(), options, token);
}
});
}
return result;
}
export async function formatDocumentRangeWithProvider(
accessor: ServicesAccessor,
provider: DocumentRangeFormattingEditProvider,
editorOrModel: ITextModel | IActiveCodeEditor,
range: Range,
token: CancellationToken
): Promise<boolean> {
const workerService = accessor.get(IEditorWorkerService);
let model: ITextModel;
let validate: () => boolean;
if (isCodeEditor(editorOrModel)) {
model = editorOrModel.getModel();
const state = new EditorState(editorOrModel, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
validate = () => state.validate(editorOrModel);
} else {
model = editorOrModel;
const versionNow = editorOrModel.getVersionId();
validate = () => versionNow === editorOrModel.getVersionId();
}
const rawEdits = await provider.provideDocumentRangeFormattingEdits(
model,
range,
model.getFormattingOptions(),
token
);
const edits = await workerService.computeMoreMinimalEdits(model.uri, rawEdits);
if (!validate()) {
return true;
}
if (!edits || edits.length === 0) {
return false;
}
if (isCodeEditor(editorOrModel)) {
// use editor to apply edits
FormattingEdit.execute(editorOrModel, edits);
alertFormattingEdits(edits);
editorOrModel.pushUndoStop();
editorOrModel.focus();
editorOrModel.revealPositionInCenterIfOutsideViewport(editorOrModel.getPosition(), editorCommon.ScrollType.Immediate);
} else {
// use model to apply edits
const [{ range }] = edits;
const initialSelection = new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);
model.pushEditOperations([initialSelection], edits.map(edit => {
return {
text: edit.text,
range: Range.lift(edit.range),
forceMoveMarkers: true
};
}), undoEdits => {
for (const { range } of undoEdits) {
if (Range.areIntersectingOrTouching(range, initialSelection)) {
return [new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn)];
}
}
return null;
});
}
return true;
}
export async function formatDocumentWithProvider(
accessor: ServicesAccessor,
provider: DocumentFormattingEditProvider,
editorOrModel: ITextModel | IActiveCodeEditor,
token: CancellationToken
): Promise<boolean> {
const workerService = accessor.get(IEditorWorkerService);
let model: ITextModel;
let validate: () => boolean;
if (isCodeEditor(editorOrModel)) {
model = editorOrModel.getModel();
const state = new EditorState(editorOrModel, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
validate = () => state.validate(editorOrModel);
} else {
model = editorOrModel;
const versionNow = editorOrModel.getVersionId();
validate = () => versionNow === editorOrModel.getVersionId();
}
const rawEdits = await provider.provideDocumentFormattingEdits(
model,
model.getFormattingOptions(),
token
);
const edits = await workerService.computeMoreMinimalEdits(model.uri, rawEdits);
if (!validate()) {
return true;
}
if (!edits || edits.length === 0) {
return false;
}
if (isCodeEditor(editorOrModel)) {
// use editor to apply edits
FormattingEdit.execute(editorOrModel, edits);
alertFormattingEdits(edits);
editorOrModel.pushUndoStop();
editorOrModel.focus();
editorOrModel.revealPositionInCenterIfOutsideViewport(editorOrModel.getPosition(), editorCommon.ScrollType.Immediate);
} else {
// use model to apply edits
const [{ range }] = edits;
const initialSelection = new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn);
model.pushEditOperations([initialSelection], edits.map(edit => {
return {
text: edit.text,
range: Range.lift(edit.range),
forceMoveMarkers: true
};
}), undoEdits => {
for (const { range } of undoEdits) {
if (Range.areIntersectingOrTouching(range, initialSelection)) {
return [new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn)];
}
}
return null;
});
}
return true;
}
export async function getDocumentRangeFormattingEditsUntilResult(
workerService: IEditorWorkerService,
model: ITextModel,
range: Range,
options: FormattingOptions,
mode: FormatMode,
token: CancellationToken
): Promise<TextEdit[] | undefined | null> {
): Promise<TextEdit[] | undefined> {
const providers = DocumentRangeFormattingEditProviderRegistry.ordered(model);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"extensions" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
for (const provider of providers) {
let rawEdits = await Promise.resolve(provider.provideDocumentRangeFormattingEdits(model, range, options, token)).catch(onUnexpectedExternalError);
if (isNonEmptyArray(rawEdits)) {
return await workerService.computeMoreMinimalEdits(model.uri, rawEdits);
}
*/
telemetryService.publicLog('formatterInfo', {
type: 'range',
language: model.getLanguageIdentifier().language,
count: providers.length,
extensions: providers.map(p => p.extensionId ? ExtensionIdentifier.toKey(p.extensionId) : 'unknown')
});
invokeFormatterCallback(providers, model, mode | FormatKind.Range);
return first(providers.map(provider => () => {
return Promise.resolve(provider.provideDocumentRangeFormattingEdits(model, range, options, token)).catch(onUnexpectedExternalError);
}), isNonEmptyArray).then(edits => {
// break edits into smaller edits
return workerService.computeMoreMinimalEdits(model.uri, edits);
});
}
return undefined;
}
export function getDocumentFormattingEdits(
telemetryService: ITelemetryService,
export async function getDocumentFormattingEditsUntilResult(
workerService: IEditorWorkerService,
model: ITextModel,
options: FormattingOptions,
mode: FormatMode,
token: CancellationToken
): Promise<TextEdit[] | null | undefined> {
): Promise<TextEdit[] | undefined> {
const docFormattingProviders = DocumentFormattingEditProviderRegistry.ordered(model);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"extensions" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
const providers = getRealAndSyntheticDocumentFormattersOrdered(model);
for (const provider of providers) {
let rawEdits = await Promise.resolve(provider.provideDocumentFormattingEdits(model, options, token)).catch(onUnexpectedExternalError);
if (isNonEmptyArray(rawEdits)) {
return await workerService.computeMoreMinimalEdits(model.uri, rawEdits);
}
*/
telemetryService.publicLog('formatterInfo', {
type: 'document',
language: model.getLanguageIdentifier().language,
count: docFormattingProviders.length,
extensions: docFormattingProviders.map(p => p.extensionId ? ExtensionIdentifier.toKey(p.extensionId) : 'unknown')
});
if (docFormattingProviders.length > 0) {
return first(docFormattingProviders.map(provider => () => {
// first with result wins...
return Promise.resolve(provider.provideDocumentFormattingEdits(model, options, token)).catch(onUnexpectedExternalError);
}), isNonEmptyArray).then(edits => {
// break edits into smaller edits
return workerService.computeMoreMinimalEdits(model.uri, edits);
});
} else {
// try range formatters when no document formatter is registered
return getDocumentRangeFormattingEdits(telemetryService, workerService, model, model.getFullModelRange(), options, mode | FormatKind.Document, token);
}
return undefined;
}
export function getOnTypeFormattingEdits(
telemetryService: ITelemetryService,
workerService: IEditorWorkerService,
model: ITextModel,
position: Position,
@@ -144,21 +264,6 @@ export function getOnTypeFormattingEdits(
const providers = OnTypeFormattingEditProviderRegistry.ordered(model);
/* __GDPR__
"formatterInfo" : {
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"extensions" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
telemetryService.publicLog('formatterInfo', {
type: 'ontype',
language: model.getLanguageIdentifier().language,
count: providers.length,
extensions: providers.map(p => p.extensionId ? ExtensionIdentifier.toKey(p.extensionId) : 'unknown')
});
if (providers.length === 0) {
return Promise.resolve(undefined);
}
@@ -181,7 +286,7 @@ registerLanguageCommand('_executeFormatRangeProvider', function (accessor, args)
if (!model) {
throw illegalArgument('resource');
}
return getDocumentRangeFormattingEdits(accessor.get(ITelemetryService), accessor.get(IEditorWorkerService), model, Range.lift(range), options, FormatMode.Auto, CancellationToken.None);
return getDocumentRangeFormattingEditsUntilResult(accessor.get(IEditorWorkerService), model, Range.lift(range), options, CancellationToken.None);
});
registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, args) {
@@ -194,7 +299,7 @@ registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, ar
throw illegalArgument('resource');
}
return getDocumentFormattingEdits(accessor.get(ITelemetryService), accessor.get(IEditorWorkerService), model, options, FormatMode.Auto, CancellationToken.None);
return getDocumentFormattingEditsUntilResult(accessor.get(IEditorWorkerService), model, options, CancellationToken.None);
});
registerLanguageCommand('_executeFormatOnTypeProvider', function (accessor, args) {
@@ -207,5 +312,5 @@ registerLanguageCommand('_executeFormatOnTypeProvider', function (accessor, args
throw illegalArgument('resource');
}
return getOnTypeFormattingEdits(accessor.get(ITelemetryService), accessor.get(IEditorWorkerService), model, Position.lift(position), ch, options);
return getOnTypeFormattingEdits(accessor.get(IEditorWorkerService), model, Position.lift(position), ch, options);
});

View File

@@ -3,122 +3,27 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { alert } from 'vs/base/browser/ui/aria/aria';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { CodeEditorStateFlag, EditorState } from 'vs/editor/browser/core/editorState';
import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, registerEditorAction, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CharacterSet } from 'vs/editor/common/core/characterClassifier';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ISingleEditOperation } from 'vs/editor/common/model';
import { DocumentRangeFormattingEditProviderRegistry, FormattingOptions, OnTypeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
import { DocumentRangeFormattingEditProviderRegistry, OnTypeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { getOnTypeFormattingEdits, getDocumentFormattingEdits, getDocumentRangeFormattingEdits, FormatMode } from 'vs/editor/contrib/format/format';
import { getOnTypeFormattingEdits, formatDocumentWithProvider, formatDocumentRangeWithProvider, alertFormattingEdits, getRealAndSyntheticDocumentFormattersOrdered } from 'vs/editor/contrib/format/format';
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
import * as nls from 'vs/nls';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
function alertFormattingEdits(edits: ISingleEditOperation[]): void {
edits = edits.filter(edit => edit.range);
if (!edits.length) {
return;
}
let { range } = edits[0];
for (let i = 1; i < edits.length; i++) {
range = Range.plusRange(range, edits[i].range);
}
const { startLineNumber, endLineNumber } = range;
if (startLineNumber === endLineNumber) {
if (edits.length === 1) {
alert(nls.localize('hint11', "Made 1 formatting edit on line {0}", startLineNumber));
} else {
alert(nls.localize('hintn1', "Made {0} formatting edits on line {1}", edits.length, startLineNumber));
}
} else {
if (edits.length === 1) {
alert(nls.localize('hint1n', "Made 1 formatting edit between lines {0} and {1}", startLineNumber, endLineNumber));
} else {
alert(nls.localize('hintnn', "Made {0} formatting edits between lines {1} and {2}", edits.length, startLineNumber, endLineNumber));
}
}
}
const enum FormatRangeType {
Full,
Selection,
}
function formatDocumentRange(
telemetryService: ITelemetryService,
workerService: IEditorWorkerService,
editor: IActiveCodeEditor,
rangeOrRangeType: Range | FormatRangeType,
options: FormattingOptions,
token: CancellationToken
): Promise<void> {
const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
const model = editor.getModel();
let range: Range;
if (rangeOrRangeType === FormatRangeType.Full) {
// full
range = model.getFullModelRange();
} else if (rangeOrRangeType === FormatRangeType.Selection) {
// selection or line (when empty)
range = editor.getSelection();
if (range.isEmpty()) {
range = new Range(range.startLineNumber, 1, range.endLineNumber, model.getLineMaxColumn(range.endLineNumber));
}
} else {
// as is
range = rangeOrRangeType;
}
return getDocumentRangeFormattingEdits(telemetryService, workerService, model, range, options, FormatMode.Manual, token).then(edits => {
// make edit only when the editor didn't change while
// computing and only when there are edits
if (state.validate(editor) && isNonEmptyArray(edits)) {
FormattingEdit.execute(editor, edits);
alertFormattingEdits(edits);
editor.focus();
editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
}
});
}
function formatDocument(telemetryService: ITelemetryService, workerService: IEditorWorkerService, editor: IActiveCodeEditor, options: FormattingOptions, token: CancellationToken): Promise<void> {
const allEdits: ISingleEditOperation[] = [];
const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
return getDocumentFormattingEdits(telemetryService, workerService, editor.getModel(), options, FormatMode.Manual, token).then(edits => {
// make edit only when the editor didn't change while
// computing and only when there are edits
if (state.validate(editor) && isNonEmptyArray(edits)) {
FormattingEdit.execute(editor, edits);
alertFormattingEdits(allEdits);
editor.pushUndoStop();
editor.focus();
editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
}
});
}
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { onUnexpectedError } from 'vs/base/common/errors';
class FormatOnType implements editorCommon.IEditorContribution {
@@ -130,17 +35,25 @@ class FormatOnType implements editorCommon.IEditorContribution {
constructor(
editor: ICodeEditor,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IEditorWorkerService private readonly _workerService: IEditorWorkerService
) {
this._editor = editor;
this._callOnDispose.push(editor.onDidChangeConfiguration(() => this.update()));
this._callOnDispose.push(editor.onDidChangeModel(() => this.update()));
this._callOnDispose.push(editor.onDidChangeModelLanguage(() => this.update()));
this._callOnDispose.push(OnTypeFormattingEditProviderRegistry.onDidChange(this.update, this));
this._callOnDispose.push(editor.onDidChangeConfiguration(() => this._update()));
this._callOnDispose.push(editor.onDidChangeModel(() => this._update()));
this._callOnDispose.push(editor.onDidChangeModelLanguage(() => this._update()));
this._callOnDispose.push(OnTypeFormattingEditProviderRegistry.onDidChange(this._update, this));
}
private update(): void {
getId(): string {
return FormatOnType.ID;
}
dispose(): void {
this._callOnDispose = dispose(this._callOnDispose);
this._callOnModel = dispose(this._callOnModel);
}
private _update(): void {
// clean up
this._callOnModel = dispose(this._callOnModel);
@@ -171,12 +84,12 @@ class FormatOnType implements editorCommon.IEditorContribution {
this._callOnModel.push(this._editor.onDidType((text: string) => {
let lastCharCode = text.charCodeAt(text.length - 1);
if (triggerChars.has(lastCharCode)) {
this.trigger(String.fromCharCode(lastCharCode));
this._trigger(String.fromCharCode(lastCharCode));
}
}));
}
private trigger(ch: string): void {
private _trigger(ch: string): void {
if (!this._editor.hasModel()) {
return;
}
@@ -214,7 +127,6 @@ class FormatOnType implements editorCommon.IEditorContribution {
});
getOnTypeFormattingEdits(
this._telemetryService,
this._workerService,
model,
position,
@@ -238,42 +150,41 @@ class FormatOnType implements editorCommon.IEditorContribution {
throw err;
});
}
public getId(): string {
return FormatOnType.ID;
}
public dispose(): void {
this._callOnDispose = dispose(this._callOnDispose);
this._callOnModel = dispose(this._callOnModel);
}
}
class FormatOnPaste implements editorCommon.IEditorContribution {
private static readonly ID = 'editor.contrib.formatOnPaste';
private callOnDispose: IDisposable[];
private callOnModel: IDisposable[];
private _callOnDispose: IDisposable[];
private _callOnModel: IDisposable[];
constructor(
private readonly editor: ICodeEditor,
@IEditorWorkerService private readonly workerService: IEditorWorkerService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
this.callOnDispose = [];
this.callOnModel = [];
this._callOnDispose = [];
this._callOnModel = [];
this.callOnDispose.push(editor.onDidChangeConfiguration(() => this.update()));
this.callOnDispose.push(editor.onDidChangeModel(() => this.update()));
this.callOnDispose.push(editor.onDidChangeModelLanguage(() => this.update()));
this.callOnDispose.push(DocumentRangeFormattingEditProviderRegistry.onDidChange(this.update, this));
this._callOnDispose.push(editor.onDidChangeConfiguration(() => this._update()));
this._callOnDispose.push(editor.onDidChangeModel(() => this._update()));
this._callOnDispose.push(editor.onDidChangeModelLanguage(() => this._update()));
this._callOnDispose.push(DocumentRangeFormattingEditProviderRegistry.onDidChange(this._update, this));
}
private update(): void {
getId(): string {
return FormatOnPaste.ID;
}
dispose(): void {
this._callOnDispose = dispose(this._callOnDispose);
this._callOnModel = dispose(this._callOnModel);
}
private _update(): void {
// clean up
this.callOnModel = dispose(this.callOnModel);
this._callOnModel = dispose(this._callOnModel);
// we are disabled
if (!this.editor.getConfiguration().contribInfo.formatOnPaste) {
@@ -285,53 +196,41 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
return;
}
let model = this.editor.getModel();
// no support
if (!DocumentRangeFormattingEditProviderRegistry.has(model)) {
// no formatter
if (!DocumentRangeFormattingEditProviderRegistry.has(this.editor.getModel())) {
return;
}
this.callOnModel.push(this.editor.onDidPaste((range: Range) => {
this.trigger(range);
}));
this._callOnModel.push(this.editor.onDidPaste(range => this._trigger(range)));
}
private trigger(range: Range): void {
private _trigger(range: Range): void {
if (!this.editor.hasModel()) {
return;
}
if (this.editor.getSelections().length > 1) {
return;
}
const model = this.editor.getModel();
formatDocumentRange(this.telemetryService, this.workerService, this.editor, range, model.getFormattingOptions(), CancellationToken.None);
}
public getId(): string {
return FormatOnPaste.ID;
}
public dispose(): void {
this.callOnDispose = dispose(this.callOnDispose);
this.callOnModel = dispose(this.callOnModel);
const provider = DocumentRangeFormattingEditProviderRegistry.ordered(this.editor.getModel());
if (provider.length !== 1) {
// print status in n>1 case?
return;
}
this._instantiationService.invokeFunction(formatDocumentRangeWithProvider, provider[0], this.editor, range, CancellationToken.None).catch(onUnexpectedError);
}
}
export class FormatDocumentAction extends EditorAction {
class FormatDocumentAction extends EditorAction {
constructor() {
super({
id: 'editor.action.formatDocument',
label: nls.localize('formatDocument.label', "Format Document"),
alias: 'Format Document',
precondition: EditorContextKeys.writable,
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasDocumentFormattingProvider, EditorContextKeys.hasMultipleDocumentFormattingProvider.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
kbExpr: ContextKeyExpr.and(EditorContextKeys.editorTextFocus, EditorContextKeys.hasDocumentFormattingProvider),
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_F,
// secondary: [KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_D)],
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_I },
weight: KeybindingWeight.EditorContrib
},
@@ -343,26 +242,29 @@ export class FormatDocumentAction extends EditorAction {
});
}
run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> | void {
async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
if (!editor.hasModel()) {
return;
}
const workerService = accessor.get(IEditorWorkerService);
const telemetryService = accessor.get(ITelemetryService);
return formatDocument(telemetryService, workerService, editor, editor.getModel().getFormattingOptions(), CancellationToken.None);
const instaService = accessor.get(IInstantiationService);
const model = editor.getModel();
const [provider] = getRealAndSyntheticDocumentFormattersOrdered(model);
if (provider) {
await instaService.invokeFunction(formatDocumentWithProvider, provider, editor, CancellationToken.None);
}
}
}
export class FormatSelectionAction extends EditorAction {
class FormatSelectionAction extends EditorAction {
constructor() {
super({
id: 'editor.action.formatSelection',
label: nls.localize('formatSelection.label', "Format Selection"),
alias: 'Format Code',
precondition: ContextKeyExpr.and(EditorContextKeys.writable),
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasDocumentSelectionFormattingProvider, EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
kbExpr: ContextKeyExpr.and(EditorContextKeys.editorTextFocus, EditorContextKeys.hasDocumentSelectionFormattingProvider),
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_F),
weight: KeybindingWeight.EditorContrib
},
@@ -374,13 +276,19 @@ export class FormatSelectionAction extends EditorAction {
});
}
run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> | void {
async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
if (!editor.hasModel()) {
return;
}
const workerService = accessor.get(IEditorWorkerService);
const telemetryService = accessor.get(ITelemetryService);
return formatDocumentRange(telemetryService, workerService, editor, FormatRangeType.Selection, editor.getModel().getFormattingOptions(), CancellationToken.None);
const instaService = accessor.get(IInstantiationService);
const [best] = DocumentRangeFormattingEditProviderRegistry.ordered(editor.getModel());
if (best) {
let range: Range = editor.getSelection();
if (range.isEmpty()) {
range = new Range(range.startLineNumber, 1, range.startLineNumber, editor.getModel().getLineMaxColumn(range.startLineNumber));
}
await instaService.invokeFunction(formatDocumentRangeWithProvider, best, editor, range, CancellationToken.None);
}
}
}
@@ -391,17 +299,15 @@ registerEditorAction(FormatSelectionAction);
// this is the old format action that does both (format document OR format selection)
// and we keep it here such that existing keybinding configurations etc will still work
CommandsRegistry.registerCommand('editor.action.format', accessor => {
CommandsRegistry.registerCommand('editor.action.format', async accessor => {
const editor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
if (!editor || !editor.hasModel()) {
return undefined;
return;
}
const workerService = accessor.get(IEditorWorkerService);
const telemetryService = accessor.get(ITelemetryService);
const commandService = accessor.get(ICommandService);
if (editor.getSelection().isEmpty()) {
return formatDocument(telemetryService, workerService, editor, editor.getModel().getFormattingOptions(), CancellationToken.None);
await commandService.executeCommand('editor.action.formatDocument');
} else {
return formatDocumentRange(telemetryService, workerService, editor, FormatRangeType.Selection, editor.getModel().getFormattingOptions(), CancellationToken.None);
await commandService.executeCommand('editor.action.formatSelection');
}
});

View File

@@ -203,8 +203,8 @@ export class MarkerController implements editorCommon.IEditorContribution {
}
private readonly _editor: ICodeEditor;
private _model: MarkerModel | null;
private _widget: MarkerNavigationWidget | null;
private _model: MarkerModel | null = null;
private _widget: MarkerNavigationWidget | null = null;
private readonly _widgetVisible: IContextKey<boolean>;
private _disposeOnClose: IDisposable[] = [];

View File

@@ -21,7 +21,7 @@ export class MoveLinesCommand implements ICommand {
private readonly _autoIndent: boolean;
private _selectionId: string;
private _moveEndPositionDown: boolean;
private _moveEndPositionDown?: boolean;
private _moveEndLineSelectionShrink: boolean;
constructor(selection: Selection, isMovingDown: boolean, autoIndent: boolean) {

View File

@@ -196,10 +196,9 @@ suite('Editor Contrib - Line Operations', () => {
const endOfNonono = new Selection(5, 11, 5, 11);
editor.setSelections([beforeSecondWasoSelection, endOfBCCSelection, endOfNonono]);
let selections;
deleteAllLeftAction.run(null!, editor);
selections = editor.getSelections();
let selections = editor.getSelections()!;
assert.equal(model.getLineContent(2), '');
assert.equal(model.getLineContent(3), ' waso waso');
@@ -227,7 +226,7 @@ suite('Editor Contrib - Line Operations', () => {
], [5, 1, 5, 1]);
deleteAllLeftAction.run(null!, editor);
selections = editor.getSelections();
selections = editor.getSelections()!;
assert.equal(model.getLineContent(1), 'hi my name is Carlos Matos waso waso');
assert.equal(selections.length, 2);

View File

@@ -21,6 +21,7 @@ import { Choice, Placeholder, SnippetParser, Text, TextmateSnippet } from './sni
import { ClipboardBasedVariableResolver, CompositeSnippetVariableResolver, ModelBasedVariableResolver, SelectionBasedVariableResolver, TimeBasedVariableResolver, CommentBasedVariableResolver, WorkspaceBasedVariableResolver } from './snippetVariables';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import { withNullAsUndefined } from 'vs/base/common/types';
registerThemingParticipant((theme, collector) => {
@@ -281,7 +282,7 @@ export class OneSnippet {
let result: Range | undefined;
const model = this._editor.getModel();
this._placeholderDecorations.forEach((decorationId) => {
const placeholderRange = model.getDecorationRange(decorationId) || undefined;
const placeholderRange = withNullAsUndefined(model.getDecorationRange(decorationId));
if (!result) {
result = placeholderRange;
} else {

View File

@@ -18,8 +18,8 @@ export class SuggestAlternatives {
private _index: number;
private _model: CompletionModel | undefined;
private _acceptNext: ((selected: ISelectedSuggestion) => any) | undefined;
private _listener: IDisposable;
private _ignore: boolean;
private _listener: IDisposable | undefined;
private _ignore: boolean | undefined;
constructor(
private readonly _editor: ICodeEditor,

View File

@@ -63,16 +63,16 @@ export class Colorizer {
// Send out the event to create the mode
modeService.triggerMode(language);
let tokenizationSupport = TokenizationRegistry.get(language);
const tokenizationSupport = TokenizationRegistry.get(language);
if (tokenizationSupport) {
return _colorize(lines, tabSize, tokenizationSupport);
}
let tokenizationSupportPromise = TokenizationRegistry.getPromise(language);
const tokenizationSupportPromise = TokenizationRegistry.getPromise(language);
if (tokenizationSupportPromise) {
// A tokenizer will be registered soon
return new Promise<string>((resolve, reject) => {
tokenizationSupportPromise!.then(tokenizationSupport => {
tokenizationSupportPromise.then(tokenizationSupport => {
_colorize(lines, tabSize, tokenizationSupport).then(resolve, reject);
}, reject);
});

View File

@@ -280,7 +280,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
}));
}
public addDynamicKeybinding(commandId: string, _keybinding: number, handler: ICommandHandler, when: ContextKeyExpr | null): IDisposable {
public addDynamicKeybinding(commandId: string, _keybinding: number, handler: ICommandHandler, when: ContextKeyExpr | undefined): IDisposable {
const keybinding = createKeybinding(_keybinding, OS);
if (!keybinding) {
throw new Error(`Invalid keybinding`);
@@ -342,7 +342,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
private _toNormalizedKeybindingItems(items: IKeybindingItem[], isDefault: boolean): ResolvedKeybindingItem[] {
let result: ResolvedKeybindingItem[] = [], resultLen = 0;
for (const item of items) {
const when = (item.when ? item.when.normalize() : null);
const when = (item.when ? item.when.normalize() : undefined);
const keybinding = item.keybinding;
if (!keybinding) {
@@ -665,9 +665,5 @@ export class SimpleLayoutService implements ILayoutService {
return this._container;
}
get hasWorkbench(): boolean {
return false;
}
constructor(private _container: HTMLElement) { }
}

View File

@@ -202,7 +202,12 @@ export class DynamicStandaloneServices extends Disposable {
let contextViewService = ensure(IContextViewService, () => this._register(new ContextViewService(layoutService)));
ensure(IContextMenuService, () => this._register(new ContextMenuService(layoutService, telemetryService, notificationService, contextViewService, keybindingService, themeService)));
ensure(IContextMenuService, () => {
const contextMenuService = new ContextMenuService(telemetryService, notificationService, contextViewService, keybindingService, themeService);
contextMenuService.configure({ blockMouse: false }); // we do not want that in the standalone editor
return this._register(contextMenuService);
});
ensure(IMenuService, () => new MenuService(commandService));

View File

@@ -39,7 +39,7 @@ suite('StandaloneKeybindingService', () => {
let commandInvoked = false;
keybindingService.addDynamicKeybinding('testCommand', KeyCode.F9, () => {
commandInvoked = true;
}, null);
}, undefined);
keybindingService.testDispatch({
_standardKeyboardEventBrand: true,

View File

@@ -13,7 +13,7 @@ import { IResourceInput } from 'vs/platform/editor/common/editor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export class TestCodeEditorService extends AbstractCodeEditorService {
public lastInput: IResourceInput;
public lastInput?: IResourceInput;
public getActiveCodeEditor(): ICodeEditor | null { return null; }
public openCodeEditor(input: IResourceInput, source: ICodeEditor | null, sideBySide?: boolean): Promise<ICodeEditor | null> {
this.lastInput = input;

View File

@@ -30,7 +30,7 @@ suite('OpenerService', function () {
test('delegate to editorService, scheme:///fff', function () {
const openerService = new OpenerService(editorService, NullCommandService);
openerService.open(URI.parse('another:///somepath'));
assert.equal(editorService.lastInput.options!.selection, undefined);
assert.equal(editorService.lastInput!.options!.selection, undefined);
});
test('delegate to editorService, scheme:///fff#L123', function () {
@@ -38,22 +38,22 @@ suite('OpenerService', function () {
const openerService = new OpenerService(editorService, NullCommandService);
openerService.open(URI.parse('file:///somepath#L23'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput.resource.fragment, '');
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
openerService.open(URI.parse('another:///somepath#L23'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
openerService.open(URI.parse('another:///somepath#L23,45'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput.resource.fragment, '');
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
});
test('delegate to editorService, scheme:///fff#123,123', function () {
@@ -61,18 +61,18 @@ suite('OpenerService', function () {
const openerService = new OpenerService(editorService, NullCommandService);
openerService.open(URI.parse('file:///somepath#23'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput.resource.fragment, '');
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
openerService.open(URI.parse('file:///somepath#23,45'));
assert.equal(editorService.lastInput.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput.resource.fragment, '');
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 45);
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
assert.equal(editorService.lastInput!.resource.fragment, '');
});
test('delegate to commandsService, command:someid', function () {