Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-eslint / server / util.ts
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'
7
8 interface Change {
9   start: number
10   end: number
11   newText: string
12 }
13
14 const enum CharCode {
15   /**
16    * The `\` character.
17    */
18   Backslash = 92
19 }
20
21 /**
22  * Check if the path follows this pattern: `\\hostname\sharename`.
23  *
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
26  * always false.
27  */
28 export function isUNC(path: string): boolean {
29   if (process.platform !== 'win32') {
30     // UNC is a windows concept
31     return false
32   }
33
34   if (!path || path.length < 5) {
35     // at least \\a\b
36     return false
37   }
38
39   let code = path.charCodeAt(0)
40   if (code !== CharCode.Backslash) {
41     return false
42   }
43   code = path.charCodeAt(1)
44   if (code !== CharCode.Backslash) {
45     return false
46   }
47   let pos = 2
48   let start = pos
49   for (; pos < path.length; pos++) {
50     code = path.charCodeAt(pos)
51     if (code === CharCode.Backslash) {
52       break
53     }
54   }
55   if (start === pos) {
56     return false
57   }
58   code = path.charCodeAt(pos + 1)
59   if (isNaN(code) || code === CharCode.Backslash) {
60     return false
61   }
62   return true
63 }
64
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)
72   } else {
73     return result
74   }
75 }
76
77 export function getFilePath(documentOrUri: string | TextDocument): string {
78   if (!documentOrUri) {
79     return undefined
80   }
81   let uri = Is.string(documentOrUri)
82     ? URI.parse(documentOrUri)
83     : URI.parse(documentOrUri.uri)
84   if (uri.scheme !== 'file') {
85     return undefined
86   }
87   return getFileSystemPath(uri)
88 }
89
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) {
97       return []
98     }
99     const engine = new settings.library.CLIEngine(options)
100     const res = engine.executeOnText(content, filename)
101     if (!res.results.length) return []
102
103     const { output } = res.results[0]
104     if (output == null) return []
105
106     const change = getChange(content, output)
107     return [{
108       range: {
109         start: document.positionAt(change.start),
110         end: document.positionAt(change.end)
111       },
112       newText: change.newText
113     }]
114   })
115 }
116
117 export function getChange(oldStr: string, newStr: string): Change {
118   let result = fastDiff(oldStr, newStr, 1)
119   let curr = 0
120   let start = -1
121   let end = -1
122   let newText = ''
123   let remain = ''
124   for (let item of result) {
125     let [t, str] = item
126     // equal
127     if (t == 0) {
128       curr = curr + str.length
129       if (start != -1) remain = remain + str
130     } else {
131       if (start == -1) start = curr
132       if (t == 1) {
133         newText = newText + remain + str
134         end = curr
135       } else {
136         newText = newText + remain
137         end = curr + str.length
138       }
139       remain = ''
140       if (t == -1) curr = curr + str.length
141     }
142   }
143   return { start, end, newText }
144 }
145
146 export function resolveModule(name: string, localPath: string, globalPath: string): Promise<string> {
147   if (localPath) {
148     let path = resolveFrom.silent(localPath, name)
149     if (path) return Promise.resolve(path)
150   }
151   try {
152     let path = resolveFrom(globalPath, name)
153     return Promise.resolve(path)
154   } catch (e) {
155     return Promise.reject(e)
156   }
157 }
158
159 export function executeInWorkspaceDirectory(document: TextDocument, settings: TextDocumentSettings, newOptions: CLIOptions, callback: Function): TextEdit[] {
160   const filename = getFilePath(document)
161   const cwd = process.cwd()
162   try {
163     if (filename) {
164       if (settings.workingDirectory) {
165         newOptions.cwd = settings.workingDirectory.directory
166         if (settings.workingDirectory.changeProcessCWD) {
167           process.chdir(settings.workingDirectory.directory)
168         }
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)
175         }
176       } else if (!settings.workspaceFolder && !isUNC(filename)) {
177         const directory = path.dirname(filename)
178         if (directory && path.isAbsolute(directory)) newOptions.cwd = directory
179       }
180     }
181
182     return callback(filename, newOptions)
183   } finally {
184     if (cwd !== process.cwd()) process.chdir(cwd)
185   }
186 }