你在正确的轨道上。以下是我如何使用 typescript/javascript worker API 在混合语言环境中提供完成:
return new Promise((resolve) => {
const workerPromise = (context.language === "javascript")
? languages.typescript.getJavaScriptWorker()
: languages.typescript.getTypeScriptWorker();
void workerPromise.then((worker: (...uris: Uri[]) => Promise<TypescriptWorker>) => {
void worker(model.uri).then((service) => {
const offset = model.getOffsetAt(localPosition);
const promise = service.getCompletionsAtPosition(model.uri.toString(), offset);
void promise.then((completions: CompletionInfo | undefined) => {
if (completions) {
const info = model.getWordUntilPosition(localPosition);
const replaceRange: IRange = {
startLineNumber: position.lineNumber,
startColumn: info.startColumn,
endLineNumber: position.lineNumber,
endColumn: info.endColumn,
};
resolve({
incomplete: false,
suggestions: completions.entries.map((entry) => ({
label: entry.name,
kind: this.convertKind(entry.kind),
range: replaceRange,
insertText: entry.insertText || entry.name,
} as CompletionItem)),
});
} else {
resolve({ incomplete: false, suggestions: [] });
}
});
});
});
});
这里重要的是,您创建的子模型仅包含单一语言的部分内容(请参阅Monaco.createModel())并使用它来调用完成项代码。
在我的应用程序中,我将编辑器的内容分成多个块(每个块只覆盖整行并且附加了特定的语言)。所以他们有一条起点线和一条终点线。有了这些信息,我可以为每个块创建子模型:
/**
* @returns A local model which contains only the text of this block. The caller must dispose of it!
*/
public get model(): Monaco.ITextModel {
const editorModel = super.model; // Model for the entire editor content.
if (!this.internalModel || this.internalModel.isDisposed()) {
const localModel = Monaco.createModel("", this.language);
// Do other required preparations of the local model, if needed.
this.internalModel = localModel;
}
if (editorModel && this.modelNeedsUpdate) {
this.modelNeedsUpdate = false;
this.internalModel.setValue(editorModel.getValueInRange(
{
startLineNumber: this.startLine,
startColumn: 1,
endLineNumber: this.endLine,
endColumn: editorModel.getLineMaxColumn(this.endLine),
}, Monaco.EndOfLinePreference.LF),
);
}
return this.internalModel;
}