diff --git a/src/vs/editor/contrib/snippet/browser/snippetVariables.ts b/src/vs/editor/contrib/snippet/browser/snippetVariables.ts index 09c08f4b026ad7..96aebfb834d88e 100644 --- a/src/vs/editor/contrib/snippet/browser/snippetVariables.ts +++ b/src/vs/editor/contrib/snippet/browser/snippetVariables.ts @@ -41,6 +41,8 @@ export const KnownSnippetVariableNames: { [key: string]: true } = Object.freeze( 'TM_FILENAME_BASE': true, 'TM_DIRECTORY': true, 'TM_FILEPATH': true, + 'CURSOR_INDEX': true, // 0-offset + 'CURSOR_NUMBER': true, // 1-offset 'RELATIVE_FILEPATH': true, 'BLOCK_COMMENT_START': true, 'BLOCK_COMMENT_END': true, @@ -140,6 +142,12 @@ export class SelectionBasedVariableResolver implements VariableResolver { } else if (name === 'TM_LINE_NUMBER') { return String(this._selection.positionLineNumber); + + } else if (name === 'CURSOR_INDEX') { + return String(this._selectionIdx); + + } else if (name === 'CURSOR_NUMBER') { + return String(this._selectionIdx + 1); } return undefined; } diff --git a/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts b/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts index cfee631930bb68..fc53766a32e67c 100644 --- a/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts +++ b/src/vs/editor/contrib/snippet/test/browser/snippetVariables.test.ts @@ -118,6 +118,12 @@ suite('Snippet Variables Resolver', function () { assertVariableResolve(resolver, 'TM_CURRENT_LINE', 'this is line two'); assertVariableResolve(resolver, 'TM_LINE_INDEX', '1'); assertVariableResolve(resolver, 'TM_LINE_NUMBER', '2'); + assertVariableResolve(resolver, 'CURSOR_INDEX', '0'); + assertVariableResolve(resolver, 'CURSOR_NUMBER', '1'); + + resolver = new SelectionBasedVariableResolver(model, new Selection(1, 2, 2, 3), 4, undefined); + assertVariableResolve(resolver, 'CURSOR_INDEX', '4'); + assertVariableResolve(resolver, 'CURSOR_NUMBER', '5'); resolver = new SelectionBasedVariableResolver(model, new Selection(2, 3, 1, 2), 0, undefined); assertVariableResolve(resolver, 'TM_SELECTED_TEXT', 'his is line one\nth'); diff --git a/src/vs/workbench/api/common/extHostNotebookDocuments.ts b/src/vs/workbench/api/common/extHostNotebookDocuments.ts index 50995c9f93f1ec..fbb400ec64d990 100644 --- a/src/vs/workbench/api/common/extHostNotebookDocuments.ts +++ b/src/vs/workbench/api/common/extHostNotebookDocuments.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter } from 'vs/base/common/event'; -import { deepFreeze } from 'vs/base/common/objects'; import { URI, UriComponents } from 'vs/base/common/uri'; import { ILogService } from 'vs/platform/log/common/log'; import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol'; @@ -32,7 +31,7 @@ export class ExtHostNotebookDocuments implements extHostProtocol.ExtHostNotebook $acceptModelChanged(uri: UriComponents, event: SerializableObjectWithBuffers, isDirty: boolean, newMetadata?: NotebookDocumentMetadata): void { const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri)); const e = document.acceptModelChanged(event.value, isDirty, newMetadata); - this._onDidChangeNotebookDocument.fire(deepFreeze(e)); + this._onDidChangeNotebookDocument.fire(e); } $acceptDirtyStateChanged(uri: UriComponents, isDirty: boolean): void { diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index aadf040bcb46e5..a5d5d56e14efa0 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -16,7 +16,7 @@ import { EditorAction, registerEditorAction, registerEditorContribution } from ' import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { IRange, Range } from 'vs/editor/common/core/range'; import { IEditorContribution, IModelChangedEvent } from 'vs/editor/common/editorCommon'; -import { IModelDecorationOptions } from 'vs/editor/common/model'; +import { IModelDecorationOptions, IModelDeltaDecoration } from 'vs/editor/common/model'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import * as languages from 'vs/editor/common/languages'; import { peekViewResultsBackground, peekViewResultsSelectionBackground, peekViewTitleBackground } from 'vs/editor/contrib/peekView/browser/peekView'; @@ -61,25 +61,29 @@ export class ReviewViewZone implements IViewZone { } } -class CommentingRangeDecoration { - private _decorationId: string; +class CommentingRangeDecoration implements IModelDeltaDecoration { + private _decorationId: string | undefined; + private _startLineNumber: number; + private _endLineNumber: number; - public get id(): string { + public get id(): string | undefined { return this._decorationId; } - constructor(private _editor: ICodeEditor, private _ownerId: string, private _extensionId: string | undefined, private _label: string | undefined, private _range: IRange, commentingOptions: ModelDecorationOptions, private commentingRangesInfo: languages.CommentingRanges, public readonly isHover: boolean = false) { - const startLineNumber = _range.startLineNumber; - const endLineNumber = _range.endLineNumber; - let commentingRangeDecorations = [{ - range: { - startLineNumber: startLineNumber, startColumn: 1, - endLineNumber: endLineNumber, endColumn: 1 - }, - options: commentingOptions - }]; + public set id(id: string | undefined) { + this._decorationId = id; + } + + public get range(): IRange { + return { + startLineNumber: this._startLineNumber, startColumn: 1, + endLineNumber: this._endLineNumber, endColumn: 1 + }; + } - this._decorationId = this._editor.deltaDecorations([], commentingRangeDecorations)[0]; + constructor(private _editor: ICodeEditor, private _ownerId: string, private _extensionId: string | undefined, private _label: string | undefined, private _range: IRange, public readonly options: ModelDecorationOptions, private commentingRangesInfo: languages.CommentingRanges, public readonly isHover: boolean = false) { + this._startLineNumber = _range.startLineNumber; + this._endLineNumber = _range.endLineNumber; } public getCommentAction(): { ownerId: string; extensionId: string | undefined; label: string | undefined; commentingRangesInfo: languages.CommentingRanges } { @@ -96,7 +100,7 @@ class CommentingRangeDecoration { } public getActiveRange() { - return this._editor.getModel()!.getDecorationRange(this._decorationId); + return this.id ? this._editor.getModel()!.getDecorationRange(this.id) : undefined; } } class CommentingRangeDecorator { @@ -104,6 +108,7 @@ class CommentingRangeDecorator { private decorationOptions!: ModelDecorationOptions; private hoverDecorationOptions!: ModelDecorationOptions; private commentingRangeDecorations: CommentingRangeDecoration[] = []; + private decorationIds: string[] = []; private _editor: ICodeEditor | undefined; private _infos: ICommentInfo[] | undefined; private _lastHover: number = -1; @@ -163,8 +168,8 @@ class CommentingRangeDecorator { }); } - let oldDecorations = this.commentingRangeDecorations.map(decoration => decoration.id); - editor.deltaDecorations(oldDecorations, []); + this.decorationIds = editor.deltaDecorations(this.decorationIds, commentingRangeDecorations); + commentingRangeDecorations.forEach((decoration, index) => decoration.id = this.decorationIds[index]); const rangesDifference = this.commentingRangeDecorations.length - commentingRangeDecorations.length; this.commentingRangeDecorations = commentingRangeDecorations;