Peek reference and preview definition don't work across models
masad-frost opened this issue · 5 comments
Reproduction steps:
- Go to playground
- Paste code below
- Run
- Right click on created editor
- Peek reference
- Works fine for same model
- Throws an error if you try to look at reference in another model
Same thing happens with peek definition with a different error.
Seems like the model resolution is failing.
Example simple code:
const editor = monaco.editor.create(document.getElementById("container"), {});
const model = monaco.editor.createModel("a", null, monaco.Uri.from({
scheme: "inmemory",
path: "file1.py",
}))
const model2 = monaco.editor.createModel("b", null, monaco.Uri.from({
scheme: "inmemory",
path: "file2.py",
}))
editor.setModel(model)
monaco.languages.registerReferenceProvider("python", {
provideReferences: (model, position, context, token) => {
return [
{
uri: model.uri,
range: {
startLineNumber: 1,
startColumn: 1,
endLineNumber: 1,
endColumn: 2
}
},
{
uri: model2.uri,
range: {
startLineNumber: 1,
startColumn: 1,
endLineNumber: 1,
endColumn: 2
}
}]
}
})
So I was able to get this to work by overriding textModelService
(I wish there's a list of overrides somewhere)
const editor = monaco.editor.create(
document.getElementById("container"),
{},
{
textModelService: {
createModelReference: resource => {
const resourceModel = monaco.editor.getModel(resource);
const simpleModel = resourceModel
? new SimpleModel(resourceModel)
: null;
return window.monaco.Promise.as({
object: simpleModel,
dispose: () => {}
});
},
registerTextModelContentProvider: () => ({ dispose: () => {} })
}
}
);
@alexandrudima does this look ok to you?
If it works, then that's great. But be aware that this is internal API and things might break in the future... The standalone editor services are defined here:
and here:
I'll keep an eye out for changes. Thanks for the list
By the way we adopted Monaco at repl.it and are using language servers https://repl.it/site/blog/intel. It's a really cool and transformative project, thank you for maintaining it.
Was able to get peek, find all references and goto definition work across multiple models/tabs - had to override textModelService (as discussed earlier). This is how code change while creating monaco editor instance looks like for me ..
const editor = monaco.editor.create(document.getElementById("container")!, {
glyphMargin: true,
lightbulb: {
enabled: true
},
}, {
editorService: tkeLangCodeEditorService,
textModelService: {
createModelReference: function(uri: monaco.Uri) {
const textEditorModel = {
load() {
return Promise.resolve(textEditorModel)
},
dispose() {},
textEditorModel: monaco.editor.getModel(uri)
}
return Promise.resolve({
object: textEditorModel,
dispose() {}
})
},
registerTextModelContentProvider: () => ({ dispose: () => {} })
}
});
to make goto definition work across multiple models/tabs, had to override editorService - findModel and doOpenEditor methods. As these function are defined to work in single editor / tab environment ..
Existing standalone editorService implementation - with URI check in findModel:
StandaloneCodeEditorServiceImpl.prototype.findModel = function (editor, resource) {
var model = editor.getModel();
if (model.uri.toString() !== resource.toString()) {
return null;
}
return model;
};
Enhancement to make it work for multiple models/tab:
StandaloneCodeEditorServiceImpl.prototype.findModel = function (editor, resource) {
var model = null;
if(resource !== null)
model = monaco.editor.getModel(resource);
if(model == null) {
model = editor.getModel()
}
return model;
};
StandaloneCodeEditorServiceImpl.prototype.doOpenEditor = function (editor, input) {
var model = this.findModel(editor, input.resource);
//set editor to new model
if(model)
editor.setModel(model);
if (!model) {
if (input.resource) {
var schema = input.resource.scheme;
if (schema === Schemas.http || schema === Schemas.https) {
// This is a fully qualified http or https URL
windowOpenNoOpener(input.resource.toString());
return editor;
}
}
return null;
}
var selection = input.options.selection;
if (selection) {
if (typeof selection.endLineNumber === 'number' && typeof selection.endColumn === 'number') {
editor.setSelection(selection);
editor.revealRangeInCenter(selection, 1 /* Immediate */);
}
else {
var pos = {
lineNumber: selection.startLineNumber,
column: selection.startColumn
};
editor.setPosition(pos);
editor.revealPositionInCenter(pos, 1 /* Immediate */);
}
}
return editor;
};