diff --git a/types/src/main.ts b/types/src/main.ts index 4ef202f06..9069bc277 100644 --- a/types/src/main.ts +++ b/types/src/main.ts @@ -1562,7 +1562,7 @@ class ChangeAnnotations { public constructor(annotations?: { [id: string]: ChangeAnnotation }) { this._annotations = annotations === undefined ? Object.create(null) : annotations; this._counter = 0; - this._size = 0; + this._size = Object.keys(this._annotations).length; } public all(): { [id: string]: ChangeAnnotation } { @@ -1595,8 +1595,12 @@ class ChangeAnnotations { } private nextId(): ChangeAnnotationIdentifier { - this._counter++; - return this._counter.toString(); + let id: ChangeAnnotationIdentifier; + do { + this._counter++; + id = this._counter.toString(); + } while (this._annotations[id] !== undefined); + return id; } } diff --git a/types/src/test/edits.test.ts b/types/src/test/edits.test.ts index 08d056fa1..b8cf1d4cf 100644 --- a/types/src/test/edits.test.ts +++ b/types/src/test/edits.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import { TextDocument, TextEdit, Position, Range } from '../main'; +import { TextDocument, TextEdit, Position, Range, WorkspaceChange, WorkspaceEdit, AnnotatedTextEdit, ChangeAnnotation } from '../main'; const applyEdits = TextDocument.applyEdits; @@ -40,4 +40,28 @@ suite('Edits', () => { assert.equal(applyEdits(input, [TextEdit.replace(Range.create(Position.create(2, 0), Position.create(3, 0)), 'Hello'), TextEdit.insert(Position.create(1, 1), 'World')]), '0\n1World\nHello3\n4'); }); +}); + +suite('WorkspaceChange', () => { + + test('keeps change annotations of an existing edit', function (): any { + const workspaceEdit: WorkspaceEdit = { + documentChanges: [{ textDocument: { uri: 'file:///abc.txt', version: 1 }, edits: [AnnotatedTextEdit.insert(Position.create(0, 0), 'insert', 'a1')] }], + changeAnnotations: { a1: ChangeAnnotation.create('label', true) } + }; + const workspaceChange = new WorkspaceChange(workspaceEdit); + assert.deepStrictEqual(workspaceChange.edit.changeAnnotations, { a1: ChangeAnnotation.create('label', true) }); + }); + + test('does not reuse ids of existing change annotations', function (): any { + const first = new WorkspaceChange(); + first.getTextEditChange({ uri: 'file:///abc.txt', version: 1 }).insert(Position.create(0, 0), 'first', ChangeAnnotation.create('first')); + const second = new WorkspaceChange(first.edit); + const id = second.getTextEditChange({ uri: 'file:///xyz.txt', version: 1 }).insert(Position.create(0, 0), 'second', ChangeAnnotation.create('second')); + const annotations = second.edit.changeAnnotations!; + assert.notStrictEqual(id, '1'); + assert.strictEqual(annotations['1'].label, 'first'); + assert.strictEqual(annotations[id].label, 'second'); + }); + }); \ No newline at end of file