Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Peek definition fails on tokens coming from different models. #852

Closed
Mytrill opened this issue Apr 28, 2018 · 7 comments
Closed

Peek definition fails on tokens coming from different models. #852

Mytrill opened this issue Apr 28, 2018 · 7 comments

Comments

@Mytrill
Copy link

Mytrill commented Apr 28, 2018

monaco-editor version: 0.12.0
Browser: any (tested with Chrome and Firefox)
OS: mac OS

Code:

  const dependencyModel = monaco.editor.createModel(
    `export const value = "Hello World"`,
    "javascript",
    monaco.Uri.from({ path: "/dep.js" })
  )

  const indexModel = monaco.editor.createModel(
    `import { value } from "./dep"\nconsole.log(value)`,
    "javascript",
    monaco.Uri.from({ path: "/index.js" })
  )

  const editor = monaco.editor.create(document.getElementById("app"))
  editor.setModel(indexModel)

On the index.js model, the "Peek Definition" action on the value variable throws an exception:
screen shot 2018-04-28 at 18 04 00

Stacktrace:

Uncaught Error: 

Error
    at referencesModel.ts:174
    at n.Class.define.cancel.then (winjs.base.js:1581)
    at e.resolve (referencesModel.ts:169)
    at e.getChildren (referencesWidget.ts:197)
    at s (treeModel.ts:464)
    at treeModel.ts:106
    at new n.Class.derive._oncancel (winjs.base.js:1656)
    at e.run (treeModel.ts:98)
    at t.e.refreshChildren (treeModel.ts:519)
    at t.e.doRefresh (treeModel.ts:529)
    at referencesModel.ts:174
    at n.Class.define.cancel.then (winjs.base.js:1581)
    at e.resolve (referencesModel.ts:169)
    at e.getChildren (referencesWidget.ts:197)
    at s (treeModel.ts:464)
    at treeModel.ts:106
    at new n.Class.derive._oncancel (winjs.base.js:1656)
    at e.run (treeModel.ts:98)
    at t.e.refreshChildren (treeModel.ts:519)
    at t.e.doRefresh (treeModel.ts:529)
    at errors.ts:81

For reference, I managed to get the "Go To Definition" working by overriding the editorService but that did not solve this issue.

function getOverrides(e: HTMLElement) {
  return {
    editorService: {
      openEditor: function(input, sideBySide): Promise<any> {
        const editor = getEditor(e)
        editor.setModel(getModel(input.resource.path))
        return Promise.resolve({ getControl: () => editor })
      },
      resolveEditor: function() {
        // not called
        return Promise.resolve({})
      }
    }
  }
}

Is there another service I should override or something I should do differently?

EDIT: for reference, I found which service I had to override textModelService.createModelReference(uri):

function getOverrides(e: HTMLElement) {
  return {
    editorService: {
      openEditor: function(input, sideBySide): Promise<any> {
        const editor = getEditor(e)
        editor.setModel(getModel(input.resource.path))
        return Promise.resolve({ getControl: () => editor })
      },
      resolveEditor: function() {
        return Promise.resolve({})
      }
    },
    textModelService: {
      createModelReference(uri) {
        console.log("Called!", uri)
      }
    }
  }
}

It seems the types are slightly different in VS code source and in monaco-editor (for example IReference or ITextEditorModel are not in monaco-editor), is there a consistent way to translate the monaco-editor equivalent of the VS code types in order for me to know exactly what I have to implement?

Thank you,
Anthony

@Mytrill
Copy link
Author

Mytrill commented Apr 29, 2018

After some more work, I got a working peek definition and go to definition.

For reference, here is my implementation of the overrides:

const getOverrides = actions => (e: HTMLElement) => ({
  editorService: {
    openEditor: function(input, sideBySide): Promise<any> {
      // this actually sets the opened source
      actions.set({ opened: input.resource.path })
      // this just returns the editor itself
      return Promise.resolve({ getControl: () => getEditor(e) })
    },
    resolveEditor: function() {
      // I still don't know when/if this is used, I assume it is never called in my case
      return Promise.resolve({})
    }
  },
  textModelService: {
    createModelReference(
      uri: monaco.Uri
    ): Promise<IReference<ITextEditorModel>> {
      const model: ITextEditorModel = {
        load() {
          return Promise.resolve(model)
        },
        // in my case, I have nothing to dispose as I just re-use existing resources
        dispose() {},
        textEditorModel: getModel(uri.path)
      }

      return Promise.resolve({
        object: model,
        // in my case, I have nothing to dispose as I just re-use existing resources
        dispose() {}
      })
    }
  }
})

@ulrichb
Copy link
Contributor

ulrichb commented Jul 30, 2018

@Mytrill Nice work!

Where do I get the IReference, ITextEditorModel definitions (don't seem to be part of monaco's editor.api.d.ts).

@ulrichb
Copy link
Contributor

ulrichb commented Aug 11, 2018

As of Monaco Editor 0.14, it seems that the editorService.openEditor() API has been renamed to codeEditorService.openCodeEditor().

Unfortunately when overriding only this function, I get TypeError: _this._codeEditorService.addCodeEditor is not a function at StandaloneEditor.CodeEditorWidget ....

@ulrichb
Copy link
Contributor

ulrichb commented Aug 21, 2018

Hi @alexandrudima, any idea for #852 (comment)?

@alexdima
Copy link
Member

@ulrichb There was a refactoring -- microsoft/vscode@cf77b6e -- which resulted in the merging/folding of the ITextEditorService into ICodeEditorService, so whereas before it might have been somewhat easy to implement a custom ITextEditorService (a couple methods), now, in order to customize this all the methods of ICodeEditorService must be implemented.

@satya164
Copy link

I found that I can import the services like this, so I don't have to implement all methods:

import { StaticServices } from 'monaco-editor/esm/vs/editor/standalone/browser/standaloneServices';

const codeEditorService = StaticServices.codeEditorService.get();

@ulrichb
Copy link
Contributor

ulrichb commented Sep 29, 2018

@satya164 This was a great hint.

I now mutate the openCodeEditor prototype of StandaloneCodeEditorServiceImpl (instead of using overrides to ensure that the base c'tor gets injected the themeService).

Thanks!

@vscodebot vscodebot bot locked and limited conversation to collaborators Oct 29, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants