解决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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,087评论 19 139
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,688评论 8 265
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,161评论 1 32
  • 文/柚柚 题记:炭山窝,是我去过后还想再去一次的地方,也是我去过后很有写作冲动的地方,却因为懒惰而耽搁下来。今天,...
    柚柚yy阅读 678评论 3 1
  • “我们的爱情到这刚刚好,剩不多也不少”薛之谦的一首《刚刚好》唱出了我的心声。每个人都渴望得到一份属于自己...
    胖悦悦阅读 713评论 3 5