1 import * as path from 'path'
2 import fastDiff from 'fast-diff'
3 import { TextDocument, TextEdit } from 'vscode-languageserver'
4 import { CLIOptions, Is, TextDocumentSettings } from './types'
5 import { URI } from 'vscode-uri'
6 import resolveFrom from 'resolve-from'
22 * Check if the path follows this pattern: `\\hostname\sharename`.
24 * @see https://msdn.microsoft.com/en-us/library/gg465305.aspx
25 * @return A boolean indication if the path is a UNC path, on none-windows
28 export function isUNC(path: string): boolean {
29 if (process.platform !== 'win32') {
30 // UNC is a windows concept
34 if (!path || path.length < 5) {
39 let code = path.charCodeAt(0)
40 if (code !== CharCode.Backslash) {
43 code = path.charCodeAt(1)
44 if (code !== CharCode.Backslash) {
49 for (; pos < path.length; pos++) {
50 code = path.charCodeAt(pos)
51 if (code === CharCode.Backslash) {
58 code = path.charCodeAt(pos + 1)
59 if (isNaN(code) || code === CharCode.Backslash) {
65 function getFileSystemPath(uri: URI): string {
66 let result = uri.fsPath
67 if (process.platform === 'win32' && result.length >= 2 && result[1] === ':') {
68 // Node by default uses an upper case drive letter and ESLint uses
69 // === to compare pathes which results in the equal check failing
70 // if the drive letter is lower case in th URI. Ensure upper case.
71 return result[0].toUpperCase() + result.substr(1)
77 export function getFilePath(documentOrUri: string | TextDocument): string {
81 let uri = Is.string(documentOrUri)
82 ? URI.parse(documentOrUri)
83 : URI.parse(documentOrUri.uri)
84 if (uri.scheme !== 'file') {
87 return getFileSystemPath(uri)
90 export function getAllFixEdits(document: TextDocument, settings: TextDocumentSettings): TextEdit[] {
91 const uri = URI.parse(document.uri)
92 if (uri.scheme != 'file') return []
93 const content = document.getText()
94 const newOptions: CLIOptions = {...settings.options, fix: true}
95 return executeInWorkspaceDirectory(document, settings, newOptions, (filename: string, options: CLIOptions) => {
96 if (!settings.validate) {
99 const engine = new settings.library.CLIEngine(options)
100 const res = engine.executeOnText(content, filename)
101 if (!res.results.length) return []
103 const { output } = res.results[0]
104 if (output == null) return []
106 const change = getChange(content, output)
109 start: document.positionAt(change.start),
110 end: document.positionAt(change.end)
112 newText: change.newText
117 export function getChange(oldStr: string, newStr: string): Change {
118 let result = fastDiff(oldStr, newStr, 1)
124 for (let item of result) {
128 curr = curr + str.length
129 if (start != -1) remain = remain + str
131 if (start == -1) start = curr
133 newText = newText + remain + str
136 newText = newText + remain
137 end = curr + str.length
140 if (t == -1) curr = curr + str.length
143 return { start, end, newText }
146 export function resolveModule(name: string, localPath: string, globalPath: string): Promise<string> {
148 let path = resolveFrom.silent(localPath, name)
149 if (path) return Promise.resolve(path)
152 let path = resolveFrom(globalPath, name)
153 return Promise.resolve(path)
155 return Promise.reject(e)
159 export function executeInWorkspaceDirectory(document: TextDocument, settings: TextDocumentSettings, newOptions: CLIOptions, callback: Function): TextEdit[] {
160 const filename = getFilePath(document)
161 const cwd = process.cwd()
164 if (settings.workingDirectory) {
165 newOptions.cwd = settings.workingDirectory.directory
166 if (settings.workingDirectory.changeProcessCWD) {
167 process.chdir(settings.workingDirectory.directory)
169 } else if (settings.workspaceFolder) {
170 const workspaceFolderUri = URI.parse(settings.workspaceFolder.uri)
171 if (workspaceFolderUri.scheme === 'file') {
172 const fsPath = getFileSystemPath(workspaceFolderUri)
173 newOptions.cwd = fsPath
174 process.chdir(fsPath)
176 } else if (!settings.workspaceFolder && !isUNC(filename)) {
177 const directory = path.dirname(filename)
178 if (directory && path.isAbsolute(directory)) newOptions.cwd = directory
182 return callback(filename, newOptions)
184 if (cwd !== process.cwd()) process.chdir(cwd)