├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── LICENSE ├── README.md ├── demo.gif ├── favicon.ico ├── package.json ├── src ├── Configuration.ts ├── DefinitionProvider.ts ├── WebpackAliasSearcher.ts ├── extension.ts └── util.ts ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | package-lock.json 4 | .DS_Store -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/out/**/*.js" 18 | ], 19 | "preLaunchTask": "npm: watch" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.insertSpaces": true, 3 | "editor.tabSize": 2, 4 | "editor.detectIndentation": false, 5 | "jumpToAliasFile.alias": {} 6 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .gitignore 3 | node_modules 4 | src 5 | tsconfig.json 6 | tslint.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Wanfu Zhang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 可以对 webpack 别名路径或者自定义别名路径进行快速跳转的插件. 2 | ### 适用场景 3 | - 自定义文件夹别名和文件夹名称不同, 比如: `"@comp": "src/components"`, 别名`@comp`和文件夹名称`components`是不同的 4 | - .vue 文件, vscode 不能正确识别 .vue 文件的引入 5 | 6 | **如果你的自定义文件夹别名和文件夹名称相同, 如`"components": "src/components"`, 别名`components`和文件夹名称`components`是相同的, 通常情况下vscode可以识别到, 不需要使用此插件. 如果vscode不能自动识别, 可以使用此扩展** 7 | 8 | ![Sample](https://raw.githubusercontent.com/wanfu920/jumpToAliasFile/master/demo.gif) 9 | 10 | 11 | ### Configuration 12 | 如果使用的是 webpack 别名路径, 99% 的情况不需要做任何设置, 插件可以智能的识别出 webpack alias, 并进行自动设置. 13 | - alias: 别名路径映射, 路径为绝对路径 14 | ``` 15 | "jumpToAliasFile.alias": { 16 | "@": "/Users/xxx/project/src", 17 | } 18 | ``` 19 | - webpeckConfigPath: webpack config 文件路径, 路径可以为绝对路径或者相对路径(相对项目根目录) 20 | ``` 21 | "jumpToAliasFile.webpeckConfigPath": "./webpack.config.json" 22 | ``` 23 | 24 | ### FAQ 25 | 26 | ### TodoList -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanfu920/jumpToAliasFile/4252045b0c2db0e66d813c240d4ecc84c081c421/demo.gif -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wanfu920/jumpToAliasFile/4252045b0c2db0e66d813c240d4ecc84c081c421/favicon.ico -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jump-to-alias-file", 3 | "displayName": "Jump To Alias File", 4 | "version": "1.0.9", 5 | "publisher": "wanfu", 6 | "engines": { 7 | "vscode": "^1.18.0" 8 | }, 9 | "icon": "favicon.ico", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/wanfu920/jumpToAliasFile" 13 | }, 14 | "categories": [ 15 | "Programming Languages" 16 | ], 17 | "keywords": [ 18 | "go to definition", 19 | "webpack alias", 20 | "jump to alias file", 21 | "jump" 22 | ], 23 | "activationEvents": [ 24 | "*" 25 | ], 26 | "main": "./out/extension", 27 | "scripts": { 28 | "vscode:prepublish": "npm run compile", 29 | "compile": "tsc -p ./", 30 | "watch": "tsc -watch -p ./", 31 | "postinstall": "node ./node_modules/vscode/bin/install" 32 | }, 33 | "contributes": { 34 | "configuration": { 35 | "type": "object", 36 | "title": "jumpToAliasFile setting", 37 | "properties": { 38 | "jumpToAliasFile.alias": { 39 | "type": "object", 40 | "default": {}, 41 | "scope": "resource", 42 | "description": "同 webpack resolve.alias 配置" 43 | }, 44 | "jumpToAliasFile.webpeckConfigPath": { 45 | "type": "string", 46 | "default": "", 47 | "scope": "resource", 48 | "description": "webpack config 路径" 49 | } 50 | } 51 | } 52 | }, 53 | "devDependencies": { 54 | "@types/node": "^6.0.40", 55 | "tslint": "^5.11.0", 56 | "typescript": "^2.1.4", 57 | "vscode": "^1.1.17" 58 | } 59 | } -------------------------------------------------------------------------------- /src/Configuration.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import * as path from 'path'; 3 | import WebpackAliasSearcher from './WebpackAliasSearcher'; 4 | 5 | export default class Configuration { 6 | private _workspaceDir: string; 7 | private _configuration: vscode.WorkspaceConfiguration; 8 | private _listenConfigChangeDispose: { dispose(): any }; 9 | private _webpackAliasSearcher: WebpackAliasSearcher; 10 | constructor() { 11 | this._workspaceDir = vscode.workspace.rootPath; 12 | this._syncConfiguration(); 13 | this._listenConfigChange(); 14 | if (!Object.keys(this.alias).length) { 15 | // 不存在 alias 时, 走自动寻找 alias 策略 16 | this._webpackAliasSearcher = new WebpackAliasSearcher(this._workspaceDir); 17 | let alias = this._webpackAliasSearcher.getDefaultAlias(); 18 | this.alias = { ...this.alias, ...alias }; 19 | } 20 | } 21 | 22 | private _syncConfiguration() { 23 | let oldWebpeckConfigPath: string; 24 | if (this._configuration) { 25 | oldWebpeckConfigPath = this._configuration.get('webpeckConfigPath'); 26 | } 27 | this._configuration = vscode.workspace.getConfiguration('jumpToAliasFile', vscode.Uri.file(this._workspaceDir)); 28 | let newWebpeckConfigPath: string = this._configuration.get('webpeckConfigPath'); 29 | if (newWebpeckConfigPath && newWebpeckConfigPath !== oldWebpeckConfigPath) { 30 | // webpeckConfigPath 发生了变化, 读取 webpackConfig 文件中的 alias, 设置到 alias 中 31 | this._syncWebpeckConfigAlias(newWebpeckConfigPath); 32 | } 33 | } 34 | private _listenConfigChange() { 35 | this._listenConfigChangeDispose = vscode.workspace.onDidChangeConfiguration(this._syncConfiguration.bind(this)); 36 | } 37 | private _syncWebpeckConfigAlias(webpeckConfigPath: string) { 38 | let webpackConfig: any; 39 | try { 40 | webpackConfig = require(path.join(this._workspaceDir, webpeckConfigPath)); 41 | } catch (error) { 42 | 43 | } 44 | if (webpackConfig && webpackConfig.resolve && webpackConfig.resolve.alias && typeof webpackConfig.resolve.alias === 'object') { 45 | this.alias = { ...this.alias, ...webpackConfig.resolve.alias }; 46 | } 47 | } 48 | get alias() { 49 | return this._configuration.get('alias') || {}; 50 | } 51 | set alias(alias) { 52 | if (alias && Object.keys(alias).length) { 53 | this._configuration.update('alias', alias); 54 | } 55 | } 56 | dispose() { 57 | this._listenConfigChangeDispose.dispose(); 58 | } 59 | } -------------------------------------------------------------------------------- /src/DefinitionProvider.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import * as path from 'path'; 3 | import Configuration from './Configuration'; 4 | import { fixFilePathExtension, extractImportPathFromTextLine, getFileZeroLocationFromFilePath } from './util'; 5 | 6 | export default class DefinitionProvider implements vscode.DefinitionProvider { 7 | constructor(private readonly _configuration: Configuration) { 8 | } 9 | provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult { 10 | return this._getFileRealPosition(document, position); 11 | } 12 | private _needJump(document: vscode.TextDocument, filePath: string): boolean { 13 | if (filePath.startsWith('.') && ( 14 | /\.(less|scss|sass)$/.test(filePath) || 15 | document.fileName.endsWith('.vue') 16 | )) return true; 17 | return false; 18 | } 19 | private async _getFileRealPosition(document: vscode.TextDocument, position: vscode.Position) { 20 | const textLine = document.lineAt(position) 21 | const pathObj = extractImportPathFromTextLine(textLine); 22 | 23 | let realFilePath: string; 24 | if (pathObj && pathObj.range.contains(position)) { 25 | realFilePath = this._tranformAliasPath(pathObj.path); 26 | 27 | // 由于 vscode 不能正确识别 vue 文件的正常导入, 所以此处添加对 vue 文件的正常引入支持 28 | // 由于 vscode 不能正确识别 less scss sass 文件的导入, 添加支持 29 | if (!realFilePath && this._needJump(document, pathObj.path)) { 30 | realFilePath = path.resolve(document.fileName, '../', pathObj.path); 31 | } 32 | } 33 | 34 | if (realFilePath) { 35 | realFilePath = await fixFilePathExtension(realFilePath) 36 | } 37 | if (realFilePath) { 38 | return getFileZeroLocationFromFilePath(realFilePath) 39 | }; 40 | } 41 | private _tranformAliasPath(aliasPath: string) { 42 | let alias = this._configuration.alias; 43 | 44 | let aliasArr = aliasPath.split('/') 45 | for (let key of Object.keys(alias)) { 46 | if (key === aliasArr[0]) { 47 | let value = alias[key]; 48 | if (!value.endsWith('/')) { 49 | value += '/'; 50 | } 51 | return aliasPath.replace(key + '/', value); 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/WebpackAliasSearcher.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | 4 | const excludePaths = ['test', 'node_modules']; 5 | 6 | type webpackConfigPaths = {webpackConfigPath:string, projectDir:string}[]; 7 | /** 8 | * 自动寻找 webpack alias 算法 9 | * 10 | * 1. 确定当前工作目录使用到了 webpack 11 | * 12 | * 先寻找项目目录中 package.json 13 | * 仅搜寻当前目录和次级目录下的 package.json 14 | * 遍历 package.json 中的 script, 找出 webpack 命令使用到的 config 文件 15 | * 如果没有找到 webpack config 文件, 启用搜寻当前目录下的所有 webpack 开发的文件, 提取出 alias 16 | */ 17 | export default class WebpackAliasSearcher { 18 | private _projects: Map = new Map(); 19 | constructor(private readonly _workspaceDir: string) { 20 | try { 21 | const rootWorkspacePackagePath = path.join(this._workspaceDir, 'package.json'); 22 | if (fs.existsSync(rootWorkspacePackagePath)) { 23 | this._setProject(rootWorkspacePackagePath); 24 | } else { 25 | const files = fs.readdirSync(this._workspaceDir).filter(f => { 26 | if (excludePaths.indexOf(f) > -1) return false; 27 | if (f.includes('.')) return false; 28 | return true; 29 | }); 30 | for (let file of files) { 31 | const subWorkspacePackagePath = path.join(this._workspaceDir, file, 'package.json'); 32 | if (fs.existsSync(subWorkspacePackagePath)) { 33 | this._setProject(subWorkspacePackagePath); 34 | } 35 | } 36 | } 37 | } catch (error) { 38 | } 39 | } 40 | private _setProject(pkgPath: string) { 41 | let pkg = require(pkgPath); 42 | if ( 43 | (pkg.dependencies && pkg.dependencies.webpack) || 44 | (pkg.devDependencies && pkg.devDependencies.webpack) 45 | ) { 46 | this._projects.set(path.join(pkgPath, '../'), { pkg }); 47 | } 48 | } 49 | getDefaultAlias() { 50 | let alias: any = {}; 51 | try { 52 | if (this._projects.size) { 53 | let webpackConfigPaths = this._getWebpackConfigPathsFromPackage(); 54 | webpackConfigPaths.push(...this._getWebpackConfigsFromFileSearch()); 55 | let webpackConfigs = this._getWebpackConfigs(webpackConfigPaths); 56 | if (webpackConfigs.length) { 57 | alias = this._getAliasFromWebpackConfigs(webpackConfigs); 58 | } 59 | } 60 | } catch (error) { 61 | } 62 | return alias; 63 | } 64 | private _getWebpackConfigs(webpackConfigPaths: webpackConfigPaths) { 65 | let newWebpackConfigPaths: Map = new Map(); 66 | for (const {webpackConfigPath, projectDir} of webpackConfigPaths) { 67 | newWebpackConfigPaths.set(webpackConfigPath, projectDir); 68 | } 69 | let webpackConfigs: any[] = []; 70 | for (let [webpackConfigPath, projectDir] of newWebpackConfigPaths) { 71 | try { 72 | // 修复 create react app 使用 process.cwd() 导致路径获取不正确问题 73 | // 修复 process.cwd() = projectDir 74 | process.cwd = () => projectDir; 75 | process.env.NODE_ENV = process.env.NODE_ENV || 'development'; 76 | const webpackConfig = require(webpackConfigPath); 77 | if (webpackConfig) { 78 | webpackConfigs.push(webpackConfig); 79 | } 80 | } catch (error) { 81 | } 82 | } 83 | return webpackConfigs; 84 | } 85 | private _getWebpackConfigPathsFromPackage() { 86 | let webpackConfigPaths: webpackConfigPaths = []; 87 | for(let [projectDir, { pkg }] of this._projects) { 88 | for (let key of Object.keys(pkg.scripts || {})) { 89 | const script = pkg.scripts[key]; 90 | let webpackConfigPath = this._getWebpackConfigPathsFromScript(script, projectDir); 91 | if (webpackConfigPath) { 92 | webpackConfigPaths.push({ webpackConfigPath, projectDir }); 93 | } 94 | } 95 | } 96 | return webpackConfigPaths; 97 | } 98 | private _getWebpackConfigPathsFromScript(script: string, projectDir: string) { 99 | let tokens = script.split(' ').filter(t => t); 100 | const webpackIndex = tokens.indexOf('webpack'); 101 | if (webpackIndex > -1) { 102 | let webpackConfigPath: string; 103 | const configIndex = tokens.indexOf('--config'); 104 | if (configIndex > webpackIndex && configIndex < tokens.length - 1) { 105 | webpackConfigPath = tokens[configIndex + 1]; 106 | } else { 107 | webpackConfigPath = './webpack.config.js'; 108 | } 109 | webpackConfigPath = path.join(projectDir, webpackConfigPath); 110 | return webpackConfigPath; 111 | } 112 | } 113 | private _getAliasFromWebpackConfigs(webpackConfigs: any[]) { 114 | let alias = {}; 115 | for(let webpackConfig of webpackConfigs) { 116 | if (webpackConfig.resolve && webpackConfig.resolve.alias && typeof webpackConfig.resolve.alias === 'object') { 117 | Object.assign(alias, webpackConfig.resolve.alias); 118 | } 119 | } 120 | return alias; 121 | } 122 | private _getWebpackConfigsFromFileSearch() { 123 | let webpackConfigPaths: webpackConfigPaths = []; 124 | for(let [projectDir, { pkg }] of this._projects) { 125 | let webpackConfigPath = this._traverseGetWebpackConfigsFromFileSearch(projectDir); 126 | if (webpackConfigPath.length) { 127 | webpackConfigPaths.push(...webpackConfigPath.map(t => ({webpackConfigPath: t, projectDir}))); 128 | } 129 | } 130 | return webpackConfigPaths; 131 | } 132 | private _traverseGetWebpackConfigsFromFileSearch(filePath: string, deep = 1, maxDeep = 5) { 133 | if (deep > maxDeep) { 134 | return []; 135 | } 136 | if (!fs.statSync(filePath).isDirectory()) return []; 137 | 138 | // 去除 node_modules test 文件夹, 非 .js 后缀文件, 以及 .开头文件 139 | let files = fs.readdirSync(filePath) 140 | .filter(t => { 141 | excludePaths.indexOf(t) === -1 || t.endsWith('.js') || !t.startsWith('.') 142 | if (excludePaths.indexOf(t) > -1) return false; 143 | if (t.includes('.')) { 144 | if (t.startsWith('.')) return false; 145 | if (!t.endsWith('.js')) return false; 146 | } 147 | return true; 148 | }); 149 | let dirs = files.filter(t => !t.endsWith('.js')); 150 | files = files.filter(t => t.endsWith('.js')); 151 | 152 | let webpackConfigPaths: string[] = []; 153 | for (let file of files) { 154 | let webpackConfigPath = this._getWebpackConfigFromFilePath(path.join(filePath, file)); 155 | if (webpackConfigPath) { 156 | webpackConfigPaths.push(webpackConfigPath); 157 | } 158 | } 159 | 160 | for(let dir of dirs) { 161 | let subWebpackConfigPaths = this._traverseGetWebpackConfigsFromFileSearch(path.join(filePath, dir), deep + 1); 162 | webpackConfigPaths.push(...subWebpackConfigPaths); 163 | } 164 | return webpackConfigPaths; 165 | } 166 | private _getWebpackConfigFromFilePath(filePath: string) { 167 | const tokens = filePath.split('/'); 168 | const fileName = tokens[tokens.length - 1]; 169 | if (/^webpack\..*\.js$/.test(fileName)) { 170 | return filePath; 171 | } 172 | } 173 | } -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import Configuration from './Configuration'; 3 | import DefinitionProvider from './DefinitionProvider'; 4 | 5 | console.log('jumpToAliasFile extension start'); 6 | export function activate(context: vscode.ExtensionContext) { 7 | console.log('jumpToAliasFile extension activing'); 8 | const configuration = new Configuration(); 9 | const definitionProvider = new DefinitionProvider(configuration); 10 | const registerDefinitionProvider = vscode.languages.registerDefinitionProvider({ scheme: 'file', pattern: '**/*.{js,jsx,ts,tsx,vue}' }, definitionProvider); 11 | context.subscriptions.push(configuration); 12 | context.subscriptions.push(registerDefinitionProvider); 13 | console.log('jumpToAliasFile extension actived'); 14 | } 15 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs'; 3 | import * as vscode from 'vscode'; 4 | 5 | const extensions = ['.js', '.ts', '.json', '.jsx', '.tsx', '.vue', '.css', '.mcss', '.scss', '.less', '.html']; 6 | 7 | async function readDir(dirPath: string) { 8 | let result = await new Promise((resolve, reject) => { 9 | fs.readdir(dirPath, (err, result) => { 10 | if (err) reject(err); 11 | resolve(result); 12 | }) 13 | }); 14 | return result; 15 | } 16 | async function stat(filePath: string) { 17 | return await new Promise((resolve, reject) => { 18 | fs.stat(filePath, (err, result) => { 19 | if (err) reject(err); 20 | resolve(result); 21 | }) 22 | }); 23 | } 24 | 25 | export async function fixFilePathExtension(filePath: string) { 26 | const dirPath = path.join(filePath, '../'); 27 | const fileName = filePath.replace(dirPath, ''); 28 | 29 | // 含有扩展名, 直接返回 30 | if (fileName.indexOf('.') > 0) return filePath; 31 | 32 | async function traverse(dirPath: string, fileName: string) { 33 | let dir = await readDir(dirPath); 34 | for (let ext of extensions) { 35 | if (dir.indexOf(fileName + ext) > -1) { 36 | return path.join(dirPath, fileName + ext); 37 | } 38 | } 39 | if (dir.indexOf(fileName) !== -1) { 40 | let stats = await stat(path.join(dirPath, fileName)) as fs.Stats; 41 | if (stats.isFile()) { 42 | return path.join(dirPath, fileName); 43 | } else if (stats.isDirectory()) { 44 | return 'dir'; 45 | } 46 | } 47 | } 48 | // 遍历文件所在目录, 匹配文件名.后缀 49 | let filePathWithExt = await traverse(dirPath, fileName); 50 | if (filePathWithExt === 'dir') { 51 | filePathWithExt = await traverse(filePath, 'index'); 52 | } 53 | if (filePathWithExt && filePathWithExt !== 'dir') return filePathWithExt; 54 | } 55 | 56 | export function extractImportPathFromTextLine(textLine: vscode.TextLine): { path: string, range: vscode.Range } | undefined { 57 | const pathRegs = [ 58 | /import\s+.*\s+from\s+['"](.*)['"]/, 59 | /import\s*\(['"](.*)['"]\)/, 60 | /require\s*\(['"](.*)['"]\)/, 61 | /import\s+['"](.*)['"]/ 62 | ]; 63 | let execResult: RegExpMatchArray; 64 | for (const pathReg of pathRegs) { 65 | execResult = pathReg.exec(textLine.text); 66 | if (execResult && execResult[1]) { 67 | const filePath = execResult[1]; 68 | const filePathIndex = execResult[0].indexOf(filePath); 69 | const start = execResult.index + filePathIndex; 70 | const end = start + filePath.length; 71 | return { 72 | path: filePath, 73 | range: new vscode.Range(textLine.lineNumber, start, textLine.lineNumber, end), 74 | }; 75 | } 76 | } 77 | } 78 | 79 | export function getFileZeroLocationFromFilePath(filePath: string) { 80 | let uri = vscode.Uri.file(filePath); 81 | let range = new vscode.Range(0, 0, 0, 0); 82 | let location = new vscode.Location(uri, range); 83 | return location; 84 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "lib": [ 7 | "es6" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": "./src" 11 | }, 12 | "exclude": [ 13 | "node_modules", 14 | ".vscode-test" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [true, "tabs"], 4 | "semicolon": [true, "always"] 5 | } 6 | } --------------------------------------------------------------------------------