mirror of
https://github.com/Microsoft/vscode
synced 2024-09-19 18:48:00 +00:00
Use case-insensitive synced buffer map on case-insensitive file systems
Fixes #51183 Fixes #50505
This commit is contained in:
parent
488030350d
commit
c40a2fd096
|
@ -11,6 +11,8 @@ import { Delayer } from '../utils/async';
|
|||
import { disposeAll } from '../utils/dispose';
|
||||
import * as languageModeIds from '../utils/languageModeIds';
|
||||
import API from '../utils/api';
|
||||
import { memoize } from '../utils/memoize';
|
||||
import { getTempFile } from '../utils/temp';
|
||||
|
||||
enum BufferKind {
|
||||
TypeScript = 1,
|
||||
|
@ -69,6 +71,10 @@ class SyncedBuffer {
|
|||
this.client.execute('open', args, false);
|
||||
}
|
||||
|
||||
public get resource(): Uri {
|
||||
return this.document.uri;
|
||||
}
|
||||
|
||||
public get lineCount(): number {
|
||||
return this.document.lineCount;
|
||||
}
|
||||
|
@ -126,6 +132,10 @@ class SyncedBufferMap {
|
|||
return file ? this._map.get(file) : undefined;
|
||||
}
|
||||
|
||||
public getForPath(filePath: string): SyncedBuffer | undefined {
|
||||
return this.get(Uri.file(filePath));
|
||||
}
|
||||
|
||||
public set(resource: Uri, buffer: SyncedBuffer) {
|
||||
const file = this.toKey(resource);
|
||||
if (file) {
|
||||
|
@ -149,7 +159,8 @@ class SyncedBufferMap {
|
|||
}
|
||||
|
||||
private toKey(resource: Uri): string | null {
|
||||
return this._normalizePath(resource);
|
||||
const key = this._normalizePath(resource);
|
||||
return key ? key.toLowerCase() : key;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +189,7 @@ export default class BufferSyncSupport {
|
|||
|
||||
this.diagnosticDelayer = new Delayer<any>(300);
|
||||
|
||||
this.syncedBuffers = new SyncedBufferMap(path => this.client.normalizedPath(path));
|
||||
this.syncedBuffers = new SyncedBufferMap(path => this.normalizePath(path));
|
||||
|
||||
this.updateConfiguration();
|
||||
workspace.onDidChangeConfiguration(() => this.updateConfiguration(), null);
|
||||
|
@ -202,6 +213,14 @@ export default class BufferSyncSupport {
|
|||
return this.syncedBuffers.has(resource);
|
||||
}
|
||||
|
||||
public toResource(filePath: string): Uri {
|
||||
const buffer = this.syncedBuffers.getForPath(filePath);
|
||||
if (buffer) {
|
||||
return buffer.resource;
|
||||
}
|
||||
return Uri.file(filePath);
|
||||
}
|
||||
|
||||
public reOpenDocuments(): void {
|
||||
for (const buffer of this.syncedBuffers.allBuffers) {
|
||||
buffer.open();
|
||||
|
@ -376,4 +395,40 @@ export default class BufferSyncSupport {
|
|||
return this._validateTypeScript;
|
||||
}
|
||||
}
|
||||
|
||||
private normalizePath(path: Uri): string | null {
|
||||
const key = this.client.normalizedPath(path);
|
||||
if (!key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
return this.isCaseInsensitivePath(key) ? key.toLowerCase() : key;
|
||||
}
|
||||
|
||||
private isCaseInsensitivePath(path: string) {
|
||||
if (isWindowsPath(path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return path[0] === '/' && this.onIsCaseInsenitiveFileSystem;
|
||||
}
|
||||
|
||||
@memoize
|
||||
private get onIsCaseInsenitiveFileSystem() {
|
||||
if (process.platform === 'win32') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const temp = getTempFile('typescript-case-check');
|
||||
fs.writeFileSync(temp, '');
|
||||
return fs.existsSync(temp.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
function isWindowsPath(path: string): boolean {
|
||||
return /^[a-zA-Z]:\\/.test(path);
|
||||
}
|
|
@ -663,9 +663,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
|||
return resource;
|
||||
}
|
||||
}
|
||||
const resource = Uri.file(filepath);
|
||||
|
||||
return resource;
|
||||
return this.bufferSyncSupport.toResource(filepath);
|
||||
}
|
||||
|
||||
public getWorkspaceRootForResource(resource: Uri): string | undefined {
|
||||
|
@ -976,7 +974,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
|||
}
|
||||
|
||||
if (this.apiVersion.gte(API.v222)) {
|
||||
this.cancellationPipeName = electron.getTempFile(`tscancellation-${electron.makeRandomHexString(20)}`);
|
||||
this.cancellationPipeName = electron.getTempSock('tscancellation');
|
||||
args.push('--cancellationPipeName', this.cancellationPipeName + '*');
|
||||
}
|
||||
|
||||
|
|
|
@ -3,25 +3,21 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import Logger from './logger';
|
||||
import { getTempFile, makeRandomHexString } from './temp';
|
||||
import path = require('path');
|
||||
import os = require('os');
|
||||
import net = require('net');
|
||||
import cp = require('child_process');
|
||||
import Logger from './logger';
|
||||
|
||||
export interface IForkOptions {
|
||||
cwd?: string;
|
||||
execArgv?: string[];
|
||||
}
|
||||
|
||||
export function makeRandomHexString(length: number): string {
|
||||
let chars = ['0', '1', '2', '3', '4', '5', '6', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
||||
let result = '';
|
||||
for (let i = 0; i < length; i++) {
|
||||
const idx = Math.floor(chars.length * Math.random());
|
||||
result += chars[idx];
|
||||
}
|
||||
return result;
|
||||
export function getTempSock(prefix: string): string {
|
||||
const fullName = `vscode-${prefix}-${makeRandomHexString(20)}`;
|
||||
return getTempFile(fullName + '.sock');
|
||||
}
|
||||
|
||||
function generatePipeName(): string {
|
||||
|
@ -38,12 +34,6 @@ function getPipeName(name: string): string {
|
|||
return path.join(os.tmpdir(), fullName + '.sock');
|
||||
}
|
||||
|
||||
export function getTempFile(name: string): string {
|
||||
const fullName = 'vscode-' + name;
|
||||
return path.join(os.tmpdir(), fullName + '.sock');
|
||||
}
|
||||
|
||||
|
||||
function generatePatchedEnv(
|
||||
env: any,
|
||||
stdInPipeName: string,
|
||||
|
@ -131,7 +121,7 @@ export function fork(
|
|||
};
|
||||
|
||||
// Create the process
|
||||
logger.info('Forking TSServer', `PATH: ${newEnv['PATH']}`);
|
||||
logger.info('Forking TSServer', `PATH: ${newEnv['PATH']} `);
|
||||
|
||||
const bootstrapperPath = require.resolve('./electronForkStart');
|
||||
childProcess = cp.fork(bootstrapperPath, [modulePath].concat(args), {
|
||||
|
|
21
extensions/typescript-language-features/src/utils/temp.ts
Normal file
21
extensions/typescript-language-features/src/utils/temp.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import path = require('path');
|
||||
import os = require('os');
|
||||
|
||||
export function makeRandomHexString(length: number): string {
|
||||
let chars = ['0', '1', '2', '3', '4', '5', '6', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
||||
let result = '';
|
||||
for (let i = 0; i < length; i++) {
|
||||
const idx = Math.floor(chars.length * Math.random());
|
||||
result += chars[idx];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getTempFile(name: string): string {
|
||||
return path.join(os.tmpdir(), name);
|
||||
}
|
Loading…
Reference in a new issue