Skip to content

Commit

Permalink
refactor(demo): split code in features
Browse files Browse the repository at this point in the history
  • Loading branch information
Loïc Mangeonjean committed Jun 9, 2023
1 parent f966c60 commit 64554e1
Show file tree
Hide file tree
Showing 10 changed files with 457 additions and 423 deletions.
43 changes: 43 additions & 0 deletions demo/src/features/customView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { IDialogService } from 'vscode/services'
import { registerCustomView, ViewContainerLocation } from 'vscode/service-override/views'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
import iconUrl from '../Visual_Studio_Code_1.35_icon.svg?url'

registerCustomView({
id: 'custom-view',
name: 'Custom demo view',
order: 0,
renderBody: function (container: HTMLElement): monaco.IDisposable {
container.style.display = 'flex'
container.style.alignItems = 'center'
container.style.justifyContent = 'center'
container.innerHTML = 'This is a custom view<br />You can render anything you want here'

return {
dispose () {
}
}
},
location: ViewContainerLocation.Panel,
icon: new URL(iconUrl, window.location.href).toString(),
actions: [{
id: 'custom-action',
title: 'Custom action',
render (element) {
const button = document.createElement('button')
button.innerText = 'Ugly button'
button.style.height = '30px'
button.onclick = () => {
alert('What did you expect?')
}
element.append(button)
}
}, {
id: 'custom-action2',
title: 'Custom action2',
icon: 'dialogInfo',
async run (accessor) {
void accessor.get(IDialogService).info('This is a custom view action button')
}
}]
})
73 changes: 73 additions & 0 deletions demo/src/features/debugger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { onExtHostInitialized, registerExtension } from 'vscode/extensions'
import * as vscode from 'vscode'

await new Promise<void>(resolve => onExtHostInitialized(resolve))

const debuggerExtension = {
name: 'debugger',
publisher: 'codingame',
version: '1.0.0',
engines: {
vscode: '*'
},
contributes: {
debuggers: [{
type: 'javascript',
label: 'Test',
languages: ['javascript']
}],
breakpoints: [{
language: 'javascript'
}]
}
}

const { api: debuggerVscodeApi } = registerExtension(debuggerExtension)

class WebsocketDebugAdapter implements vscode.DebugAdapter {
constructor (private websocket: WebSocket) {
websocket.onmessage = (message) => {
this._onDidSendMessage.fire(JSON.parse(message.data))
}
}

_onDidSendMessage = new debuggerVscodeApi.EventEmitter<vscode.DebugProtocolMessage>()
onDidSendMessage = this._onDidSendMessage.event

handleMessage (message: vscode.DebugProtocolMessage): void {
this.websocket.send(JSON.stringify(message))
}

dispose () {
this.websocket.close()
}
}

debuggerVscodeApi.debug.registerDebugAdapterDescriptorFactory('javascript', {
async createDebugAdapterDescriptor () {
const websocket = new WebSocket('ws://localhost:5555')

await new Promise((resolve, reject) => {
websocket.onopen = resolve
websocket.onerror = () => reject(new Error('Unable to connect to debugger server. Run `npm run start:debugServer`'))
})

websocket.send(JSON.stringify({
main: '/tmp/test.js',
files: {
'/tmp/test.js': new TextDecoder().decode(await vscode.workspace.fs.readFile(vscode.Uri.file('/tmp/test.js')))
}
}))

const adapter = new WebsocketDebugAdapter(websocket)

// eslint-disable-next-line @typescript-eslint/no-explicit-any
adapter.onDidSendMessage((message: any) => {
if (message.type === 'event' && message.event === 'output') {
// eslint-disable-next-line no-console
console.log('OUTPUT', message.body.output)
}
})
return new debuggerVscodeApi.DebugAdapterInlineImplementation(adapter)
}
})
68 changes: 68 additions & 0 deletions demo/src/features/editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { IResolvedTextEditorModel, IReference, OpenEditor } from 'vscode/service-override/views'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
import { createConfiguredEditor } from 'vscode/monaco'

let currentEditor: ({
modelRef: IReference<IResolvedTextEditorModel>
editor: monaco.editor.IStandaloneCodeEditor
} & monaco.IDisposable) | null = null
export const openNewCodeEditor: OpenEditor = async (modelRef) => {
if (currentEditor != null) {
currentEditor.dispose()
currentEditor = null
}
const container = document.createElement('div')
container.style.position = 'fixed'
container.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
container.style.top = container.style.bottom = container.style.left = container.style.right = '0'
container.style.cursor = 'pointer'

const editorElem = document.createElement('div')
editorElem.style.position = 'absolute'
editorElem.style.top = editorElem.style.bottom = editorElem.style.left = editorElem.style.right = '0'
editorElem.style.margin = 'auto'
editorElem.style.width = '80%'
editorElem.style.height = '80%'

container.appendChild(editorElem)

document.body.appendChild(container)
try {
const editor = createConfiguredEditor(
editorElem,
{
model: modelRef.object.textEditorModel,
readOnly: true,
automaticLayout: true
}
)

currentEditor = {
dispose: () => {
editor.dispose()
modelRef.dispose()
document.body.removeChild(container)
currentEditor = null
},
modelRef,
editor
}

editor.onDidBlurEditorWidget(() => {
currentEditor?.dispose()
})
container.addEventListener('mousedown', (event) => {
if (event.target !== container) {
return
}

currentEditor?.dispose()
})

return editor
} catch (error) {
document.body.removeChild(container)
currentEditor = null
throw error
}
}
29 changes: 29 additions & 0 deletions demo/src/features/filesystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { SimpleTextFileSystemProvider, registerFileSystemOverlay, FileType, HTMLFileSystemProvider } from 'vscode/service-override/files'
import * as vscode from 'vscode'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'

class FakeFileSystem extends SimpleTextFileSystemProvider {
private files: Record<string, string> = {
[vscode.Uri.file('/tmp/test2.js').toString(true)]: 'This is another file'
}

protected override async getFileContent (resource: monaco.Uri): Promise<string | undefined> {
return this.files[resource.toString(true)]
}

protected override async setFileContent (resource: monaco.Uri, content: string): Promise<void> {
this.files[resource.toString(true)] = content
}

override async delete (): Promise<void> {
}

override async readdir (directory: monaco.Uri): Promise<[string, FileType][]> {
if (directory.path === '/tmp') {
return [['test2.js', FileType.File]]
}
return []
}
}

registerFileSystemOverlay(new FakeFileSystem())
97 changes: 97 additions & 0 deletions demo/src/features/intellisense.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import * as vscode from 'vscode'
import 'monaco-editor/esm/vs/language/json/monaco.contribution.js'
import 'monaco-editor/esm/vs/language/typescript/monaco.contribution.js'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
import { synchronizeJsonSchemas } from 'vscode/monaco'
import { onExtHostInitialized } from 'vscode/extensions'
import typescriptGlobal from '../../node_modules/@types/node/globals.d.ts?raw'
import typescriptConsole from '../../node_modules/@types/node/console.d.ts?raw'
import typescriptProcess from '../../node_modules/@types/node/process.d.ts?raw'

await new Promise<void>(resolve => onExtHostInitialized(resolve))

vscode.languages.registerCallHierarchyProvider('javascript', {
prepareCallHierarchy: function (): vscode.ProviderResult<vscode.CallHierarchyItem | vscode.CallHierarchyItem[]> {
return {
name: 'Fake call hierarchy',
kind: vscode.SymbolKind.Class,
uri: vscode.Uri.file('/tmp/test.js'),
range: new vscode.Range(0, 0, 0, 10),
selectionRange: new vscode.Range(0, 0, 0, 10)
}
},
provideCallHierarchyIncomingCalls: function (): vscode.ProviderResult<vscode.CallHierarchyIncomingCall[]> {
return [{
from: {
name: 'Fake incomming call',
kind: vscode.SymbolKind.Class,
uri: vscode.Uri.file('/tmp/test.js'),
range: new vscode.Range(0, 0, 0, 10),
selectionRange: new vscode.Range(0, 0, 0, 10)
},
fromRanges: [new vscode.Range(2, 0, 2, 10)]
}]
},
provideCallHierarchyOutgoingCalls: function (): vscode.ProviderResult<vscode.CallHierarchyOutgoingCall[]> {
return []
}
})

vscode.languages.registerHoverProvider('javascript', {
async provideHover (document, position) {
return {
contents: [
'# Hello',
`This is a hover on ${document.uri.toString()} at position ${position.line}:${position.character}`
]
}
}
})

vscode.languages.registerCompletionItemProvider('javascript', {
provideCompletionItems () {
return [{
label: 'Demo completion',
detail: 'This is a demo completion registered via the vscode api',
insertText: 'hello world'
}]
}
})

const compilerOptions: Parameters<typeof monaco.languages.typescript.typescriptDefaults.setCompilerOptions>[0] = {
target: monaco.languages.typescript.ScriptTarget.ES2016,
allowNonTsExtensions: true,
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
module: monaco.languages.typescript.ModuleKind.CommonJS,
noEmit: true,
lib: ['es2020']
}

monaco.languages.typescript.typescriptDefaults.setCompilerOptions(compilerOptions)
monaco.languages.typescript.typescriptDefaults.addExtraLib(typescriptGlobal, 'node/globals.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(typescriptConsole, 'node/console.d.ts')
monaco.languages.typescript.typescriptDefaults.addExtraLib(typescriptProcess, 'node/process.d.ts')
monaco.languages.typescript.javascriptDefaults.setCompilerOptions(compilerOptions)
monaco.languages.typescript.javascriptDefaults.addExtraLib(typescriptGlobal, 'node/globals.d.ts')
monaco.languages.typescript.javascriptDefaults.addExtraLib(typescriptConsole, 'node/console.d.ts')
monaco.languages.typescript.javascriptDefaults.addExtraLib(typescriptProcess, 'node/process.d.ts')

monaco.languages.json.jsonDefaults.setModeConfiguration({
...monaco.languages.json.jsonDefaults.modeConfiguration,
tokens: false // Disable monarch tokenizer as we use TextMate here
})

synchronizeJsonSchemas()

vscode.languages.registerDefinitionProvider('javascript', {
provideDefinition (document, position) {
const wordRange = document.getWordRangeAtPosition(position)
if (wordRange != null && document.getText(wordRange) === 'anotherfile') {
return {
range: wordRange,
uri: vscode.Uri.file('/tmp/test2.js')
}
}
return []
}
})
17 changes: 17 additions & 0 deletions demo/src/features/notifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as vscode from 'vscode'
import { onExtHostInitialized } from 'vscode/extensions'

await new Promise<void>(resolve => onExtHostInitialized(resolve))

void vscode.window.showInformationMessage('Hello', {
detail: 'Welcome to the monaco-vscode-api demo',
modal: true
}).then(() => {
void vscode.window.showInformationMessage('Try to change the settings or the configuration, the changes will be applied to all 3 editors')
})

setTimeout(() => {
vscode.workspace.onDidChangeConfiguration(() => {
void vscode.window.showInformationMessage('The configuration was changed')
})
}, 1000)
14 changes: 14 additions & 0 deletions demo/src/features/output.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as vscode from 'vscode'
import { onExtHostInitialized } from 'vscode/extensions'

await new Promise<void>(resolve => onExtHostInitialized(resolve))

const fakeOutputChannel = vscode.window.createOutputChannel('Fake output')
const anotherFakeOutputChannel = vscode.window.createOutputChannel('Your code', 'javascript')

fakeOutputChannel.append('Here\'s some fake output\n')
setInterval(() => {
fakeOutputChannel.append('Hello world\n')
}, 1000)

export { anotherFakeOutputChannel }
Loading

0 comments on commit 64554e1

Please sign in to comment.