Monaco Editor 代码提示功能的源码位置

关键函数入口:

    function provideSuggestionItems(model, position, options = CompletionOptions.default, context = { triggerKind: 0 /* Invoke */ }, token = cancellation_1.CancellationToken.None) {
        return __awaiter(this, void 0, void 0, function* () {
            // const t1 = Date.now();
            position = position.clone();
            const word = model.getWordAtPosition(position);
            const defaultReplaceRange = word ? new range_1.Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn) : range_1.Range.fromPositions(position);
            const defaultRange = { replace: defaultReplaceRange, insert: defaultReplaceRange.setEndPosition(position.lineNumber, position.column) };
            const result = [];
            const disposables = new lifecycle_1.DisposableStore();
            let needsClipboard = false;
            const onCompletionList = (provider, container) => {
                if (!container) {
                    return;
                }
                for (let suggestion of container.suggestions) {
                    if (!options.kindFilter.has(suggestion.kind)) {
                        // fill in default range when missing
                        if (!suggestion.range) {
                            suggestion.range = defaultRange;
                        }
                        // fill in default sortText when missing
                        if (!suggestion.sortText) {
                            suggestion.sortText = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.name;
                        }
                        if (!needsClipboard && suggestion.insertTextRules && suggestion.insertTextRules & 4 /* InsertAsSnippet */) {
                            needsClipboard = snippetParser_1.SnippetParser.guessNeedsClipboard(suggestion.insertText);
                        }
                        result.push(new CompletionItem(position, suggestion, container, provider));
                    }
                }
                if (lifecycle_1.isDisposable(container)) {
                    disposables.add(container);
                }
            };
            // ask for snippets in parallel to asking "real" providers. Only do something if configured to
            // do so - no snippet filter, no special-providers-only request
            const snippetCompletions = (() => __awaiter(this, void 0, void 0, function* () {
                if (!_snippetSuggestSupport || options.kindFilter.has(27 /* Snippet */)) {
                    return;
                }
                if (options.providerFilter.size > 0 && !options.providerFilter.has(_snippetSuggestSupport)) {
                    return;
                }
                // 关键代码导出提示列表->>>>>>>
                const list = yield _snippetSuggestSupport.provideCompletionItems(model, position, context, token);
                onCompletionList(_snippetSuggestSupport, list);
            }))();
            // add suggestions from contributed providers - providers are ordered in groups of
            // equal score and once a group produces a result the process stops
            // get provider groups, always add snippet suggestion provider
            for (let providerGroup of modes.CompletionProviderRegistry.orderedGroups(model)) {
                // for each support in the group ask for suggestions
                let lenBefore = result.length;
                yield Promise.all(providerGroup.map((provider) => __awaiter(this, void 0, void 0, function* () {
                    let isRet = options.providerFilter.size > 0 && !options.providerFilter.has(provider);
                    if (isRet) {
                        return;
                    }
                    try {
                        const list = yield provider.provideCompletionItems(model, position, context, token);
                        onCompletionList(provider, list);
                    }
                    catch (err) {
                        errors_1.onUnexpectedExternalError(err);
                    }
                })));
                if (lenBefore !== result.length || token.isCancellationRequested) {
                    break;
                }
            }
            yield snippetCompletions;
            if (token.isCancellationRequested) {
                disposables.dispose();
                return Promise.reject(errors_1.canceled());
            }
            // console.log(`${result.length} items AFTER ${Date.now() - t1}ms`);
            // result.reverse();
            return new CompletionItemModel(result.sort(getSuggestionComparator(options.snippetSortOrder)), needsClipboard, disposables);
        });
    }

解析 js/ts 代码模块提取提示信息的地方:

var SuggestAdapter = /** @class */ (function (_super) {
        __extends(SuggestAdapter, _super);
        function SuggestAdapter() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Object.defineProperty(SuggestAdapter.prototype, "triggerCharacters", {
            get: function () {
                return ['.'];
            },
            enumerable: false,
            configurable: true
        });
        SuggestAdapter.prototype.provideCompletionItems = function (model, position, _context, token) {
            return __awaiter(this, void 0, void 0, function () {
                var wordInfo, wordRange, resource, offset, worker, info, suggestions;
                return __generator(this, function (_a) {
                    switch (_a.label) {
                        case 0:
                            wordInfo = model.getWordUntilPosition(position);
                            wordRange = new monaco_editor_core_1.Range(position.lineNumber, wordInfo.startColumn, position.lineNumber, wordInfo.endColumn);
                            resource = model.uri;
                            offset = model.getOffsetAt(position);
                            return [4 /*yield*/, this._worker(resource)];
                        case 1:
                            worker = _a.sent();
                            return [4 /*yield*/, worker.getCompletionsAtPosition(resource.toString(), offset)];
                        case 2:
                            info = _a.sent();
                            if (!info || model.isDisposed()) {
                                return [2 /*return*/];
                            }
                            suggestions = info.entries.map(function (entry) {
                                var _a;
                                var range = wordRange;
                                if (entry.replacementSpan) {
                                    var p1 = model.getPositionAt(entry.replacementSpan.start);
                                    var p2 = model.getPositionAt(entry.replacementSpan.start + entry.replacementSpan.length);
                                    range = new monaco_editor_core_1.Range(p1.lineNumber, p1.column, p2.lineNumber, p2.column);
                                }
                                var tags = [];
                                if (((_a = entry.kindModifiers) === null || _a === void 0 ? void 0 : _a.indexOf('deprecated')) !== -1) {
                                    tags.push(monaco_editor_core_1.languages.CompletionItemTag.Deprecated);
                                }
                                return {
                                    uri: resource,
                                    position: position,
                                    offset: offset,
                                    range: range,
                                    label: entry.name,
                                    insertText: entry.name,
                                    sortText: entry.sortText,
                                    kind: SuggestAdapter.convertKind(entry.kind),
                                    tags: tags
                                };
                            });
                            return [2 /*return*/, {
                                    suggestions: suggestions
                                }];
                    }
                });
            })

tsWorker 解析核心:

		// 获得变量对象成员符号列表
        function getCompletionEntryDetails(fileName, position, name, formattingOptions, source, preferences) {
            if (preferences === void 0) { preferences = ts.emptyOptions; }
            synchronizeHostData();
            return ts.Completions.getCompletionEntryDetails(program, log, getValidSourceFile(fileName), position, { name: name, source: source }, host, (formattingOptions && ts.formatting.getFormatContext(formattingOptions, host)), // TODO: GH#18217
            preferences, cancellationToken);
        }
Monaco Editor 是一个功能强大的代码编辑器,它提供了丰富的代码提示功能。要启用 Monaco Editor代码提示,你需要使用相应的语言服务。 首先,你需要引入 Monaco Editor 的 JavaScript 文件。然后,创建一个 `Monaco.editor.IStandaloneCodeEditor` 实例,并传入相应的配置选项。 接下来,你需要为编辑器设置语言服务。语言服务是代码提示的关键部分,它提供了对特定编程语言的语法分析和代码提示功能。你可以使用现有的语言服务,也可以开发自己的语言服务。 如果你想为 JavaScript 提供代码提示,可以使用 TypeScript 的语言服务。以下是一个示例: ```javascript // 引入 Monaco Editor 的 JavaScript 文件 require.config({ paths: { 'vs': 'path/to/monaco-editor/min/vs' }}); require(['vs/editor/editor.main'], function() { // 创建 Monaco Editor 实例 var editor = monaco.editor.create(document.getElementById('container'), { value: "", language: "javascript" }); // 设置 JavaScript 的语言服务 monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true); // 开始代码提示 monaco.languages.registerCompletionItemProvider('javascript', { provideCompletionItems: function(model, position) { // 这里可以根据输入的代码位置和上下文来提供代码提示 // 返回一个包含代码提示项的数组 return [ { label: 'console', kind: monaco.languages.CompletionItemKind.Function, insertText: 'console.log()' }, { label: 'if', kind: monaco.languages.CompletionItemKind.Keyword, insertText: 'if () {\n\n}' }, // ... ]; } }); }); ``` 以上代码示例中,我们使用 `monaco.languages.registerCompletionItemProvider` 方法注册了一个 JavaScript 的代码提示提供者。在 `provideCompletionItems` 方法中,你可以根据输入的代码位置和上下文来提供相应的代码提示项。 这只是一个简单的示例,你可以根据具体需求进行更复杂的代码提示逻辑。希望能对你有所帮助!如果有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值