parent
c8c5d7eba5
commit
cca85a2724
4 changed files with 82 additions and 46 deletions
|
@ -135,7 +135,7 @@ class PendingDiagnostics extends ResourceMap<number> {
|
|||
public getOrderedFileSet(): ResourceMap<void> {
|
||||
const orderedResources = Array.from(this.entries)
|
||||
.sort((a, b) => a.value - b.value)
|
||||
.map(entry => entry.resource)
|
||||
.map(entry => entry.uri)
|
||||
|
||||
const map = new ResourceMap<void>(this._normalizePath)
|
||||
for (const resource of orderedResources) {
|
||||
|
@ -270,24 +270,25 @@ class GetErrRequest {
|
|||
|
||||
public static executeGetErrRequest(
|
||||
client: ITypeScriptServiceClient,
|
||||
files: string[],
|
||||
uris: Uri[],
|
||||
onDone: () => void
|
||||
): GetErrRequest {
|
||||
const token = new CancellationTokenSource()
|
||||
return new GetErrRequest(client, files, token, onDone)
|
||||
return new GetErrRequest(client, uris, token, onDone)
|
||||
}
|
||||
|
||||
private _done = false
|
||||
|
||||
private constructor(
|
||||
client: ITypeScriptServiceClient,
|
||||
public readonly files: string[],
|
||||
public readonly uris: Uri[],
|
||||
private readonly _token: CancellationTokenSource,
|
||||
onDone: () => void
|
||||
) {
|
||||
let files = uris.map(uri => client.normalizePath(uri))
|
||||
const args: Proto.GeterrRequestArgs = {
|
||||
delay: 0,
|
||||
files: this.files
|
||||
files
|
||||
}
|
||||
const done = () => {
|
||||
if (this._done) {
|
||||
|
@ -522,8 +523,8 @@ export default class BufferSyncSupport {
|
|||
const orderedFileSet = this.pendingDiagnostics.getOrderedFileSet()
|
||||
if (this.pendingGetErr) {
|
||||
this.pendingGetErr.cancel()
|
||||
for (const file of this.pendingGetErr.files) {
|
||||
let resource = Uri.file(file).toString()
|
||||
for (const uri of this.pendingGetErr.uris) {
|
||||
let resource = uri.toString()
|
||||
if (this.syncedBuffers.get(resource)) {
|
||||
orderedFileSet.set(resource, undefined)
|
||||
}
|
||||
|
@ -535,8 +536,8 @@ export default class BufferSyncSupport {
|
|||
orderedFileSet.set(buffer.resource, undefined)
|
||||
}
|
||||
if (orderedFileSet.size) {
|
||||
let files = Array.from(orderedFileSet.keys).map(uri => this.client.normalizePath(Uri.parse(uri)))
|
||||
const getErr = this.pendingGetErr = GetErrRequest.executeGetErrRequest(this.client, files, () => {
|
||||
let uris = Array.from(orderedFileSet.uris).map(uri => Uri.parse(uri))
|
||||
const getErr = this.pendingGetErr = GetErrRequest.executeGetErrRequest(this.client, uris, () => {
|
||||
if (this.pendingGetErr === getErr) {
|
||||
this.pendingGetErr = undefined
|
||||
}
|
||||
|
|
|
@ -2,70 +2,79 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { Uri } from 'coc.nvim'
|
||||
|
||||
function defaultPathNormalizer(resource: string): string {
|
||||
let u = Uri.parse(resource)
|
||||
if (u.scheme === 'file') {
|
||||
return u.fsPath
|
||||
}
|
||||
return resource.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps of file resources
|
||||
* Maps of file uris
|
||||
*
|
||||
* Attempts to handle correct mapping on both case sensitive and case in-sensitive
|
||||
* file systems.
|
||||
*/
|
||||
export class ResourceMap<T> {
|
||||
private readonly _map = new Map<string, T>()
|
||||
private readonly _map = new Map<string, { uri: string, value: T }>()
|
||||
|
||||
constructor(
|
||||
protected readonly _normalizePath?: (resource: string) => string | null
|
||||
protected readonly _normalizePath: (uri: string) => string | null = defaultPathNormalizer
|
||||
) { }
|
||||
|
||||
public get size() {
|
||||
return this._map.size
|
||||
}
|
||||
|
||||
public get entries(): { resource: string, value: T }[] {
|
||||
return Array.from(this._map.keys()).map(key => {
|
||||
return { resource: key, value: this._map[key] }
|
||||
})
|
||||
public get entries(): Iterable<{ uri: string, value: T }> {
|
||||
return this._map.values()
|
||||
}
|
||||
|
||||
public has(resource: string): boolean {
|
||||
const file = this.toKey(resource)
|
||||
public has(uri: string): boolean {
|
||||
const file = this.toKey(uri)
|
||||
return !!file && this._map.has(file)
|
||||
}
|
||||
|
||||
public get(resource: string): T | undefined {
|
||||
const file = this.toKey(resource)
|
||||
return file ? this._map.get(file) : undefined
|
||||
public get(uri: string): T | undefined {
|
||||
const file = this.toKey(uri)
|
||||
if (!file) return undefined
|
||||
let entry = this._map.get(file)
|
||||
return entry ? entry.value : undefined
|
||||
}
|
||||
|
||||
public set(resource: string, value: T): void {
|
||||
const file = this.toKey(resource)
|
||||
public set(uri: string, value: T): void {
|
||||
const file = this.toKey(uri)
|
||||
if (file) {
|
||||
this._map.set(file, value)
|
||||
this._map.set(file, { uri, value })
|
||||
}
|
||||
}
|
||||
|
||||
public delete(resource: string): void {
|
||||
const file = this.toKey(resource)
|
||||
public delete(uri: string): void {
|
||||
const file = this.toKey(uri)
|
||||
if (file) {
|
||||
this._map.delete(file)
|
||||
}
|
||||
}
|
||||
|
||||
public get values(): Iterable<T> {
|
||||
return this._map.values()
|
||||
return Array.from(this._map.values()).map(x => x.value)
|
||||
}
|
||||
|
||||
public get keys(): Iterable<string> {
|
||||
return this._map.keys()
|
||||
public get uris(): Iterable<string> {
|
||||
return Array.from(this._map.values()).map(x => x.uri)
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
this._map.clear()
|
||||
}
|
||||
|
||||
private toKey(resource: string): string | null {
|
||||
private toKey(uri: string): string | null {
|
||||
const key = this._normalizePath
|
||||
? this._normalizePath(resource)
|
||||
: resource
|
||||
? this._normalizePath(uri)
|
||||
: uri
|
||||
if (!key) {
|
||||
return key
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import fs from 'fs'
|
|||
import os from 'os'
|
||||
import path from 'path'
|
||||
import { CancellationToken, CancellationTokenSource, Disposable, Emitter, Event } from 'vscode-languageserver-protocol'
|
||||
import * as fileSchemes from '../utils/fileSchemess'
|
||||
import { PluginManager } from '../utils/plugins'
|
||||
import { CallbackMap } from './callbackMap'
|
||||
import BufferSyncSupport from './features/bufferSyncSupport'
|
||||
|
@ -506,22 +507,22 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
|||
return Uri.file(filepath).toString()
|
||||
}
|
||||
|
||||
public normalizePath(resource: Uri): string | null {
|
||||
if (this._apiVersion.gte(API.v213)) {
|
||||
if (resource.scheme == 'untitled') {
|
||||
const dirName = path.dirname(resource.path)
|
||||
const fileName = this.inMemoryResourcePrefix + path.basename(resource.path)
|
||||
return resource
|
||||
.with({ path: path.posix.join(dirName, fileName) })
|
||||
.toString(true)
|
||||
public normalizePath(resource: Uri): string | undefined {
|
||||
if (fileSchemes.disabledSchemes.has(resource.scheme)) {
|
||||
return undefined
|
||||
}
|
||||
switch (resource.scheme) {
|
||||
case fileSchemes.file: {
|
||||
let result = resource.fsPath
|
||||
if (!result) return undefined
|
||||
result = path.normalize(result)
|
||||
// Both \ and / must be escaped in regular expressions
|
||||
return result.replace(new RegExp('\\' + this.pathSeparator, 'g'), '/')
|
||||
}
|
||||
default: {
|
||||
return this.inMemoryResourcePrefix + resource.toString(true)
|
||||
}
|
||||
}
|
||||
|
||||
const result = resource.fsPath
|
||||
if (!result) return null
|
||||
|
||||
// Both \ and / must be escaped in regular expressions
|
||||
return result.replace(new RegExp('\\' + this.pathSeparator, 'g'), '/')
|
||||
}
|
||||
|
||||
private get inMemoryResourcePrefix(): string {
|
||||
|
|
25
src/utils/fileSchemess.ts
Normal file
25
src/utils/fileSchemess.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export const file = 'file'
|
||||
export const untitled = 'untitled'
|
||||
export const git = 'git'
|
||||
/** Live share scheme */
|
||||
export const vsls = 'vsls'
|
||||
export const walkThroughSnippet = 'walkThroughSnippet'
|
||||
|
||||
export const semanticSupportedSchemes = [
|
||||
file,
|
||||
untitled,
|
||||
walkThroughSnippet,
|
||||
]
|
||||
|
||||
/**
|
||||
* File scheme for which JS/TS language feature should be disabled
|
||||
*/
|
||||
export const disabledSchemes = new Set([
|
||||
git,
|
||||
vsls
|
||||
])
|
Loading…
Reference in a new issue