-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
go to definition - different model: loading via http #291
Comments
You would need to provide a custom implementation of /**
* Create a new editor under `domElement`.
* `domElement` should be empty (not contain other dom nodes).
* The editor will read the size of `domElement`.
*/
export function create(domElement: HTMLElement, options?: IEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneCodeEditor; i.e. monaco.editor.create(domNode, options, { editorService: myEditorServiceInstanceHere }); You would need to find the service shape from vscode's sources, we do not plan to expose all services shapes in the public API ( |
@alexandrudima I have tried doing as instructed, but I am not getting the editor service called when I would expect it to... Here is the stub service I have at the moment: class EditorService {
_serviceBrand: any;
openEditor(input: ResourceInput, sideBySide?: boolean): Promise<monaco.editor.IEditor> {
console.log('openEditor', input);
return Promise.resolve({});
}
resolveEditor(input: ResourceInput, refresh?: boolean): Promise<TextEditorModel> {
console.log('resolveEditor', input);
return Promise.resolve({});
}
} And here is how I am creating my editor instance: const editorService = new EditorService();
const editor = monaco.editor.create(_root, options, { editorService }); But I can't seem to find any action in the editor that calls those methods. I have tried the "Go to Definition" and the other commands and I am just not getting anything logged to the console. It feels like there is something else I need to wire up... |
@kitsonk 👍 That is the correct way to inject a different You can run it anywhere in the playground monaco.languages.register({ id: 'mySpecialLanguage' });
monaco.languages.registerDefinitionProvider('mySpecialLanguage', {
provideDefinition: function(model, position, cancellationToken) {
return {
uri: monaco.Uri.parse('http://a/different/file.txt'),
range: new monaco.Range(3, 1, 3, 1)
};
}
});
var editorService = {
openEditor: function() {
alert(`open editor called!` + JSON.stringify(arguments));
},
resolveEditor: function() {
alert(`resolve editor called!` + JSON.stringify(arguments));
}
};
monaco.editor.create(document.getElementById("container"), {
value: '\n\Go to definition on this text',
language: 'mySpecialLanguage'
}, { editorService: editorService });
|
Ok, thanks!! I will try again and try to figure where I got it wrong. 😁 |
Just for future generations... I was missing a definition provider for the language I was trying to provide the editor service for. Without a definition provider, the editor service doesn't get called. |
I find this statement a bit counter productive and am asking the monaco/vscode team to reconsider. I am writing a custom integration to monaco where I have to replace some of these services as well. The types are there, and the implementation can be overridden using the public API (third parameter of constructor). Is there any con to exposing all services interfaces as well? |
@AviVahl Exposing the services will leak hundreds of new types to The 3rd argument is there exactly to allow custom more advanced integrators to do fun things... If you are doing such custom advanced stuff, I hope you can spend the extra few minutes to copy-paste the services types from the vscode repo and into your project... I know it is not optimal, but please keep in mind that the Monaco Editor is a by-product of VS Code and its sole reason for existance is VS Code. |
I'd argue that that's not completely true anymore. MS uses the monaco-editor outside of VSCode in quite a few places, like in their Azure Cloud products, Microsoft Teams and SQL Operations Studio. But also outside of MS it plays a big role, for example the next-gen IDE of Eclipse (Eclipse Theia) uses the monaco-editor at the heart of their product. The list of dependants keep growing, which proves what a great editor you've created, but it also puts the weight of their expectations on your shoulders. But rest assured, IMO you're handling this responsibility really well by allowing consumers to extend almost every corner of the editor. Naturally, there are always compromises to be made because otherwise it would stall VSCode development. |
A type is not "leaking" if it's already part of the public API. When an API is exposed as The overhead of generating the Copying and inlining interfaces is not a good practice. It's not just the wasted development time. These interfaces can give me a false positive build if I fail to keep them up-to-date with monaco/vscode. In addition, it's not always clear which interface matches which version (mix and match game from my end). Looking at the growing number of consumers of monaco, I propose a much wider change:
I would (personally) even go as further as creating a monorepo that contains all Microsoft's monaco integrations, along side the EDIT: and just in case it wasn't clear... I only suggest these changes because I find your team's work awesome and would like to enjoy using it in more of my own and work projects. |
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 ..
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:
Enhancement to make it work for multiple models/tab:
Let me know if you guys see any issues with this implementation? |
@alexandrudima I found the demo you provided didn't work. It won't monaco.languages.register({ id: 'mySpecialLanguage' });
monaco.languages.registerDefinitionProvider('mySpecialLanguage', {
provideDefinition: function(model, position, cancellationToken) {
return {
uri: monaco.Uri.parse('http://a/different/file.txt'),
range: new monaco.Range(3, 1, 3, 1)
};
}
});
var editorService = {
openEditor: function() {
alert(`open editor called!` + JSON.stringify(arguments));
},
resolveEditor: function() {
alert(`resolve editor called!` + JSON.stringify(arguments));
}
};
monaco.editor.create(document.getElementById("container"), {
value: '\n\Go to definition on this text',
language: 'mySpecialLanguage'
}, { editorService: editorService }); any update about this demo? |
I find the in
So even though I pass a the @alexandrudima may you can give us a new demo ? |
@frankLife as @abhaygupta mentioned, you could just override Still, it would be nice if there's a better solution without override the prototype like @alexandrudima offered |
@ChrisFan Thanks a lot and I will try in this weekend. |
@alexandrudima #291 (comment) I've observed the same with Monaco >= 0.14.x, used to work before. |
I've created #1296 to track the regression on our side... |
It seems like there's quite a bit of re-implementation which is necessary to override the text model and code editor services. And alternate approach which accesses quite a bit more private state but may be more maintainable in the longer approach is to patch the existing services: const services = [...editor._instantiationService._parent._services._entries.values()];
const textModelService = services.find((service) => 'createModelReference' in Object.getPrototypeOf(service));
// GoToDefinition validates that the range is within the bounds of
// the text model, so just generate a really big one that will work
// for any range.
const navigationTextModel = monaco.editor.createModel(new Array(10000).fill('').join('\n'));
textModelService.createModelReference = async (uri) => {
const reference = {
async load() {
return navigationTextModel;
},
dispose() {},
textEditorModel: navigationTextModel,
};
return {
object: reference,
dispose() {},
};
};
const codeEditorService = editor._codeEditorService;
codeEditorService.openCodeEditor = ({resource, options}) => {
const file = resource.path;
const range = options.selection;
// Add code here to open the code editor.
} |
This might have improved after microsoft/vscode#85129 |
Hi. Today, your example is not working |
i'm adding a go to definition feature using a langserver.
monaco notices it's a new model 👍, and then tries to load it.
the ranges of the place that contains definition is correct.
does monaco support in-place replacement of the model?
what i'm seeing is that it just offers to download the whole
file containing the resulting definition, i.e., this line
window.open(data.resource.toString());
.https://github.com/Microsoft/vscode/blob/0d6a9f8389cd044851ac994e527969bd53d2d387/src/vs/editor/browser/standalone/simpleServices.ts#L134
in my monaco build:
The text was updated successfully, but these errors were encountered: