Keeping models in separate projects and preventing cross-over file references #5087
-
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Updated:The OLD solution below doesn't actually work completely. It gets close, but it's so strict that built-in library references stop working. e.g., Trying to control-click I developed a full working solution here. It started off with the OLD solution, but got more involved as I went on: The main 'configure' entrypoint method is here: OLD:The gist of the solution:
Ouch! It was quite a bit harder than I thought, but with the help of ChatGPT, I figured it out. For those wondering the answer, there are a couple options it suggested:
Pre-requisite: When you create your editor Models, supply your own URI with I didn't try # 2 - though it looks like it might work - but I implemented solution # 1 which looks like the following, written in TypeScript: import * as monaco from "monaco-editor";
import type ts from "typescript";
// prevent cross-file references
// disable built-in definition / references behavior
const modeConfig = { references: false, definitions: false };
monaco.languages.typescript.typescriptDefaults.setModeConfiguration(modeConfig);
monaco.languages.typescript.javascriptDefaults.setModeConfiguration(modeConfig);
// helper to get worker for model
const getWorker = async (model: monaco.editor.ITextModel) => {
const lang = model.getLanguageId();
const getter =
lang === "typescript"
? await monaco.languages.typescript.getTypeScriptWorker()
: await monaco.languages.typescript.getJavaScriptWorker();
return await getter(model.uri);
};
// helper to create range from numeric start / end
const spanToRange = (
model: monaco.editor.ITextModel,
start: number,
length: number
) => {
const s = model.getPositionAt(start);
const e = model.getPositionAt(start + length);
return new Range(s.lineNumber, s.column, e.lineNumber, e.column);
};
// list of affected languages
const languages = ["javascript", "typescript"];
// helper type for found definition / reference entries
type ReferenceEntry = ts.DefinitionInfo | ts.ReferenceEntry;
// helper for filtering definitions / references by model path
const makeFilter = (model: monaco.editor.ITextModel) => {
// NOTE: THIS IS WHERE THE FILTERING CODE OCCURS: <-----------------
// In my case, I decided that each unique scheme/authority (`scheme://<authority>/path`) gets
// its own separate look-up context.
const prefix = `${model.uri.scheme}://${model.uri.authority}/`;
// return a filter function
return (match: ReferenceEntry) => match.fileName.startsWith(prefix);
};
// helper for converting definitions / references to monaco locations
const makeConverter = (model: monaco.editor.ITextModel) => {
// return a converter to convert from typescript definition / reference to monaco location
return (match: ReferenceEntry): monaco.languages.Location => ({
uri: model.uri,
range: spanToRange(model, match.textSpan.start, match.textSpan.length),
});
};
// register replacement definition / reference providers
monaco.languages.registerDefinitionProvider(languages, {
async provideDefinition(model, position) {
const worker = await getWorker(model);
const offset = model.getOffsetAt(position);
const defs = (await worker.getDefinitionAtPosition(
model.uri.toString(),
offset
)) as ts.DefinitionInfo[] | undefined;
return defs?.filter(makeFilter(model)).map(makeConverter(model)) ?? [];
},
});
monaco.languages.registerReferenceProvider(languages, {
async provideReferences(model, position, _context) {
const worker = await getWorker(model);
const offset = model.getOffsetAt(position);
let refs = (await worker.getReferencesAtPosition(
model.uri.toString(),
offset
)) as ts.ReferenceEntry[] | undefined;
return refs?.filter(makeFilter(model)).map(makeConverter(model)) ?? [];
},
}); |
Beta Was this translation helpful? Give feedback.

Updated:
The OLD solution below doesn't actually work completely. It gets close, but it's so strict that built-in library references stop working. e.g., Trying to control-click
Proxy/Mapfails, and none of them provide intellisense.I developed a full working solution here. It started off with the OLD solution, but got more involved as I went on:
https://github.com/CodeSmith32/WebScripts/blob/main/src/includes/services/monacoService.ts#L65-L245
The main 'configure' entrypoint method is here:
https://github.com/CodeSmith32/WebScripts/blob/main/src/includes/services/monacoService.ts#L149
OLD:
The gist of the solution:
truein themodeConfigoption…