Skip to content

Commit

Permalink
refactor: extract code
Browse files Browse the repository at this point in the history
  • Loading branch information
Loïc Mangeonjean committed Jun 5, 2023
1 parent 0302713 commit a126016
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 83 deletions.
94 changes: 11 additions & 83 deletions src/service-override/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,27 @@ import { IEditorOverrideServices, StandaloneServices } from 'vs/editor/standalon
import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'
import { CodeEditorService } from 'vs/workbench/services/editor/browser/codeEditorService'
import { IEditorService, isPreferredGroup, PreferredGroup, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'
import { IEditorControl, IEditorPane, IResourceDiffEditorInput, isEditorInput, isResourceEditorInput, ITextDiffEditorPane, IUntitledTextResourceEditorInput, IUntypedEditorInput } from 'vs/workbench/common/editor'
import { IEditorService, PreferredGroup } from 'vs/workbench/services/editor/common/editorService'
import { IEditorPane, IResourceDiffEditorInput, ITextDiffEditorPane, IUntitledTextResourceEditorInput, IUntypedEditorInput } from 'vs/workbench/common/editor'
import { Emitter, Event } from 'vs/base/common/event'
import { EditorInput } from 'vs/workbench/common/editor/editorInput'
import { IEditorOptions, IResourceEditorInput, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'
import { DEFAULT_EDITOR_MAX_DIMENSIONS, DEFAULT_EDITOR_MIN_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor'
import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'
import { IEditor, ScrollType } from 'vs/editor/common/editorCommon'
import { IEditor } from 'vs/editor/common/editorCommon'
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'
import { Disposable, IReference } from 'vs/base/common/lifecycle'
import { ICodeEditor } from 'vs/editor/browser/editorBrowser'
import { ITextEditorService, TextEditorService } from 'vs/workbench/services/textfile/common/textEditorService'
import 'vs/workbench/browser/parts/editor/editor.contribution'
import { OpenEditor, wrapOpenEditor } from './tools/editor'
import { unsupported } from '../tools'

type OpenEditor = (modelRef: IReference<IResolvedTextEditorModel>, options: IEditorOptions | undefined, sideBySide?: boolean) => Promise<ICodeEditor | undefined>

class SimpleEditorPane implements IEditorPane {
constructor (private editor?: ICodeEditor) {}

onDidChangeControl = Event.None
onDidChangeSizeConstraints = Event.None
onDidFocus = Event.None
onDidBlur = Event.None
input = undefined
options = undefined
group = undefined
scopedContextKeyService = undefined
get minimumWidth () { return DEFAULT_EDITOR_MIN_DIMENSIONS.width }
get maximumWidth () { return DEFAULT_EDITOR_MAX_DIMENSIONS.width }
get minimumHeight () { return DEFAULT_EDITOR_MIN_DIMENSIONS.height }
get maximumHeight () { return DEFAULT_EDITOR_MAX_DIMENSIONS.height }
getViewState = unsupported
isVisible = unsupported
hasFocus = unsupported
getId = unsupported
getTitle = unsupported
focus = unsupported

getControl (): IEditorControl | undefined {
return this.editor
}
}
import 'vs/workbench/browser/parts/editor/editor.contribution'

class EditorService extends Disposable implements IEditorService {
public activeTextEditorControl: IEditor | undefined
private _onDidActiveEditorChange = this._register(new Emitter<void>())

constructor (
private _openEditor: OpenEditor,
@ITextModelService private textModelService: ITextModelService
_openEditor: OpenEditor,
@ITextModelService textModelService: ITextModelService
) {
super()

Expand All @@ -74,6 +44,8 @@ class EditorService extends Disposable implements IEditorService {
this._register(codeEditorService.onCodeEditorAdd(handleCodeEditor))
codeEditorService.listCodeEditors().forEach(handleCodeEditor)
})

this.openEditor = wrapOpenEditor(textModelService, this.openEditor.bind(this), _openEditor)
}

readonly _serviceBrand: undefined
Expand All @@ -97,52 +69,8 @@ class EditorService extends Disposable implements IEditorService {
openEditor(editor: ITextResourceEditorInput | IUntitledTextResourceEditorInput, group?: PreferredGroup): Promise<IEditorPane | undefined>
openEditor(editor: IResourceDiffEditorInput, group?: PreferredGroup): Promise<ITextDiffEditorPane | undefined>
openEditor(editor: EditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | PreferredGroup, preferredGroup?: PreferredGroup): Promise<IEditorPane | undefined>
async openEditor (editor: EditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | PreferredGroup, preferredGroup?: PreferredGroup): Promise<IEditorPane | undefined> {
const options = isEditorInput(editor) ? optionsOrPreferredGroup as IEditorOptions : editor.options

if (isPreferredGroup(optionsOrPreferredGroup)) {
preferredGroup = optionsOrPreferredGroup
}

const resource = isResourceEditorInput(editor) || isEditorInput(editor) ? editor.resource : undefined

if (resource == null) {
throw new Error('Diff editors not supported')
}

let modelEditor: ICodeEditor | undefined

// The model doesn't exist, resolve it
const modelRef = await this.textModelService.createModelReference(resource)

// If the model was already existing, try to find an associated editor
const codeEditors = StandaloneServices.get(ICodeEditorService).listCodeEditors()
modelEditor = codeEditors.find(editor => editor.getModel() === modelRef.object.textEditorModel)

// If there is no editor associated to the model, try to open a new one
if (modelEditor == null) {
modelEditor = await this._openEditor(modelRef, options, preferredGroup === SIDE_GROUP)
}

if (modelEditor == null) {
// Dispose the newly created model if `openEditor` wasn't able to open it
modelRef.dispose()
return undefined
}

// Otherwise, let the user destroy the model, never destroy the reference

if (options != null) {
// Apply selection
applyTextEditorOptions(options, modelEditor, ScrollType.Immediate)
}

if (!(options?.preserveFocus ?? false)) {
modelEditor.focus()
}

// Return a very simple editor pane, only the `getControl` method is used
return new SimpleEditorPane(modelEditor)
async openEditor () {
return undefined
}

openEditors = unsupported
Expand Down
110 changes: 110 additions & 0 deletions src/service-override/tools/editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { StandaloneServices } from 'vs/editor/standalone/browser/standaloneServices'
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'
import { IEditorService, isPreferredGroup, PreferredGroup, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'
import { IEditorControl, IEditorPane, IResourceDiffEditorInput, isEditorInput, isResourceEditorInput, ITextDiffEditorPane, IUntitledTextResourceEditorInput, IUntypedEditorInput } from 'vs/workbench/common/editor'
import { EditorInput } from 'vs/workbench/common/editor/editorInput'
import { IEditorOptions, IResourceEditorInput, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'
import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'
import { ScrollType } from 'vs/editor/common/editorCommon'
import { ICodeEditor } from 'vs/editor/browser/editorBrowser'
import { Event } from 'vs/base/common/event'
import { DEFAULT_EDITOR_MAX_DIMENSIONS, DEFAULT_EDITOR_MIN_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor'
import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'
import { StandaloneEditor } from 'vs/editor/standalone/browser/standaloneCodeEditor'
import { IReference } from 'vs/base/common/lifecycle'
import { unsupported } from '../../tools'

export type OpenEditor = (modelRef: IReference<IResolvedTextEditorModel>, options: IEditorOptions | undefined, sideBySide?: boolean) => Promise<ICodeEditor | undefined>

class SimpleEditorPane implements IEditorPane {
constructor (private editor?: ICodeEditor) {}

onDidChangeControl = Event.None
onDidChangeSizeConstraints = Event.None
onDidFocus = Event.None
onDidBlur = Event.None
input = undefined
options = undefined
group = undefined
scopedContextKeyService = undefined
get minimumWidth () { return DEFAULT_EDITOR_MIN_DIMENSIONS.width }
get maximumWidth () { return DEFAULT_EDITOR_MAX_DIMENSIONS.width }
get minimumHeight () { return DEFAULT_EDITOR_MIN_DIMENSIONS.height }
get maximumHeight () { return DEFAULT_EDITOR_MAX_DIMENSIONS.height }
getViewState = unsupported
isVisible = unsupported
hasFocus = unsupported
getId = unsupported
getTitle = unsupported
focus = unsupported

getControl (): IEditorControl | undefined {
return this.editor
}
}

export function wrapOpenEditor (textModelService: ITextModelService, defaultBehavior: IEditorService['openEditor'], fallbackBahavior?: OpenEditor): IEditorService['openEditor'] {
function openEditor(editor: EditorInput, options?: IEditorOptions, group?: PreferredGroup): Promise<IEditorPane | undefined>
function openEditor(editor: IUntypedEditorInput, group?: PreferredGroup): Promise<IEditorPane | undefined>
function openEditor(editor: IResourceEditorInput, group?: PreferredGroup): Promise<IEditorPane | undefined>
function openEditor(editor: ITextResourceEditorInput | IUntitledTextResourceEditorInput, group?: PreferredGroup): Promise<IEditorPane | undefined>
function openEditor(editor: IResourceDiffEditorInput, group?: PreferredGroup): Promise<ITextDiffEditorPane | undefined>
function openEditor(editor: EditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | PreferredGroup, preferredGroup?: PreferredGroup): Promise<IEditorPane | undefined>
async function openEditor (editor: EditorInput | IUntypedEditorInput, optionsOrPreferredGroup?: IEditorOptions | PreferredGroup, preferredGroup?: PreferredGroup): Promise<IEditorPane | undefined> {
const options = isEditorInput(editor) ? optionsOrPreferredGroup as IEditorOptions : editor.options

if (isPreferredGroup(optionsOrPreferredGroup)) {
preferredGroup = optionsOrPreferredGroup
}

const resource = isResourceEditorInput(editor) || isEditorInput(editor) ? editor.resource : undefined

if (resource == null) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return defaultBehavior(editor as any, optionsOrPreferredGroup as any, preferredGroup)
}

let modelEditor: ICodeEditor | undefined

// The model doesn't exist, resolve it
const modelRef = await textModelService.createModelReference(resource)

// If the model is already existing, try to find an associated editor
const codeEditors = StandaloneServices.get(ICodeEditorService).listCodeEditors()
modelEditor = codeEditors.find(editor => editor instanceof StandaloneEditor && editor.getModel() === modelRef.object.textEditorModel)

if (modelEditor == null) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const defaultBehaviorResult = await defaultBehavior(editor as any, optionsOrPreferredGroup as any, preferredGroup)
if (defaultBehaviorResult != null) {
modelRef.dispose()
return defaultBehaviorResult
}

modelEditor = await fallbackBahavior?.(modelRef, options, preferredGroup === SIDE_GROUP)
}

if (modelEditor == null) {
// Dispose the newly created model if `openEditor` wasn't able to open it
modelRef.dispose()
return undefined
}

// Otherwise, let the user destroy the model, never destroy the reference

if (options != null) {
// Apply selection
applyTextEditorOptions(options, modelEditor, ScrollType.Immediate)
}

if (!(options?.preserveFocus ?? false)) {
modelEditor.focus()
modelEditor.getContainerDomNode().scrollIntoView()
}

// Return a very simple editor pane, only the `getControl` method is used
return new SimpleEditorPane(modelEditor)
}

return openEditor
}

0 comments on commit a126016

Please sign in to comment.