解决vscode插件path-autocomplete有多个相同前缀别名路径下无法正常使用

背景

前几天在搞一个前端的新项目, 使用到webpack中的一个alias(别名)可以避免引用路径的混乱, 但是vscode无法很好地支持别名的路径提示

参考了网上某篇博客的介绍, 算是基本满足了自身的要求

其中介绍使用了一个path-autocomplete的插件, 简单介绍就是可以设置好别名对应的实际路径, 然后再推断路径提示的时候将别名替换为设置好的路径.

// src\features\PathAutocompleteProvider.ts
// configuration.data.pathMappings 即为一个 key为别名, value为真实路径的对象
Object.keys(configuration.data.pathMappings || {})
            .map((key) => {
                var candidatePaths = configuration.data.pathMappings[key];
                if (typeof candidatePaths == 'string') {
                    candidatePaths = [candidatePaths];
                }
                return candidatePaths.map(candidatePath => {
                    if (workspaceRootPath) {
                        candidatePath = candidatePath.replace('${workspace}', workspaceRootPath);
                    }
    
                    if (workspaceFolderPath) {
                        candidatePath = candidatePath.replace('${folder}', workspaceFolderPath);
                    }
    
                    candidatePath = candidatePath.replace('${home}', configuration.data.homeDirectory);
    
                    return {
                        key: key,
                        path: candidatePath
                    };
                });
            })
            .some((mappings) => {
                var found = false;

                mappings.forEach(mapping => {
// 关键的地方在这里, insertedPath 为当前编辑器输入的路径
// 判断输入的路径是否是以某个key值开头的, 如果是则将key进行替换成设置好的路径, 并返回
                    if (insertedPath.startsWith(mapping.key) || (mapping.key === '$root' && !insertedPath.startsWith('.'))) {
                        items.push({
                            // 该别名对应的路径
                            currentDir: mapping.path,
                            // 从路径中去掉别名
                            insertedPath: insertedPath.replace(mapping.key, '')
                        });
                        found = true;
                    }
                });

                // stop after the first mapping found
                return found;
            });

大部分情况下, 该插件是可以正常使用, 但是当配置中的key有相同前缀时, 就会出现问题了

比如我的设置是这样

// .setting.json
"path-autocomplete.pathMappings": {
    "@": "${folder}/src",
    "@view": "${folder}/src/components"
  },

而此时输入insertedPath = '@view', 我的本意应该是去寻找"${folder}/src/components", 但是根据上述代码, 因为Object.keys()返回的顺序是按照属性创建的先后顺序来的, 故@排在@view前面, 又因为@满足insertedPath.startsWith(mapping.key)这个条件, 导致插件误认为找到正确对应的路径, 造成错误, 无法显示正确路径

解决

解决办法很简单, 只要让路径匹配到有最长的有相同前缀的key就行了, 即如果路径是@view, 则让@view排前面, 路径是@则让key@排前面, 只需在Object.keys()后多加一个sort(), 按匹配前缀长度大小排列

// .src\features\PathAutocompleteProvider.ts
Object.keys(configuration.data.pathMappings || {})
           // 插上这个即可
            .sort((key1, key2) => {
                const f1 = insertedPath.startsWith(key1) ? key1.length : 0;
                const f2 = insertedPath.startsWith(key2) ? key2.length : 0;
                return f2 - f1;
            })
            .map((key) => {
                // ... 省略, 与前面一样
            })
            .some((mappings) => {
               // ... 省略, 与前面一样
            });

提交的PR

你可能感兴趣的:(解决vscode插件path-autocomplete有多个相同前缀别名路径下无法正常使用)