-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
47 changed files
with
1,430 additions
and
439 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
import { TextEdit } from '../common/text-edit'; | ||
import { Diagnostic } from './diagnostic'; | ||
|
||
export interface DiagnosticFix { | ||
export interface DiagnosticFix<T = TextEdit> { | ||
title: string; | ||
diagnostic: Diagnostic; | ||
isPreferred?: boolean; | ||
edits: TextEdit[]; | ||
edits: T[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { Observable } from 'rxjs'; | ||
|
||
import { Document } from './document'; | ||
|
||
export interface DocumentCreated<T extends Document> { | ||
document: T; | ||
} | ||
|
||
export interface DocumentClosed { | ||
uri: string; | ||
} | ||
|
||
export interface DocumentOpened<T extends Document> { | ||
document: T; | ||
} | ||
|
||
export interface DocumentDeleted { | ||
uri: string; | ||
} | ||
|
||
export interface DocumentChanged<T extends Document> { | ||
document: T; | ||
} | ||
|
||
export interface DocumentAccessor<T extends Document = Document> { | ||
readonly created$: Observable<DocumentCreated<T>>; | ||
readonly closed$: Observable<DocumentClosed>; | ||
readonly opened$: Observable<DocumentOpened<T>>; | ||
readonly deleted$: Observable<DocumentDeleted>; | ||
readonly changed$: Observable<DocumentChanged<T>>; | ||
|
||
get(uri: string): Promise<T | undefined>; | ||
all(): Promise<T[]>; | ||
active(): Promise<T[]>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,7 @@ | ||
import { Range } from '../common/range'; | ||
import { Document } from './document'; | ||
import { TextDocumentChange } from './text-document-change'; | ||
|
||
export interface DocumentChange { | ||
range?: Range; | ||
text: string; | ||
} | ||
|
||
export interface DocumentFactory<T extends Document> { | ||
create(uri: string, format: string, version: number, content: string): T; | ||
update(document: T, changes: readonly DocumentChange[], version: number): T; | ||
export interface DocumentFactory<TDoc extends Document = Document, TChange = TextDocumentChange> { | ||
create(uri: string, format: string, version: number, content: string): TDoc; | ||
update(document: TDoc, changes: readonly TChange[], version: number): TDoc; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,118 +1,105 @@ | ||
import { firstValueFrom } from 'rxjs'; | ||
import { describe, expect, it } from 'vitest'; | ||
import { mock, MockProxy } from 'vitest-mock-extended'; | ||
|
||
import { Document } from './document'; | ||
import { DocumentFactory } from './document-factory'; | ||
import { DocumentManager } from './document-manager'; | ||
import { DocumentReader } from './document-reader'; | ||
import { TextDocument } from './text-document'; | ||
import { TextDocumentFactory } from './text-document-factory'; | ||
|
||
describe('DocumentManager', () => { | ||
it('all', async () => { | ||
const env = new TestEnvironment(); | ||
|
||
await expect(env.docManager.all()).resolves.toEqual([ | ||
{ uri: 'file1', format: 'plaintext', version: 1, content: 'This is file1.' }, | ||
{ uri: 'file2', format: 'plaintext', version: 1, content: 'This is file2.' }, | ||
]); | ||
const docs = await env.docManager.all(); | ||
expect(docs).toHaveLength(2); | ||
expect(docs[0].content).toEqual('This is file1.'); | ||
expect(docs[1].content).toEqual('This is file2.'); | ||
}); | ||
|
||
it('get', async () => { | ||
const env = new TestEnvironment(); | ||
|
||
await expect(env.docManager.get('file2')).resolves.toEqual({ | ||
uri: 'file2', | ||
format: 'plaintext', | ||
version: 1, | ||
content: 'This is file2.', | ||
}); | ||
const doc = await env.docManager.get('file2'); | ||
expect(doc).not.toBeNull(); | ||
expect(doc?.content).toEqual('This is file2.'); | ||
}); | ||
|
||
it('fire created event', async () => { | ||
const env = new TestEnvironment(); | ||
|
||
expect.assertions(1); | ||
env.docManager.created$.subscribe((e) => { | ||
expect(e.document).toEqual({ uri: 'file1', format: 'plaintext', version: 1, content: 'This is file1.' }); | ||
}); | ||
const createdPromise = firstValueFrom(env.docManager.created$); | ||
await env.docManager.fireCreated('file1'); | ||
const createdEvent = await createdPromise; | ||
expect(createdEvent.document.uri).toEqual('file1'); | ||
expect(createdEvent.document.content).toEqual('This is file1.'); | ||
}); | ||
|
||
it('fire opened event', async () => { | ||
const env = new TestEnvironment(); | ||
|
||
expect.assertions(3); | ||
env.docManager.opened$.subscribe((e) => { | ||
expect(e.document).toEqual({ uri: 'file1', format: 'plaintext', version: 1, content: 'This is opened file1.' }); | ||
}); | ||
const openedPromise = firstValueFrom(env.docManager.opened$); | ||
await expect(env.docManager.active()).resolves.toHaveLength(0); | ||
await env.docManager.fireOpened('file1', 'plaintext', 1, 'This is opened file1.'); | ||
await expect(env.docManager.active()).resolves.toHaveLength(1); | ||
const openedEvent = await openedPromise; | ||
expect(openedEvent.document.uri).toEqual('file1'); | ||
expect(openedEvent.document.content).toEqual('This is opened file1.'); | ||
}); | ||
|
||
it('fire closed event', async () => { | ||
const env = new TestEnvironment(); | ||
await env.docManager.fireOpened('file1', 'plaintext', 1, 'content'); | ||
|
||
expect.assertions(3); | ||
env.docManager.closed$.subscribe((e) => { | ||
expect(e.uri).toEqual('file1'); | ||
}); | ||
const closedPromise = firstValueFrom(env.docManager.closed$); | ||
await expect(env.docManager.active()).resolves.toHaveLength(1); | ||
await env.docManager.fireClosed('file1'); | ||
await expect(env.docManager.active()).resolves.toHaveLength(0); | ||
const closedEvent = await closedPromise; | ||
expect(closedEvent.uri).toEqual('file1'); | ||
}); | ||
|
||
it('fire deleted event', async () => { | ||
const env = new TestEnvironment(); | ||
|
||
expect.assertions(2); | ||
env.docManager.deleted$.subscribe((e) => { | ||
expect(e.uri).toEqual('file1'); | ||
}); | ||
const deletedPromise = firstValueFrom(env.docManager.deleted$); | ||
await env.docManager.fireDeleted('file1'); | ||
env.docReader.keys.mockReturnValue(['file2']); | ||
await expect(env.docManager.all()).resolves.toHaveLength(1); | ||
const deletedEvent = await deletedPromise; | ||
expect(deletedEvent.uri).toEqual('file1'); | ||
}); | ||
|
||
it('fire changed event', async () => { | ||
const env = new TestEnvironment(); | ||
|
||
expect.assertions(2); | ||
const sub = env.docManager.changed$.subscribe((e) => { | ||
expect(e.document).toEqual({ uri: 'file1', format: 'plaintext', version: 2, content: 'This is changed file1.' }); | ||
}); | ||
const changedPromise = firstValueFrom(env.docManager.changed$); | ||
await env.docManager.fireChanged('file1', [{ text: 'This is changed file1.' }], 2); | ||
sub.unsubscribe(); | ||
const changedEvent = await changedPromise; | ||
expect(changedEvent.document.uri).toEqual('file1'); | ||
expect(changedEvent.document.version).toEqual(2); | ||
expect(changedEvent.document.content).toEqual('This is changed file1.'); | ||
|
||
// reload document from reader | ||
await env.docManager.fireChanged('file1'); | ||
await expect(env.docManager.get('file1')).resolves.toEqual({ | ||
uri: 'file1', | ||
format: 'plaintext', | ||
version: 1, | ||
content: 'This is file1.', | ||
}); | ||
const doc = await env.docManager.get('file1'); | ||
expect(doc).not.toBeNull(); | ||
expect(doc?.content).toEqual('This is file1.'); | ||
}); | ||
}); | ||
|
||
class TestEnvironment { | ||
readonly docReader: MockProxy<DocumentReader>; | ||
readonly docFactory: MockProxy<DocumentFactory<Document>>; | ||
readonly docManager: DocumentManager<Document>; | ||
readonly docFactory: TextDocumentFactory; | ||
readonly docManager: DocumentManager<TextDocument>; | ||
|
||
constructor() { | ||
this.docReader = mock<DocumentReader>(); | ||
this.docReader.read.mockImplementation((uri) => { | ||
return Promise.resolve({ format: 'plaintext', version: 1, content: `This is ${uri}.` }); | ||
}); | ||
this.docReader.keys.mockReturnValue(['file1', 'file2']); | ||
|
||
this.docFactory = mock<DocumentFactory<Document>>(); | ||
this.docFactory.create.mockImplementation((uri, format, version, content) => { | ||
return { uri, format, version, content }; | ||
}); | ||
this.docFactory.update.mockImplementation((document, changes, version) => { | ||
return { uri: document.uri, format: 'plaintext', version, content: changes[0].text }; | ||
}); | ||
|
||
this.docFactory = new TextDocumentFactory(); | ||
this.docManager = new DocumentManager(this.docFactory, this.docReader); | ||
} | ||
} |
Oops, something went wrong.