0

我正在创建一个语言服务器,目前有一个静态/预加载完成项的列表。.script此语言服务器将在任何文件上激活。在同一个目录下会有一个.map文件(任意扩展名,我不是指JS源映射文件)。映射文件只是一个纯文本文档,其中包含类名和名称列表(对于每个“实体”)。一个典型的条目可能如下所示:

// entity 237
{
"classname" "func_static"
"name" "func_static_237"
"origin" "200 179.5 -181"
"rotation" "0 -1 0 1 0 0 0 0 1"
}

我正在尝试将每个名称/类名对添加到完成列表中(名称是完成项标签,类名是详细信息)。这是我到目前为止所做的:

由于不幸的是“类名”的单个案例,我选择使用匹配两行的正则表达式。然后我使用了两个捕获组(一个用于名称,一个用于类名)将两者都推送到一个数组中。然后我遍历数组中的每一对并将其添加到完成列表中。

这个想法是我将映射文件中的变量预加载到相应的脚本文件中(它们都将具有相同的文件名并位于同一目录中)。

代码如下所示:

'use strict';

import * as path from 'path';
import * as vscode from 'vscode';
import * as fs from 'fs';

export function activate(context: vscode.ExtensionContext) {

    ...

    // each pair will go into this
    var objArray = new Array;

    function readTextFile() {
        // load the map file
        var text = fs.readFileSync(context.asAbsolutePath(path.join('donkey.map')));
        // match classname and name
        var regex = /\"classname\"\s\"(\w+)\"(?:\r\n|[\r\n])\"name\"\s\"(\w+)\"/g
        getMatches(text.toString(), regex);
    }

    function getMatches(string: string, regex: RegExp) {
        var match;
        while (match = regex.exec(string)){
            // capture group 1 = classname
            // capture group 2 = name
            // pushing name first because it's more important
            objArray.push([match[2], match[1]]);
        }
    }

    var loop1 = function (i: number) {
        // create a new completion item
        vscode.languages.registerCompletionItemProvider('quadscript', {
            provideCompletionItems: function () {
                var compItem = new vscode.CompletionItem(objArray[i][0], vscode.CompletionItemKind.Variable);
                compItem.insertText = ("$" + objArray[i][0]);
                compItem.detail = (objArray[i][1]);
                return [
                    compItem
                ];
            }
        });
    }

    for (var i = 0; i < objArray.length; i++) {
        loop1(i);
    }

    readTextFile();
}

当我在扩展开发主机中调试扩展时,调试控制台会显示:

C:\Program Files\Microsoft VS Code\Code.exe --debugBrkPluginHost=37535 --debugId=cfbf2c6d-c313-46fa-8c44-4e64f44eb97f --extensionDevelopmentPath=c:\Users\thefyrewire\Documents\VSCode\quadscript

然后,当我键入func时,它们按预期显示,表明它们已成功从文件中读取(存在于c:\Users\thefyrewire\Documents\VSCode\quadscript\donkey.map,对应于在调试控制台中看到的extensionDevelopmentPath )。

完成项从另一个文件中成功读取

我接下来去了并将and文件c:\Users\thefyrewire\Documents\test移动到这里,然后打包并安装了扩展。当我进入脚本文件并调出完成列表时,func_static 项目不存在。我认为这是因为它试图从安装扩展程序的位置读取,当我移动文件时,该扩展程序现在不存在。donkey.scriptdonkey.map.vscode\extensions\<extension>\donkey.map

因此,我尝试更改读取地图文件的路径并使用绝对路径作为测试。

var text = fs.readFileSync("file:///C:/Users/thefyrewire/Documents/test/donkey.map");

调试时,我得到了返回:

ENOENT:没有这样的文件或目录,打开 'C:\Program Files\Microsoft VS Code\file:\C:\Users\thefyrewire\Documents\test\donkey.map'。关闭警告

使用这样的相对路径:

var text = fs.readFileSync("./donkey.map");

回报:

ENOENT:没有这样的文件或目录,打开“C:\Program Files\Microsoft VS Code\donkey.map”。关闭警告

我尝试了多种其他 fs 方法,但似乎只能从C:\Program Files\Microsoft VS Code.

所以最后我的问题是:我需要做什么才能让我的扩展从与加载的任何脚本文件相同的目录中动态读取?任何建议将不胜感激,谢谢!

编辑:我意识到这还不清楚。我所说的“脚本文件”不是指 JS 脚本文件,它又是自定义语言的一部分(因此是语言服务器)。

4

1 回答 1

0

您可以使用__dirname

var fs = require('fs')
var path = require('path')

var text = fs.readFileSync(path.join(__dirname, donkey.map));
于 2017-12-14T06:29:48.660 回答